Detours - jmp 00000000

时间:2015-01-21 12:56:19

标签: c++ assembly reverse-engineering detours

这是我正在使用的代码:

#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),我设置的唯一两个代码就是printf和messageBoxA。

1 个答案:

答案 0 :(得分:2)

我能够重现这个问题(虽然只有绕道1.5),所以我做了一些挖掘。似乎问题只是你的绕行功能是空的。

当您通过从另一个调用返回来结束调用时,编译器会执行特定的优化:它不会调用该函数,而是通过跳转而不是调用来直接推迟控制。这不会推送返回地址,因此,当下一个函数返回时,它使用前一个函数返回地址,并同时从两个函数返回地址返回。简而言之,该函数以jmp func而不是call func; ret结束。

现在,当你的函数为空时,这个跳转是函数中唯一的指令。另一个事实是你通过变量调用原始函数,这转化为间接跳转。问题是,Detours 1.5专门检查你的函数是否以间接跳转开始,如果是,它会根据找到的间接跳转直接跳转目标函数。为什么?因为许多函数(如DLL调用)是通过间接跳转表调用的,而Detours如果找到它就会尝试快捷方式。

在你的情况下,目标函数被钩到跳转到originalFunction,但是当你安装钩子时这个变量是0,因此是jmp 0。在钩子之前尝试将originalFunction设置为3,你会看到。如果你的功能不是空的话,这个问题不会发生,所以不要担心。返回之前的简单__nop();即使它是空的也会使它工作。