这是我正在使用的代码:
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <detours.h>
#include <fstream>
#define real_sendto 0x152942C6
void(__cdecl* originalFunction)();
void tompa_sendto() {
printf("Hellooo");
return originalFunction();
}
void hook() {
originalFunction = (void(__cdecl*)())DetourFunction((PBYTE)real_sendto, (PBYTE)tompa_sendto);
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH: hook(); break;
case DLL_PROCESS_DETACH: return FALSE; break;
}
return TRUE;
}
这段代码没有问题,它将钩子(Hook)放在0x152942C6处,我可以看到它跳转到我的tompa_sendto()并再次返回。
当我使用此代码作为 Hook 时,它没有正确设置 Hook ,
在内存中我可以在0x152942C6处看到:jmp 00000000
void tompa_sendto() {
char buffer[] = {'x', 'y', 'z'};
return originalFunction();
}
无论我在 tompa_sendto() 中放置什么代码都会使程序崩溃(因为 jmp 错误),我设法放置的唯一 2 个代码是 printf 和 messageBoxA。
最佳答案
我能够重现这个问题(尽管只有 detours 1.5),所以我做了一些挖掘。看来问题只是你的绕行函数是空的。
当您通过从另一个调用返回来结束调用时,编译器会进行特定的优化:它不会调用该函数,而是通过跳转而不是调用来直接延迟控制。这不会推送返回地址,因此,当下一个函数返回时,它使用前一个函数的返回地址,并同时从两个函数返回。长话短说,函数以 jmp func
结尾,而不是 call func; ret
.
现在,当你的函数为空时,这个跳转是函数中唯一的指令。另一个事实是,您通过变量调用原始函数,这转化为间接跳转。问题是,Detours 1.5 专门检查您的函数是否以间接跳转开始,如果是,它会根据找到的间接跳转通过直接跳转来 Hook 目标函数。为什么 ?因为许多函数(例如 DLL 调用)都是通过间接跳转表调用的,如果 Detours 找到一个跳转表,就会尝试快捷方式。
在您的情况下,目标函数通过跳转到 originalFunction
进行 Hook ,但当您安装 Hook 时此变量为 0,因此 jmp 0
。尝试在钩子(Hook)之前将 originalFunction
设置为 3,你会看到。如果你的函数不为空就不会出现这个问题,所以不用担心。返回之前的一个简单的 __nop();
将使其工作,即使它是空的。
关于c++ - 弯路 - jmp 00000000,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28067801/