绕行 DrawText

Posted

技术标签:

【中文标题】绕行 DrawText【英文标题】:Detouring DrawText 【发布时间】:2009-09-09 17:52:02 【问题描述】:

我已经下载并编译了 Microsoft detouring 库。在我的项目中,我包含了头文件并添加了 .lib 文件作为依赖项。一切都编译没有错误。现在我一直在尝试绕过 DrawText,但由于某种原因,根本没有调用 detoured 函数。类似地,我尝试绕过 Sleep 函数,它按预期工作,并且调用了我绕过的函数。

我不太精通 API 编程业务或任何其他低级活动。我怀疑这可能与我试图在控制台应用程序中执行此操作而不是在 DLL 中完成绕行这一事实有关。我只是觉得奇怪的是,在这种情况下它能够绕过 Sleep。

我的方法有问题还是代码有问题?

#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;

【问题讨论】:

在 main 中,您调用的是 Sleep 而不是 DrawTextA,这只是复制/粘贴错误还是您使用过的真实示例? 如果我自己调用 DrawTextA 而不是 sleep,那么我的路由函数会被调用来代替函数。我有兴趣在全球范围内或至少在另一个窗口中发生这种情况。我希望有另一种方法,而不是将我的库注入应用程序。 【参考方案1】:

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

LRESULT CALLBACK CBTProcedure(int nCode, WPARAM wParam, LPARAM lParam) 如果 (nCode IsRegisteredWindow(hWnd)) if (g_pClient->RegisterWindow(hWnd)) 休息; 案例 HCBT_DESTROYWND: if (g_pClient->IsRegisteredWindow(hWnd)) g_pClient->UnregisterWindow(hWnd); 休息; 返回0; bool __0XYOUROWN_API InstallHook() // 从你的主进程调用这个;设置系统范围的挂钩。 g_hHook = SetWindowsHookEx(WH_CBT, (HOOKPROC)CBTProcedure, g_hInstance, 0); /** #pragma data_seg("共享") * HHOOK g_hHook = NULL; * #pragma data_seg() */ 返回 g_hHook != NULL; /** 实际的 DLL... * * */ BOOL APIENTRY DllMain(句柄 hModule,DWORD ul_reason_for_call,LPVOID lpReserved) 开关(ul_reason_for_call) 案例 DLL_PROCESS_ATTACH: g_hInstance = (HINSTANCE)hModule; if (::GetModuleHandle(_T("THEDESIREDMODULE.EXE")) != NULL) g_pClient = 新客户端(); 如果(g_pClient) InitializeCriticalSection(&g_CriticalSection); // 你可以设置一个评论家。秒。用于以后同步... DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourAttach(&(PVOID&)Real_DrawTextW, Mine_DrawTextW); DetourTransactionCommit(); 休息; 案例 DLL_THREAD_ATTACH:中断; 案例 DLL_THREAD_DETACH:中断; 案例 DLL_PROCESS_DETACH: if (::GetModuleHandle(_T("THEDESIREDMODULE.EXE")) != NULL) 如果(g_pClient) DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourDetach(&(PVOID&)Real_DrawTextW, Mine_DrawTextW); DetourTransactionCommit(); 删除 g_pClient; g_pClient = NULL; 休息;

【讨论】:

如果是这样的话,我的迂回函数不会仍然被调用来绘制控制台窗口的文本吗?问题是 DllMain 似乎既在我自己的项目中声明,也在“detour.lib”中声明,这会导致错误。 请看 MSalters 的回答。 你说得对。迂回只发生在注入程序中,这意味着我必须注入几乎所有东西,直到找到选择的程序。顺便说一句,你的代码看起来很漂亮 哦,是的,示例来自我当前的一个项目。【参考方案2】:

您似乎假设 printf() 将调用 DrawText()。它不会。 DrawText() 是一个 GDI 函数。 printf() 转到 WriteConsole()。这些不混合。 “控制台窗口”与所有其他窗口完全不同。这种区别是基本的架构区别。它们甚至由单独的内核组件管理。

【讨论】:

【参考方案3】:

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

【讨论】:

以上是关于绕行 DrawText的主要内容,如果未能解决你的问题,请参考以下文章

恢复绕行的库函数

为啥尝试绕行winapi时进程崩溃?

绕行 DrawText

哈密顿绕行世界问题(dfs+记录路径)

Linux Ubuntu下的绕行功能

# Cesium实现卫星在轨绕行