写在前面
1.UE4.23以下与4.23以上版本是有所区别的,笔者所使用的UE源码为4.27。
2.UE4为开源的GitHub项目,但你想下载其源码需要将epic账号与GitHub账号绑定,其次会收到一封邮件以加入GitHub组织。
https://github.com/EpicGames
一、开始之前
1.由于C++没有反射,而UE自行实现的反射导致其暴露出了非常多的接口,所以我们可以利用这些暴露出来的接口。
2.GNames是Unicode字符串的数组。
3.GObject是类指针的数组。
拥有GObjects以后,可以访问游戏中大部分对象,而GName则对应其对象的名称?
拥有这些信息以后,可以生成出一个SDK来修改游戏。
二、GNames
a.什么是Gnames
1.GNames 指的是 alignas(FNamePool) static uint8 NamePoolData[sizeof(FNamePool)];
2.也就是NamePoolData。
3.它是一个数组结构。
b.NamePoolData/FNamePool
以下是该结构体原型:
class FNamePool
{
public:
FNamePool();
void Reserve(uint32 NumBlocks, uint32 NumEntries);
FNameEntryId Store(FNameStringView View);
FNameEntryId Find(FNameStringView View) const;
FNameEntryId Find(EName Ename) const;
const EName* FindEName(FNameEntryId Id) const;
/** @pre !!Handle */
FNameEntry& Resolve(FNameEntryHandle Handle) const { return Entries.Resolve(Handle); }
bool IsValid(FNameEntryHandle Handle) const;
FNameEntryId StoreValue(const FNameComparisonValue& Value);
void StoreBatch(uint32 ShardIdx, TArrayView<FNameComparisonLoad> Batch) { ComparisonShards[ShardIdx].InsertBatch(Batch); }
#if WITH_CASE_PRESERVING_NAME
FNameEntryId StoreValue(const FNameDisplayValue& Value, bool bReuseComparisonId);
void StoreBatch(uint32 ShardIdx, TArrayView<FNameDisplayLoad> Batch) { DisplayShards[ShardIdx].InsertBatch(Batch); }
bool ReuseComparisonEntry(bool bAddedComparisonEntry, const FNameDisplayValue& DisplayValue);
#endif
/// Stats and debug related functions ///
uint32 NumEntries() const;
uint32 NumAnsiEntries() const;
uint32 NumWideEntries() const;
uint32 NumBlocks() const { return Entries.NumBlocks(); }
uint32 NumSlots() const;
void LogStats(FOutputDevice& Ar) const;
uint8** GetBlocksForDebugVisualizer() { return Entries.GetBlocksForDebugVisualizer(); }
TArray<const FNameEntry*> DebugDump() const;
private:
enum { MaxENames = 512 };
FNameEntryAllocator Entries;
#if WITH_CASE_PRESERVING_NAME
FNamePoolShard<ENameCase::CaseSensitive> DisplayShards[FNamePoolShards];
#endif
FNamePoolShard<ENameCase::IgnoreCase> ComparisonShards[FNamePoolShards];
// Put constant lookup on separate cache line to avoid it being constantly invalidated by insertion
alignas(PLATFORM_CACHE_LINE_SIZE) FNameEntryId ENameToEntry[NAME_MaxHardcodedNameIndex] = {};
uint32 LargestEnameUnstableId;
TMap<FNameEntryId, EName, TInlineSetAllocator<MaxENames>> EntryToEName;
};
c.FNameEntryAllocator
1.FNamePool结构体之中的大部分我们都可以忽略。
2.更需要重点关注其中的:FNameEntryAllocator Entries;
class FNamePool
{
private:
FNameEntryAllocator Entries;
};
需要注意 FNameEntryAllocator 并不是一个指针,而是完整的结构体。
可以将其视作为FNamePool。
FNamePool = FNameEntryAllocator。
同样的,该结构体中的大部分都可以忽略,重点关注以下内容:
static constexpr uint32 FNameMaxBlocks = 1 << FNameMaxBlockBits;
class FNameEntryAllocator
{
mutable FRWLock Lock; //0x0000
uint32 CurrentBlock = 0; //0x0008
uint32 CurrentByteCursor = 0; //0x000C
uint8* Blocks[FNameMaxBlocks] = {}; //0x0010
};
FName中存储的其实就是一堆字符串,而字符串中的内容是什么样的呢?
接下来我们开始查找它。
三、查找NamePoolData
1.想要查找NamePoolData其实非常简单,只需要打开游戏并使用CE附加游戏。
2.搜索字符串:MulticastDelegateProperty,注意不要勾选UTF-16(宽字符)。
3.搜索字符串后浏览内存相关区域,快捷键Ctrl+B,并向上翻:
看到内存区域类似.None.....ByteProperty.....IntProperty即可。
4.此时从None往前推6个字节,即:......None,并将该地址记录下来:
记录下该地址,回到CE中进行新的扫描,勾选HEX扫描8字节:
如果扫描不到可以尝试调整CE的可写选项
注意:
可尝试先前推2个字节拿到地址进行搜索,如果搜索不到再向前推更多字节。
如该游戏前推2个字节搜索不到结果,笔者这里直接将地址的最后一位用0替换(也就是前推6个字节),即可搜索到了。
不同的游戏可能不一样。
扫描出的地址:"DeadByDaylight-Win64-Shipping.exe"+D20C610
其指向的就是 FNameEntryAllocator 中的 uint8* Blocks[FNameMaxBlocks] = {};
static constexpr uint32 FNameMaxBlocks = 1 << FNameMaxBlockBits; class FNameEntryAllocator { mutable FRWLock Lock; //0x0000 uint32 CurrentBlock = 0; //0x0008 uint32 CurrentByteCursor = 0; //0x000C uint8* Blocks[FNameMaxBlocks] = {}; //0x0010 };
5.现在,只需要使用扫描出的地址减去 Blocks(uint8* Blocks[FNameMaxBlocks] = {};) 的偏移0x10,即可得出FNamePool,使用ReClass验证一下:
1.打开ReClass并打开文件选择附件里的FNamePool.reclass。
2.点击Select按钮选择游戏进程。
3.点击Edit按钮,选择FNamePool,并将地址填入进行验证。
至此,查找NamePoolData的工作就完成了,通过修改UnrealDumper 的源码即可导出Names:文章来源:https://www.toymoban.com/news/detail-762484.html
文章来源地址https://www.toymoban.com/news/detail-762484.html
到了这里,关于UE4逆向篇-1_FNamePool的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!