It's certainly possible. For various reasons, we've spent a lot of effort of the last 30-40 years trying to make it as difficult as possible, but it is possible. In most systems now, there are hardware and software mechanisms that attempt to protect data space from being executed.
The basics, though, are fairly straightforward: you construct a piece of code, and assemble it, either by hand or4 via a compiler. You then need a fragment of code space, so you insert the code into your program
unsigned int prgm[] = { 0x0F, 0xAB, 0x9A ... }; // Random numbers, just as an example
since you wanted to use the heap you need to malloc the space
void * myspace ;
if((myspace= malloc(sizeof(prgm))) != NULL) {
memcpy(myspace, pgrm, sizeof(pgrm));
} else { // allocation error
}
Now, what you need is a way to get the program counter to point to that chunk of data that is also your chunk of code. Here's where you need a little craftiness. Setting the program counter is no big deal; that's just a JUMP instruction for your underlying machine. But how to do that?
One of the easiest ways is by purposefully messing with the stack. The stack, again conceptually, looks something like this (the details depend on both your OS and compiler pairs, and on your hardware):
| subroutine return addr |
| parameters ... |
| automatic variables |
The basic trick here is to sneakily get the address of your code into the return address; when a routine returns, it basically jumps to that return addrfess. If you can fake it out, the PC will be set to where you like.
So, what you need is a routine, let's call it "goThere()"
void goThere(void * addr){
int a ; // observe above; this is the first space
// on the stack following the parameters
int * pa; // so we use it's address
pa = (&a - (sizeof(int)+(2*sizeof(void*))) ; // so use the address
// but back up by the size of an int, the pointer on the
// stack, and the return address
// Now 'pa' points to the routine's return add on the stack.
*pa = addr; // sneak the address of the new code into return addr
return ; // and return, tricking it into "returning"
// to the address of your special code block
}
Will it work? Well, maybe, depending on the hardware and OS. Most modern OS's will protect the heap (via memory mapping or similar) from the PC moving into it. This is a useful thing for security purposes, because we'd just as well not let you take that kind of complete control.