UE3如何找到所需的偏移量
在本教程中,我将向您展示如何在 UObject 中查找 GNames
、全局对象表
和 ProcessEvent 索引
。一切都是用 IDA 完成的,我将以虚幻竞技场 3 为例。
首先,我将向您介绍如何查找GNames
。您可以通过搜索其中一个硬编码名称来执行此作。通过搜索 ByteProperty
您将来到这里:
Code:
.text:00B7ECD7 push offset aNone_19 ; "None"
.text:00B7ECDC mov dword_1DAA1B8, ebx
.text:00B7ECE2 mov dword_1DD26E8, eax <--- 全局名称表
.text:00B7ECE7 mov dword_1DD26EC, eax
.text:00B7ECEC mov dword_1DD26F0, eax
.text:00B7ECF1 rep stosd
.text:00B7ECF3 call sub_B7E030
.text:00B7ECF8 push eax
.text:00B7ECF9 call sub_B7EB50
.text:00B7ECFE push 0 ; int
.text:00B7ED00 push 0 ; int
.text:00B7ED02 push 0 ; int
.text:00B7ED04 push ebx ; int
.text:00B7ED05 push offset aByteproperty ; "ByteProperty"
Code:
#define GLOBALNAME_OFFSET 0x1DD26E8
我有GObject的方法,有时第一个方法是不可能的,然后我使用第二个方法。我将从第一个方法开始。
第一个方法是搜索 Dependencies of %s:
:
Code:
.text:00B930D8 push offset aDependenciesOf ; "Dependencies of %s:"
.text:00B930DD push eax
.text:00B930DE call sub_B54240
.text:00B930E3 add esp, 0Ch
.text:00B930E6 lea ecx, [esp+0D84h+var_CB8]
.text:00B930ED mov byte ptr [esp+0D84h+var_4], 17h
.text:00B930F5 call sub_404A00
.text:00B930FA mov edx, [esp+0D84h+var_D48]
.text:00B930FE lea ecx, [esp+0D84h+var_D20]
.text:00B93102 push ecx
.text:00B93103 push offset aRecurse ; "RECURSE"
.text:00B93108 push edx
.text:00B93109 mov [esp+0D90h+var_D20], edi
.text:00B9310D call sub_B527B0
.text:00B93112 add esp, 0Ch
.text:00B93115 push edi
.text:00B93116 mov [esp+0D88h+var_CAC], eax
.text:00B9311D call sub_40A480
.text:00B93122 push eax
.text:00B93123 lea ecx, [esp+0D8Ch+var_D04]
.text:00B9312A call sub_40CB00
.text:00B9312F mov esi, [esp+0D84h+var_D00]
.text:00B93136 cmp esi, dword_1DE3FA8
.text:00B9313C jge loc_B931FC
.text:00B93142
.text:00B93142 loc_B93142: ; CODE XREF: sub_B91D20+14D6_j
.text:00B93142 mov edi, dword_1DE3FA4 <--- Global Object Table
.text:00B93148 mov eax, [esp+0D84h+var_D40]
.text:00B9314C mov ebx, [edi+esi*4]
第二个方法是搜索 bSerializeStartupPackagesFromMemory
:
Code:
.text:00406DFE mov eax, [eax+4]
.text:00406E01 push offset aBserializestar ; "bSerializeStartupPackagesFromMemory"
.text:00406E06 push offset aEngine_start_0 ; "Engine.StartupPackages"
.text:00406E0B call eax
.text:00406E0D mov [ebp+var_20], ebx
.text:00406E10 mov [ebp+var_1C], ebx
.text:00406E13 mov [ebp+var_18], ebx
.text:00406E16 xor ecx, ecx
.text:00406E18 cmp dword_1DBBD58, ebx
.text:00406E1E lea edx, [ebp+var_20]
.text:00406E21 setz cl
.text:00406E24 mov [ebp+var_4], ebx
.text:00406E27 push ecx
.text:00406E28 push edx
.text:00406E29 call sub_405B30
.text:00406E2E xor eax, eax
.text:00406E30 cmp dword_1DBBD58, ebx
.text:00406E36 lea ecx, [ebp+var_20]
.text:00406E39 setz al
.text:00406E3C push eax
.text:00406E3D push ecx
.text:00406E3E call sub_405990
.text:00406E43 add esp, 10h
.text:00406E46 cmp dword_1DBBD58, ebx
.text:00406E4C jz loc_406F9D
.text:00406E52 cmp [ebp+var_1C], ebx
.text:00406E55 mov [ebp+var_10], ebx
.text:00406E58 jle loc_406F9D
然后你必须向下滚动,直到你看到字符串Core
:
Code:
.text:004070BA loc_4070BA: ; CODE XREF: sub_406DC0+2F3j
.text:004070BA cmp dword_1DCE27C, ebx
.text:004070C0 jnz short loc_4070D9
.text:004070C2 push offset aCore_0 ; "Core"
.text:004070C7 call sub_B719D0
.text:004070CC add esp, 4
.text:004070CF mov dword_1DCE27C, eax
.text:004070D4 call sub_B6FE30
.text:004070D9
.text:004070D9 loc_4070D9: ; CODE XREF: sub_406DC0+300j
.text:004070D9 mov edx, dword_1DCE27C
.text:004070DF push 1 ; int
.text:004070E1 push edi ; Src
.text:004070E2 push ebx ; int
.text:004070E3 push edx ; int
.text:004070E4 call sub_B86A50
.text:004070E9 push eax
.text:004070EA call sub_B89690
.text:004070EF mov eax, [ebp+var_10]
.text:004070F2 add eax, 1
.text:004070F5 add esp, 14h
.text:004070F8 add esi, 0Ch
.text:004070FB cmp eax, [ebp+var_1C]
.text:004070FE mov [ebp+var_10], eax
.text:00407101 jl short loc_4070A7
.text:00407103 jmp short loc_40714A
.text:00407105 ; ---------------------------------------------------------------------------
.text:00407105
.text:00407105 loc_407105: ; CODE XREF: sub_406DC0+2CFj
.text:00407105 ; sub_406DC0+2D7j
.text:00407105 push ebx
.text:00407106 lea ecx, [ebp+var_54]
.text:00407109 call sub_40D280
.text:0040710E mov eax, [ebp+Str1]
.text:00407111 cmp eax, dword_1DE3FA8
.text:00407117 jge short loc_40714A
.text:00407119 lea esp, [esp+0]
.text:00407120
.text:00407120 loc_407120: ; CODE XREF: sub_406DC0+388j
.text:00407120 mov ecx, dword_1DE3FA4 <--- Global Object Table
.text:00407126 mov ecx, [ecx+eax*4]
.text:00407129 call sub_B88AD0
.text:0040712E push eax
.text:0040712F call sub_B89690
.text:00407134 add esp, 4
.text:00407137 lea ecx, [ebp+var_54]
.text:0040713A call sub_40B8E0
.text:0040713F mov eax, [ebp+Str1]
.text:00407142 cmp eax, dword_1DE3FA8
.text:00407148 jl short loc_407120
Code:
#define GLOBALOBJECTS_OFFSET 0x1DE3FA4
我将展示的最后一件事是如何查找 ProcessEvent 的索引
。我所做的是搜索字符串 __%s__Delegate
:
Code:
.text:00D98F29 loc_D98F29: ; CODE XREF: sub_D98E20+102_j
.text:00D98F29 push eax
.text:00D98F2A lea edx, [esp+44h+var_24]
.text:00D98F2E push offset a__S__delegat_3 ; "__%s__Delegate"
.text:00D98F33 push edx
.text:00D98F34 call sub_4189F0
.text:00D98F39 add esp, 0Ch
.text:00D98F3C cmp dword ptr [eax+4], 0
.text:00D98F40 mov byte ptr [esp+40h+var_4], 2
.text:00D98F45 jz short loc_D98F4B
.text:00D98F47 mov ecx, [eax]
.text:00D98F49 jmp short loc_D98F50
.text:00D98F4B ; ---------------------------------------------------------------------------
.text:00D98F4B
.text:00D98F4B loc_D98F4B: ; CODE XREF: sub_D98E20+125_j
.text:00D98F4B mov ecx, offset Str1
.text:00D98F50
.text:00D98F50 loc_D98F50: ; CODE XREF: sub_D98E20+129_j
.text:00D98F50 mov eax, [edi+34h]
.text:00D98F53 push ecx
.text:00D98F54 push eax
.text:00D98F55 call sub_59B530
.text:00D98F5A add esp, 8
.text:00D98F5D lea ecx, [esp+40h+var_24]
.text:00D98F61 mov ebp, eax
.text:00D98F63 mov byte ptr [esp+40h+var_4], 1
.text:00D98F68 call sub_404A00
.text:00D98F6D lea ecx, [esp+40h+var_18]
.text:00D98F71 mov [esp+40h+var_4], 0FFFFFFFFh
.text:00D98F79 call sub_404A00
.text:00D98F7E mov ecx, [ebp+64h]
.text:00D98F81 mov edx, [esi+4]
.text:00D98F84 mov eax, [edi]
.text:00D98F86 push 0
.text:00D98F88 push 0
.text:00D98F8A add ecx, edi
.text:00D98F8C push ecx
.text:00D98F8D mov ecx, [esi]
.text:00D98F8F push edx
.text:00D98F90 mov edx, [eax+0F0h]
.text:00D98F96 push ecx
.text:00D98F97 mov ecx, edi
.text:00D98F99 call edx
.text:00D98F9B mov ecx, [esp+40h+var_C]
.text:00D98F9F mov large fs:0, ecx
.text:00D98FA6 pop ecx
.text:00D98FA7 pop edi
.text:00D98FA8 pop esi
.text:00D98FA9 pop ebp
.text:00D98FAA add esp, 30h
.text:00D98FAD retn 4
.text:00D98FB0 ; ---------------------------------------------------------------------------
.text:00D98FB0
.text:00D98FB0 loc_D98FB0: ; CODE XREF: sub_D98E20+DF_j
.text:00D98FB0 mov edx, [edi]
.text:00D98FB2 push 0
.text:00D98FB4 push 0
.text:00D98FB6 push eax
.text:00D98FB7 mov eax, [edx+0ECh] <--- ProcessEvent Index
Code:
#define PROCESSEVENT_INDEX 0xEC
/ 4\
对于无法找到 ProcessEvent
偏移量的人来说,有一点额外的信息:
下面的签名在大多数游戏中都有效。那些它不起作用的,只有某个部分是无效的。因此,使用它的不同变体(如前半部分,如果不起作用,则使用后半部分),你将能够毫无问题地找到 ProcessEvent
:
code:
74 ? 83 C0 07 83 E0 F8 E8 ? ? ? ? 8B C4
另外说明:
如果您出于某种原因想要找到任何具有iNative
的 UFunction 的本机等效项,您可以使用以下签名(稍作修改):
code:
68 ? ? ? ? 68 [iNative as little edian (4 bytes)]
E8 ? ? ? ? 83 C4 08
示例:对于 America’s Army 3.X,“Function Engine.Actor.FastTrace”的 iNative 为 0x224,因此:
code:
68 ? ? ? ? 68 24 02 00 00 E8 ? ? ? ? 83 C4 08
这将带您进入 GRegisterNatives
调用,只需按照传递给 GRegisterNative
的第一个参数(指针)指向exec
函数。在本例中为 execFastTrace
。在这里,您可以看到游戏如何处理本机代码,并了解如何避免使用游戏的函数来完成所有作。
查找 GNames
和 GObjects
的另一种方法:
这些是我的一些旧笔记,老实说,我不记得它们的日期了。所以有些模式可能不适用于最新的游戏,但对于刚开始使用虚幻引擎的人来说,它们是一个很好的开始。
code:
// GObjects
// 1) 8B ? ? ? ? ? ? ? ? 6A 01 8B ? E8
// 2) 8B 41 04 8B ? ? ? ? ? 8B 04 81 C3
// GObject 和 GNames
// 4) A1 ? ? ? ? 8B 04 88
// GNames
// 1) 3B 05 ? ? ? ? 7D ? 8B ? ? ? ? ? ? ? ? 74
// 2) 3B 05 ? ? ? ? ? ? 8B 0D ? ? ? ? 83 ? ? ? ? ? B8 01 00 00 00
编辑:呵呵,我刚刚也找到了这些笔记,日期为 2009 年 11 月,我相信从这些笔记中我设计了上述代码块中的概念:
主要概念
GObjects
A1 ? ? ? ? 8B 04 ? 8B ? ? 25 00 02 00 00
\xA1\x00\x00\x00\x00\x8B\x04\x00\x8B\x00\x00\x25\x00\x02\x00\x00
x????xxxxxxxxxxx
+ 0x1
Games Supported
UT3
Parabellum
Gears of War
America's Army
8B ? ? ? ? ? 8B 04 ? 8B ? ? 25 00 02 00 00
\x8B\x00\x00\x00\x00\x00\x8B\x04\x00\x8B\x00\x00\x25\x00\x02\x00\x00
x?????xx?x??xxxxx
+ 0x2
AvA
AA3
GOW
UT3
Parabellum
GNames
A1 ? ? ? ? 8B 04 ? 8B ? ? 81 E1 00 10 00 00
\xA1\x00\x00\x00\x00\x8B\x04\x00\x8B\x00\x00\x81\xE1\x00\x01\x00\x00
x????xxxxxxxxxxxx
+ 0x1
Games Supported
UT3
Parabellum
Gears of War
Alliance of Valiant Arms
ProcessEvent 签名在地址 + 0x25F 中找到
搜索每个 VTable 的大小以获取 0x500 的模式
74 ? 83 C0 07
应添加:
83 E0 F8 E8 ? ? ? ? 8B C4
x?xxxxxxx????xx
8B 0D ? ? ? ? 8B 04 ? 8B ? ? 81 E1 00 10 00 00
8B ? ? ? ? ? ? ? ? 6A 01 8B ? E8 ? ? ? ? 56 E8 ? ? ? ? 8D
\x8B\x00\x00\x00\x00\x00\x00\x00\x00\x6A\x01\x8B\x00\xE8\x00\x00\x00\x00\x56\xE8\x00\x00\x00\x00\x8D
x????????xxx?x????xx????x
为 AvA 工作
次要概念
GObjects
8B ? ? ? ? ? ? ? ? 6A 01 8B ? E8 ? ? ? ? 8B ? E8
x????????xxx?x????x?x
+ 0x2
适用于 2 款游戏
GNames
3B 05 ? ? ? ? ? ? 8B 0D ? ? ? ? 83 ? ? ? ? ? B8 01 00 00 00
\x3B\x05\x00\x00\x00\x00\x00\x00\x8B\x0D\x00\x00\x00\x00\x83\x00\x00\x00\x00\x00\xB8\x01\x00\x00\x00
xx??????xx????x?????xxxxx
+ 0xA
Works on America's Army
Works on AvA
GObjects: 7D ? 8B 0D ? ? ? ? 8B 04 81
+ 0x4
AvA
AA3
UT3
Borderlands
Parabellum
GNames: 8B ? 8B 0D ? ? ? ? 8B 04 81
+ 0x4
AvA
AA3
UT3
8B 44 24 04 8B 0D ? ? ? ? 8B 04 81 C3