Skip to content

Commit e6591fe

Browse files
committed
.NET Reactor: Fix MethodsDecrypter for newer versions
1 parent 6d03925 commit e6591fe

3 files changed

Lines changed: 64 additions & 16 deletions

File tree

de4dot.code/deobfuscators/dotNET_Reactor/v4/Deobfuscator.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,8 @@ public override IDeobfuscator ModuleReloaded(ModuleDefMD module) {
446446
newOne.peImage = new MyPEImage(fileData);
447447
newOne.methodsDecrypter = new MethodsDecrypter(module, methodsDecrypter);
448448
newOne.proxyCallFixer = new ProxyCallFixer(module, proxyCallFixer);
449-
newOne.devirtualizer = new Devirtualizer(module, devirtualizer);
449+
newOne.devirtualizer = new Devirtualizer(DeobfuscatedFile, module);
450+
newOne.devirtualizer.Find();
450451
newOne.stringDecrypter = new StringDecrypter(module, stringDecrypter);
451452
newOne.booleanDecrypter = new BooleanDecrypter(module, booleanDecrypter);
452453
newOne.assemblyResolver = new AssemblyResolver(module, assemblyResolver);

de4dot.code/deobfuscators/dotNET_Reactor/v4/MethodsDecrypter.cs

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ You should have received a copy of the GNU General Public License
2020
using System;
2121
using System.Collections.Generic;
2222
using System.IO;
23+
using System.Linq;
2324
using dnlib.IO;
2425
using dnlib.DotNet;
2526
using dnlib.DotNet.MD;
@@ -126,15 +127,23 @@ public bool Decrypt(MyPEImage peImage, ISimpleDeobfuscator simpleDeobfuscator, r
126127

127128
var methodsDataReader = ByteArrayDataReaderFactory.CreateReader(methodsData);
128129

129-
int tmp = methodsDataReader.ReadInt32();
130-
if ((tmp & 0xFF000000) == 0x06000000)
131-
methodsDataReader.ReadInt32();
132-
else
133-
methodsDataReader.Position -= 4;
130+
int tmp;
131+
if (FindBinaryReaderMethod(simpleDeobfuscator, out var popCallsCount) && popCallsCount > 3)
132+
for (var i = 0; i < popCallsCount; i++)
133+
methodsDataReader.ReadInt32();
134+
else {
135+
tmp = methodsDataReader.ReadInt32();
136+
if ((tmp & 0xFF000000) == 0x06000000)
137+
methodsDataReader.ReadInt32();
138+
else
139+
methodsDataReader.Position -= 4;
140+
}
134141

135142
int patchCount = methodsDataReader.ReadInt32();
136-
int mode = methodsDataReader.ReadInt32();
143+
if (patchCount > methodsDataReader.BytesLeft / 8)
144+
patchCount = methodsDataReader.ReadInt32();
137145

146+
int mode = methodsDataReader.ReadInt32();
138147
tmp = methodsDataReader.ReadInt32();
139148
methodsDataReader.Position -= 4;
140149
if ((tmp & 0xFF000000) == 0x06000000) {
@@ -253,6 +262,53 @@ public bool Decrypt(MyPEImage peImage, ISimpleDeobfuscator simpleDeobfuscator, r
253262
return true;
254263
}
255264

265+
// Adapted from SychicBoy's NETReactorSlayer
266+
private bool FindBinaryReaderMethod(ISimpleDeobfuscator simpleDeobfuscator, out int popCallsCount) {
267+
popCallsCount = 0;
268+
var decrypterMethod = encryptedResource.Method;
269+
var calls = decrypterMethod.Body.Instructions
270+
.Where(x => x.OpCode == OpCodes.Callvirt && x.Operand is MethodDef md && md.MethodSig.RetType.FullName == "System.Int32")
271+
.Select(x => x.Operand)
272+
.Cast<MethodDef>();
273+
foreach (var method in calls)
274+
try {
275+
simpleDeobfuscator.Deobfuscate(method);
276+
if (method.Body.Instructions.Count != 4)
277+
continue;
278+
279+
if (!method.Body.Instructions[0].IsLdarg()
280+
|| method.Body.Instructions[1].OpCode != OpCodes.Ldfld
281+
|| method.Body.Instructions[2].OpCode.Code is not (Code.Callvirt or Code.Call)
282+
|| method.Body.Instructions[3].OpCode != OpCodes.Ret)
283+
continue;
284+
285+
if (!method.Body.Instructions[2].Operand.ToString()!.Contains("System.Int32"))
286+
continue;
287+
288+
for (var i = 0; i < decrypterMethod.Body.Instructions.Count; i++)
289+
try {
290+
if (!decrypterMethod.Body.Instructions[i].IsLdloc()
291+
|| decrypterMethod.Body.Instructions[i + 1].OpCode != OpCodes.Callvirt
292+
|| decrypterMethod.Body.Instructions[i + 1].Operand is not MethodDef calledMethod
293+
|| decrypterMethod.Body.Instructions[i + 2].OpCode != OpCodes.Pop)
294+
continue;
295+
296+
if (MethodEqualityComparer.CompareDeclaringTypes.Equals(calledMethod, method))
297+
popCallsCount++;
298+
}
299+
catch {
300+
// ignored
301+
}
302+
303+
return true;
304+
}
305+
catch {
306+
// ignored
307+
}
308+
309+
return false;
310+
}
311+
256312
public static bool IsNewer45Decryption(MethodDef method) {
257313
if (method == null || method.Body == null)
258314
return false;

de4dot.code/deobfuscators/dotNET_Reactor/v4/vm/Devirtualizer.cs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,6 @@ public Devirtualizer(ISimpleDeobfuscator deobfuscator, ModuleDefMD module) {
4747
_module = module;
4848
}
4949

50-
public Devirtualizer(ModuleDefMD module, Devirtualizer oldOne) {
51-
_module = module;
52-
_deobfuscator = oldOne._deobfuscator;
53-
_vmType = DeobUtils.Lookup(module, oldOne._vmType, "Could not find VM type");
54-
if (oldOne._resource != null)
55-
_resource = DotNetUtils.GetResource(module, oldOne._resource.Name.String) as EmbeddedResource;
56-
StreamHasPrependedByte = oldOne.StreamHasPrependedByte;
57-
}
58-
5950
public void Find() {
6051
_vmType = _module.Types.FirstOrDefault(type =>
6152
type.Methods.Any(method =>

0 commit comments

Comments
 (0)