基于 Unreal Engine 4 的 TslGame.exe 内存架构深度分析,包含所有核心指针、偏移量及数据结构解析
UE4 内存逆向工程现代3D游戏(尤其是基于 Unreal Engine 4 开发的作品)将所有游戏数据存储在内存中。理解这些数据的内存布局,是进行游戏修改、辅助工具开发或逆向工程的基础。本文档详细解析 TslGame.exe(PUBG)的内存架构。
| 术语 | 全称 | 说明 | 类型 |
|---|---|---|---|
| ImageBase | Image Base Address | 可执行文件加载到内存的起始地址,所有静态偏移以此为基准 | uintptr |
| Pointer/Pointer | 内存指针 | 存储另一个内存地址的变量,指针的值是另一个数据的内存位置 | uintptr |
| Offset | 偏移量 | 从基地址到目标数据的字节距离,如 Base + 0x10A5F8 | int |
| Decrypt/Xe | 解密指针 | 需要通过特殊算法解密的指针值,用于对抗游戏反作弊检测 | uintptr |
| Vec3 | 三维向量 | 包含 X, Y, Z 三个浮点数的结构,用于表示位置、方向等 | struct |
| 标记 | 含义 | 处理方式 |
|---|---|---|
| Xe Decrypt | 需要解密才能读取 | 必须先通过 XeDecryptPtr 函数解密,再读取解密后的地址 |
| NO Decrypt | 直接读取 | 指针值是明文,可以直接使用,无需额外解密步骤 |
ImageBase 是 TslGame.exe 可执行文件加载到内存中的起始地址,也称为模块基址。这是所有静态偏移量的计算起点。
操作系统将程序加载到内存时,每次启动的加载地址可能不同(ASLR 随机化)。通过使用相对偏移,我们可以计算出在任何加载地址下都能正确访问的目标地址:
例如:ImageBase + 0x10A5F8 = UWorld 指针的实际内存地址
| 指针名称 | 偏移 | 解密 | 说明 |
|---|---|---|---|
| XeDecryptPtr | XenuineDecrypt | NO | 用于解密其他 Xe 类型指针的解密函数入口点 |
| SPOOFCALL | SPOOFCALL | NO | 调用伪造函数,用于绕过反作弊系统对系统调用的检测 |
| GNames | GNames | Xe | 全局名称表,存储所有游戏对象(Actor、Class、Enum 等)的名称字符串 |
| UWorld | UWorld | Xe | 游戏世界管理器,包含当前游戏会话的所有信息 |
PUBG 使用名为 "Xenuine" 的反作弊系统,该系统对关键内存指针进行加密保护。XeDecryptPtr 是一个内置的解密函数,通过它可以将加密的指针值转换回可用的内存地址。这是对抗自动化检测的重要机制。
UWorld 是 Unreal Engine 4 的核心对象,代表一个游戏"世界"或"地图"。它包含当前游戏会话的所有信息:当前级别、所有Actors、持久数据等。从 UWorld 可以访问游戏的几乎所有重要组件。
游戏实例是从游戏启动到退出始终存在的全局对象。通过它可以访问所有本地玩家信息。
当前活动的地图/关卡,包含该地图上的所有 Actors。
GameInstance 是一个跨会话持久存在的对象,从主菜单一直存活到游戏结束。它是管理全局游戏状态和本地玩家数据的主要入口点。
在 Unreal Engine 中,Level(关卡)会在切换地图时销毁重建。但 GameInstance 不会——它从游戏启动到退出始终存在。这使其成为存储需要持久数据的理想位置,如本地玩家设置、存档信息等。
LocalPlayer 代表本地机器上的玩家数据。它包含了访问玩家控制器所需的信息,以及一些本地特定的设置(如控制方案、音频设置等)。
| 属性 | 类型 | 说明 |
|---|---|---|
| PlayerController | uintptr | 玩家控制器指针,管理输入和相机 |
| Player | uintptr | 底层 Player 对象引用 |
| PlayerState | uintptr | 玩家状态信息(分数、队伍等) |
PlayerController 是处理玩家输入和控制游戏角色的核心类。它连接玩家的输入设备(键盘、鼠标、手柄)与游戏中的 Pawn(角色实体)。
相机的专门管理者,负责管理相机的位置、旋转、FOV(视野角度)等视觉参数。
当前被服务器确认的玩家控制 Pawn(即当前操控的角色)。在死亡后切换观战时,AcknowledgedPawn 会变为观战目标。
相机管理器负责计算和存储最终的相机状态。它综合考虑多种因素(玩家输入、角色动画、瞄准状态等)来生成最终的相机参数。
| 参数 | 类型 | 说明 | 用途 |
|---|---|---|---|
| CameraCacheLocation | Vec3 | 相机的世界坐标位置 | 计算距离、射线检测 |
| CameraCacheRotation | Vec3 | 相机的旋转角度(Pitch, Yaw, Roll) | 计算方向向量 |
| CameraCacheFOV | float | 视野角度,单位:度 | FOV 调整、透视变换 |
在第三人称游戏中,相机位置通常不是角色的眼睛位置,而是经过后处理计算的位置(考虑角色模型大小、障碍物碰撞等)。理解 CameraCacheLocation 而不是直接使用 Pawn 的位置,是准确定位玩家视角的关键。
Pawn 是游戏世界中可以被控制的实体。对于玩家来说,Pawn 就是操控的角色;对于敌人来说,Pawn 是 AI 控制的 NPC 或其他玩家。Pawn 包含实体的所有物理和视觉属性。
| 组件 | 类型 | 解密 | 说明 |
|---|---|---|---|
| RootComponent | uintptr | Xe | 根组件,决定实体的世界位置和方向 |
| PlayerState | uintptr | NO | 玩家状态信息(不混淆) |
| Mesh | uintptr | NO | 骨骼网格体,用于获取骨骼位置 |
| WeaponProcessor | uintptr | uintptr | 武器处理器 |
| 属性 | 类型 | 说明 |
|---|---|---|
| LastTeamNum | int | 队伍编号,用于判断敌我 |
| GroggyHealth | float | 残血/击倒状态的生命值(倒地后显示) |
| CharacterName | wchar_t* | 角色名称字符串指针 |
| CharacterState | uint8_t | 角色状态标识 |
| SpectatedCount | int | 观战人数 |
以下是完整的生命值系统结构,但当前代码中并未启用。
| 属性 | 类型 | 说明 |
|---|---|---|
| HeaFlag | uint8 | 生命值有效标志 |
| Health1 ~ Health6 | float | 多个生命值层级(护甲、生命值分层) |
| decryptedHealthOffsets0~15 | Key | 解密后的生命值偏移量 |
SkeletalMesh(骨骼网格体)是具有骨骼动画的 3D 模型。每个角色、武器、载具都有对应的 SkeletalMesh。它不仅用于渲染,还提供了访问骨骼位置的能力。
| 属性 | 类型 | 说明 |
|---|---|---|
| ComponentToWorld | FTransform | 组件到世界的变换矩阵,包含位置、旋转、缩放 |
| StaticMesh | uintptr | 静态网格体引用 |
| BoneArray | uintptr | 骨骼数组指针,存储所有骨骼的变换信息 |
| BoneCount | int | 骨骼总数 |
| BoundBox | struct | 边界盒,用于碰撞检测和可见性判断 |
| Eyes | float | 眼睛高度偏移,用于计算头部位置 |
| 属性 | 类型 | 说明 |
|---|---|---|
| LastSubmitTime | float | 上次提交到 GPU 的时间戳 |
| LastRenderTimeOnScreen | float | 上次在屏幕上渲染的时间,用于判断可见性 |
| bAlwaysCreatePhysicsState | BYTE | 是否始终创建物理状态 |
骨骼数组存储了模型所有骨骼的世界坐标变换。通过指定骨骼索引,可以获取特定骨骼的位置:
注意:不同模型的骨骼索引可能不同,通常需要通过名称查找特定骨骼。
动画脚本实例是运行中的动画系统的数据容器。它存储了角色的当前动画状态、动作轨迹、旋转信息等。对于读取后坐力控制、左右倾斜等数据至关重要。
| 属性 | 类型 | 说明 |
|---|---|---|
| ControlRotation_CP | Vec3 | 控制旋转(Control Rotation),即玩家期望的视角旋转。这不受动画影响,是纯输入值。 |
| RecoilADSRotation_CP | Vec3 | ADS(瞄准)状态下的后坐力旋转。包含武器后坐力带来的额外旋转。 |
| LeanLeftAlpha_CP | float | 向左倾斜的程度(0.0 ~ 1.0)。用于检测玩家是否在向左歪头。 |
| LeanRightAlpha_CP | float | 向右倾斜的程度(0.0 ~ 1.0)。用于检测玩家是否在向右歪头。 |
_CP 后缀表示这些值是通过 "Copy Pose"(复制姿态)机制获取的。Unreal Engine 的动画系统会复制角色的姿态数据到这些成员变量中,以便外部系统(如 AI、网络同步)访问。
武器处理器是管理角色当前装备和使用的武器的核心组件。它追踪当前武器索引、武器库、以及弹道数据。
装备武器数组,存储角色当前携带的所有武器。
| 槽位 | 偏移 | 说明 |
|---|---|---|
| WeaponSlot[0] | +0x0 | 主武器槽1 |
| WeaponSlot[1] | +0x8 | 主武器槽2 / 副武器槽 |
| WeaponSlot[2] | +0x10 | 近战/投掷物槽 |
uint8_t
当前使用的武器索引。通过这个值可以确定玩家当前手持的是什么武器。
弹道数据包含子弹的物理飞行参数,用于计算弹道轨迹和击中点。
| 属性 | 类型 | 说明 |
|---|---|---|
| TrajectoryConfig | struct | 弹道配置结构体 |
| InitialSpeed | float | 子弹初速度(单位:单位/秒)。不同武器有不同的初速度。 |
要获取武器名称,需要:
载具骑乘组件附加在角色身上,当角色进入载具时激活。它追踪角色与载具的交互状态,包括坐在哪个座位、当前驾驶的载具等。
| 属性 | 类型 | 说明 |
|---|---|---|
| SeatIndex | int | 当前座位索引。0=驾驶位,1=副驾,2+=后排座位 |
| LastVehiclePawn | uintptr | 上次/当前乘坐的载具 Pawn 指针 |
| VehicleMovement | uintptr | 载具移动组件,控制载具的物理运动 |
载具 Pawn 是载具本身的数据容器,包含载具的位置、油量、耐久度等信息。
| 属性 | 类型 | 说明 |
|---|---|---|
| ReplicatedMovement | Vec3 | 复制的移动数据(位置)。用于网络同步载具位置。 |
当玩家进入载具时:Player.Pawn → VehicleRiderComponent → LastVehiclePawn → VehiclePawn.RootComponent → ComponentLocation 可以获取载具的世界坐标。
GameState 是服务器权威的游戏状态管理器,在多人游戏中由服务器维护。它包含游戏会话的全局信息,对所有玩家可见。
| 属性 | 类型 | 说明 |
|---|---|---|
| PlayerArray | TArray | 所有玩家的 PlayerState 数组,用于获取所有玩家的信息 |
| GameModeClass | uintptr | 游戏模式类定义 |
| MatchState | FName | 比赛状态(热身、游戏中、结算等) |
| ElapsedTime | float | 比赛已进行时间(秒) |
GameState 由服务器更新后同步到所有客户端。在客户端读取 GameState 时,可能会有一小段时间的延迟(网络延迟 + 快照间隔)。理解这一点对于设计实时性要求高的功能很重要。
Actors 是场景中所有实体的动态数组,包含玩家、Bot、AI、物品、载具、投掷物等一切游戏对象。通过遍历这个数组,可以访问场景中的任何实体。
| 属性 | 偏移 | 类型 | 说明 |
|---|---|---|---|
| Actors_Array | +0x0 | DWORD_PTR | 实体指针数组的数据指针 |
| Actors_Count | +0x8 | int | 数组中实体的数量(通常最多 2000 个) |
每个 Actor 实体都包含以下关键信息:
| 属性 | 类型 | 说明 |
|---|---|---|
| ObjID | CIndex | 对象的唯一标识符,用于在 GNames 中查询对象名称 |
| PlayerState | uintptr | 玩家状态(仅玩家/Bot 有值) |
| LastTeamNum | int | 队伍编号 |
| GroggyHealth | float | 残血值 |
| CharacterState | uint8 | 角色状态 |
| RootComponent | uintptr | 根组件(Xe 解密) |
| Mesh | uintptr | 骨骼网格体(不混淆) |
| WeaponProcessor | uintptr | 武器系统 |
GNames 是全局名称表,存储了所有游戏对象的字符串名称。通过 ObjID 可以在 GNames 中查找任意对象的名称。
例如:ObjID=12345 → GNames[12345] = "BP_PlayerMale_A_C"
用于表示 3D 空间中的点或方向,包含 X, Y, Z 三个浮点数。
struct Vec3 { float X; // 左右 (右为正) float Y; // 前后 (前为正) float Z; // 上下 (上为正) }
表示 3D 空间中的旋转,使用欧拉角。
struct Rotator { float Pitch; // 俯仰 (-90° ~ +90°) float Yaw; // 偏航 (0° ~ 360°) float Roll; // 翻滚 (-90° ~ +90°) }
包含位置、旋转、缩放的完整变换信息。
struct FTransform { Rotator Rotation; // 旋转 Vec3 Translation; // 位置 Vec3 Scale3D; // 缩放 }
Unreal Engine 的动态数组类型。
struct TArray<T> { uintptr Data; // 数据指针 int Count; // 元素数量 int Max; // 分配的数组大小 }
橙色节点 = 需要 XeDecrypt 解密 绿色节点 = 直接读取