识别并拦截函数调用

时间:2012-11-24 03:32:59

标签: windows hook reverse-engineering disassembly ida

我正在为游戏开发一个发射器。 想拦截游戏中打印文本的功能。

我不知道包含此函数的代码是动态链接还是静态链接。所以我甚至不知道函数名称。

我通过微软Detours,Ninject和其他一些人拦截了这个游戏的一些windows-api调用。

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

我该怎么做才能接到这个函数调用?应该使用什么样的分析器? IDA?如何做到这一点?


修改

终于找到了功能地址。谢谢,Skino!

试图用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.pnghttp://i46.tinypic.com/dfeh4.png

原始功能反汇编:

http://pastebin.com/1Ydg7NED

绕道后:

http://pastebin.com/eM3L8EJh

EDIT2:

绕道后:

http://pastebin.com/GuJXtyad

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

我对ASM不好,请说出可能出错的地方?

2 个答案:

答案 0 :(得分:1)

在这个阶段听起来你没有关于你想要挂钩的库函数的概念,并且你已经声明它(实际上至少是)导入表中的导入外部函数可能意味着负责生成文本的函数可能位于您直接拆卸或动态加载的应用程序的.text内,文本生成(特别是在游戏中)可能是应用程序的一部分。

根据我的经验,找到难以跟踪的代码的最简单方法是在文本显示期间或之前/之后不久停止应用程序,并使用IDA的神话般的调用图功能来确定负责编写的内容它(大量使用手表和断点!)

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

我强烈反对它,但为了完整起见,你也可以在system service dispatch table中挂钩NtSetInformationThread。这里是针对不同Windows版本here的表的良好转储。如果你想自己获取表中的索引,你可以从ntdll.dll中反汇编NtSetInformationThread导出。

答案 1 :(得分:1)

  

想拦截游戏对打印文字功能的要求。

您可以将调试程序用于调查阶段。无论是IDA,还是Visual Studio(与例如HxD结合使用)都应该这样做。使用以下步骤识别功能应该相对容易:

  1. 标识要跟踪其打印的文本的特定片段(例如Hello World!
  2. 游戏正常打印上面标识的片段之前中断游戏执行
  3. 在游戏内存中搜索文本片段查找Unicode或ANSI )。 IDA将允许您执行IIRC,免费HxDExtras> Open RAM...
  4. 一旦识别出片段的地址,设置一个断开访问/读取数据断点,以便调试器可以控制游戏尝试读取的时刻所述片段(在展示之前或之前)
  5. 恢复执行,等待数据断点触发
  6. 检查堆栈跟踪并寻找适合挂钩的候选人
  7. 从片段从内存中读取片段直到打印出来,如果您想探索其他潜在的钩点,请逐步完成
  8. †提供的文字不会被压缩(或者,无论出于何种原因,加密)直到最后一刻

    完成调查阶段后,您已确定要注射钩子的位置,编写启动器时有两个选项

    1. 如果基于上述练习,您终于可以识别出口/导入,那么使用任何API挂钩技术
    2. 编辑使用Microsoft Detours,确保首先正确identify the calling convention (cdecl, fastcall, stdcall)您要绕道的功能,并将该调用约定用于原始原型以及用于实现虚拟。见examples
    3. 如果没有,你必须这样做
      • 使用Debugging API以编程方式加载游戏
      • 根据您的调查阶段计算挂钩地址(作为模块基础的硬编码偏移量,或者通过查找钩子站点周围的指令字节
      • 设置断点
      • 恢复过程
      • 等待断点触发,做任何你必须做的事情
      • 恢复执行,等待下一次触发等再次,所有这些都由您的启动程序通过调试API 以编程方式完成。
    4. ‡能够继续使用游戏的最终补丁版本