I have been studying computer vulnerabilities and have been working on this problem for countless hours. I cannot seem to get the heap to overflow correctly. Despite glibc detecting a memory corruption, after disabling MALLOC_CHECK_ my program executes and exits correctly as if overwriting the chunk header didn't matter. I am running Kubuntu 12.04.
This exercise is from "The Shellcoder's Handbook, 2nd Edition" and is also featured on Heap Overflow tutorials online. I have followed the instructions to a T multiple times and have received the same result.
Here is the code of my program:
/*basicheap*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char ** argv){
char *buf;
char *buf2;
buf=(char*)malloc(1024);
buf2=(char*)malloc(1024);
printf("buf=%p buf2=%p\n", buf, buf2);
strcpy(buf,argv[1]);
free(buf2);
free(buf);
}
when I write past the buffer with glibc on:
xxx@xxx-xxx:~/CProgs$ ./basicheap $(perl -e 'print "A"x1028')
buf=0x9356718 buf2=0x9356b20
*** glibc detected *** ./basicheap: double free or corruption (!prev): 0x09356b20 ***
======= Backtrace: =========
[0x804abff]
[0x8048f4a]
[0x80490d6]
[0x8048e29]
======= Memory map: ========
08048000-080ec000 r-xp 00000000 08:07 6816172 /home/xxx/CProgs/basicheap
080ec000-080ee000 rw-p 000a3000 08:07 6816172 /home/xxx/CProgs/basicheap
080ee000-080f0000 rw-p 00000000 00:00 0
09355000-09377000 rw-p 00000000 00:00 0 [heap]
b772a000-b772c000 rw-p 00000000 00:00 0
b772c000-b772d000 r-xp 00000000 00:00 0 [vdso]
bfc14000-bfc36000 rw-p 00000000 00:00 0 [stack]
Aborted (core dumped)
xxx@xxx-xxx:~/CProgs$
When I write past the buffer with glibc off:
xxx@xxx-xxx:~/CProgs$ MALLOC_CHECK_=0 ./basicheap $(perl -e 'print "A"x1028')
buf=0xa077718 buf2=0xa077b20
xxx@xxx-xxx:~/CProgs$
GDB of the Chunk header without overwrite:
(gdb) run $(perl -e 'print "A"x1024')
Starting program: /home/xxx/CProgs/basicheap $(perl -e 'print "A"x1024')
buf=0x80f1718 buf2=0x80f1b20
Breakpoint 1, main (argc=2, argv=0xbfffedf4) at basicheap.c:16
16 free(buf2);
(gdb) x/x buf2-4
0x80f1b1c: 0x00000409
(gdb) x/x buf2-8
0x80f1b18: 0x00000000
(gdb) x/x buf2-12
0x80f1b14: 0x41414141
(gdb)
GDB of the chunk header with overwrite:
(gdb) run $(perl -e 'print "A"x1032')
Starting program: /home/xxx/CProgs/basicheap $(perl -e 'print "A"x1032')
buf=0x80f1718 buf2=0x80f1b20
Breakpoint 1, main (argc=2, argv=0xbfffede4) at basicheap.c:16
16 free(buf2);
(gdb) x/x buf2-4
0x80f1b1c: 0x41414141
(gdb) x/x buf2-8
0x80f1b18: 0x41414141
(gdb) x/x buf2-12
0x80f1b14: 0x41414141
(gdb)
Both times the program exits normally. What am I missing? Did they change up how the heap works on the latest versions of Ubuntu? Any help would be greatly appreciated!
UPDATE: I have stepped through the assembly in gdb and have found that my program enters the function free_check() and the function mem2chunk_check().
In the mem2chunk_check() function, my overwritten value is picked up in the ESI register, and the EDI register points to the address of that value. The only thing I see it doing with my value in ESI is subtracting 1 and then dumping the value.
I have not been able to find any documentation on the mem2chunk_check() function after many google searches.
Are these heap overflows obsolete on modern systems?