堆入门攻略-how2heap学习总结
how2heap是一个开源的堆漏洞系列教程,这里简单的总结一下。后续会把一些漏洞详细的利用过程写成博客。
原地址:https://github.com/shellphish/how2heap
a = malloc(512) = 0x2490010
b = malloc(256) = 0x2490220
free(a)
c = malloc(500) = 0x2490010
a = malloc(8) = 0x7a8010
b = malloc(8) = 0x7a8030
c = malloc(8) = 0x7a8050
free(a)
free(b)
free(a)
d = malloc(8) = 0x7a8010
e = malloc(8) = 0x7a8030
f = malloc(8) = 0x7a8010
unsigned long long stack_var = 0x20
a = malloc(8);b = malloc(8);c = malloc(8)
free(a);free(b);free(a)
d = malloc(8);malloc(8)
d = (unsigned long long) (((char)&stack_var) - 8)
malloc(8)
malloc(8) == ((char*)&stack_var) + 8
a = malloc(0x40) = 0x1b69010
b = malloc(0x40) = 0x1b69060
free(a)
c = malloc(0x400)//申请large bin的时候已经执行了malloc_consolidate
free(a)//并不会报错,这个时候a已经被放到了unsorted bin之中
malloc(0x40) = 0x1b69010;malloc(0x40) = 0x1b69010
(P->fd->bk != P || P->bk->fd != P) = False
fd = ptr - size*3
bk = ptr - size*2
(chunksize(P) != prev_size (next_chunk(P)) == False
修改对应的prev_inuse和prev_size
unlink执行之后
ptr = ptr - size*3
ptr[3]可以修改ptr指向的内容
+------------------+
| 可控区域1 |
+------------------+
| 目标区域(不可控, |
| 多为返回地址或函数 |
| 指针等) |
+------------------+
| 可控区域2 |
+------------------+
想要控制的目标区域前面一段和后面一段都是可控区域。
存在可覆盖的堆指针
伪造堆块,在可控区域1和2中构造数据,将目标区域伪造成一个fast chunk。
覆盖堆指针指向伪造的fast chun。
释放伪造的fast chunk到fastbin单链表中。
申请刚刚释放的chunk,使得可以向目标区域中写入数据。
分配三个稍大的chunk
a = (uint8_t*) malloc(0x100)
b = (uint8_t*) malloc(0x200)
c = (uint8_t*) malloc(0x100)
在free(b)之前伪造一个假的下个chunk的prev_size,即(((uint64_t )c) - 2 -2) = b.size & (~0xff),以此绕过再次分配的chunksize(P) != prev_size (next_chunk(P))
(size_t)(b+0x1f0) = 0x200
free(b)
触发漏洞
a[0x108] = 0
分配两个较小的chunk
b1 = malloc(0x100)
b2 = malloc(0x80)
依次free,因为c的prev_size没有更新,造成合并
free(b1)
free(c)
再次分配大小覆盖b2的chunk,可对b2任意写
d = malloc(0x300)
d == b
需要控制small bin chunk的bk指针
控制指定位置的chunk的fd指针
修改small bin中chunk的bk指针指向fake chunk 令fake chunk的fd指向small bin中的chunk//绕过检查 fake chunk不能是small bin的最后一个chunk//绕过检查 free(small bin chunk) malloc(size);malloc(size)//最后一次返回的是我们构造的fake chunk
p1 = malloc(0x100 - 8);p2 = malloc(0x100 - 8);p3 = malloc(0x100 - 8)
free(p2);p2->unsorted bin
通过溢出修改chunk p2的size
p4 = malloc(0x180)//p2和p3被一起分配出来了
可以对p4进行操作,顺便写了p3,也可以通过修改p3来修改p4的内容
p1 = malloc(1000);p2 = malloc(1000);p3 = malloc(1000);p4 = malloc(1000);p5 = malloc(1000)
free(p4)//因为p5的存在所以p4在free之后不会被合并入top chunk
p2.size = p2.size + p3.size + prev_inuse//修改p2的size大小
free(p2)
p6 = malloc(2000);p6 == p2
能够以溢出等方式修改top chunk的size域
自由控制堆分配的大小
malloc(100)//随便分配一个chunk
使用溢出修改top chunk的size为一个大数//不会去调用mmap
malloc(size)//size=目标地址减去 top chunk 地址,再减去 chunk 头的大小
p = malloc(100); p == 目标地址
victim = malloc(0x100);p1 = malloc(100);free(victim)//p1防止victim和top chunk合并
在栈上fake一个chunk,bk指向自身
通过溢出漏洞修改victim的bk指向fake chunk
下一次malloc就会遍历unsortedbin从而找到fake chunk.fake chunk的fd指针被修改成了unsortedbin的地址,可以泄露libc地址。
p1 = malloc(0x100);p2 = malloc(0x100);free(p1)
利用溢出修改怕p1的bk为目标地址-2,相当于在目标地址有一个fake free chunk
此时malloc系统就会循着bk去找fake chunk
a = malloc(0x38);b = malloc(0xf8
fake一个chunk
使b的PREV_INUSE = 0,prev_size = b - addr(fake_chunk) - sizeof(size_t)*2
使fake_chunk的size=prev_size
free(b)//这个时候PREV_IN_USE为0,unlink会根据prev_size去找上一个free chunk并合并.这个时候top chunk->fake_chunk
这个时候malloc的话返回的将是fake chunk的位置
关于我
blog:https://0x2l.github.io/
看雪ID:0x2l
https://bbs.pediy.com/user-862439.htm
推荐文章++++
好书推荐