3

我正在为游戏开发启动器。想要拦截游戏对打印文本的函数的调用。

不知道包含这个函数的代码是动态链接的还是静态链接的。所以我什至不知道函数名。

我确实通过Microsoft Detours、Ninject 和其他一些人截获了这个游戏的一些windows-api 调用。

但这一个也不在导入表中。

我应该怎么做才能捕捉到这个函数调用?应该使用什么分析器?国际开发协会?如何做到这一点?


编辑:

终于找到函数地址了。谢谢,斯金诺!

试图将它与 Detours 挂钩,注入 dll。注入的 DllMain:

typedef int (WINAPI *PrintTextType)(char *, int, float , int);

static PrintTextType PrintText_Origin = NULL;

int WINAPI PrintText_Hooked(char * a, int b, float c, int d)
{
    return PrintText_Origin(a, b, c , d);
}

HMODULE game_dll_base;
/* game_dll_base initialization goes here */

BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    if(fdwReason==DLL_PROCESS_ATTACH)
    {
        DisableThreadLibraryCalls(hinstDLL);
        DetourTransactionBegin();
        DetourUpdateThread(GetCurrentThread());
        PrintText_Origin = (PrintTextType)((DWORD)game_dll_base + 0x6049B0);
        DetourAttach((PVOID *)&PrintText_Origin , PrintText_Hooked);
        DetourTransactionCommit();
    }
}

它按预期挂钩。参数a具有应显示的文本。但是当调用原始函数应用程序return PrintText_Origin (a, b, c , d);崩溃http://i46.tinypic.com/ohabm.png,http://i46.tinypic.com/dfeh4.png

原功能拆解:

http://pastebin.com/1Ydg7NED

绕道后:

http://pastebin.com/eM3L8EJh

编辑2:

绕道后:

http://pastebin.com/GuJXtyad

PrintText_Hooked反汇编http://pastebin.com/FPRMK5qt w3_loader.dll是注入的dll

我不擅长 ASM,请告诉我可能出了什么问题?

4

2 回答 2

1

在这个阶段,听起来您不知道要挂钩的库函数,并且您已经声明它不是(显然至少)导入表中的导入外部函数,这可能意味着该函数负责生成文本可能位于您直接反汇编或动态加载的应用程序的 .text 中,文本生成(尤其是在游戏中)可能是应用程序的一部分。

根据我的经验,查找难以追踪的代码的最简单方法是在显示文本期间或之前/之后立即停止应用程序,并使用 IDA 出色的调用图功能来确定负责将其写出的内容(自由使用手表和断点!)

如果您有理由相信此功能可能由未显示在导入表中的导出函数提供,请仔细查看对CreateRemoteThread或任何其他常用动态加载机制的调用。

我强烈建议不要这样做,但为了完整起见,您也可以在系统服务调度表中挂钩 NtSetInformationThread 。这里是不同 Windows 版本的一个很好的表格转储。如果您想自己获取表中的索引,您可以从 ntdll.dll 反汇编 NtSetInformationThread 导出。

于 2012-11-24T07:01:39.483 回答
1

想要拦截游戏对打印文本的函数的调用。

您可以在调查阶段使用调试器。IDA 甚至 Visual Studio(与例如 HxD 结合)都应该这样做。使用以下步骤识别函数应该相对容易:

  1. 识别要跟踪其打印的特定文本片段(例如Hello World!
  2. 在游戏正常打印您在上面确定的片段之前的任何时候中断游戏执行
  3. 在游戏内存中搜索该文本片段†</sup>(查找 Unicode 或 ANSI )。IDA 将允许您执行 IIRC,免费的HxD ( Extras> Open RAM...)
  4. 一旦确定了片段的地址,设置一个访问中断/读取数据断点,这样调试器就会让您控制游戏尝试读取所述片段的时刻(在显示它的同时或之前)
  5. 恢复执行,等待数据断点触发
  6. 检查堆栈跟踪并寻找合适的挂钩候选者
  7. 如果您想探索其他潜在的挂钩点,请从从内存中读取片段到打印片段的那一刻逐步进行

†提供的文本直到最后一刻才保持压缩(或者,无论出于何种原因,加密)

完成调查阶段并确定要在哪里注入钩子后,在编写启动器时有两种选择

  1. 如果根据上述练习,您毕竟能够识别导出/导入,那么使用任何 API 挂钩技术
  2. 编辑使用 Microsoft Detours,确保您首先正确识别您尝试绕行的函数的调用约定(cdecl、fastcall、stdcall),并将该调用约定用于原始原型以及实现假人。请参阅示例
  3. 如果没有,你将不得不
    • 使用调试 API以编程方式加载游戏
    • 根据您的调查阶段计算挂钩地址(作为与模块库的硬编码偏移量,或通过在挂钩站点周围查找指令字节‡</sup>)
    • 设置断点
    • 恢复进程
    • 等待断点触发,做你该做的事
    • 恢复执行,再次等待下一个触发器等,所有这些都由您的启动器通过 Debugging API 以编程方式完成

‡能够继续使用游戏的最终补丁版本

于 2012-11-24T15:32:53.067 回答