XiaoTouM1ng 发表于 2023-4-19 14:43

游戏安全之Unity3D-GameObjectManage

### 简介:

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

### 如何寻找GameObjectManage:

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



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




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



### GOM数据结构:

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

```
GameObjectManager{

List<ListNode<GameObject>> m_TaggedNodes;
List<ListNode<GameObject>> m_ActiveNodes;

}
```

内存中如下所示:



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

```
class BaseObject
{
public:
BaseObject* m_lastObject; //0x0000
BaseObject* m_nextObjects; //0x0008
GameObject* m_objectEntity; //0x0010
};
```

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

```
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中所有的对象



#### 代码:

```
#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));

        }
       
}
```

plzyp 发表于 2023-9-21 11:16

作为一个新手学习一下,尝试重现一下,卡到第第3步了,尝试许久还是上来问一下吧。
第一步:使用的是 just-ero/Unity-PDB-Downloader 的2.0版本
第二部:使用Unity-PDB-Downloader加载UnityPlayer.dll文件,导出pdb文件足有220MB。
第三步:在ida中导入pdb文件,可提示 PDB: total 0 symbols loaded for /Users/xxxx/Downloads/UnityPlayer_Win64_mono_x64.pdb
第四步:两眼转圈中。。。。。

实在不知道咋搞了?有没有大佬点拨一下~~

XiaoTouM1ng 发表于 2023-4-24 13:04

Hmily 发表于 2023-4-24 11:54
这游戏还提供pdb下载功能。。。

不是游戏,pdb是unity官方提供的。所有使用unity开发的游戏都能下载到unityplayer.dll的pdb

cnpsx 发表于 2023-4-19 15:02

学习学习,共同进步

qwennnnn 发表于 2023-4-19 15:28

xytf 发表于 2023-4-19 15:50

支持一下, 希望能出更多的相关教程, 好一起学习学习.

banrui5 发表于 2023-4-19 15:53

感谢您的分享

laustar 发表于 2023-4-19 17:09

用心讨论,共获提升!

mzc659068 发表于 2023-4-19 18:25

谢谢楼主分享

ZeBianSir 发表于 2023-4-19 21:26

谢谢楼主分享

lizhuowu 发表于 2023-4-19 22:00

Unity PDB Downloader.exe 什么地址有?

malone2010 发表于 2023-4-19 22:45

感谢分享,学习了
页: [1] 2 3 4
查看完整版本: 游戏安全之Unity3D-GameObjectManage