Detours - jmp 00000000

Detours - jmp 00000000

本文关键字:00000000 jmp Detours      更新时间:2023-10-16

这是我正在使用的代码:

#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();即使它是空的,也可以使用它。