-
-
[原创]UE4逆向笔记之GObjectArray
-
发表于:
2023-1-11 16:01
12397
-
GObjectArray逆向:
首先查看源代码:

此处上面存在字符串特征:
1 | Cannot Cancel Async Loading while async loading is suspended.
|
直接搜索该字符串就可以定位到GUObjectArray.GetObjectArrayNum():

然后查看GetObjectArrayNum的源代码:
1 2 3 4 | FORCEINLINE int32 GetObjectArrayNum() const
{
return ObjObjects.Num();
}
|
跟进ObjObjects发现定义如下:
1 | TUObjectArray ObjObjects;
|
继续跟进:
1 | typedef FChunkedFixedUObjectArray TUObjectArray;
|
得到如下类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class FChunkedFixedUObjectArray
{
enum
{
NumElementsPerChunk = 64 * 1024,
};
/** Master table to chunks of pointers **/
FUObjectItem** Objects;
/** If requested, a contiguous memory where all objects are allocated **/
FUObjectItem* PreAllocatedObjects;
/** Maximum number of elements **/
int32 MaxElements;
/** Number of elements we currently have **/
int32 NumElements;
/** Maximum number of chunks **/
int32 MaxChunks;
/** Number of chunks we currently have **/
int32 NumChunks;
|
找到方法的定义如下:
1 2 3 4 | FORCEINLINE int32 Num() const
{
return NumElements;
}
|
发现返回的就是NumElements这个,所以7FF78E0D11A4该地址其实就是ObjObjects.NumElements,而上面存在5个元素,5*4=0x14,所以该地址-0x14就可以得到GObjectArray:

此时的第一个元素为:
1 2 3 4 5 6 7 8 9 10 11 | class FUObjectItem
{
// Pointer to the allocated object
class UObjectBase* Object;
// Internal flags
int32 Flags;
// UObject Owner Cluster Index
int32 ClusterRootIndex;
// Weak Object Pointer Serial number associated with the object
int32 SerialNumber;
}
|

继续查看第一个元素就是UObject:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | class UObject
{
/** virtual function table */
void* vtf;
/** Flags used to track and report various object states. This needs to be 8 byte
aligned on 32-bit
platforms to reduce memory waste */
EObjectFlags ObjectFlags;
/** Index into GObjectArray...very private. */
int32 InternalIndex; //表明该对象在
GObjectArray中的第几个
/** Class the object belongs to. */
UClass* ClassPrivate;
/** Name of this object */
FName NamePrivate;
/** Object this object resides in. */
UObject* OuterPrivate;
}
|

通过UObject就可以遍历出UE4引擎的所有对象了
使用代码遍历:
通过观察代码我们知道Objct是一个二级指针:
也就是说他和Gname一样是以表的形式存在的,所以我们想要遍历他就需要知道当前需要遍历的对象在哪张表中,算法如下:
1 2 3 4 5 6 7 8 9 10 11 12 | UObject* UobjectArray::GetObjectPtr(int id) {
if (id >= NumElements) return 0;
DWORD64 chunkIndex = id / 65536; //chunkIndex = 0
if (chunkIndex >= NumChunks) return 0;
auto chunk = Process::ReadProcess<void*>(Objects+(chunkIndex * 8));//
if (!chunk) return 0;
DWORD withinChunkIndex = id % 65536 * 32; //这里的32是根据游戏实际结构体大小决定了,默认情况下为32
auto item = Process::ReadProcess<PVOID>((PVOID)((DWORD64)chunk + withinChunkIndex));
return (DWORD64)item;
}
|
官方给出的SDK代码中就有,可以复制过来直接用:

遍历代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 | GobjectArray = Process::ReadProcess<UobjectArray>((PVOID)((DWORD64)Process::GetProcessMoudleBase() + 0x8031190));
//int NumElements = Process::ReadProcess<int>((PVOID)(GobjectArray + 0x14));
cout << "NumElements: " << hex << GobjectArray.NumElements << endl;
for (int i = 0; i < GobjectArray.NumElements; i++) {
cout <<"ID:" << i << " Uobject Address: " << GobjectArray.GetObjectPtr(i) << endl;
}
|
测试结果:

当能够遍历出Object后还需要使用到Gname遍历Object的名称,具体可以查看我之前的文章,部分代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | string GetObjectName(DWORD64 Address) {
string Name;
DWORD64 UobjectOuter = Process::ReadProcess<DWORD64>((PVOID)(Address + 0x20)); //获取UObject->OuterPrivate
if (UobjectOuter != 0)
{
for (DWORD64 Outer = UobjectOuter; Outer; Outer = Process::ReadProcess<DWORD64>((PVOID)(Outer + 0x20)))
{
Name = GetName_New(GetFName(Outer).ComparisonIndex) + "." + Name;
}
Name = GetKlassName(Address) + " " + Name + GetName_New(GetFName(Address).ComparisonIndex);
return Name;
}
Name = GetKlassName(Address) + " " + GetName_New(GetFName(Address).ComparisonIndex);
return Name;
}
|
遍历结果如下:


参考代码:
debK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6Y4N6i4c8@1K9i4t1I4y4q4)9J5c8V1y4Z5k6h3q4@1d9i4b7`.
ae8K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6j5K9h3q4G2g2r3!0#2e0h3W2F1k6%4W2G2i4K6u0r3g2f1f1@1c8X3!0J5k6h3q4U0K9p5y4D9j5i4y4K6
代码下载及交流群:662851495
[培训]传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!