/* We overlay this structure on the user-data portion of a chunk when the chunk is stored in the per-thread cache. */typedefstruct tcache_entry{struct tcache_entry *next;} tcache_entry;/* There is one of these for each thread, which contains the per-thread cache (hence "tcache_perthread_struct"). Keeping overall size low is mildly important. Note that COUNTS and ENTRIES are redundant (we could have just counted the linked list each time), this is for performance reasons. */typedefstruct tcache_perthread_struct{charcounts[TCACHE_MAX_BINS]; tcache_entry *entries[TCACHE_MAX_BINS];} tcache_perthread_struct;static __thread char tcache_shutting_down =0;static __thread tcache_perthread_struct *tcache =NULL;
Exploitation
If you get control of the next pointer of a freed chunk, we can allocate to an arbitrary address giving us a write primitive.
This challenge is an example of that.
We have the ability to create 16 allocations and there is no NULL of pointers after freeing, giving us UAF with the edit_dance function.
We can overwrite one of the GOT functions with win such as exit as there is no FULL RELRO.
We also need to bypass safe-linking which requires a heap leak.