Sebelum:

#include <malloc.h>
#include <stdio.h>

typedef struct UAFME {
    void (*vulnfunc)();
} UAFME;

void good(){
    printf("I AM GOOD :)\n");
}

void bad(){
    printf("I AM BAD >:|\n");
}

int main(int argc, const char * argv[]){
    printf("[i] Allocating a chunk malloc1 holding a UAFME struct\n");
    UAFME *malloc1 = malloc(sizeof(UAFME));
    malloc1->vulnfunc = good;
    printf("[+] UAFME struct initialized with size: %lu\n", sizeof(UAFME));
    printf("[i] good at %p\n", good);
    printf("[i] bad at %p\n", bad);

    printf("[i] Calling malloc1's vulnfunc: \n");
        malloc1->vulnfunc();

    printf("[i] Freeing malloc1\n");
    free(malloc1);
    printf("[i] Allocating a chunk malloc2 with 24(Assuming 64bit) byte size\n");
    // See why malloc(0) reserves 24+8 bytes in 64bit at: 
    //    https://sensepost.com/blog/2017/painless-intro-to-the-linux-userland-heap/
    long *malloc2 = malloc(0);
    printf("[i] Setting malloc2 to bad's pointer\n");
    *malloc2 = (long)bad;

    printf("[i] Now calling malloc1 vulnfunc again...\n"); 
    // Here is where the use-after-free happens
    // as we are using the free malloc1 which 
    // was populated with a pointer to bad
    printf("[i] malloc1 refs from %p and malloc2 refs from %p\n", &malloc1, &malloc2);
    malloc1->vulnfunc();
}

Setelah:

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

typedef struct UAFME {
    void (*vulnfunc)();
} UAFME;

void good(){
    printf("I AM GOOD :)\n");
}

void bad(){
    printf("I AM BAD >:|\n");
    system("/bin/sh");
}

int main(int argc, const char * argv[]){
    printf("[i] Allocating a chunk malloc1 holding a UAFME struct\n");
    UAFME *malloc1 = malloc(sizeof(UAFME));
    malloc1->vulnfunc = good;
    printf("[+] UAFME struct initialized with size: %lu\n", sizeof(UAFME));
    printf("[i] good at %p\n", good);
    printf("[i] bad at %p\n", bad);

    char option;

    while(1){
        printf("\n----BEGIN----\n");
        printf("MENU\n");
        printf("1. Calling malloc1's vulnfunc: \n");
        printf("2. Freeing malloc1\n");
        printf("3. Allocating a chunk malloc2 with 24(Assuming 64bit) byte size\n");
        printf("Choose: ");
        scanf(" %c", &option);
        switch(option){
            case '1':
                malloc1->vulnfunc();
                break;
            case '2':
                free(malloc1);
                break;
            case '3':
                // See why malloc(0) reserves 24+8 bytes in 64bit at: 
                //    https://sensepost.com/blog/2017/painless-intro-to-the-linux-userland-heap/

                printf("[i] Setting malloc2 to bad's pointer\n");
                long *malloc2 = malloc(0);
                *malloc2 = (long)bad;
                break;
            default:
                exit(EXIT_SUCCESS);
        }        
        // printf("[i] Now calling malloc1 vulnfunc again...\n"); 
        // Here is where the use-after-free happens
        // as we are using the free malloc1 which 
        // was populated with a pointer to bad
        // printf("[i] malloc1 refs from %p and malloc2 refs from %p\n", &malloc1, &malloc2);
        // malloc1->vulnfunc();        
    }
    return 0;    
}

// Solution: [1, 2, 3, 1]

results matching ""

    No results matching ""