简介:
在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));
}
}