Hook malloc

An example to hook malloc

Source


/*
 *  gcc -o hook main.c
 *  ./hook
 */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <sys/mman.h>

typedef int (*foo_func)(int a);

foo_func ptr_foo = NULL;

int foo(int a)
{
    return a + 2;
}

int foo_hook(int a)
{
    printf("foo_hook - %d\n", a);
    a += 2;
    return ptr_foo(a);
}

#pragma pack(push, 1)
struct thunk
{
    char e9;
    unsigned int offset;
};
#pragma pack(pop)

struct thunk thunk_foo;

void test_malloc_hook();

int main()
{
    int ret;
    int foo_size;
    printf("hook!\n");
    printf("sizeof(struct thunk) =%ld\n", sizeof(struct thunk));
    printf("foo =%p\n", foo);
    printf("foo_hook =%p\n", foo_hook);

    foo_size = (int)((unsigned long)foo_hook - (unsigned long)foo);

    printf("foo_size =%d\n", foo_size);

    thunk_foo.e9 = 0xe9;
    thunk_foo.offset = foo_size - 5;

    printf("foo offset =%d\n", thunk_foo.offset);

    /*
     * make a copy of original foo
     */

    void *foo2 = mmap(NULL, 4096, PROT_READ | PROT_WRITE | PROT_EXEC,
                    MAP_ANON | MAP_PRIVATE, -1, 0);
    memcpy(foo2, foo, foo_size);
    ptr_foo = foo2;

    /*
     * test the copy foo2 works
     */
    printf("foo(10)=%d\n", foo(10));
    printf("ptr_foo(20)=%d\n", ptr_foo(20));

    /*
     * hook the original foo by thunk_foo which is a jump to foo_hook
     */
    void *page = (void *)((unsigned long)foo & ~0xfffUL);

    ret = mprotect(page, 4096, PROT_READ | PROT_WRITE | PROT_EXEC);
    if (ret < 0)
    {
        perror("mprotect failed!\n");
        exit(ret);
    }
    memcpy(foo, &thunk_foo, sizeof(struct thunk));
    printf("foo(10)=%d\n", foo(10));

    test_malloc_hook();

    return ret;
}

typedef int (*foo_func)(int a);

void af()
{
    printf("af\n");
    void *p = malloc(1024);
    free(p);
}

typedef void *(*malloc_func)(size_t size);

void malloc_hook_restore();
void malloc_hook_enable();

void *malloc_hook(size_t size)
{
    void *p;
    printf("malloc_hook- size = %ld\n", size);
    malloc_hook_restore();
    p = malloc(size);
    malloc_hook_enable();
    return p;
}

int malloc_size = 0;

void dump5(void *addr)
{
    unsigned char *p = addr;
    printf("%2.2X %2.2X %2.2X %2.2X %2.2X\n", p[0], p[1], p[2], p[3], p[4]);
}

unsigned char malloc5byte[5];
struct thunk thunk_malloc;
void malloc_hook_enable()
{
    /* 
     * save the first 5 bytes
     */

    memcpy(malloc5byte, malloc, 5);

    malloc_size = (int)((unsigned long)malloc_hook - (unsigned long)malloc);

    thunk_malloc.e9 = 0xe9;
    thunk_malloc.offset = malloc_size - 5;
    void *page = (void *)((unsigned long)malloc & ~0xfffUL);
    int ret = mprotect(page, 4096, PROT_READ | PROT_WRITE | PROT_EXEC);
    if (ret < 0)
    {
        perror("mprotect failed!\n");
        exit(ret);
    }
    memcpy(malloc, &thunk_malloc, 5);
}

void malloc_hook_restore()
{
    memcpy(malloc, malloc5byte, 5);
}

void test_malloc_hook()
{
    printf("test_malloc_hook\n");
    af();
    malloc_hook_enable();
    af();
    af();
    af();
}