https://github.com/shellphish/how2heap/blob/master/glibc_2.31/poison_null_byte.c
又是一篇充满艺术的构造
step1:构造padding,是的prev chunk最低两位地址为0000
void *tmp = malloc(0x1);
void *heap_base = (void *)((long)tmp & (~0xfff));
printf("heap address: %p\n", heap_base);
size_t size = 0x10000 - ((long)tmp&0xffff) - 0x20;
printf("Calculate padding chunk size: 0x%lx\n", size);
puts("Allocate the padding. This is required to avoid a 4-bit bruteforce because we are going to overwrite least significant two bytes.");
void *padding= malloc(size);
0x10000 - ((long)tmp&0xffff) 表示地址0xffff段tmp用完剩余的
- 0x20 tmp和padding两个chunk,(prev_size+size)*2大小
分配完tmp与padding后,段0xffff被tmp与padding 用完,prev 从0000开始,prev chunk末尾两字节地址就清晰了。
step2:
分配 prev chunk(0x500大小),分配victim chunk(0x4f0)
分配 0x10 大小chunk,防止victim chunk与后续chunk consolidate
Step3:
分配 a chunk(0x4f0),分配0x10大小chunk,分配b chunk(0x510),分配0x10大小chunk
free(a),free(b),free(prev),使得prev->b->a进入unsort bin
malloc(0x1000),使得b->prev->a进入largebin(按大小排序)
这样
prev->fd=a, prev->bk=b。
prev->fd_nextsize=a,prev->bk_nextsize=b。
step4:
malloc(0x500),把prev从largebin分配,largebin剩余b->a
在prev +0x10出构造fake_chunk,size 为0x501,下一块chunk(victim) prev_size为0x500
step5:
把chunk b从largebin分配出去 ,通过如下代码使得b->fd指向fake_chunk
((char*)b2)[0] = '\x10';
((char*)b2)[1] = '\x00';
由于step1处理,使得prev最后两位地址为0000,fake chunk在prev chunk内部偏移0x10字节(fd字段),达到b->fd指向fake_chunk
把 chunk a 从largebin分配出去 ,free(a)进入 unsort bin
free(victim),进入unsort bin: victim->a,这样a->bk=victim,
把a从unsort bin取出。
通过如下代码使得a->bk=fake chunk(同B)
void *a3 = malloc(0x4f0);
((char*)a3)[8] = '\x10';
((char*)a3)[9] = '\x00';
到目前为止构造了 b->fake_chunk->a链路
step6:
victim从unsort bin取出
改写size最后一个bit prev_use为0
free(victim),由于上面改写,fake chunk即将被consolidate 并且进入unsort bin
step7:
新分配的内存,可以用prev指针引用。
有个知识点
当size> 0x408(mp_tcache_max_bytes )时,不进tcache
# define TCACHE_MAX_BINS 64
# define MAX_TCACHE_SIZE tidx2usize (TCACHE_MAX_BINS-1)
/* Only used to pre-fill the tunables. */
# define tidx2usize(idx) (((size_t) idx) * MALLOC_ALIGNMENT + MINSIZE - SIZE_SZ)








网友评论