하나씩 끄기 [Android Internals CTF Ex8]
20298 단어 cybersecuritysecurityandroid
지침
의 시작하자
어떤 파일인지 살펴보겠습니다.
┌──(razali㉿razali)-[~/…/Ivy/AndroidVulnResearch/ctf/offByOne]
└─$ file a.out
a.out: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, with debug_info, not stripped
arm 파일이므로 Android 기기에 푸시해 보겠습니다.
──(razali㉿razali)-[~/…/Ivy/AndroidVulnResearch/ctf/offByOne]
└─$ adb push a.out /data/local/tmp
* daemon not running; starting now at tcp:5037
* daemon started successfully
a.out: 1 file pushed. 0.2 MB/s (3392956 bytes in 13.310s)
다음으로 Android 기기에서 실행해 보세요.
126|root@hammerhead:/data/local/tmp # chmod +x a.out
root@hammerhead:/data/local/tmp # ./a.out
usage: ./a.out <argument>
인수가 필요합니다. 나는 짧고 긴 논쟁을 계속했다.
root@hammerhead:/data/local/tmp # ./a.out aaaa
You failed :(
root@hammerhead:/data/local/tmp # /a.out aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
You failed :(
둘 다 실패로 이어졌습니다.
다음으로 IDA
를 사용하여 정적 분석을 수행해 보겠습니다.
아주 작은 프로그램처럼 보입니다. 그럼 처음부터 반전을 시작합시다.
정적 분석을 수행할 때 각 코드 블록에 대해 많은 주석을 넣는 것이 가장 좋습니다.
더 명확할 수 있으므로 IDA
보기와 nasm markdown
보기를 모두 표시할 것입니다.
main
함수의 시작 부분을 살펴보겠습니다.
; int __cdecl main(int argc, const char **argv, const char **envp)
EXPORT main
main
var_124= -0x124
var_120= -0x120
var_11C= -0x11C
var_115= -0x115
var_15= -0x15
var_14= -0x14
var_10= -0x10
var_C= -0xC
PUSH {R4,R5,R11,LR}
ADD R11, SP, #8
SUB SP, SP, #0x120
MOV R2, #0
STR R2, [R11,#var_C]
STR R0, [R11,#var_10]
STR R1, [R11,#var_14]
LDR R0, [R11,#var_10]
CMP R0, #2
BGE loc_857C
우리는 알고,R0
- argc
를 나타냅니다.R1
- argv
를 나타냅니다.R2
- envp
를 나타냅니다.
따라서 변수의 이름을 바꾸고 주석을 추가하겠습니다. 위의 코드 블록은 이제 다음과 같습니다.
; Attributes: bp-based frame
; int __cdecl main(int argc, const char **argv, const char **envp)
EXPORT main
main
var_124= -0x124
var_120= -0x120
var_11C= -0x11C
var_115= -0x115
var_15= -0x15
argv= -0x14
argc= -0x10
envp= -0xC
PUSH {R4,R5,R11,LR}
ADD R11, SP, #8
SUB SP, SP, #0x120
MOV R2, #0
STR R2, [R11,#envp]
STR R0, [R11,#argc]
STR R1, [R11,#argv]
LDR R0, [R11,#argc]
CMP R0, #2 ; Checking if argc is >=2
BGE loc_857C
인수를 넣었는지 여부에 따라 분기하기 때문에 우리의 경우에는 1
인수를 제공하여 argc
count 2
를 만듭니다. 따라서 프로그램은 오른쪽으로 분기됩니다.
오른쪽 블록을 살펴보겠습니다.
loc_857C
LDR R0, =(byte_6325B - 0x8588)
ADD R0, PC, R0 ; byte_6325B
LDRB R0, [R0]
STRB R0, [R11,#var_15]
LDR R0, [R11,#argv]
LDR R0, [R0,#4] ; s
BL strlen
CMP R0, #0x100
BLS loc_85BC
그것을 뒤집으면,
This code executes when there are atleast 1 cmd line argument
loc_857C
LDR R0, =(byte_6325B - 0x8588)
ADD R0, PC, R0 ; byte_6325B
LDRB R0, [R0]
STRB R0, [R11,#var_15]
LDR R0, [R11,#argv] ;
; The below line gets the first argument
LDR R0, [R0,#4] ; s
BL strlen ; gets the first argument and performs a strlen on it
CMP R0, #0x100 ; Length of the first argument is compared against 256
BLS loc_85BC ; Branch to the right if LOWER OR SAME than 256
왼쪽 블록의 코드를 보면 Length higher than 256 is not allowed
입니다. 길이가 256
이면 어떻게 됩니까? 엣지 케이스를 테스트해야 합니다.
이제 오른쪽 블록을 살펴보겠습니다.
loc_85BC
ADD R0, SP, #0x128+var_115
LDR R1, [R11,#argv]
LDR R1, [R1,#4]
BL strcpy
LDRB R1, [R11,#var_15]
CMP R1, #0
BNE loc_8604
그것을 뒤집으면,
Copies the first argument to the destination buffer
loc_85BC ; dest to strcpy
ADD R0, SP, #0x128+destBuffer
LDR R1, [R11,#argv]
LDR R1, [R1,#4] ; LOAD THE FIRST ARGUMENT as src to strcpy
BL strcpy
LDRB R1, [R11,#var_15]
CMP R1, #0
BNE loc_8604 ; if R1 is zero, we will get the flag!
R1이 Not Equal
~ 0
인 경우 오른쪽으로 실패한다는 것을 알 수 있습니다. 따라서 플래그를 얻으려면 R1이 0이어야 합니다.
R1은 스택 변수var_15
에서 값을 가져옵니다.var_15
는 readonly
라는 이름의 =(byte_6325B - 0x8588)
메모리 위치에서 이전 블록의 값을 가져옵니다.
.rodata
에 무엇이 포함되어 있는지 보기 위해 마우스를 올려 봅시다.
단순히 숫자 1
를 포함합니다.
따라서 우리는 var_15
가 숫자 1
를 포함한다는 것을 알고 있지만 플래그를 얻으려면 어떻게든 숫자를 0
로 만들어야 합니다.
변수의 스택 위치, 바로 메인 시작 부분을 살펴보겠습니다.
우리가 살펴본 코드는 최대 256
바이트를 쓸 수 있으며 두 변수는 서로 정확히 256바이트입니다. 따라서 var_15
로 재정의하려면 최소 257자가 필요합니다. 또한 플래그를 가져오려면 재정의하는 문자var_15
가 0이어야 합니다.
여기서 결함은 strcpy
에 의존합니다. 256자를 전달하면 strcpy
는 256자를 모두 buffer
에 복사하고 NULL
, \0
를 다음 위치인 257번째 위치에 추가하여 문자열을 종료합니다. 이 257번째 위치는 우리의 var_15
입니다.
따라서 호스트 시스템에서 파이썬을 사용하여 길이가 256
인 문자열을 빠르게 생성할 수 있습니다.
┌──(razali㉿razali)-[~/…/Ivy/AndroidVulnResearch/ctf/offByOne]
└─$ python -c 'print "a"*256'
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
그런 다음 이 문자열을 Android에 복사할 수 있습니다.
root@hammerhead:/data/local/tmp # ./a.out aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
You did it!
The flag is: "off_by_one"
그리고 우리는 깃발을 얻었습니다.
Reference
이 문제에 관하여(하나씩 끄기 [Android Internals CTF Ex8]), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/wireless90/off-by-one-android-internals-ctf-ex8-3ihe
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
┌──(razali㉿razali)-[~/…/Ivy/AndroidVulnResearch/ctf/offByOne]
└─$ file a.out
a.out: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, with debug_info, not stripped
──(razali㉿razali)-[~/…/Ivy/AndroidVulnResearch/ctf/offByOne]
└─$ adb push a.out /data/local/tmp
* daemon not running; starting now at tcp:5037
* daemon started successfully
a.out: 1 file pushed. 0.2 MB/s (3392956 bytes in 13.310s)
126|root@hammerhead:/data/local/tmp # chmod +x a.out
root@hammerhead:/data/local/tmp # ./a.out
usage: ./a.out <argument>
root@hammerhead:/data/local/tmp # ./a.out aaaa
You failed :(
root@hammerhead:/data/local/tmp # /a.out aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
You failed :(
; int __cdecl main(int argc, const char **argv, const char **envp)
EXPORT main
main
var_124= -0x124
var_120= -0x120
var_11C= -0x11C
var_115= -0x115
var_15= -0x15
var_14= -0x14
var_10= -0x10
var_C= -0xC
PUSH {R4,R5,R11,LR}
ADD R11, SP, #8
SUB SP, SP, #0x120
MOV R2, #0
STR R2, [R11,#var_C]
STR R0, [R11,#var_10]
STR R1, [R11,#var_14]
LDR R0, [R11,#var_10]
CMP R0, #2
BGE loc_857C
; Attributes: bp-based frame
; int __cdecl main(int argc, const char **argv, const char **envp)
EXPORT main
main
var_124= -0x124
var_120= -0x120
var_11C= -0x11C
var_115= -0x115
var_15= -0x15
argv= -0x14
argc= -0x10
envp= -0xC
PUSH {R4,R5,R11,LR}
ADD R11, SP, #8
SUB SP, SP, #0x120
MOV R2, #0
STR R2, [R11,#envp]
STR R0, [R11,#argc]
STR R1, [R11,#argv]
LDR R0, [R11,#argc]
CMP R0, #2 ; Checking if argc is >=2
BGE loc_857C
loc_857C
LDR R0, =(byte_6325B - 0x8588)
ADD R0, PC, R0 ; byte_6325B
LDRB R0, [R0]
STRB R0, [R11,#var_15]
LDR R0, [R11,#argv]
LDR R0, [R0,#4] ; s
BL strlen
CMP R0, #0x100
BLS loc_85BC
This code executes when there are atleast 1 cmd line argument
loc_857C
LDR R0, =(byte_6325B - 0x8588)
ADD R0, PC, R0 ; byte_6325B
LDRB R0, [R0]
STRB R0, [R11,#var_15]
LDR R0, [R11,#argv] ;
; The below line gets the first argument
LDR R0, [R0,#4] ; s
BL strlen ; gets the first argument and performs a strlen on it
CMP R0, #0x100 ; Length of the first argument is compared against 256
BLS loc_85BC ; Branch to the right if LOWER OR SAME than 256
loc_85BC
ADD R0, SP, #0x128+var_115
LDR R1, [R11,#argv]
LDR R1, [R1,#4]
BL strcpy
LDRB R1, [R11,#var_15]
CMP R1, #0
BNE loc_8604
Copies the first argument to the destination buffer
loc_85BC ; dest to strcpy
ADD R0, SP, #0x128+destBuffer
LDR R1, [R11,#argv]
LDR R1, [R1,#4] ; LOAD THE FIRST ARGUMENT as src to strcpy
BL strcpy
LDRB R1, [R11,#var_15]
CMP R1, #0
BNE loc_8604 ; if R1 is zero, we will get the flag!
┌──(razali㉿razali)-[~/…/Ivy/AndroidVulnResearch/ctf/offByOne]
└─$ python -c 'print "a"*256'
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
root@hammerhead:/data/local/tmp # ./a.out aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
You did it!
The flag is: "off_by_one"
Reference
이 문제에 관하여(하나씩 끄기 [Android Internals CTF Ex8]), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/wireless90/off-by-one-android-internals-ctf-ex8-3ihe텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)