## Tcache Poisoning

Tcache Poisoning is an exploitation technique that targets glibc's thread local cache(tcache) mechanism. The attack leverages a use-after-free vulnerability to corrupt the forward pointers in tcache entries. By manipulating these pointers, an attacker can trick `malloc` into returning a pointer to an arbitrary memory location, effectively gaining the ability to write to any desired memory address. ### How it works 1. The exploit works by `malloc`ing some space on the heap and then freeing it. When freed this chunk (specifically the pointer) ends up in the tcache. 2. Afterwawrds we rewrite this freed fwd ptr in the free'ds chunk metadata with our desire pointer. This rewrite works because, when `malloc`ed memory is freed, It isn't truly freed. > [...when allocated memory is freed, memory behind it doesn't get released to the operating system immediately. Allocated memory region(of size 1000 bytes) is released only to 'glibc malloc' library, which adds this freed block to main arenas bin... Later when user requests memory, 'glibc malloc' doesn't get new heap memory drom kernel, instead it will try to find a free block in bin. And only when no free block exists, it obtains memory from kernel.] (https://sploitfun.wordpress.com/2015/02/10/understanding-glibc-malloc/) So technically that chunk still remains in the heap with a different metadata structure. Hence if when free, and the chunk's pointer succesffully ends up in the tcache, then this exploits has a chance of working. 3. Lastly, make another call to `malloc` with the same size of the previous freed `malloc`. The tcache or specifically `malloc` returns the corrupted forward pointer from the tcache. Now we've successfully tricked `malloc` into returing our desired pointer to an arbitrary location in memory. ```c #include #include #include /* To bypass the safelink protection on ptr-> from glibc */ #define PROTECT_PTR(pos, ptr) \ ((__typeof (ptr)) ((((size_t) pos) >> 12) ^ ((size_t) ptr))) #define REVEAL_PTR(ptr) PROTECT_PTR (&ptr, ptr) int main() { char *str = "H3LLO V01D!"; char buf[16] = {0}; chcar *ptr1 = malloc(0x10); char *ptr2 = malloc(0x10); free(ptr1); free(ptr2); *(size_t *) ptr2 = (size_t)PROTECT_PTR((size_t *)ptr2, (char*)buf); malloc(0x10); // take first chunk char *exploit = malloc(0x10); // get stack buffer strcpy(exploit, str); // write to stack printf("%s\n", buf); return 0; } ``` .