heapoverflow之chunk_overlap

又看不懂wp了。。。。再学习一种新的攻击方法好了


heapoverflow之chunk_overlap

同样从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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/*
A simple tale of overlapping chunk.
This technique is taken from
http://www.contextis.com/documents/120/Glibc_Adventures-The_Forgotten_Chunks.pdf
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

int main(int argc , char* argv[]){


intptr_t *p1,*p2,*p3,*p4;

printf("\nThis is a simple chunks overlapping problem\n\n");
printf("Let's start to allocate 3 chunks on the heap\n");

p1 = malloc(0x100 - 8);
p2 = malloc(0x100 - 8);
p3 = malloc(0x80 - 8);

printf("The 3 chunks have been allocated here:\np1=%p\np2=%p\np3=%p\n", p1, p2, p3);

memset(p1, '1', 0x100 - 8);
memset(p2, '2', 0x100 - 8);
memset(p3, '3', 0x80 - 8);

printf("\nNow let's free the chunk p2\n");
free(p2);
printf("The chunk p2 is now in the unsorted bin ready to serve possible\nnew malloc() of its size\n");

printf("Now let's simulate an overflow that can overwrite the size of the\nchunk freed p2.\n");
printf("For a toy program, the value of the last 3 bits is unimportant;"
" however, it is best to maintain the stability of the heap.\n");
printf("To achieve this stability we will mark the least signifigant bit as 1 (prev_inuse),"
" to assure that p1 is not mistaken for a free chunk.\n");

int evil_chunk_size = 0x181;
int evil_region_size = 0x180 - 8;
printf("We are going to set the size of chunk p2 to to %d, which gives us\na region size of %d\n",
evil_chunk_size, evil_region_size);

*(p2-1) = evil_chunk_size; // we are overwriting the "size" field of chunk p2

printf("\nNow let's allocate another chunk with a size equal to the data\n"
"size of the chunk p2 injected size\n");
printf("This malloc will be served from the previously freed chunk that\n"
"is parked in the unsorted bin which size has been modified by us\n");
p4 = malloc(evil_region_size);

printf("\np4 has been allocated at %p and ends at %p\n", p4, p4+evil_region_size);
printf("p3 starts at %p and ends at %p\n", p3, p3+80);
printf("p4 should overlap with p3, in this case p4 includes all p3.\n");

printf("\nNow everything copied inside chunk p4 can overwrites data on\nchunk p3,"
" and data written to chunk p3 can overwrite data\nstored in the p4 chunk.\n\n");

printf("Let's run through an example. Right now, we have:\n");
printf("p4 = %s\n", (char *)p4);
printf("p3 = %s\n", (char *)p3);

printf("\nIf we memset(p4, '4', %d), we have:\n", evil_region_size);
memset(p4, '4', evil_region_size);
printf("p4 = %s\n", (char *)p4);
printf("p3 = %s\n", (char *)p3);

printf("\nAnd if we then memset(p3, '3', 80), we have:\n");
memset(p3, '3', 80);
printf("p4 = %s\n", (char *)p4);
printf("p3 = %s\n", (char *)p3);
}

首先我们分配三个块,并且把中间的那个块free:
```C
p1 = malloc(0x100 - 8);// 这个 - 8是因为要排除size,之后分配的时候能正好对齐
p2 = malloc(0x100 - 8);
p3 = malloc(0x80 - 8);

memset(p1, '1', 0x100 - 8);
memset(p2, '2', 0x100 - 8);
memset(p3, '3', 0x80 - 8);

printf("\nNow let's free the chunk p2\n");
free(p2);

接下来,我们修改p2的标志位,让glibc认为这个堆的大小为0x180(也即是p2和p3)的总和:

1
2
3
4
5
6
int evil_chunk_size = 0x181;
int evil_region_size = 0x180 - 8;
printf("We are going to set the size of chunk p2 to to %d, which gives us\na region size of %d\n",
evil_chunk_size, evil_region_size);

*(p2-1) = evil_chunk_size; // we are overwriting the "size" field of chunk p2

这里同样,由于为了对齐,我们需要去掉size的大小,所以实际大小为0x180 - 8。由于我们将used为改成了0x181,于是这个地方glibc发现【上一个块被使用,但是当前块由于在unsorted bin中,于是分配当前块给我们,大小为之前声明的0x180】。此时我们就得到了一个0x180大小的chunk:

1
2
3
4
5
p4 = malloc(evil_region_size);

printf("\np4 has been allocated at %p and ends at %p\n", p4, p4+evil_region_size);
printf("p3 starts at %p and ends at %p\n", p3, p3+80);
printf("p4 should overlap with p3, in this case p4 includes all p3.\n");


在这里能看到,p4整个把p3给包括了。那么此时p4就能够随意修改p3的prev size等内容,从而完成攻击.