002

4/13/21

Use After Free - Concept - 4/13/21

The archive directory is the attempt that i had failed, i had prepared too much for one day :(

from now on, i think i should limit myself to 1 challenge a day :(((

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void demo1() {
    char msg[] = "about to malloc()\n";
    write(1, msg, strlen(msg));
    // we want to read the mapping of this process, before and after the malloc
    sendfile(0, open("/proc/self/maps", 0), 0, 4000);
    malloc(16);
    sendfile(0, open("/proc/self/maps", 0), 0, 4000);
}

void demo2() {
    // allocate 8 bytes on heap, and return memory address into char input?, or pointer to value
    // ok i think i understand now
    // malloc will return an address, something like 0xdeadbeefcafec0de or something of the sort
    // we will use the dereference operator/pointer, to get the VALUE at the ADDRESS given
    // and that value at that address will be a char, or an array of them for our input
    char *input = malloc(8);
    printf("Address of input on heap: %p\n", input);
    int inputaddr = *input;
    printf("Enter your name: ");
    // read in a maximum of 7 bytes, without and it might "overflow"
    scanf("%7s", input);
    printf("Hello %s!\n", input);

    free(input); // we have free'd our memory on the heap, this no longer exists

    long *auth = malloc(8);
    *auth=0;

    printf("Enter your password: ");
    scanf("%7s", input);
// ----------------------------------------------------------------- //
/* IMPORTANT
we will print the value at the address of auth after we run the program
lets run the program, and enter one char, 'a', as the username and password
now lets see what decimal integer it outputs

97

ok, so it outputs a 97, what is this?
we need to convert this into ascii, we could do a decimal to ascii, but python hex and pwntools is much
faster for me

hex(97)
'0x61'

unhex 61

'a'

ok, so we got our char back, a
now we know, that the auth pointer has been overwritten due to use after free

this may seem a bit confusing, so lets walk through this semi visually


          HEAP
+-------+-------+-------+
|       |       |       |
+-------+-------+-------+
|       |       |       |
+-------+-------+-------+
|       |       |       |
+-------+-------+-------+

here we have our heap

" char *input = malloc(8); "

the we have malloc'd 8 bytes on our heap to make room for input


          HEAP
+-------+-------+-------+
| input |       |       |
+-------+-------+-------+
|       |       |       |
+-------+-------+-------+
|       |       |       |
+-------+-------+-------+

that is where our input will be stored, on the heap, at that location
so now, we have our free

" free(input); "

and this is the result of that


          HEAP
+-------+-------+-------+
|       |       |       |
+-------+-------+-------+
|       |       |       |
+-------+-------+-------+
|       |       |       |
+-------+-------+-------+

our heap is empty again, there is nothing on our heap now
now, the dumb developer of the program, they forget that they free'd the input, they forgot that there is
nothing left on the heap.

so they allocate a new chunk of data on the heap, this time making room for the auth variable they
will be checking for


" long *auth = malloc(8);
*auth=0; "

they allocate 8 more bytes, then set the value at that address to 0

remember, that the address of auth is the same as input, and the value is 0, anything other than
0 and c will interpret that integer as true

lets see how the heap looks now

          HEAP
+-------+-------+-------+
|auth=0 |       |       |
+-------+-------+-------+
|       |       |       |
+-------+-------+-------+
|       |       |       |
+-------+-------+-------+

we have our auth variable on the heap now, at the exact same place that input was at

then, the program will prompt us for the password

" scanf("%7s", input); "

and read 7 bytes into our input, where auth exists in it's place
now after that, lets take a look at our heap one more time

          HEAP
+-------+-------+-------+
|auth=97|       |       |
+-------+-------+-------+
|       |       |       |
+-------+-------+-------+
|       |       |       |
+-------+-------+-------+

since we had inputted 'a's, that ascii char was turned into decimal
the value 97 is still seen as a true value, and the check for auth will be passed, and our flag will
be opened and sent to us:

if (*auth) sendfile(0, open("/flag", 0), 0, 128);

this does not check if the value at auth is equals to something, only checks if true

and that is how we get our flag

*/
    printf("Value of auth: %d\n", *auth);

// ----------------------------------------------------------------- //
    // if login correct, then sendfile/ read/write flag to stdout

    (strcmp(input, "hunter2")==0) ? *auth=1 : printf("AUTH IS NOT SET");
    if (*auth) sendfile(0, open("/flag", 0), 0, 128);

    sleep(1);
    puts("\nNow that should have printed out the flag, correct?");
    puts("Why is that?, you didnt enter the correct password, your auth variable isnt set!");
    sleep(1);
    printf("\nLets take a look at some addresses:\nauth address: %p\n", auth);
    // my though process behind this is, if input addr is not equals to the deref pointer for input
    // and we have free'd it, if i were to just do inputaddr = input, then done %p, that would have
    // gotten the address of inputaddr on the stack, not input on the heap, so i figured i would let
    // try and demonstrate that it is gone, free'd, null and void
    printf("input address: %p", inputaddr);
    sleep(1);
    puts("\nNow as you can see, the address of input is now (nil), while the address of auth is ");
    puts("where our input used to lie, so when we overwrite the");
}

int main(int argc, char**argv) {
    // turn off buffering
    setvbuf(stdout, NULL, _IONBF, 0);
    int buffer[1];
    printf("Welcome to demo!\n[1]\tstrace malloc\n[2]\tUAF\nEnter: ");
    read(0, buffer, 1);
    switch(atoi(buffer)) {
    case 1:
        demo1();
        break;
    case 2:
        demo2();
        break;
    default:
        printf("ERROR");
    }
}

Last updated