如何挂钩Win32 API中没有的函数?

时间:2014-07-09 21:09:48

标签: c++ assembly hook reverse-engineering dll-injection

我做了一个非常简单的程序,创建一个窗口并显示"随机数是:[从0到9的随机数]"在左上角。显示数字的功能如下所示:

void DisplayThings(HDC hdc, HWND hWnd, int randomNum)
{
    std::stringstream text;
    text << "Random number is: " << randomNum;
    TextOut(hdc, 0, 0, text.str().c_str(), text.str().length());
}

在OllyDBG中,我发现它位于地址0x11211A0:

DisplayThings function

接下来,我创建了一个试图在Microsoft Detour的帮助下绕过DisplayThings函数的dll,这是dll的样子:

#pragma comment(lib, "detours.lib")

#include <Windows.h>
#include <detours.h>
#include <tchar.h>
#include <sstream>

typedef void (*pDisplayThingsFunc)(HDC hdc, HWND hWnd, int randomNum);
void DisplayThingsFunc(HDC hdc, HWND hWnd, int randomNum)
{
    printf("function is being detoured\n");
    TextOut(hdc, 0, 20, L"detoured", 8);
}
pDisplayThingsFunc DisplayThingsFuncToDetour = (pDisplayThingsFunc)(0x11211A0);

BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved  )
{
    //DWORD *hiddenValueAdress = (DWORD*)(*(DWORD*)0x020FAB8);

    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:

        AllocConsole();
        freopen("CONOUT$", "w", stdout);

        DetourTransactionBegin(); 
        DetourUpdateThread(GetCurrentThread());

        DetourAttach(&(PVOID&)DisplayThingsFuncToDetour, DisplayThingsFunc);

        DetourTransactionCommit();

        break;

    case DLL_PROCESS_DETACH:
        FreeConsole();

        DetourTransactionBegin(); 
        DetourUpdateThread(GetCurrentThread());

        DetourDetach(&(PVOID&)DisplayThingsFuncToDetour, DisplayThingsFunc);

        DetourTransactionCommit();
        break;
    }

    return TRUE;
}

一旦我注入了dll,地址就会被JMP正确替换为我的新功能,但随后发生了一些奇怪的事情......控制台继续打印&#34;功能正在被绕开&#34;但TextOut函数无法显示任何内容......

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:-1)

编译器正在优化代码,因为它推断出它可以安全地为此函数执行此操作。

  • 不会导出。
  • 它不与函数指针一起使用。
  • 不在分析范围之外使用。 (取决于编译器设置)
  • 最有可能只有一个呼叫者(如果有更多不同的呼叫者使用不同的设置,那么参数得到优化的可能性就会降低)。

您可以更改其中一项(例如,通过导出符号,将其分配给函数指针等)。

或者您可以尝试按原样挂钩。

首先,你需要推断出你感兴趣的论点在哪里被传递,which is most likely a register. 最简单的方法是分析对TextOut的调用并追溯hdc参数。 如果你很幸运并且只是通过快速调用来优化它,可以将函数和函数指针的类型更改为fastcall,然后完成。

如果你没那么幸运,你可能不得不从内联汇编的额外寄存器中获取它。