House of Spirit
Free a fake fastbin chunk to get malloc to return a nearly-arbitrary pointer. said How2Heap
fastbin attack的要点在于通过fastbin单链表的特性申请到敏感地址完成任意地址写,一种是类似double free和UAF这种申请真的chunk,另外一种方法就是伪造chunk。
Principe
通过绕过fastbin的free()的相关检查,将fake_chunk放入fastbin
Arbitrary Alloc:劫持chunk的fd指针指向任意的可写内存,只要满足目标地址存在合法的 size 域
Premise
能够劫持chunk的fd指针
能够构造符合下列条件的fake_chunk
- fake chunk 的 ISMMAP 位不为 1
- fake chunk 地址需对齐,MALLOC_ALIGN_MASK
- fake chunk 的 size 大小需要满足对应的 fastbin 的需求,同时也得对齐。
- fake chunk 的 next chunk 的大小不能小于
2 * SIZE_SZ
,同时也不能大于av->system_mem
。- fake chunk 对应的 fastbin 链表头部不能是该 fake chunk,即不能构成 double free 的情况。
Steps
将存在的指针改写指向我们伪造的块(这个块可以位于堆、栈、bss任何一个位置)并且free掉欺骗glibc达到把伪造块回收到bins中。
不过在free之前,需要设置当前伪造块和下一个伪造块的size字段,满足free()的安全检测机制,从而欺骗glibc。
Example
hack.lu oreo
Reverse Analysis
1 | puts("What would you like to do?\n"); |
以为会是卖饼干的,结果是卖军火的,sad
1 | oreo: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.26, BuildID[sha1]=f591eececd05c63140b9d658578aea6c24450f8b, stripped |
1 | gdb-peda$ checksec |
add()
1 | v1 = record;//record是bss段的全局变量 |
可以看到,从record + 25到record + 52有31个字节,而这里可以读入56个字节,说明rifle_name可以覆盖掉record + 52的old_record指针
存在堆溢出漏洞:record总大小才0x40,name都读到+81的地方了,会覆盖到下一个chunk
1 | record的布局 |
show()
1 | printf("Rifle to be ordered:\n%s\n", "==================================="); |
每个chunk的+52位构成了一个单链表,这里遍历了该链表
message()
1 | printf("Enter any notice you'd like to submit with your order: "); |
我们可以往这里输入ROP chain,通过申请fake chunk执行ROPchain
order()
1 | v2 = record; |
没有将所有被释放的指针置零,存在dangling pointer
Exploitation
利用思路:
通过堆溢出覆盖next_record为got表地址,再通过show() leak libc。
伪造chunk
我们希望申请到message_0正好是fd指针的chunk,就需要将message_0 - 4(fake_chunk_size),即number的内容改写为0x40(因为rifle的大小是0x38,对应chunk大小为0x40),也就是add0x40个rifle。
现在可以进行任意地址写了,改写某 got 项为 system 地址,就能get shell