So this was a fun experiment. The idea was something along the lines of “Can we use a pointer to some data as a function?”. Turns out, yes that is perfectly possible! Although this is probably a very bad idea to actually use in any actual code. The only reason I wanted to try this, was to see if it could be used for a CTF style challenge.

So let’s get started! I started with two very simple functions.

int getnum1(int x) {
    x += 1;
    return x * x;
}

int getnum2(int x) {
    x += 2;
    return x * x;
}

Lets compile them, from the resulting binary we can extract the getnum2() function (eg. using objdump). So we get the following HEX in an array.

uint8_t magic[20] = {0x55, 0x48, 0x89, 0xe5, 0x89, 0x7d, 0xfc,
                     0x83, 0x45, 0xfc, 0x02, 0x8b, 0x45, 0xfc,
                     0x0f, 0xaf, 0x45, 0xfc, 0x5d, 0xc3};

Next we need to see how to make our program execute this block. Normally data blocks are protected from execution, however using the mprotect() call we can allow execution on a block of memory. For detailed usage see the mprotect man page.

static char *magicbuffer;

// Get the page size
pagesize = sysconf(_SC_PAGE_SIZE);
if (pagesize == -1) {
    printf("Sysconf error\n");
}

// Get aligned page of memory
magicbuffer = memalign(pagesize, 1 * pagesize);

// Set execute on memory
if (mprotect(magicbuffer, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) {
    printf("Setting memory protections failed\n");
}

// Copy instructions to memory
memcpy(magicbuffer, magic, 20);

Now, lets try to execute those instructions.

int (*func)(int) = &getnum1;
printf("Num 1: %d\n", func(1));
func = (int (*)(int))magicbuffer;
printf("Num 2: %d\n", func(1));

This prints the output of getnum1() and getnum2(), without getnum2() needing to be defined.

Conclusion

This as just a fun experiment, I had no idea this was possible. It’s always good to know what’s possible, but I don’t really know any practical uses for this. I rarely write any articles, so any feedback is appreciated.

View full code