Windows 识别和拦截函数调用
我正在为游戏开发一个发射器。 想要拦截游戏对打印文本的函数的调用 我不知道包含此函数的代码是动态链接的还是静态链接的。所以我甚至不知道函数名 我确实通过microsoft Detours、Ninject和其他一些工具截获了这个游戏的一些windows api调用 但这个也不在导入表中 我应该做什么来捕捉这个函数调用?应该使用什么分析器?艾达?如何做到这一点Windows 识别和拦截函数调用,windows,hook,reverse-engineering,disassembly,ida,Windows,Hook,Reverse Engineering,Disassembly,Ida,我正在为游戏开发一个发射器。 想要拦截游戏对打印文本的函数的调用 我不知道包含此函数的代码是动态链接的还是静态链接的。所以我甚至不知道函数名 我确实通过microsoft Detours、Ninject和其他一些工具截获了这个游戏的一些windows api调用 但这个也不在导入表中 我应该做什么来捕捉这个函数调用?应该使用什么分析器?艾达?如何做到这一点 编辑: 最后找到函数地址。谢谢你,斯基诺 试图用迂回的方式钩住它。注入式DllMain: typedef int (WINAPI *Pri
编辑: 最后找到函数地址。谢谢你,斯基诺 试图用迂回的方式钩住它。注入式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
具有应显示的文本。但是调用原始函数时返回PrintText_Origin(a、b、c、d)代码>应用程序崩溃(,)
原功能反汇编:
绕道后:
EDIT2:
绕道后:
PrintText\u Hooked
discompositionw3\u loader.dll是注入的dll
我不擅长ASM,请告诉我什么地方会出错?在这个阶段,听起来你不知道你想挂接什么库函数,而且你已经声明它不是(显然至少是这样)导入表中导入的外部函数,这可能意味着负责生成文本的函数可能位于直接反汇编或动态加载的应用程序的文本中。文本生成(特别是在游戏中)可能是应用程序的一部分
根据我的经验,查找难以跟踪的代码的最简单方法是在文本显示期间或之前/之后立即停止应用程序,并使用IDA出色的调用图功能确定编写代码的原因(自由地使用手表和断点!)
如果您有理由相信此功能可能由导入表中未显示的导出函数提供,请仔细查看对或任何其他常用动态加载机制的调用
我强烈建议不要这样做,但为了完整起见,您也可以在中钩住NtSetInformationThread。下面是不同Windows版本的表的一个很好的转储。如果您想自己获取表中的索引,可以从ntdll.dll反汇编NtSetInformationThread导出
想要拦截游戏对打印文本的函数的调用
您可以在调查阶段使用调试器。IDA,甚至Visual Studio(与HxD结合使用)都应该这样做。使用以下步骤识别功能应该相对容易:
确定要跟踪其打印的特定文本片段(例如,Hello World!
)
在游戏正常打印您在上面识别的片段之前的任何时候中断游戏执行
在游戏内存中搜索文本片段†(查找Unicode或ANSI)。IDA将允许你做IIRC,免费的(Extras
打开RAM…
)
一旦确定了片段的地址,在访问/读取时设置一个中断数据断点,这样调试器将在游戏尝试读取所述片段时(显示片段时或之前)为您提供控制
继续执行,等待数据断点触发
检查堆栈轨迹,并寻找合适的挂钩候选对象
如果您想探索其他潜在的钩子点,请从从内存读取片段的那一刻开始逐步执行,直到打印出来
†提供的文本直到最后一刻才被压缩(或出于任何原因加密)
一旦完成了调查阶段并确定了要将钩子注入的位置,编写启动器时就有两个选项:
如果基于上述练习,您最终能够识别导出/导入,那么请使用任何API挂钩技术
编辑使用Microsoft Detours,确保首先正确使用要绕行的函数,并将该调用约定用于原始原型和虚拟实现。看
如果没有,你将不得不这样做
- 使用以编程方式加载游戏
- 根据调查阶段计算钩子地址(作为与模块基的硬编码偏移量,或者通过查找钩子站点周围的指令字节来计算)
- 设置断点
- 恢复进程
- 等待断点触发,执行所有必须执行的操作
- 继续执行,等待下一个触发器等。所有这些都是由启动器通过调试API编程完成的
‡为了能够继续使用游戏的最终补丁版本您是否在游戏代码中找到了此功能?或者你需要如何找到它的指导,这样你就可以截取它?实际上我不知道如何找到这个函数。甚至不知道去哪里。我只知道这是可能的;)然后,看起来你必须潜入调试器或反汇编程序。我们不能在这个评论框中给你一个教程:)(出于好奇,这是什么游戏?)已经反汇编了主DLL。拆卸有很多功能。如何找到我要找的东西?我应该使用什么策略?(游戏是暴雪的wc3)正如我所说的,这个问题太广泛了,这里无法回答——看看一些反向工程教程。一个可能的开始是寻找硬编码的字符串、Primf格式说明符或C++ IO Strua。