- create bunch of char array in a file containing the machine code(not as const)
- mark the memory as executable with mprotect or VirtualProtect.
- declare typedef function with their correct parameters and pointing to the address of our char array
- call it
Okay so let's start. I've been make simple function that XOR 7303014 by x. This is the code
#include <stdio.h> int foo_bar(int baz) { int foo=7303014; return foo^baz; } int main() { int val=1904132; int out=foo_bar(val); printf("%s",&out); return 0; }
It looks simple right. It only prints string "bar" in the console. Now what we need is the foo_bar function as machine code. Open Hex Editor and open the executable then find the function.
Note: We are using x86 byte code for this. Take care of this if you're try to compile it as 64-bit code.
The highlighted hex is the foo_bar function that we need to get their machine code representation and put them in our new code. This is our char array declaration
char foo_bar[]={0x55, 0x89, 0xE5, 0x83, 0xEC, 0x10, 0xC7, 0x45, 0xFC, 0x66, 0x6F, 0x6F, 0x00, 0x8B, 0x45, 0x08, 0x8B, 0x55, 0xFC, 0x31, 0xD0, 0xC9, 0xC3};
Now we have completed point 1 above, now let's make some code to finish point 2, 3, and 4
typedef int (*foo_bar_t)(int );
int main() { foo_bar_t foo=(foo_bar_t)(void*)foo_bar; DWORD old_protect; VirtualProtect(foo,sizeof(foo_bar),PAGE_EXECUTE_READWRITE,&old_protect); int out=foo(0); printf("%s",&out); return 0; }
Q: Why cast to void* first then cast it to foo_bar_t?
A: Visual Studio doesn't like casting foo_bar_t directly from char* so, cast it to void* first. GCC works fine without cast to void* above.
Ok that's our complete main function. Now let's explain it.
The point 2 is in the VirtualProtect function. VirtualProtect function mark address pointed by foo variable to be executable, readable, and writeable(see PAGE_EXECUTE_READWRITE). Without this call, point 4 will very likely to fail(throws Segmentation Fault/Access Violation)(be sure to include Windows.h)
The point 3 is above the main. The typedef.
Then, point 4 is below point 2. Again, calling the function without setting the memory protection would likely causes your program stop working.
Alright, this is the complete code
#include <stdio.h> #include <windows.h> typedef int (*foo_bar_t)(int ); char foo_bar[]={0x55, 0x89, 0xE5, 0x83, 0xEC, 0x10, 0xC7, 0x45, 0xFC, 0x66, 0x6F, 0x6F, 0x00, 0x8B, 0x45, 0x08, 0x8B, 0x55, 0xFC, 0x31, 0xD0, 0xC9, 0xC3}; int main() { foo_bar_t foo=(foo_bar_t)(void*)foo_bar; DWORD old_protect; VirtualProtect(foo,sizeof(foo_bar),PAGE_EXECUTE_READWRITE,&old_protect); int out=foo(0); printf("%s",&out); return 0; }
Now let's compile it and run it.
Our program run without error. That means we've been successfully run our machine code. That's for today.
Challenge: Compile both complete code above and find out why it prints "bar" and "foo".