rsp-∞
[Bomb Lab] Phase_3 본문
pwndbg> disassemble phase_3
Dump of assembler code for function phase_3:
0x0000000000400f43 <+0>: sub rsp,0x18
0x0000000000400f47 <+4>: lea rcx,[rsp+0xc]
0x0000000000400f4c <+9>: lea rdx,[rsp+0x8]
0x0000000000400f51 <+14>: mov esi,0x4025cf
0x0000000000400f56 <+19>: mov eax,0x0
0x0000000000400f5b <+24>: call 0x400bf0 <__isoc99_sscanf@plt>
0x0000000000400f60 <+29>: cmp eax,0x1
0x0000000000400f63 <+32>: jg 0x400f6a <phase_3+39>
0x0000000000400f65 <+34>: call 0x40143a <explode_bomb>
0x0000000000400f6a <+39>: cmp DWORD PTR [rsp+0x8],0x7
0x0000000000400f6f <+44>: ja 0x400fad <phase_3+106>
0x0000000000400f71 <+46>: mov eax,DWORD PTR [rsp+0x8]
0x0000000000400f75 <+50>: jmp QWORD PTR [rax*8+0x402470]
0x0000000000400f7c <+57>: mov eax,0xcf
0x0000000000400f81 <+62>: jmp 0x400fbe <phase_3+123>
0x0000000000400f83 <+64>: mov eax,0x2c3
0x0000000000400f88 <+69>: jmp 0x400fbe <phase_3+123>
0x0000000000400f8a <+71>: mov eax,0x100
0x0000000000400f8f <+76>: jmp 0x400fbe <phase_3+123>
0x0000000000400f91 <+78>: mov eax,0x185
0x0000000000400f96 <+83>: jmp 0x400fbe <phase_3+123>
0x0000000000400f98 <+85>: mov eax,0xce
0x0000000000400f9d <+90>: jmp 0x400fbe <phase_3+123>
0x0000000000400f9f <+92>: mov eax,0x2aa
0x0000000000400fa4 <+97>: jmp 0x400fbe <phase_3+123>
0x0000000000400fa6 <+99>: mov eax,0x147
0x0000000000400fab <+104>: jmp 0x400fbe <phase_3+123>
0x0000000000400fad <+106>: call 0x40143a <explode_bomb>
0x0000000000400fb2 <+111>: mov eax,0x0
0x0000000000400fb7 <+116>: jmp 0x400fbe <phase_3+123>
0x0000000000400fb9 <+118>: mov eax,0x137
0x0000000000400fbe <+123>: cmp eax,DWORD PTR [rsp+0xc]
0x0000000000400fc2 <+127>: je 0x400fc9 <phase_3+134>
0x0000000000400fc4 <+129>: call 0x40143a <explode_bomb>
0x0000000000400fc9 <+134>: add rsp,0x18
0x0000000000400fcd <+138>: ret
phase_3을 디스어셈블한다. jmp 명령어를 사용하는 분기문이 많은데 전부 <+123>으로 이동한다. Phase_3에서도 sscanf가 등장한다. 폭탄이 터지는 34번째 줄을 피하기 위해서는 32번째 비교문을 통과해야 하는데, 29번째 줄의 sscanf에서 받은 값을 29번째 줄에서 0x1과 비교하였을 때 입력값이 0x1보다 더 크면 된다. 29번째 줄에서 cmp 이전에 eax에 들어 있는 값을 확인하기 위해 break point를 걸어 보자.
Breakpoint 3, 0x0000000000400f60 in phase_3 ()
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
────────────────────────────────────────────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]─────────────────────────────────────────────────────────────────────
*RAX 0x2
RBX 0x0
*RCX 0x20
RDX 0x0
*RDI 0x7fffffffd790 ◂— 0x7ffff7fb0032 /* '2' */
*RSI 0x2
*R8 0x1999999999999999
R9 0x0
*R10 0x7ffff7dbeac0 (_nl_C_LC_CTYPE_toupper+512) ◂— 0x100000000
*R11 0x7ffff7dbf3c0 (_nl_C_LC_CTYPE_class+256) ◂— 0x2000200020002
*R12 0x7fffffffdf18 —▸ 0x7fffffffe288 ◂— '/home/chaehyeonkim/Documents/bomb/bomb'
*R13 0x400da0 (main) ◂— push rbx
R14 0x0
*R15 0x7ffff7ffd040 (_rtld_global) —▸ 0x7ffff7ffe2e0 ◂— 0x0
*RBP 0x1
*RSP 0x7fffffffdde0 ◂— 0x0
*RIP 0x400f60 (phase_3+29) ◂— cmp eax, 1
임의로 1 2를 입력하였는데, 우리가 넣은 인자 값 rdi(eax의 값이라고 봐도 무방하다)에 2가 저장되어 있는 것을 볼 수 있다. 한 개의 숫자를 입력했을 때에는 rdi에 1이 저장돼 있었는데, 세 개의 숫자를 입력해 보니 두 개의 숫자를 입력했을 때와 같이 2가 저장되어 있었다. 0x1과 비교하였을 때 2가 나와야 해당 분기를 넘어갈 수 있으므로 우리가 입력할 숫자의 개수는 최소 2개이다. 입력값은 어디에 있을까?
pwndbg> x/6d $rsp
0x7fffffffdde0: 0 0 1 2
0x7fffffffddf0: 0 0
rsp+0x8과 0xc에 들어 있는 것을 볼 수 있다.
0x0000000000400f6a <+39>: cmp DWORD PTR [rsp+0x8],0x7
0x0000000000400f6f <+44>: ja 0x400fad <phase_3+106></phase_3+106>
첫 번째 분기를 통과한 뒤 두 줄을 읽어 보면 우리가 첫 번째로 넣은 값을 0x7과 비교하고 있다. 여기서는 ja 때문에 첫 번째 인자의 값이 두 번째 인자의 값보다 크면 안 된다. 106번째 줄에는 폭탄을 터뜨리는 함수가 대기하고 있다. (ㄷㄷ) 그러므로 우리가 첫 번째 값으로 넣을 수 있는 수는 0, 1, 2, 3, 4, 5, 6, 7의 8가지 숫자이다.
0x0000000000400f71 <+46>: mov eax,DWORD PTR [rsp+0x8]
0x0000000000400f75 <+50>: jmp QWORD PTR [rax*8+0x402470]
eax에 우리가 첫 번째로 입력한 값을 넣고, 50번째 줄에서는 그 첫 번째 입력값에 특정 연산을 수행하여 해당 주소가 가리키는 곳으로 이동시킨다. 해당 줄까지 함수를 진행시키고 rax에 특정 연산을 수행하면 rax에 어떤 값이 들어가게 되는지 찾아보자.
pwndbg> x/gx $rax*8+0x402470
0x402478: 0x0000000000400fb9
400fb9라는 값을 얻었다. 해당 주소로 찾아가 보자.
0x400fb9 <phase_3+118> mov eax, 0x137
eax에 0x137을 저장하고 있다. 십진수로 변환하면 311이므로, 폭탄을 제거하는 데에 1 311을 입력하면 해당 phase를 통과할 수 있을 것 같다. 0부터 7까지의 입력값이 첫 번째 숫자로 가능한 김에 각 입력값에 맞는 두 번째 값을 찾아볼 수 있을 것 같다. 첫 번째 입력값을 주고 마찬가지로 x/gx $rax*8+0x402470 명령어를 입력하면 두 번째 입력값을 받고, 해당 쌍을 입력하여 안전하게 phase를 통과할 수 있을 것이다. 구한 결과는 아래와 같다.
0 207
1 311
2 707
3 256
4 389
5 206
6 682
7 327
'Write-ups > system' 카테고리의 다른 글
[DreamHack] basic_exploitation_001 (0) | 2024.03.30 |
---|---|
[DreamHack] Return Address Overwrite 쉘 획득하기 (0) | 2024.03.30 |
[Bomb Lab] Phase_2 (0) | 2024.03.23 |
[Bomb Lab] Phase_1 (0) | 2024.03.23 |
[DreamHack] System Hacking 로드맵 Quiz: x86 Assembly 3 (0) | 2024.03.16 |