首页
社区
课程
招聘
[原创]游戏安全之Unity3DGameObjectManage
发表于: 2023-4-19 14:47 8559

[原创]游戏安全之Unity3DGameObjectManage

2023-4-19 14:47
8559

简介:

在Unity3D游戏中,最基本的就是寻找Unity3D中的GameObjectManage

如何寻找GameObjectManage:

在Unity游戏中通常存在UnityPlayer.dll文件,我们在运行游戏后在运行Unity PDB Downloader.exe来获取游戏符号文件

 

 

在获取到文件后导入刀ida pro中直接搜索GetGameObject就能找到函数了:

 

 

找到该函数后,通过x64dbg跳转过去拿到基础地址:

 

GOM数据结构:

通过ida pro能查看到GOM的数据结构为:

1
2
3
4
5
6
GameObjectManager{
 
List<ListNode<GameObject>> m_TaggedNodes;
List<ListNode<GameObject>> m_ActiveNodes;
 
}

内存中如下所示:

 

 

很明显的双链表结构,其中每个元素都是GameObject

1
2
3
4
5
6
7
class BaseObject
{
public:
BaseObject* m_lastObject; //0x0000
BaseObject* m_nextObjects; //0x0008
GameObject* m_objectEntity; //0x0010
};

从0x10的位置才是该对象的Entry,GameObject在ida中如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
00000000 GameObject struc ; (sizeof=0x88, align=0x8, copyof_11640)
00000000                                         ; XREF: ?BuildGenericAvatar@AvatarBuilderBindings@@YA?AVScriptingObjectPtr@@PEAVGameObject@@AEBV?$basic_string@DV?$StringStorageDefault@D@core@@@core@@@Z/r
00000000 baseclass_0 EditorExtension ?           ; XREF: AvatarBuilderBindings::BuildGenericAvatar(GameObject *,core::basic_string<char,core::StringStorageDefault<char>> const &)+87/w
00000000                                         ; AvatarBuilderBindings::BuildGenericAvatar(GameObject *,core::basic_string<char,core::StringStorageDefault<char>> const &)+8C/w ...
00000030 m_Component dynamic_array<GameObject::ComponentPair,0> ?
00000030                                         ; XREF: AvatarBuilderBindings::BuildGenericAvatar(GameObject *,core::basic_string<char,core::StringStorageDefault<char>> const &)+A3/w
00000030                                         ; AvatarBuilderBindings::BuildGenericAvatar(GameObject *,core::basic_string<char,core::StringStorageDefault<char>> const &)+AB/w ...
00000050 m_CullSceneMask dq ?                    ; XREF: AvatarBuilderBindings::BuildGenericAvatar(GameObject *,core::basic_string<char,core::StringStorageDefault<char>> const &):HumanDescription__Reset_0/o
00000050                                         ; AvatarBuilderBindings::BuildGenericAvatar(GameObject *,core::basic_string<char,core::StringStorageDefault<char>> const &)+B6/w ...
00000058 m_Layer dd ?                            ; XREF: AvatarBuilderBindings::BuildGenericAvatar(GameObject *,core::basic_string<char,core::StringStorageDefault<char>> const &)+BE/w
00000058                                         ; AvatarBuilderBindings::BuildGenericAvatar(GameObject *,core::basic_string<char,core::StringStorageDefault<char>> const &)+128/r ...
0000005C m_Tag dw ?
0000005E m_IsActive db ?
0000005F m_IsActiveCached db ?
00000060 m_ActivationState dd ?                  ; enum GameObject::ActivationState
00000064 m_SupportedMessages dd ?
00000068 m_Name ConstantString ?                 ; XREF: AvatarBuilderBindings::BuildGenericAvatar(GameObject *,core::basic_string<char,core::StringStorageDefault<char>> const &)+BA/w
00000068                                         ; AvatarBuilderBindings::BuildGenericAvatar(GameObject *,core::basic_string<char,core::StringStorageDefault<char>> const &)+13A/w
00000070 m_ActiveGONode ListNode<GameObject> ?   ; XREF: AvatarBuilderBindings::BuildGenericAvatar(GameObject *,core::basic_string<char,core::StringStorageDefault<char>> const &):core__basic_string_char_core__StringStorageDefault_char______ctor__1380/w
00000070                                         ; AvatarBuilderBindings::BuildGenericAvatar(GameObject *,core::basic_string<char,core::StringStorageDefault<char>> const &)+F5/w ...
00000088 GameObject ends

+0x68为对象的名称:

 

遍历:

通过上面的知识,我们很容易就能遍历出unity中所有的对象

 

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <windows.h>
#include <iostream>
 
using namespace std;
 
HANDLE pHandle = 0;
 
bool ReadMemory(PVOID address, PVOID buffer, size_t size)
{
    SIZE_T ret_size;
    return ReadProcessMemory(pHandle, address, buffer, size, &ret_size);
}
 
ULONG64 ReadMemoryULong64(PVOID address)
{
    ULONG64 returnUlong = 0;
    SIZE_T ret_size;
    ReadProcessMemory(pHandle, address, &returnUlong, sizeof(ULONG64), &ret_size);
    return returnUlong;
}
 
void main() {
 
    pHandle = OpenProcess(PROCESS_ALL_ACCESS,FALSE,0x244c);
 
    ULONG64 GameObjectManageBase = 0x7FF89C2D44E8;
    ULONG64 GameObjectManageValue = ReadMemoryULong64((PVOID)GameObjectManageBase);
    ULONG64 NextObject,GameEntry,NameAddress = 0;
    NextObject = ReadMemoryULong64((PVOID)(GameObjectManageValue + 0x8));
    char* NameBuffer = (char*)malloc(40);
    memset(NameBuffer,0,40);
    while (true)
    {
        if (NextObject == GameObjectManageValue)
        {
            break;
        }
        GameEntry = ReadMemoryULong64((PVOID)(NextObject + 0x10));
        NameAddress = ReadMemoryULong64((PVOID)(GameEntry + 0x68));
        ReadMemory((PVOID)NameAddress, NameBuffer, 40);
        cout << "[+] Address: " << hex << GameEntry << " Name: " << NameBuffer << endl;
        memset(NameBuffer, 0, 40);
 
        NextObject = ReadMemoryULong64((PVOID)(NextObject + 0x8));
 
    }
 
}

交流群:

662851495


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 79
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
群主我申请进群,希望通过
2024-4-21 19:31
0
游客
登录 | 注册 方可回帖
返回
//