ue4游戏逆向之GName内存解析(4.23版本以下)
ue4游戏中的所有对象名称都保存在GName中,4.23版本以下的GName解析与高版本的不同。
解析GName#
4.23版本以下可以通过FName::GNames()
获取到GName
指针,对应的GName指针就是static TNameEntryArray* Names
,利用ue4Dumper
时输入的GName
就是这个静态指针变量。
TNameEntryArray
类型是通过类模板TStaticIndirectArrayThreadSafeRead
定义的,实际TNameEntryArray
就相当于一个[2 * 1024 * 1024]
大小的数组,数组的每一个元素又指向一个新的数组FNameEntry* [0x4000]
对TNameEntryArray
类型进行简化后如下图所示。
其中类模板TStaticIndirectArrayThreadSafeRead
中定义了重载运算符[]
完成元素的索引
那么名称的索引保存在何处呢,看一下FName::GetComparisonNameEntry()
函数,其通过调用GetComparisonIndex()
函数获取FName
的成员变量ComparisonIndex
,这个就是名称的索引。
遍历所有的Actor名称#
UE4游戏逆向时可以通过GWorld->GameInstance->LocalPlayer->PlayerController->AcknowledgedPawn
获取控制角色的Actor
,也可以通过GWorld->Level->Actors
获取Actor数组,然后再通过Actor的名称过滤出控制角色和敌人。
32位ue4而言Level
的偏移为GWorld + 0x20
Actors
的偏移为Level + 0x70
AActor的基类为UObject类,继承关系为AActor->UObject->UObjectBaseUtility->UObjectBase
,对应的FName
就是UObjectBase
类的NamePrivate
,对应的偏移为Actor + 0x10
,而且FName
类的第一个成员就是ComparisonIndex
名称索引,所以名称索引的偏移也是Actor + 0x10
frida脚本遍历ue4的actors
数组并获取对应的名称。
function hook_ue4(){
var libUE4_module = Module.findBaseAddress("libUE4.so")
console.log("libUE4_module is :", libUE4_module)
var GWorld_Offset = 0x4924570
var GName_Offset = 0x4877034
var GWorld = libUE4_module.add(GWorld_Offset).readPointer()
var Level_Offset = 0x20
var Level = GWorld.add(Level_Offset).readPointer()
console.log("Level :", Level)
var Actors_Offset = 0x70
var Actors = Level.add(Actors_Offset).readPointer()
console.log("Actors Array :", Actors)
var Actors_Num = Level.add(Actors_Offset).add(4).readU32()
console.log("Actors_num :", Actors_Num)
var Actors_Max = Level.add(Actors_Offset).add(8).readU32()
console.log("Actors_Max :", Actors_Max)
for(var index = 0; index < Actors_Num; index++){
var actor = Actors.add(index * 4).readPointer()
//console.log("actor", actor)
//通过角色actor获取其成员变量FName
var FName_Offset = 0x10
var FName = actor.add(FName_Offset);
//console.log("FName", FName)
//解析TNameEntryArray
var ComparisonIndex = FName.add(0).readU32()
var ChunkIndex = parseInt(ComparisonIndex / 0x4000)
var WithinChunkIndex = ComparisonIndex % 0x4000
var TNameEntryArray = libUE4_module.add(GName_Offset).readPointer()
var Chunks = TNameEntryArray
var FNameEntry = Chunks.add(ChunkIndex * 4).readPointer().add(WithinChunkIndex * 4).readPointer();
console.log("actor : ", actor, " ", FNameEntry.add(8).readCString() )
}
}
最后的结果如下,可以获取到控制角色actor的名称为FirstPersonCharacter_C
。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】