Uobject结构体:
在UE4中所有类都需要继承该类才能被引擎所承认是一个UE对象。
class UObject
{
void* vtf;
EObjectFlags ObjectFlags;
int32 InternalIndex;
UClass* ClassPrivate; //表明对象所属的基类
FName NamePrivate;
UObject* OuterPrivate;
}
每个对象都会存在ClassPrivate该字段。
FName结构体:
struct FName
{
int32_t ComparisonIndex;
int32_t Number;
};
以Uworld为例子手动解析:
通过下图前20个字节就能判断是否为一个对象,在CE中看到如下图中的结构体就可以判断他是一个UE4对象:
所以我们只需要判断地址+0x10是否存在值就可以知道目标是否是一个Uobject结构体,代码如下:
DWORD64 GetClassName(DWORD64 Address) {
DWORD64 UobjectClass = ReadProcessDword((PVOID)(Address + 0x10));
if (UobjectClass != NULL)
{
return UobjectClass;
}
return NULL;
}
如果Class存在那么我们就获取该Class的Fname:
FName GetFName(DWORD64 Address) {
FName Name = ReadProcessFname((PVOID)(Address + 0x18));
if (Name.ComparisonIndex)
return Name;
return FName{};
}
int FnameComparisonIndex = GetFName(Address).ComparisonIndex; //这里获取的是基类的Gname编号
获取到FName后就可以通过算法拿到GName中的名称了:
std::string GetNameOld(int i) //旧版本算法
{
DWORD64 G_Names = ReadProcessDword((PVOID)GNames);
int Id = (int)(i / (int)0x4000);
int Idtemp = (int)(i % (int)0x4000);
auto NamePtr = ReadProcessDword((PVOID)(G_Names + Id * 8));
auto Name = ReadProcessDword((PVOID)(NamePtr + 8 * Idtemp));
char name[0x100] = { 0 };
if (ReadMemory(PVOID(Name + 0xC), name, 0x100)) //0xC需要手动推算,默认是0x10
{
return name;
}
return std::string();
}
std::string GetName(DWORD64 Address) {
int FnameComparisonIndex = GetFName(Address).ComparisonIndex; //这里获取的是基类的Gname编号
std::string GetName = GetName_Old(FnameComparisonIndex); //旧算法获取Name
return GetName;
}
使用CE查看可以得到该地址为UWorld:
通过我们的程序跑UWorld,就能快速拿到Level一级GameInstance了:
遍历自身:
遍历自身的代码和遍历基类是一样的,只不过是从ClassPrivate属性改成了OuterPrivate而已
|