Friday, 6 September 2013

Exploit exercises - Protostar - Heap 3

In the heap 3 task 3 portions of memory are allocated on the heap. Then 3 command-line arguments are copied without bounds checking and later the allocated memory is freed. We are supposed to exploit Doug Lea way of allocation and deallocation of memory. There is a nice online page with a description of the way how to exploit it.

Exploitation is based on the fact that while memory is being freed, if there is a free block next to the one that is being freed, free function merges two blocks and write some metadata at the calculated addresses. That means that we can make free function overwrite value at the user provided address after corrupting metadata of the allocated blocks. We should make free think that previous block is free and change metadata to influence address calculation. In the task blocks are allocated in a way that is pictured on the image:

All size fields are set to 29 which is 28 with the least significant bit set up because prev_size is not used. So to make free function think that previous block is not allocated we should clear that bit. The simplest way to make it 0xfffffffc, which is -4. This value is good because it doesn't contains NULL bytes and near the current pointer. If we will overwrite 3rd block metadata with the second call to the strcpy, we should take into account that 3rd call to strcpy will overwrite some part of the data. Therefore we will set prev_size = -4 so the previous chunk will point the same chunk but with 4-byte offset. Previous chunk data will be assumed to start at the place where some_addr1 is located. free function will unlink prevoius chunk by overwriting values of the next and prev pointers of the list. So it will do the following:
*(some_addr1 + 12) = some_addr2
*(some_addr2 + 8) = some_addr1

All we need to do is provide good pointers, so that we can modify program flow. Let's overwrite puts address in global offset table. Let's use objdump -R /opt/protostar/bin/heap3 to locate address where puts address will be stored. It is at the 0x804b128. We will need to subtract 0xc from it, so that after free function adds 0xc we will get original pointer. Also let's located winner function address using objdump -t . It is at the 0x8048864. There is a problem. We cannot use that pointer in our exploit because it points to the read-only .text section which will result in error when free will try to write there. We can use pointer that references argv[2] where our input is located. To find argv[2] address you can write a demo program that prints addresses of the command line arguments. Also notice that call in shell of the heap3 binary and your argument-printing program must both have the same length.
Code:
#include <stdio.h>

int main(int argc, char* argv[])
{
    int i = 0;
    printf("argc:%d\nargv:%08x\n",argc,argv);
    for( i = 0; i < argc; ++i)
    {
        printf("%d:%08x\n",i,argv[i]);
    }
    return 0;
}

Since we will use data at the argv[2] as execution path, we will just jump to the winner function. call instruction is specified by the \xeb byte and offset. I will provide 32bit offset. Let's calculate it: we need to jump from the place where argv[2] is stored to the 0x8048864 . In my case that was 0xbffff9c1 . So the difference is
(gdb) p/x 0x8048864 - 0xbffff9c1
0x48048ea3
So the whole exploit is on the picture:

No comments:

Post a Comment