rsp-∞

[Bomb Lab] Phase_3 본문

Write-ups/system

[Bomb Lab] Phase_3

portrait.kim 2024. 3. 23. 15:53

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