Горячая исправление функции
Я пытаюсь установить исправление exe в памяти, источник доступен, но я делаю это для целей обучения. (поэтому, пожалуйста, никаких комментариев, предлагающих изменить исходный код или использовать обходные пути или любые другие библиотеки)
Ниже приведены функции, с которыми у меня проблемы.
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);
}
У меня есть функция VM_Create, которую я хочу вызывать вместо исходной функции. Я еще не написал батут, поэтому он падает (как и ожидалось). Однако окно сообщения не всплывает, что я отклонил оригинальную виртуальную машину к своей собственной. Я верю, что так я переписываю оригинальные инструкции.
1 ответ
Я вижу несколько вопросов.
Я предполагаю что 0x00477C3E
это адрес оригинала VM_Create
функция. Вы действительно не должны жестко кодировать это. использование &VM_Create
вместо. Конечно, это будет означать, что вам нужно использовать другое имя для функции замены.
Смещение рассчитано неверно. Вы ошиблись знаком. Более того, смещение применяется к указателю инструкции в конце инструкции, а не в начале. Поэтому вам нужно сдвинуть его на 5 (размер инструкции). Смещение также должно быть целым числом со знаком.
В идеале, если принять во внимание мой первый пункт, код будет выглядеть так:
int32_t offset = (int32_t)&New_VM_Create - ((int32_t)&VM_Create+5);
Спасибо Hans Passant за исправление моей собственной глупой ошибки в оригинальной версии!
Если вы работаете на 64-битной машине, вам нужно выполнить арифметику в 64-битном формате и, как только вы вычислили смещение, обрезать его до 32-битного смещения.
Еще один нюанс заключается в том, что вы должны сбросить память только для чтения после записи нового JMP
инструкция и звонок FlushInstructionCache
,