7.UE-游戏逆向-绕过游戏的反调试
免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!
本次游戏没法给
内容参考于:微尘网络安全
上一个内容:6.UE-游戏逆向-查找游戏中的GName,查找GName地址
什么是反调试,就是不管使用CE还是spy++还是OD还是xdbg只要打开它就会被检测到,检测到会把这些调试软件(CE、spy++、OD、x32dbg、x64dbg)给关闭或游戏退出等操作,也就是说调试软件根本就打不开,本次写的是使用检测窗口(窗口类名、窗口标题)的手段来实现反调试的情况
首先ue的游戏运行后会有下图红框的进程,SC-Plugin for UE4,它就是用来检测调试软件的
如果使用任务管理器的结束任务按钮,关闭进程,它还是会自动运行
怎么办?首先使用ida反编译游戏的exe文件,如下图ida反编译完成后
然后ida里有一个导入表,下图的Imports就是导入表窗口
然后按CTRL+F,然后输入FindW,就可以出现下图蓝框里的内容,下图蓝框里的FIndWindow开头的函数就是用来查找窗口的
然后双击上图蓝框里的FIndWindowA进入下图位置,然后鼠标左键双击下图红框位置
然后就进入了调用FIndWindowA函数的位置
按下空格键,就能把上图的样子变成下图的样子,下图的样子比较好看
如下图红框它们都是窗口的类名,也就是在这里进行的调试器检测
然后按下F5,通过伪C++代码查看,通过下图可以看得出来通过GetProcAddress函数获取IsDebuggerPresent函数地址,然后调用IsDebuggerPresent函数从而得到当前是否有被调试,如果有被调试就退出,如果没有调试就调用OpenFileMappingW和FindWindowA检测调试器,所以说下图红框的函数,也就是叫sub_1408B4A60的函数是用来做反调试的,如果想过反调试就把sub_1408B4A60函数第一行写一句retn,retn的意思只要运行了retn就说明当前函数执行完了,然后返回
代码说明
// 函数:sub_1408B4A60
// 参数:a1(一个内存地址,可能是某个对象的指针)
// 返回值:HWND(窗口句柄,即窗口的唯一标识)
HWND __fastcall sub_1408B4A60(__int64 a1)
{HWND result; // 用于存储最终返回的窗口句柄HMODULE Library; // 用于加载的系统库(如kernel32.dll)BOOL (__stdcall *IsDebuggerPresent)(); // 指向"检查是否有调试器"的函数// 第一步:尝试获取窗口句柄(两种方式)// 1. 先检查a1+48地址处的变量是否有效,或调用sub_14106D010()获取窗口句柄// 2. 如果失败,调用sub_1408BF9D0(a1)作为备用方案获取窗口句柄if ( !*(_QWORD *)(a1 + 48) || (result = (HWND)sub_14106D010(), !(_BYTE)result) )result = (HWND)sub_1408BF9D0(a1);// 第二步:反调试检测(仅当a1+109地址处的标志为0时执行)if ( !*(_BYTE *)(a1 + 109) ){// 加载系统库kernel32.dll(包含基础系统函数)Library = LoadLibraryExW(L"kernel32.dll", 0, 0);// 从kernel32.dll中获取"IsDebuggerPresent"函数的地址// 这个函数的作用是:检查当前程序是否正在被调试器(如Visual Studio调试器)调试IsDebuggerPresent = (BOOL (__stdcall *)())GetProcAddress(Library, "IsDebuggerPresent");// 如果成功获取到IsDebuggerPresent函数,且调用后发现有调试器if ( IsDebuggerPresent && ((__int64 (*)(void))IsDebuggerPresent)() ){FreeLibrary(Library); // 释放加载的kernel32.dllreturn (HWND)sub_140F432C0(0); // 触发反制(可能是退出程序、报错等)}else{FreeLibrary(Library); // 没有调试器,释放库// 检查是否存在名为"CEHYPERSCANSETTINGS"的文件映射(Cheat Engine的特征)if ( OpenFileMappingW(6u, 0, L"CEHYPERSCANSETTINGS") )return (HWND)sub_140F432C0(0); // 检测到Cheat Engine,触发反制// 检查是否存在WinDbg调试器窗口(类名为"WinDbgFrameClass")if ( FindWindowA("WinDbgFrameClass", 0) )return (HWND)sub_140F432C0(0); // 检测到WinDbg,触发反制// 重复检查WinDbg窗口(可能是冗余逻辑或特定场景适配)if ( FindWindowA("WinDbgFrameClass", 0) )return (HWND)sub_140F432C0(0);// 检查是否存在OllyDbg调试器窗口(类名为"OLLYDBG")if ( FindWindowA("OLLYDBG", 0) )return (HWND)sub_140F432C0(0); // 检测到OllyDbg,触发反制// 检查是否存在类名为"Window"的可疑窗口(可能是其他调试/作弊工具)result = FindWindowA("Window", 0);if ( result )return (HWND)sub_140F432C0(0); // 检测到可疑窗口,触发反制}}// 如果没检测到调试器,返回之前获取的窗口句柄return result;
}
然后点击下图红框的IDA VIew-A,然后鼠标左键单击sub_1408B4A60头部
然后选择下图中的Change byte
然后把下图红框的内容替换成c3,c3的就代表了汇编代码retn,也就是说retn这个汇编代码的硬编码是c3
改完之后如下图红框,第一行就变成了retn,游戏是x64的不需要关心堆栈平衡
改完之后点击下图中的 Apply patches to input file进行保存
什么都不需要改直接点击ok,注意如果游戏在运行它会保存失败
然后再次打开游戏,然后再次找到 SC-Plugin for UE4进行,然后选中它,然后点击结束任务,就会发现SC-Plugin for UE4不会再次运行了,然后就可以打开调试器了,spy++也能打开获取游戏的窗口类名了
如下图石头spy++获取类名和打开ce