Program code (with Pseudo code part):
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
int controlled1=10;
int controlled2=20;
int controlled3=300;
//test.bin file is also controlled
unsigned char * pData;
unsigned char * pTemp;
FILE * f1;
if ((f1 = fopen("test.bin", "rb")) == 0)
{
printf("Error: can't open file\n");
exit(1);
}
pTemp = (unsigned char *)malloc(controlled1);
pData = (unsigned char *)malloc(controlled2);
printf("pTemp:%p\npData:%p\n",pTemp,pData);
fread(pData, 1, controlled3, f1);
//pseudo code part:
//here pData can be used or not by other internal function (based on parameters in pData)
free(pData);
free(pTemp);
}
Variables named controlled* are controlled and can be adjusted to what is needed.
Below gdb output:
root@laptop:~/security/testprog# gdb testprog
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from testprog...(no debugging symbols found)...done.
(gdb) r
Starting program: /home/user/security/testprog/testprog
pTemp:0x602240
pData:0x602260
*** Error in `/home/user/security/testprog/testprog': free(): invalid next size (fast): 0x0000000000602260 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7ffff7a857e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x7fe0a)[0x7ffff7a8de0a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7ffff7a9198c]
/home/user/security/testprog/testprog[0x400811]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7ffff7a2e830]
/home/user/security/testprog/testprog[0x400679]
======= Memory map: ========
00400000-00401000 r-xp 00000000 fc:00 4616045 /home/user/security/testprog/testprog
00600000-00601000 r--p 00000000 fc:00 4616045 /home/user/security/testprog/testprog
00601000-00602000 rw-p 00001000 fc:00 4616045 /home/user/security/testprog/testprog
00602000-00623000 rw-p 00000000 00:00 0 [heap]
7ffff0000000-7ffff0021000 rw-p 00000000 00:00 0
7ffff0021000-7ffff4000000 ---p 00000000 00:00 0
7ffff77f8000-7ffff780e000 r-xp 00000000 fc:00 11801003 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff780e000-7ffff7a0d000 ---p 00016000 fc:00 11801003 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff7a0d000-7ffff7a0e000 rw-p 00015000 fc:00 11801003 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffff7a0e000-7ffff7bcd000 r-xp 00000000 fc:00 11801086 /lib/x86_64-linux-gnu/libc-2.23.so
7ffff7bcd000-7ffff7dcd000 ---p 001bf000 fc:00 11801086 /lib/x86_64-linux-gnu/libc-2.23.so
7ffff7dcd000-7ffff7dd1000 r--p 001bf000 fc:00 11801086 /lib/x86_64-linux-gnu/libc-2.23.so
7ffff7dd1000-7ffff7dd3000 rw-p 001c3000 fc:00 11801086 /lib/x86_64-linux-gnu/libc-2.23.so
7ffff7dd3000-7ffff7dd7000 rw-p 00000000 00:00 0
7ffff7dd7000-7ffff7dfd000 r-xp 00000000 fc:00 11796505 /lib/x86_64-linux-gnu/ld-2.23.so
7ffff7fd4000-7ffff7fd7000 rw-p 00000000 00:00 0
7ffff7ff5000-7ffff7ff8000 rw-p 00000000 00:00 0
7ffff7ff8000-7ffff7ffa000 r--p 00000000 00:00 0 [vvar]
7ffff7ffa000-7ffff7ffc000 r-xp 00000000 00:00 0 [vdso]
7ffff7ffc000-7ffff7ffd000 r--p 00025000 fc:00 11796505 /lib/x86_64-linux-gnu/ld-2.23.so
7ffff7ffd000-7ffff7ffe000 rw-p 00026000 fc:00 11796505 /lib/x86_64-linux-gnu/ld-2.23.so
7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0
7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0 [stack]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Program received signal SIGABRT, Aborted.
0x00007ffff7a43428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
54 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0 0x00007ffff7a43428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
#1 0x00007ffff7a4502a in __GI_abort () at abort.c:89
#2 0x00007ffff7a857ea in __libc_message (do_abort=do_abort@entry=2, fmt=fmt@entry=0x7ffff7b9e2e0 "*** Error in `%s': %s: 0x%s ***\n")
at ../sysdeps/posix/libc_fatal.c:175
#3 0x00007ffff7a8de0a in malloc_printerr (ar_ptr=<optimized out>, ptr=<optimized out>,
str=0x7ffff7b9e358 "free(): invalid next size (fast)", action=3) at malloc.c:5004
#4 _int_free (av=<optimized out>, p=<optimized out>, have_lock=0) at malloc.c:3865
#5 0x00007ffff7a9198c in __GI___libc_free (mem=<optimized out>) at malloc.c:2966
#6 0x0000000000400811 in main ()
(gdb)
I noticed that I can controll malloc structure and here it is overwritten to nonsense that's why free complaints:
free(): invalid next size (fast)
Is there a way to exploit this program? What technique should be used?