OrpheusQ 发表于 2021-4-14 21:09

2021腾讯游戏安全技术竞赛PC客户端方向-思路分享

本帖最后由 OrpheusQ 于 2021-4-14 21:55 编辑

[写在前面]
<帖子发晚了,前几天都在练科三,今天才考完,得空整理一下分析报告>

快要毕业了,却还没参加过一次CTF之类的比赛,为了不留遗憾,就报名了此次的比赛,作为自己不怎么秀的首秀(决赛肯定是无望了hhhh)。
以下仅仅是个人的分析思路,分享给大家,适合像我一样的逆向初学者阅读,也勉强算是为吾爱做出一点微薄的贡献了~
(参考答案or更精彩的解法还得参考同版块下其他/她师傅的帖子)

[主要分析结论]
1. 外挂通过读取 hack.dat 文件中的 flag, 通过自定义算法 1 解码+拼接后生成游戏进程名:
ShooterClient.exe。
2. 外挂通过自定义算法 2 解析出 hack.dll 文件的字节码,并通过写内存、创建远程线程的方
式使得黑模块得以执行。
3. 在黑模块中,通过 GetAsyncKeyState 截获鼠标右键的按下情况作为外挂的开关,以遍
历对象、基址+偏移的方式获取人物坐标,并计算、改写俯仰角(pitch)、偏航角(yaw),以
实现自瞄功能。

[分析过程]
<hack.exe 部分>
1. 先将 hack.exe 拖入 ida 中静态分析,依次调用 CreateFileA->GetFileSize->ReadFile,
不难猜出,此处读取的文件内容即为 flag。由于文件名是计算出来的,动态调试得:
hack.dat。




2. 之后进入到一个函数 hack.exe@1400014D0,该函数由 2 个 if 语句组成,分别都会进行
解密操作,但是只有第 2 个 if 语句才能解出 flag(第一个 if 是用于解析出黑模块 hack.dll
的,不同的情况下只会进入 1 个 if 语句中):
(注意:此处对flag的分析不够周到,虽然我猜出来的flag可以开启外挂,但后面看了其他/她师傅的帖子才发现有且仅有一个官方的flag, 原以为只要创建一个能把外挂成功运行起来的hack.dat就算是通过第一关了......不够细*1)





解析 flag 的操作:将 flag 的每个字节与 0x3F 异或,之后减去 0x13。


3. flag 解密完成后,会将 flag 从第 2 字节开始的偶数位拼接到局部变量 ProcName 中,结
合下文分析推测,应该是要打开游戏进程“ShooterClient.exe”,所以可得 flag 解密后
的特征应该是:除 0 外的偶数位保证为特定字节(游戏进程名), 其余位置可为任意值(这里
采用 0x00)。




分析出 flag 的解密过程和 flag 解密后的样子之后,便可反过来计算 flag,计算脚本如下:




使用 16 进制编辑器,写入到 hack.dat 中:





4. 拼接完进程名后,以拍摄快照的方式遍历进程,匹配字符串成功,打开进程:




之后,同样以解密文件名的方式,解析出 ntdll.dll,并获取了该模块中的:LdrLoadDll、
RtlInitAnsiString、RtlFreeUnicodeString、LdrGetProcedureAddress、
NtAllocateVirtualMemory、RtlAnsiStringToUnicodeString 函数地址。


5. 最后,调用 WriteProcessMemory,写入外挂代码,调用 CreateRemoteThreadEx 创建
远程线程执行黑模块代码。



其中写入的部分,最重要的是调用 hack.exe@1400014D0 解密得到的黑模块文件,以下2图分别为解密前后的内存:



解密 hack.dll 的算法(已在注释中详细说明):



至此,外挂 hack.exe 可以被打开,并成功使用,外挂功能为自瞄。




<hack.dll 部分>
1. 将外挂黑模块 dump 下来分析,dllmain 中创建工作线程,进入线程回调,开头获取了游
戏进程基址,并由基址+偏移的方式获取了多个全局变量,其中就包括较为重要的,游戏
引擎 this 指针。




2. 由于外挂的自瞄功能是需要在鼠标右键按下的情况下启动,所以根据这个特点,查找
GetAsyncKeyState 等相关函数的引用情况可以快速定位到外挂的核心代码:



3. 在该函数中,外挂事先根据游戏引擎的 this 指针(this_engine = [module_base +
0x2F71060]),获取到角色的 this 指针(this_player =
[[[[+0x160]+0x38]+0]+0x30]),并获取角色的 3 维坐标
(float)。
x = [[+0x158]+0x164]
y = [[+0x158]+0x168]
z = [[+0x158]+0x16C]



添加到 ce 中验证一下:


再通过遍历人物对象的方式(调用 hack.dll@180004510),获取到敌人的指针,选出离自
己较近的敌人后(xy 坐标系的距离<24.0),以相同的方式获取其 3 维坐标。
(注意:此处分析有误,看完其他/她师傅的帖子才发现这里计算的应该是屏幕中心和敌人之间的距离,不够细*2)





之后调用 sqrtf 求出角色和敌人在 xy 坐标系上的相对距离,调用 atan2f 求出俯仰角;再
调用一次 atan2f 求出偏航角,并将所求结果写入到对应的游戏内存中,以实现自瞄:
= pitch
= yaw






[自瞄实现]
大致思路:
·根据基址+偏移的方式获取对象数组,过滤筛选出敌人对象(观察发现敌人对象在对
象数组中的存放顺序在角色之后(推测是先创建了角色 再生成的敌人))。
·计算每个敌人对象与角色对象的距离,选出距离最近的敌人对象,并获得其 3 维坐标。
·通过获取的摄像机矩阵(如图),将 3 维的世界坐标转换成 2 维的屏幕坐标。最后通过
模拟鼠标消息,移动到敌人在屏幕的位置,实现自瞄。



·已将上述思路转成代码的表达形式(附件),遗憾的是最终未能完全实现预期的效
果(一个没有成功的代码就不在吾爱放出来干扰大家了)。不过在这些天的比赛中,对于一个初次分析 FPS 游戏的自己而言已经是收获不少,学
习到了很多新知识,路漫漫其修远兮,吾将上下而求索!






0097 发表于 2021-4-23 20:01

反正 我已经跪地上了   !!!!!!!!!

lyl610abc 发表于 2021-4-15 11:20

大佬太厉害了,没打过CTF的萌新前来学习{:301_1003:}

Eaysuild.xean 发表于 2021-4-15 17:29

感谢楼主分享的思路,顺便鉴定楼主,不是逆向小白{:301_997:}

nur11111 发表于 2021-4-15 22:28

感觉好厉害

烈焰乌龙茶 发表于 2021-4-15 22:57

学习了,谢谢楼主

awseq 发表于 2021-4-16 06:54

大佬有点牛逼

阿高mango 发表于 2021-4-16 09:13

学习了,谢谢楼主

panyang199044 发表于 2021-4-16 10:23

看不懂,我才是小白

Gaho2002 发表于 2021-4-16 10:49

程序员牛P

pdcba 发表于 2021-4-16 17:53

思路好棒啊
页: [1] 2 3 4 5 6
查看完整版本: 2021腾讯游戏安全技术竞赛PC客户端方向-思路分享