0.特殊的offbyone
offbynull是offbyone的一种特殊情况。它的特点是溢出的一字节为NULL字节。
与传统的offbyone思路相似,我们也是要通过这溢出的NULL字节来实现chunk overlap,从而实现内存泄漏或是修改堆指针。
1.利用思路
我们知道,当一个大小属于unsortedbin的chunk被释放后,会触发合并操作。而向前合并的依据就是该chunk的prev_inuse位为0,并且是通过prev_size字段来找到定位一个chunk的。
既然这样,假设我们的堆布局是这样的:
有四个申请大小都等于0xf8(实际大小为0x100)的相邻chunk,从低地址向高地址分别为ABCD。假设存在offbynull,则我们可以在B处利用offbynull,使得C的prev_inuse位为0,并同时修改C的prev_size大小为0x200(即A+B的大小)。这样,在释放C后,C就会将A+B视为一个chunk合并。需要注意的是,在释放C前需要先释放A,否则会报错。
这样一来,虽然ABC合并为一个unsortedbin chunk,但是,由于B并没有被真正free掉,因此造成了chunk overlap。
但是,在实际的利用中,被合并的堆块不一定要是unsortedbin大小的堆块,也可以是fastbin大小的堆块,便于进行后续的fastbin attack。(但要保证头部的chunk大小必须符合unsortedbin) 例如,将上述的B换成申请大小为0x68(实际为0x70)的chunk,在ABC合并后,我们可以申请一个实际大小为A+B的chunk,这样根据ptmalloc机制,会将ABC分割并返回AB给我们。这样,堆块AB和堆块B重叠,free掉B,B就会进入fastbin,此时我们还可以访问到它,后续就是fastbin attack了。
2.例子
2-1.附件
点击下载:offbynull
libc版本为2.23。
2-2.分析
漏洞在add函数。
在写入初始content时,会在结尾添加\x00,由于边界检查不严格,导致如果填满的话\x00会溢出,存在offbynull。
leak的思路和上一个offbyone相同,不多赘述。
主要讲讲offbynull的利用。
不知道为什么,此题如果我合并三个堆块的话就会在free时报错,但是如果合并4个就不会。
这题我是先申请了五个大小分别为0xf8、0x68、0xf8、0xf8、0xf8(实际大小分别加上0x8)的堆块。先释放掉第三个,再申请回来,申请的同时完成offbyone的利用,使得第四个堆块的prev_size为0x270(即一二三个相加的实际大小),prev_inuse位为0。再依次释放第一、第四个堆块,这样前四个堆块就会合并为一个大小为unsortedbin chunk。此后申请一个大小为0x160(实际0x170)的chunk,就会把第一第二个切下给我们(当成一个堆块)。此时未被释放的第二个堆块和被当成一个堆块的一二堆块就会发生重叠,释放掉第二个堆块,它会进入fastbin。之后再fastbin attack即可。
如果一开始没用0x70的堆块,而是同样是0x100的堆块则在上述步骤中需要修改其中一个被合并的堆块size为0x70,并在之后伪造一个chunk头(保证prev_inuse位为1),这样才能伪造一个fastbin chunk释放。后续再利用fastbin attack。
2-3.exp
完整的exp如下:
1 | from pwn import * |