Code:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include <windows.h>
void win_error( char * message, BOOL exit )
{
char buffer[BUFSIZ] = { 0 };
DWORD error_code = GetLastError( );
FormatMessage
(
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
error_code,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) buffer,
BUFSIZ,
NULL
);
MessageBox(NULL, buffer, message, MB_ICONWARNING | MB_OK );
if ( exit ) ExitProcess( error_code );
return;
}
void function_a( )
{
/* Do some stuff */
int stuff = 0;
stuff = pow( 2, 5 );
printf( "Important stuff from function a : %d\n", stuff );
return;
}
void function_b( )
{
/* Do some stuff */
int stuff = 0;
stuff = pow( 10, 5 );
printf( "Important stuff from function b : %d\n", stuff );
return;
}
int main( )
{
void ( * function_trampoline ) ( ) = NULL;
DWORD process_id = 0;
HANDLE process_handle = NULL;
BYTE * memory = NULL;
BYTE jmp_instruction[] = { 0xE9, 0x00, 0x00, 0x00, 0x00, 0x90 };
memset( &jmp_instruction[1], ( uint32_t )function_b, sizeof( jmp_instruction - 1 ) );
BYTE jmp_instructionB[] = { 0xE9, 0x00, 0x00, 0x00, 0x00, 0x90 };
memset( &jmp_instructionB[1], ( uint32_t )( function_a + sizeof( jmp_instruction ) ), sizeof( jmp_instructionB - 1 ) );
BYTE prev_opcodes[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
if ( !( memory = ( BYTE * )VirtualAlloc( NULL, sizeof( jmp_instruction ), MEM_RESERVE, PAGE_EXECUTE_READWRITE ) ) )
win_error( "VirtualAlloc( )", TRUE );
process_id = GetCurrentProcessId( );
if ( !( process_handle = OpenProcess( PROCESS_ALL_ACCESS, FALSE, process_id ) ) )
win_error( "OpenProcess( )", TRUE );
if ( !FlushInstructionCache( process_handle, memory, sizeof( jmp_instruction ) ) )
win_error( "FlushInstructionCache( )", TRUE );
if ( !ReadProcessMemory( process_handle, function_a, &prev_opcodes, sizeof( jmp_instruction ), NULL ) )
win_error( "ReadProcessMemory( )", TRUE );
if ( !WriteProcessMemory( process_handle, function_a, &jmp_instruction, sizeof( jmp_instruction ), NULL ) )
win_error( "WriteProcessMemory( )", TRUE );
memset( memory, ( uint32_t )prev_opcodes, sizeof( prev_opcodes ) );
function_trampoline = ( void * )memory;
function_a( );
function_trampoline( );
CloseHandle( process_handle );
if ( !VirtualFree( memory, 0, MEM_RELEASE ) )
win_error( "VirtualFree( )", TRUE );
return 0;
}
I usually get a segmentation fault at the memset() line, I tried using more conventional functions( e.g. WriteProcessMemory() ), but it's apparently not a valid address in my process. I read in the documentation somewhere that it doesn't actually activate the memory until I write something to it, so I tried using memset(). This has caused undefined behavior so far, usually in the form of a violation error. I have also gotten past the memset() function without it throwing that violation error, but it gets a violation error when on the first part of function_a. I'm guessing this is my fault for using invalid machine instructions, but I'm not entirely sure what I need to use instead. When I disassemble it, it just appears with the ADD instruction as I mentioned earlier. I added a NOP instruction to see if that might help, but memset() started to throw errors so I can't see what my change did.