Detours - jmp 00000000
Detours - jmp 00000000
这是我正在使用的代码:
#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;
}
这段代码没有问题,它将钩子放在0x152942C6,我可以看到它跳到我的 tompa_sendto() 并再次返回。
当我使用此代码作为钩子时,它没有正确设置钩子,
在我可以看到的内存中0x152942C6:jmp 00000000
void tompa_sendto() {
char buffer[] = {'x', 'y', 'z'};
return originalFunction();
}
无论我在 tompa_sendto() 中放置什么代码都会使程序崩溃(因为糟糕的 jmp),我设法放在那里的唯一 2 个代码是 printf 和 messageBoxA。
我能够重现这个问题(虽然只有绕道 1.5),所以我做了一些挖掘。似乎问题只是您的绕行功能是空的。
当您通过从另一个调用返回来结束调用时,编译器会进行特定的优化:它不调用函数,而是通过跳转而不是调用直接延迟控件。这不会推送返回地址,因此,当下一个函数返回时,它使用前一个函数返回地址,并同时从这两个函数返回。长话短说,该函数以 jmp func
而不是 call func; ret
结尾。
现在,当你的函数为空时,这个跳转是函数中唯一的指令。另一个事实是,您通过变量调用原始函数,这转换为间接跳转。问题是,Detours 1.5 专门检查您的函数是否以间接跳转开始,如果是这样,它会根据它找到的间接跳转将目标函数与直接跳转挂钩。为什么?因为许多函数(如 DLL 调用)都是通过间接跳转表调用的,而 Detours 如果找到一个,它会尝试快捷方式。
在您的情况下,目标函数通过跳转到 originalFunction
挂钩,但是当您安装钩子时,此变量为 0,因此jmp 0
.尝试在钩子之前将originalFunction
设置为 3,您将看到。如果您的函数不为空,则不会发生此问题,因此请不要担心。返回前的简单__nop();
即使它是空的,也可以使用它。