Hacktricks-skills house-of-spirit-exploit
House of Spirit heap exploitation guide. Use this skill whenever the user mentions heap exploitation, fake chunks, tcache poisoning, fastbin attacks, binary exploitation with heap vulnerabilities, or needs to create fake heap chunks for CTF challenges. This skill helps create fake heap chunks that bypass glibc security checks to achieve arbitrary memory allocation.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/binary-exploitation/libc-heap/house-of-spirit/SKILL.MDHouse of Spirit Exploitation
A guide for creating fake heap chunks to bypass glibc security checks and achieve arbitrary memory allocation.
What is House of Spirit?
House of Spirit is a heap exploitation technique where you create fake heap chunks in arbitrary memory locations (stack, BSS, etc.) and trick the allocator into thinking they're real chunks. When freed, these fake chunks enter the fastbin or tcache, allowing you to allocate them back and write to arbitrary addresses.
When to Use This Attack
- You have a way to control a pointer that will be freed
- You need to allocate memory at a specific address (e.g., to overlap with a target buffer)
- You want to achieve arbitrary write primitives
- You're working with heap vulnerabilities in CTF challenges
Requirements
Fastbin Variant (glibc < 2.26 or when tcache is disabled)
- Create two consecutive fake chunks with valid sizes
- First chunk's size must be in fastbin range (0x20-0x70 on x64)
- Second chunk's size must also be valid (for next-chunk size check)
- Both chunks must be properly aligned
Tcache Variant (glibc ≥ 2.26)
- Create one fake chunk (simpler!)
- Chunk must be 16-byte aligned
- Size must be in tcache bin range (0x20-0x410 on x64)
- Size must have
bit set (prev_inuse
)size | 1 - Tcache for that bin must not be full (max 7 entries)
Attack Flow
- Create fake chunk(s) in a controllable memory region (stack, BSS, etc.)
- Set up chunk headers with valid sizes
- Overwrite a pointer to point to your fake chunk's content area
- Free the pointer - fake chunk enters fastbin/tcache
- Allocate - you get a pointer to your fake chunk's content
- Write to target - use the allocated memory to overwrite your target
Chunk Layout
Fastbin (2 chunks required)
+-------+---------------------+------+ <- fake_chunks[0] | 0x00: | Chunk #0 prev_size | 0x00 | +-------+---------------------+------+ | 0x08: | Chunk #0 size | 0x60 | +-------+---------------------+------+ | 0x10: | Chunk #0 content | 0x00 | +-------+---------------------+------+ | 0x60: | Chunk #1 prev_size | 0x00 | +-------+---------------------+------+ | 0x68: | Chunk #1 size | 0x40 | +-------+---------------------+------+ | 0x70: | Chunk #1 content | 0x00 | +-------+---------------------+------+
Tcache (1 chunk required)
+-------+---------------------+------+ <- fake[0] | 0x00: | prev_size (ignored) | 0x00 | +-------+---------------------+------+ | 0x08: | size (with prev_inuse)| 0x41 | +-------+---------------------+------+ | 0x10: | content starts here | 0x00 | +-------+---------------------+------+
Code Templates
Fastbin House of Spirit
#include <unistd.h> #include <stdlib.h> #include <string.h> #include <stdio.h> struct fast_chunk { size_t prev_size; size_t size; struct fast_chunk *fd; struct fast_chunk *bk; char buf[0x20]; }; int main() { struct fast_chunk fake_chunks[2]; void *ptr, *victim; // Allocate to get a pointer we can overwrite ptr = malloc(0x30); // Set up fake chunk sizes fake_chunks[0].size = sizeof(struct fast_chunk); fake_chunks[1].size = sizeof(struct fast_chunk); // Overwrite pointer to point to fake chunk's content ptr = (void *)&fake_chunks[0].fd; // Free the fake chunk free(ptr); // Allocate - returns pointer to fake chunk content victim = malloc(0x30); printf("Victim: %p\n", victim); return 0; }
Tcache House of Spirit (Simpler!)
#include <stdio.h> #include <stdlib.h> int main() { // 16-byte aligned array for fake chunk unsigned long long fake[6] __attribute__((aligned(0x10))); // Set fake size (0x40 bin, prev_inuse=1) fake[1] = 0x41; // Pointer to content area (after header) void *p = &fake[2]; // Free - goes straight into tcache free(p); // Allocate - returns stack address void *q = malloc(0x30); printf("Got stack address: %p\n", q); return 0; }
Common Use Cases
1. Libc Leak
- Create fake chunk overlapping GOT entry
- Allocate and read the GOT entry
- Leak libc address
2. Arbitrary Write
- Create fake chunk overlapping target buffer
- Allocate and write to target
- Overwrite function pointers, vtables, etc.
3. Overlapping Chunks
- Free fake chunk inside valid chunk
- Allocate to get overlapping memory
- Use for tcache poisoning
Validation Checklist
Before attempting the attack, verify:
- You can control a pointer that will be freed
- You have a writable memory region for fake chunks
- Chunk sizes are in valid bin ranges
- Alignment requirements are met (16-byte for tcache)
- Tcache is not full (if using tcache variant)
- You understand the target's memory layout
Debugging Tips
- Check alignment: Use
to verify 16-byte alignmentprintf("%p\n", &fake_chunk) - Verify sizes: Ensure sizes match bin requirements
- Use gdb: Set breakpoints on
andfree
to trace executionmalloc - Check tcache: Use
in gdb to see tcache stateinfo tcache
References
- heap-exploitation.dhavalkapil.com - House of Spirit
- guyinatuxedo - House of Spirit
- shellphish/how2heap - tcache_house_of_spirit.c
Next Steps
- Identify the vulnerability in your target
- Choose fastbin or tcache variant based on glibc version
- Create fake chunk(s) in appropriate memory region
- Overwrite pointer and free
- Allocate and use the returned pointer
- Achieve your goal (leak, write, shellcode execution)