首页
社区
课程
招聘
[原创]UE4逆向笔记之GObjectArray
2023-1-11 16:01 9387

[原创]UE4逆向笔记之GObjectArray

2023-1-11 16:01
9387

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是一个二级指针:

1
FUObjectItem** Objects;

也就是说他和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;
}

遍历结果如下:

 

 

参考代码:

https://github.com/guttir14/CheatIt

https://github.com/XiaoTouMingyo/UE4ForeachClass

 

代码下载及交流群:662851495


[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

收藏
点赞3
打赏
分享
最新回复 (1)
雪    币: 463
活跃值: (1686)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
Istaroth 2023-4-23 19:21
2
0
发现返回的就是NumElements这个,所以7FF78E0D11A4该地址其实就是ObjObjects.NumElements,而上面存在5个元素,5*4=0x14,所以该地址-0x14就可以得到GObjectArray:这里应该是-0x14就可以得到ObjObjects把
游客
登录 | 注册 方可回帖
返回