#include #include #include typedef void (* FNPTR )( ); bool HotPatch( FNPTR oldProc,FNPTR newProc,FNPTR* ppOrigFn ) { bool result = false; DWORD oldProtect = 0; WORD* pJumpBack = ( WORD* ) oldProc; BYTE* pLongJump = ( ( BYTE* ) oldProc - 5); DWORD* pLongJumpAdr = ( ( DWORD* ) oldProc - 1 ); // Change protection VirtualProtect( pLongJump,20,PAGE_EXECUTE_WRITECOPY,&oldProtect ); if( ( 0xFF8B == *pJumpBack ) && ( 0x90 == *pLongJump ) && ( 0x90909090 == *pLongJumpAdr ) ) { // Long jump *pLongJump = 0xE9; *pLongJumpAdr = ( ( DWORD ) newProc ) - ( ( DWORD ) oldProc ); /* The first byte of a SHORT Jump is always EB and the second is a relative offset from 00h to 7Fh for Forward jumps, and from 80h to FFh for Reverse (or Backward) jumps. Unlike Forward Jumps, the seemingly largest offset byte here actually indicates the shortest backward jump. Do short jump back -7 (back 5, plus two for this jump), yielding two's complement 0xF9 */ *pJumpBack = 0xF9EB; if( ppOrigFn ) *ppOrigFn = ( FNPTR ) ( ( ( BYTE* ) oldProc ) + 2 ); result = true; } VirtualProtect( pLongJump,20,oldProtect,&oldProtect ); return result; } // the original fn ptr, not "ppOrigFn" from HotPatch bool HotUnpatch( FNPTR oldProc ) { bool result = false; DWORD oldProtect = 0; WORD* pJumpBack = ( WORD* ) oldProc; VirtualProtect( pJumpBack,2,PAGE_EXECUTE_WRITECOPY,&oldProtect ); if( 0xF9EB == *pJumpBack ) { // Remove the jump back *pJumpBack = 0xFF8B; // mov edi, edi result = true; } VirtualProtect( pJumpBack,2,oldProtect,&oldProtect ); return result; } typedef int ( WINAPI * MSGBOXFN )( HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT uType ); static MSGBOXFN volatile pfnOrigMessageBox = 0; static CRITICAL_SECTION cs; int WINAPI OurMessageBox( HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT uType) { // Too lazy to deallocate, but this can be dangerous with long strings ... char* message = ( char* ) alloca( strlen( lpText ) + 20 ); strcpy( message,"Tampering message: " ); strcat( message,lpText ); EnterCriticalSection( &cs ); int rv = pfnOrigMessageBox( hWnd,message,lpCaption,uType ); LeaveCriticalSection( &cs ); return rv; } extern "C" __declspec( dllexport ) void HotpatchMessageBox( ) { InitializeCriticalSection( &cs ); MessageBox( NULL,"This is your last message without tampering","You'll see",MB_OK ); EnterCriticalSection( &cs ); HotPatch( ( FNPTR ) &MessageBox,( FNPTR ) &OurMessageBox,( FNPTR* ) &pfnOrigMessageBox ); LeaveCriticalSection( &cs ); }