0.chunk extend
chunk extend(堆拓展),这种方法其实之前有讲过,就是通过修改chunk size使原有的堆块长度扩展,从而覆盖其后的堆块,造成overlap,以达到leak或者attack的目的。
这种利用手法常见于有堆溢出漏洞尤其是offbyone的题。
1.heapcreator
这是BUU上的一题,edit_heap函数存在offbyone漏洞:
这道题还有一个注意的点就是,在create_heap函数中,在malloc给我们用的堆块前还malloc了一个0x10(实际大小为0x20)的chunk,这个chunk用于记录给我们用的chunk的信息,包括大小,写入地址。
这也就意味着当我们调用了create_heap函数后,实际上系统会分先后分配两个chunk,第一个用于记录给用户使用的堆块(即第二个)的信息,第二个才是给用户使用的。
如下图,当我们正常申请一个0x60大小的堆块后的实际堆布局:
可以看出,正常调用create_heap函数后,生成的两个堆块是紧挨着的,且存放信息的堆块在给我们用户使用的堆块前面,当我们调用delete_heap函数后,系统会释放这两个堆块:
这样的话理论上无论怎样申请都会形成图示的堆布局;并且将指针清空(清空的是信息堆块的指针,用户堆块的指针保存在信息堆块中,原理上只要无法访问到信息堆块就无法找到用户堆块。),因此并没有明显的UAF漏洞。
但是,试想这样一种情况,假设我们申请一个0x10大小的堆块:
由于存在offbyone的漏洞,我们可以通过前一个申请的堆块修改这个信息堆块的size,利用chunk extend使得这个堆块实际长度为0x40,这样可以刚好覆盖用户堆块,从而造成overlap:
这样,当我们调用delete_heap后,实际会释放两个堆块,一个是实际大小为0x40的,一个是实际大小为0x20的,并且他们重叠,并且会进入不同的fastbin。
这样,当我们再申请一个0x30大小的堆块后,根据create_heap的规则,会先申请一个0x10的堆块存放信息,这样,刚刚我们0x20大小的位于fastbin的用户堆块就会被检索到,返回给当作信息堆块使用。而刚刚的0x40大小的堆块就会被当作用户堆块使用:
从上图可以看出,效果相当于将用户堆块和信息堆块“调换了位置”,并且他们重叠。这样,我们就可以访问到信息堆块,将指针改为我们的目标地址,这样我们再访问这个堆块时,实际访问的就是目标地址了。
例如,我们修改为free@got,这样,我们就可以修改got表了(程序RELRO没全开):
还有一点需要注意的是,远程的U16和我虚拟机使用的libc应该存在一个小版本差异,因此要用LibcSearcher,但是LibcSearcher无法识别main_arena等的符号表,因此不能用unsortedbin leak。
这里leak的思路是将指针改为free@got后调用show_heap函数,由于之前调用过了free,因此此时free@got里面存放的是free函数的真实地址,这样就能leak出free,就能使用LibcSearcher了。
完整的exp如下:
1 | from pwn import * |
成功获取了flag: