Skip to content
This repository was archived by the owner on Jun 22, 2022. It is now read-only.

Commit 81c9125

Browse files
committed
Added method references
1 parent b21cf57 commit 81c9125

16 files changed

+369
-316
lines changed

Core/Dissasembler.cs

Lines changed: 22 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44
using Gee.External.Capstone.X86;
55
using Il2CppInspector.Model;
66
using Il2CppInspector.Reflection;
7-
using System;
87
using System.Collections.Generic;
8+
using System.Linq;
99
using System.Text;
10-
using System.Text.RegularExpressions;
1110
using Unitor.Core.Reflection;
1211

1312
namespace Unitor.Core
@@ -26,7 +25,6 @@ public static string DissasembleIl2CppMethod(MethodInfo method, UnitorModel modu
2625
CapstoneX86Disassembler disassembler = CapstoneDisassembler.CreateX86Disassembler(mode);
2726
disassembler.EnableInstructionDetails = true;
2827

29-
AddressMap map = module.AppModel.GetAddressMap();
3028
Dictionary<ulong, string> stringTable = module.AppModel.Strings;
3129

3230
var asm = disassembler.Disassemble(method.GetMethodBody(), (long)method.VirtualAddress.Value.Start);
@@ -35,11 +33,11 @@ public static string DissasembleIl2CppMethod(MethodInfo method, UnitorModel modu
3533
{
3634
if (ShoudCheckForMethods(ins.Id))
3735
{
38-
output.AppendLine(ins.Mnemonic + " " + ins.Operand + " " + GetMethodFromInstruction2(ins, map));
36+
output.AppendLine(ins.Mnemonic + " " + ins.Operand + " " + GetMethodFromInstruction(ins, module));
3937
}
4038
else if (ShouldCheckForString(ins.Id))
4139
{
42-
output.AppendLine(ins.Mnemonic + " " + ins.Operand + " " + GetStringFromInstruction(ins, stringTable));
40+
output.AppendLine(ins.Mnemonic + " " + ins.Operand + " " + GetStringFromInstruction(ins, stringTable).Item2);
4341
}
4442
else
4543
{
@@ -148,29 +146,31 @@ public static bool ShouldCheckForString(X86InstructionId id)
148146
X86InstructionId.X86_INS_MOV,
149147
}.Contains(id);
150148
}
151-
public static string GetStringFromInstruction(X86Instruction ins, Dictionary<ulong, string> stringTable)
149+
150+
public static (ulong, string) GetStringFromInstruction(X86Instruction ins, Dictionary<ulong, string> stringTable)
152151
{
153152
if (!ins.HasDetails)
154153
{
155-
return null;
154+
return (0x0, null);
156155
}
157156
X86Operand[] operands = ins.Details.Operands;
158157
if (operands.Length == 0)
159158
{
160-
return null;
159+
return (0x0, null);
161160
}
162161
ulong address = GetAdressFromInstruction(ins);
163162
if (address == 0x0)
164163
{
165-
return null;
164+
return (0x0, null);
166165
}
167166
if (stringTable.TryGetValue(address, out string s))
168167
{
169-
return s;
168+
return (address, s);
170169
}
171-
return null;
170+
return (0x0, null);
172171
}
173-
public static MethodBase GetMethodFromInstruction2(X86Instruction ins, AddressMap map)
172+
173+
public static UnitorMethod GetMethodFromInstruction(X86Instruction ins, UnitorModel model)
174174
{
175175
if (!ins.HasDetails)
176176
{
@@ -186,15 +186,23 @@ public static MethodBase GetMethodFromInstruction2(X86Instruction ins, AddressMa
186186
{
187187
return null;
188188
}
189-
if (map.TryGetValue(address, out object content))
189+
if (model.AppModel.GetAddressMap().TryGetValue(address, out object content))
190190
{
191191
if (content is AppMethod appMethod)
192192
{
193-
return appMethod.Method;
193+
if (model.Il2CppTypeMatches.TryGetValue(appMethod.Method.DeclaringType, out UnitorType type))
194+
{
195+
if (type.Methods == null)
196+
{
197+
return null;
198+
}
199+
return model.Il2CppTypeMatches[appMethod.Method.DeclaringType].Methods.FirstOrDefault(m => m.Name == appMethod.Method.Name);
200+
}
194201
}
195202
}
196203
return null;
197204
}
205+
198206
public static ulong GetAdressFromInstruction(X86Instruction ins)
199207
{
200208
if (!ins.HasDetails)
@@ -224,49 +232,5 @@ public static ulong GetAdressFromInstruction(X86Instruction ins)
224232
}
225233
return address;
226234
}
227-
228-
public static MethodBase GetMethodFromInstruction(X86Instruction ins, AddressMap map)
229-
{
230-
if (!ins.Operand.Contains("0x") || Regex.IsMatch(ins.Operand, @"dword ptr ([a-z]{1}s:)?\[[a-z0-9]{3} ?[\+\-&\*/\^\?]"))
231-
{
232-
return null;
233-
}
234-
235-
ulong address = 0x0;
236-
if (Regex.IsMatch(ins.Operand, @"qword ptr \[rip ?[\+\-&\*/\^\?]"))
237-
{
238-
ulong rip = (ulong)ins.Address;
239-
Match match = Regex.Match(ins.Operand, @"(?<Operator>[\+\-&\*/\^\?]) (?<Address>0x[a-z0-9]+)");
240-
if (match.Groups.TryGetValue("Operator", out Group op) && match.Groups.TryGetValue("Address", out Group add))
241-
{
242-
address = (op.ToString()) switch
243-
{
244-
"+" => rip + Convert.ToUInt64(add.ToString(), 16),
245-
"-" => rip - Convert.ToUInt64(add.ToString(), 16),
246-
_ => Convert.ToUInt64(add.ToString(), 16),
247-
};
248-
}
249-
}
250-
else if (Regex.IsMatch(ins.Operand, @"qword ptr ([a-z]{1}s:)?\[[a-z0-9]{1,3} ?[\+\-&\*/\^\?]"))
251-
{
252-
return null;
253-
}
254-
else if (Regex.IsMatch(ins.Operand, @"\[0x[a-z0-9]{1,}\]"))
255-
{
256-
address = Convert.ToUInt64(Regex.Match(ins.Operand, @"(?!\[)[a-z0-9]{1,}(?=])").Value, 16);
257-
}
258-
else
259-
{
260-
address = Convert.ToUInt64(ins.Operand, 16);
261-
}
262-
if (map.TryGetValue(address, out object content))
263-
{
264-
if (content is AppMethod appMethod)
265-
{
266-
return appMethod.Method;
267-
}
268-
}
269-
return null;
270-
}
271235
}
272236
}

Core/Extensions.cs

Lines changed: 1 addition & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -1,139 +1,7 @@
1-
using dnlib.DotNet;
2-
using dnlib.DotNet.Emit;
3-
using Gee.External.Capstone;
4-
using Gee.External.Capstone.X86;
5-
using Il2CppInspector.Model;
6-
using Il2CppInspector.Reflection;
7-
using System;
8-
using System.Collections.Generic;
9-
using System.Linq;
10-
using Unitor.Core.Reflection;
11-
12-
namespace Unitor.Core
1+
namespace Unitor.Core
132
{
143
public static class Extensions
154
{
16-
public static IEnumerable<UnitorMethod> GetCalls(this UnitorMethod method, AppModel appModel)
17-
{
18-
if (method.IsEmpty)
19-
{
20-
yield break;
21-
}
22-
if (method.Il2CppMethod != null)
23-
{
24-
IEnumerable<MethodBase> methods = method.Il2CppMethod.GetCalls(appModel);
25-
foreach (MethodBase methodCall in methods)
26-
{
27-
if (method.Owner.ProcessedIl2CppTypes.Contains(methodCall.DeclaringType))
28-
{
29-
UnitorType type = method.Owner.Il2CppTypeMatches[methodCall.DeclaringType];
30-
if (type.Methods == null)
31-
{
32-
continue;
33-
}
34-
UnitorMethod methodCallMatch = type.Methods.FirstOrDefault(m => m.Name == methodCall.Name);
35-
if (methodCallMatch != null)
36-
{
37-
yield return methodCallMatch;
38-
}
39-
}
40-
}
41-
}
42-
else
43-
{
44-
IEnumerable<MethodDef> methods = method.MonoMethod.GetCalls();
45-
foreach (MethodDef methodCall in methods)
46-
{
47-
if (method.Owner.ProcessedMonoTypes.Contains(methodCall.DeclaringType))
48-
{
49-
UnitorType type = method.Owner.MonoTypeMatches[methodCall.DeclaringType];
50-
if (type.Methods == null)
51-
{
52-
continue;
53-
}
54-
UnitorMethod methodCallMatch = type.Methods.FirstOrDefault(m => m.Name == methodCall.Name);
55-
if (methodCallMatch != null)
56-
{
57-
yield return methodCallMatch;
58-
}
59-
}
60-
}
61-
}
62-
}
63-
public static IEnumerable<MethodBase> GetCalls(this MethodInfo method, AppModel model)
64-
{
65-
if (!method.VirtualAddress.HasValue)
66-
{
67-
yield break;
68-
}
69-
70-
X86DisassembleMode mode = model.Image.Arch == "x64" ? X86DisassembleMode.Bit64 : X86DisassembleMode.Bit32;
71-
CapstoneX86Disassembler disassembler = CapstoneDisassembler.CreateX86Disassembler(mode);
72-
73-
// disassembler.EnableInstructionDetails = true; set when Using GetMethodFromInstruction2
74-
75-
AddressMap map = model.GetAddressMap();
76-
77-
var asm = disassembler.Disassemble(method.GetMethodBody(), (long)method.VirtualAddress.Value.Start);
78-
foreach (X86Instruction ins in asm)
79-
{
80-
if (Dissasembler.ShoudCheckForMethods(ins.Id))
81-
{
82-
// GetMethodFromInstruction2 is cleaner but GetMethodFromInstruction is faster
83-
MethodBase m = Dissasembler.GetMethodFromInstruction(ins, map);
84-
if (m != null)
85-
{
86-
yield return m;
87-
}
88-
}
89-
}
90-
disassembler.Dispose();
91-
}
92-
93-
public static IEnumerable<MethodDef> GetCalls(this MethodDef method)
94-
{
95-
if (method.Body == null)
96-
{
97-
yield break;
98-
}
99-
100-
foreach (Instruction ins in method.Body.Instructions)
101-
{
102-
if ((ins.OpCode.Code == Code.Call || ins.OpCode.Code == Code.Calli || ins.OpCode.Code == Code.Callvirt) && ins.Operand is MethodDef m)
103-
{
104-
yield return m;
105-
}
106-
}
107-
}
108-
public static IEnumerable<(ulong, string)> GetStrings(this UnitorMethod method)
109-
{
110-
if (method.IsEmpty)
111-
{
112-
return null;
113-
}
114-
if (method.Il2CppMethod != null)
115-
{
116-
return null;
117-
}
118-
else
119-
{
120-
return GetStrings(method.MonoMethod);
121-
}
122-
}
123-
public static IEnumerable<(ulong, string)> GetStrings(this MethodDef method)
124-
{
125-
if (method.Body == null)
126-
{
127-
yield break;
128-
}
1295

130-
foreach (Instruction ins in method.Body.Instructions)
131-
{
132-
if (ins.OpCode.Code == Code.Ldstr && ins.Operand is string s)
133-
{
134-
yield return ((ulong)(method.RVA + ins.Offset), s);
135-
}
136-
}
137-
}
1386
}
1397
}

Core/Game.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ public static BackendInfo FromPath(string path, string name, EventHandler<string
122122
throw new ArgumentException("Cannot find Assembly-CSharp.dll");
123123
}
124124

125-
125+
126126
ModuleContext modCtx = ModuleDef.CreateModuleContext();
127127
ModuleDefMD module = ModuleDefMD.Load(@$"{path}\{name}_Data\Managed\Assembly-CSharp.dll", modCtx);
128128

Core/Helpers.cs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using System.Collections.Generic;
2+
using Unitor.Core.Reflection;
3+
4+
namespace Unitor.Core
5+
{
6+
public static class Helpers
7+
{
8+
public static bool IsUnityMonobehaviourMessage(UnitorMethod m)
9+
{
10+
return new List<string>() {
11+
"Awake",
12+
"FixedUpdate",
13+
"LateUpdate",
14+
"OnAnimatorIK",
15+
"OnAnimatorMove",
16+
"OnApplicationFocus",
17+
"OnApplicationPause",
18+
"OnApplicationQuit",
19+
"OnAudioFilterRead",
20+
"OnBecameInvisible",
21+
"OnBecameVisible",
22+
"OnCollisionEnter",
23+
"OnCollisionEnter2D",
24+
"OnCollisionExit",
25+
"OnCollisionExit2D",
26+
"OnCollisionStay",
27+
"OnCollisionStay2D",
28+
"OnConnectedToServer",
29+
"OnControllerColliderHit",
30+
"OnDestroy",
31+
"OnDisable",
32+
"OnDisconnectedFromServer",
33+
"OnDrawGizmos",
34+
"OnDrawGizmosSelected",
35+
"OnEnable",
36+
"OnFailedToConnect",
37+
"OnFailedToConnectToMasterServer",
38+
"OnGUI",
39+
"OnJointBreak",
40+
"OnJointBreak2D",
41+
"OnMasterServerEvent",
42+
"OnMouseDown",
43+
"OnMouseDrag",
44+
"OnMouseEnter",
45+
"OnMouseExit",
46+
"OnMouseOver",
47+
"OnMouseUp",
48+
"OnMouseUpAsButton",
49+
"OnNetworkInstantiate",
50+
"OnParticleCollision",
51+
"OnParticleSystemStopped",
52+
"OnParticleTrigger",
53+
"OnParticleUpdateJobScheduled",
54+
"OnPlayerConnected",
55+
"OnPlayerDisconnected",
56+
"OnPostRender",
57+
"OnPreCull",
58+
"OnPreRender",
59+
"OnRenderImage",
60+
"OnRenderObject",
61+
"OnSerializeNetworkView",
62+
"OnServerInitialized",
63+
"OnTransformChildrenChanged",
64+
"OnTransformParentChanged",
65+
"OnTriggerEnter",
66+
"OnTriggerEnter2D",
67+
"OnTriggerExit",
68+
"OnTriggerExit2D",
69+
"OnTriggerStay",
70+
"OnTriggerStay2D",
71+
"OnValidate",
72+
"OnWillRenderObject",
73+
"Reset",
74+
"Start",
75+
"Update"
76+
}.Contains(m.Name);
77+
}
78+
}
79+
}

0 commit comments

Comments
 (0)