#include<stdio.h> #include<stdlib.h> int chunk_time =0; int chunk_size[50]; char *chunk_ptr[50]; voidinit(){ setvbuf(stdout, 0, 2, 0); setvbuf(stdin, 0, 2, 0); } voidmenu(){ puts("Life is fucking movie"); puts("Life is always full of unhappiness, like this question"); puts("Anyway, what's your answer"); puts(">"); } voidadd(){ int index; char size[20]; puts("What do you really want?"); if(chunk_time<=32&&chunk_time>=0){ if(!chunk_ptr[chunk_time]){ printf("This is the %dth choice in your life\n",chunk_time); puts("You can customize the size of chunk, but what about your life"); read(0,size,0x8); chunk_size[chunk_time] = atoi(size); chunk_ptr[chunk_time] = malloc(chunk_size[chunk_time]); puts("Although your life is a piece of shit, you still have the initiative, right?"); read(0,chunk_ptr[chunk_time],chunk_size[chunk_time]); chunk_time++; }else{ puts("error"); exit(0); } }else{ exit(0); puts(""); } } voiddelete(){ char data[100]; int index; puts("I didn't set the pointer to zero, just like some things can't be repeated"); scanf("%d",&index); free(chunk_ptr[index]); } voidedit(){ int index; puts("It's never too late to start again. What do you regret?"); scanf("%d",&index); puts("You all know that there can be overflows here, so why do you set limits on your life?"); read(0,chunk_size[index],0x8); puts("Come back!"); read(0,chunk_ptr[index],chunk_size[index]); } voidshow(){ puts("You can't live a perfect life without making any effort"); int index; scanf("%d",&index); puts(chunk_ptr[index]); } intmain(){ int choice; init(); puts("This program is used to debug heap vulnerabilities"); puts("write by chen"); while(1){ menu(); scanf("%d",&choice); switch(choice){ case1: add(); break; case2: delete(); break; case3: edit(); break; case4: show(); break; case5: puts("The fog of that morning cleared, not only in the morning, but also in the fog"); puts("You will be stronger next time I see you"); exit(0); break; } } }
defadd(size,payload): io.recvuntil(">") io.sendline(b'1') io.recvuntil("You can customize the size of chunk, but what about your life") io.sendline(str(size)) io.recvuntil("Although your life is a piece of shit, you still have the initiative, right?") io.send(payload)
defdelete(index): io.recvuntil(">") io.sendline(b'2') io.recvuntil("I didn't set the pointer to zero, just like some things can't be repeated") io.sendline(str(index))
defedit(index,size,payload): io.recvuntil(">") io.sendline(b'3') io.recvuntil("It's never too late to start again. What do you regret?") io.sendline(str(index)) io.recvuntil("You all know that there can be overflows here, so why do you set limits on your life?") io.sendline(str(size)) io.recvuntil("Come back!") io.send(payload)
defshow(index): io.recvuntil(">") io.sendline(b'4') io.recvuntil("You can't live a perfect life without making any effort") io.sendline(str(index))
struct malloc_state { /* Serialize access. */ __libc_lock_define (, mutex); /* Flags (formerly in max_fast). */ int flags; /* Set if the fastbin chunks contain recently inserted free blocks. */ /* Note this is a bool but not all targets support atomics on booleans. */ int have_fastchunks; /* Fastbins */ mfastbinptr fastbinsY[NFASTBINS]; /* Base of the topmost chunk -- not otherwise kept in a bin */ mchunkptr top; /* The remainder from the most recent split of a small request */ mchunkptr last_remainder; /* Normal bins packed as described above */ mchunkptr bins[NBINS * 2 - 2]; /* Bitmap of bins */ unsigned int binmap[BINMAPSIZE]; /* Linked list */ struct malloc_state *next; /* Linked list for free arenas. Access to this field is serialized by free_list_lock in arena.c. */ struct malloc_state *next_free; /* Number of threads attached to this arena. 0 if the arena is on the free list. Access to this field is serialized by free_list_lock in arena.c. */ INTERNAL_SIZE_T attached_threads; /* Memory allocated from the system in this arena. */ INTERNAL_SIZE_T system_mem; INTERNAL_SIZE_T max_system_mem; };
if (SINGLE_THREAD_P) { /* Check that the top of the bin is not the record we are going to add (i.e., double free). */ if (__builtin_expect (old == p, 0)) malloc_printerr ("double free or corruption (fasttop)"); p->fd = PROTECT_PTR (&p->fd, old); *fb = p; }
如果我们直接释放两次chunk1
*** Error in `./testheap’: double free or corruption (fasttop): 0x000055df88768010 ***