UE4引擎具有很多固定特征和特性
所以我们在逆向UE4引擎开发的游戏的时候,可以利用这些特征和特性.
当然,正常思路逆向也是没问题的(例如我们的ttw课程全数据逆向),你就当多了一个针对于该引擎逆向的快捷方式 或则多了一个思路即可.
正常逆向+引擎分析,使逆向结果全面且快速.
了解一下我们的学习顺序,
先熟悉UE4特性,找到UWord,GName,GetName,GObject等关键数据(入门阶段不使用IDA,但是效率更快)
然后把这些数据跟正常逆向的关系对应清晰,以提高对UE4的熟悉
再学习UE4正向开发和源码,从根本上了解该引擎
最后完整性dump游戏数据,边角数据用逆向方式补全即可
1.查看游戏的引擎版本
首先我们来查看游戏引擎版本
游戏启动程序所在目录如下:(任何UE4游戏都是类似目录)
![]()
我们可以右键属性查看游戏版本,如果长期分析经验以后,可以根据版本做出更多的判断
实际情况还是我们跟着最新版本即可,老版本等于淘汰.
下面这个4.26.2.0 已经是目前的新版本了

同时需要注意,附加进程也是
![]()
2.UWorld
首先我们先来获取一下UE4引擎中的UWorld.
UWorld其实就是世界数组基地址 .
世界数组基地址下面挂着一个包含所有对象的数组,这在我们讲FPS专题的时候已经讲解过了,忘了的同学可以翻回FPS转体复习一下.
根据ue4引擎世界对象数组的特点,我们可以采取以下方式来进行扫描,
例如 打枪数组对象数量 +1或则+2,拿出手雷 +1或者+2,也就是说出现新物品+不定数量,还有什么增加方式,大家可以找到以后多观察一下.
例如手雷增加,原本手雷不在模型上显示,打出的子弹也是有对象的,所以子弹打中某个碰撞体也会增加。
RPG也是相同,对象只会增加不会减少这是他的一个很容易被利用的特点,所以我们就利用这个道理进行扫描.
进入游戏,选择一个小地图,方便我们可以搜少点的值
搜索0-1000
像障碍物或则目标开枪 搜索增加的数值 增加可能是1可能是2
最终可以锁定地址
到OD中下断追表达式:
r14+B0

往上继续追 得到表达式 r15+B0

追到函数头部 得到表达式 [rcx+30]+B0

返回,发现 [rax+30]+B0 此时RAX 来源于一个call

这地方有三种方法
第一种直接调call 取得的返回值就是 UWORD 里的值
第二种方法直接CE搜索就可以搜索到UWORD的基地址
![]()
UWorld = deathlystillnessgame-win64-shipping.exe+460F4F0
第三种也可以继续逆向来源
call 内来源

继续进call, 由于是虚表可以进入很多位置,算法也都不同
其中有一个是我们追熟悉的位置

再进call

好像发现了什么吗?
就是天堂W里类似取对象的call,可以参考天堂W,他的过程类似于一个加密过程,忘记了 可以回去看下天堂W课程
其实这里追不到UWORD的基地址,但是我们得到的加密表达式 是可以执行UWORD里的的,一样是可以当UWORD来使用.
相比之下,低版本的UE4的UWORD就比较好找了
例如
低版本吃鸡模拟器的世界数组数量如下:
[["BattleRoyaleTrainer-Win64-Shipping.exe"+2AF0FB8] +138 ]+ b8
[["BattleRoyaleTrainer-Win64-Shipping.exe"+2AF0FB8 ] +30 ]+ b8
"BattleRoyaleTrainer-Win64-Shipping.exe"+2AF0FB8就是UWORD
经过了正常逆向,我们看看还有什么快捷方式来搜索到UWORD
就是引擎特征码了.
我们用XDBG 搜索所有模块字符串,需要等待一会,速度会比较慢,用IDA搜索这个速度更慢
xdbg搜索字符串: SeamlessTravel FlushLevelStreaming

剩余唯一一个结果
![]()
用IDA搜索这个速度慢,而且IDA搜索到的位置可能会不全,可以用xdbg搜索字符串,用IDA查看伪代码
跳转到这个地址向上翻可以得到btr edx,0x7,再向上遇到的第一个基地址,就是UWorld

UWorld = deathlystillnessgame-win64-shipping.exe+460F4F0

跟我们正常逆向的结果一样的
当然,正常逆的方式是比较通用的,特征的方式很容易在几个版本之后失效,当然失效以后,我们可以在通过正向开发的方式找到新的特征不是吗?
有了UWORD ,实际上我们就能遍历到周围环境所有对象.
3.GName
什么是GName?GName保存着UE4整个世界对象的名字
世界对象下只有Key(可以理解成名称ID),没有直接的名字的,所以想要获取名字必须要先搞定GName
说的直白点,GName是存放游戏里面所有名称字符串的基地址
分析清晰这些字符串的结构
然后通过GetName函数(也就是从Key到字符串的转换)调用取得名称字符串
名称字符串内存中的格式一般如下:
None
ByteProperty
...
...
前两个 一般是None 和ByteProperty
CE扫描ByteProperty, 以后版本不是 ByteProperty怎么办? 可以正向编译一个最新版本,看看里面任意一个相对比较特殊的字符串即可,我们不是要一个精确的位置
一个大概的位置即可

所有地址拉下来
CTRL+b 挨个查看,找到连续字符串,并且开头第一个是None,当然目前所有版本都是这样,改动我们可以人为识别

观察结构 就是 2字节+一个字符串 再2字节 再一个字符串 以此类推(后面我们会知道这个2字节就是加密长度)
那么ByteProperty字符串 - 8 的位置应该就是结构头部
CE直接搜索 2024E3C0008 - 8 = 2024E3C0000

直接得到基地址 , 再 -10就是 GName
GName =

本文介绍UE4引擎的逆向分析方法,包括游戏版本查看、UWorld获取、GName解析及GetName函数分析等内容,适用于逆向工程学习者。
5647

被折叠的 条评论
为什么被折叠?



