I'm learning how to hotpatch functions and I have the following code which works fine in 32-bit programs. However, I'm trying to get it to work in 64-bit programs as well but it just crashes.
#ifndef __x86_64
std::uint8_t Store[8] = {0};
#else
std::uint8_t Store[15] = {0};
#endif
void Patch(std::uint8_t* OriginalAddress, std::uint8_t* ReplacementAddress)
{
#ifndef __x86_64
const static std::uint8_t jmp[] = {0xb8, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0}; /** movl $0x0, %eax ;;; jmp *%eax **/
#else
const static std::uint8_t jmp[] = {0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0x90, 0x90}; /** movq $0x0, %rax ;;; jmp *%rax **/
#endif
DWORD dwProtect = 0;
const static std::int8_t jmp_size = sizeof(jmp) / sizeof(std::uint8_t);
VirtualProtect(OriginalAddress, jmp_size, PAGE_EXECUTE_READWRITE, &dwProtect);
memcpy(Store, OriginalAddress, jmp_size);
memcpy(OriginalAddress, jmp, jmp_size);
memcpy(OriginalAddress + 1, &ReplacementAddress, sizeof(void*));
VirtualProtect(OriginalAddress, jmp_size, dwProtect, &dwProtect);
}
Any ideas what is wrong with the code?
const static std::uint8_t jmp[] = {0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0x90, 0x90};
...
memcpy(OriginalAddress + 1, &ReplacementAddress, sizeof(void*));
For your x86-64 instructions, the address to jump to, the 0x0000000000000000 in your jmp
array, starts at the third byte, not at the second. You're overwriting part of the mov
instruction, and what you end up with is an invalid instruction if you're lucky.
As a side note, I'm doubtful it's safe to just overwrite %eax
/%rax
like that. Have you determined that those registers will never contain any values of interest?