Hot Patching A Function

I am trying to use a hot exe patch in memory, the source is available, but I am doing this for training purposes. (therefore, please, no comments suggesting changing the original source or using workarounds or any other libraries)

The following are the features I'm having problems with.

vm_t* VM_Create( const char *module, intptr_t (*systemCalls)(intptr_t *), vmInterpret_t interpret ) { MessageBox(NULL, L"Oh snap! We hooked VM_Create!", L"Success!", MB_OK); return NULL; } void Hook_VM_Create(void) { DWORD dwBackup; VirtualProtect((void*)0x00477C3E, 7, PAGE_EXECUTE_READWRITE, &dwBackup); //Patch the original VM_Create to jump to our detoured one. BYTE *jmp = (BYTE*)malloc(5); uint32_t offset = 0x00477C3E - (uint32_t)&VM_Create; //find the offset of the original function from our own memset((void*)jmp, 0xE9, 1); memcpy((void*)(jmp+1), &offset, sizeof(offset)); memcpy((void*)0x00477C3E, jmp, 5); free(jmp); } 

I have a VM_Create function that I want to call instead of the original function. I haven't written a trampoline yet, so it falls (as expected). However, a message box does not appear that I disabled the original virtual machine myself. I believe that I am rewriting the original instructions.

+4
source share
1 answer

I see a few problems.

I assume that 0x00477C3E is the address of the original VM_Create function. You really shouldn't do this. Use &VM_Create . Of course, this will mean that you need to use a different name for your replacement function.

The offset is not calculated correctly. You have the wrong sign. What else is the offset applied to the instruction pointer at the end of the instruction, and not to the beginning. Therefore, you need to shift it by 5 (instruction size). The offset must also be a signed integer.

Ideally, given my first point, the code would look like this:

 int32_t offset = (int32_t)&New_VM_Create - ((int32_t)&VM_Create+5); 

Thanks to Hans Passant for fixing my own stupid bug in the original version!

If you are working on a 64-bit machine, you need to perform arithmetic in 64 bits and, as soon as you calculate the offset, truncate it to a 32-bit offset.

Another caveat is that you should reset to save memory only after writing a new JMP instruction and calling FlushInstructionCache .

+4
source

Source: https://habr.com/ru/post/1380702/


All Articles