I learned about function pointers recently in class and I was wondering if you could assign a function pointer to a block of memory allocated by a program, fill the memory block with assembly commands (hex values of op codes), then call the memory block using the function pointer.
I don't know much about function pointers, but I'm guessing you can't assign them wherever you want in memory, they need to point to a function. If that's true, how can you create a function in memory to be called? Is that even possible?
Here's some code I typed up to show the concept. I used various opcode values to see if anything would work, and 0x90 (NOP) did not break it sometimes (but it did other times), and 0xC3 (ret) always broke it.
#include <stdlib.h> //for malloc
#include <cstring> //for memcpy
int main() //program entry
{
void(*test)() = NULL; //create function pointer, initialize to NULL
void* hold_address = (void*)malloc(100); //allocate memory, save the address it returns in a dummy pointer
int asm_commands[] = {0x90}; //create array of assembly commands, hex values
memcpy(hold_address, asm_commands, sizeof(asm_commands)); //copy the array into the reserved memory
test = (void(*)())hold_address; //set the function pointer to start of the allocated memory
test(); //call the function, crashes here
return 0; //exit the program
}
Function calling is more complex than that.
You must at least modify the base pointer. I suggest you look at the dissassembly of a function call and try to mimic it
A few points:
your
asm_commands[]
should probably beunsigned char
(oruint8_t
) - as is, you'll be copying 3 NUL/0 characters as well as the0x90
some Operating Systems will just not let you execute instructions in memory you've allocated with
malloc()
- they'll SIGSEGV or similar instead - that's intended to prevent certain types of stack overflow and other hackeryI suggest you write an actual function
void f() { }
and see what opcodes are generated for it, usingg++ -S
or whatever your compiler offers, as you might need to do something more than just0xC3
to return properly (e.g. pop certain registers)You can do what you describe. However, memory allocated with
malloc()
might not have the permission for code execution - depending on your platform.The way to allocate executable memory differs from OS to OS. On Linux, check
mmap
. On Windows, seeVirtualAlloc
.