绕道DrawText

时间:2009-09-09 17:52:02

标签: c++ winapi detours

我已经下载并编译了Microsoft绕行库。在我的项目中,我已经包含了头文件并添加了 .lib 文件作为依赖项。一切都编译没有错误。现在我一直试图绕开DrawText,但由于某种原因,完全没有调用绕道函数。同样地,我尝试绕过睡眠功能并按预期工作,并调用我绕道的功能。

我对API编程业务以及其他任何低级别活动都不是很精通。我怀疑它可能与我试图在控制台应用程序中执行此操作而不是在DLL内部进行绕行的事实有关。我觉得奇怪的是,在那种情况下,它可以绕开睡眠。

我的方法有问题还是错误存在于代码中?

#include <windows.h>
#include <stdio.h>
#include "detours.h"

int ( WINAPI *Real_DrawText )(HDC a0, LPCSTR a1, int a2, LPRECT a3, UINT a4) = DrawTextA;

int Mine_DrawText(HDC hdc, LPCSTR text,  int nCount, LPRECT lpRect, UINT uOptions)
{
   printf("TEST");
   return Real_DrawText(hdc, text, nCount, lpRect, uOptions);
}

int main(int argc, char **argv)
{
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    DetourAttach(&(PVOID&)Real_DrawText, Mine_DrawText);
    DetourTransactionCommit();
    printf("Calling Sleep\n");
    Sleep(1000);
    printf("Second callout");
    Sleep(5000);

    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());
    DetourDetach(&(PVOID&)Real_DrawText, Mine_DrawText);
    DetourTransactionCommit();
    return 0;
}

3 个答案:

答案 0 :(得分:1)

根据您的代码示例,您似乎只是在绕过自己的流程。因此绕道DrawText不输出任何东西。也许,您需要将代码注入所需目标的进程内存并从那里绕过API调用。例如,您可以创建系统范围的CBT挂钩,它可以满足您的绕行需求。这样的事情,指出你的方向:

LRESULT CALLBACK CBTProcedure(int nCode, WPARAM wParam, LPARAM lParam)
{
        if (nCode < 0)
                return CallNextHookEx(g_hHook, nCode, wParam, lParam);
        else if (!g_pClient)
                return 0;

        HWND hWnd = (HWND)wParam;

        if (!hWnd)
                return 0;

        switch (nCode) {
                case HCBT_ACTIVATE:
                        /** Here, you can check up against the handle to see,
                          * if the target window is the one you're looking for...
                          *
                          */
                        if (!g_pClient->IsRegisteredWindow(hWnd))
                                if (g_pClient->RegisterWindow(hWnd)) {
                                }

                break;

                case HCBT_DESTROYWND:
                        if (g_pClient->IsRegisteredWindow(hWnd))
                                g_pClient->UnregisterWindow(hWnd);

                break;
        }

        return 0;
}

bool __0XYOUROWN_API InstallHook()
{
        // Call this one from your main process; set's up the system-wide hook.

        g_hHook = SetWindowsHookEx(WH_CBT, (HOOKPROC)CBTProcedure, g_hInstance, 0);

        /** #pragma data_seg("Shared")
          *         HHOOK g_hHook = NULL;
          * #pragma data_seg()
          */

        return g_hHook != NULL;
}

/** The actual DLL...
  *
  *
  */
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
        switch (ul_reason_for_call) {
                case DLL_PROCESS_ATTACH:
                        g_hInstance = (HINSTANCE)hModule;

                        if (::GetModuleHandle(_T("THEDESIREDMODULE.EXE")) != NULL) {
                                g_pClient = new Client();

                                if (g_pClient) {
                                        InitializeCriticalSection(&g_CriticalSection); // You can setup a critic. sec. for later synchronization...
                                        DetourTransactionBegin();
                                        DetourUpdateThread(GetCurrentThread());
                                        DetourAttach(&(PVOID&)Real_DrawTextW, Mine_DrawTextW);
                                        DetourTransactionCommit();
                                }
                        }

                break;

                case DLL_THREAD_ATTACH: break;

                case DLL_THREAD_DETACH: break;

                case DLL_PROCESS_DETACH:
                        if (::GetModuleHandle(_T("THEDESIREDMODULE.EXE")) != NULL) {
                                if (g_pClient) {
                                        DetourTransactionBegin(); 
                                        DetourUpdateThread(GetCurrentThread());
                                        DetourDetach(&(PVOID&)Real_DrawTextW, Mine_DrawTextW);
                                        DetourTransactionCommit();

                                        delete g_pClient;

                                        g_pClient = NULL;
                                }
                        }

                break;
        }
}

答案 1 :(得分:1)

看来你假设printf()会调用DrawText()。它不会。 DrawText()是一个GDI函数。 printf()转到WriteConsole()。这些不混合。 “控制台Windows”与所有其他窗口完全不同。这种区别是一个基本的建筑;它们甚至由独立的内核组件管理。

答案 2 :(得分:1)

只有附注:EasyHook - The reinvention of Windows API Hooking是一个开源(LGPL)项目,正在开发Detours的后续项目。它已经相当成熟了。