diff --git a/de4dot.code/deobfuscators/dotNET_Reactor/v4/Deobfuscator.cs b/de4dot.code/deobfuscators/dotNET_Reactor/v4/Deobfuscator.cs index 59cb0b46..ec0b2a6c 100644 --- a/de4dot.code/deobfuscators/dotNET_Reactor/v4/Deobfuscator.cs +++ b/de4dot.code/deobfuscators/dotNET_Reactor/v4/Deobfuscator.cs @@ -345,8 +345,14 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 { return DeobfuscatorInfo.THE_NAME + " 4.1"; return DeobfuscatorInfo.THE_NAME + " 4.0"; } - if (!hasCorEnableProfilingString) - return DeobfuscatorInfo.THE_NAME + " 4.x"; + if (!hasCorEnableProfilingString) { + // 4.x or 4.5 + bool callsReverse = DotNetUtils.callsMethod(methodsDecrypter.Method, "System.Void System.Array::Reverse(System.Array)"); + if (!callsReverse) + return DeobfuscatorInfo.THE_NAME + " 4.x"; + return DeobfuscatorInfo.THE_NAME + " 4.5"; + } + // 4.2-4.4 if (!localTypes.exists("System.Byte&")) diff --git a/de4dot.code/deobfuscators/dotNET_Reactor/v4/EncryptedResource.cs b/de4dot.code/deobfuscators/dotNET_Reactor/v4/EncryptedResource.cs index 60bbda7b..490ba263 100644 --- a/de4dot.code/deobfuscators/dotNET_Reactor/v4/EncryptedResource.cs +++ b/de4dot.code/deobfuscators/dotNET_Reactor/v4/EncryptedResource.cs @@ -116,6 +116,8 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 { iv = ArrayFinder.getInitializedByteArray(resourceDecrypterMethod, 16); if (iv == null) throw new ApplicationException("Could not find resource decrypter IV"); + if (needReverse()) + Array.Reverse(iv); // DNR 4.5.0.0 if (usesPublicKeyToken()) { var publicKeyToken = module.Assembly.PublicKeyToken; if (publicKeyToken != null && publicKeyToken.Data.Length > 0) { @@ -146,6 +148,10 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 { return false; } + bool needReverse() { + return DotNetUtils.callsMethod(resourceDecrypterMethod, "System.Void System.Array::Reverse(System.Array)"); + } + EmbeddedResource findMethodsDecrypterResource(MethodDef method) { foreach (var s in DotNetUtils.getCodeStrings(method)) { var resource = DotNetUtils.getResource(module, s) as EmbeddedResource; diff --git a/de4dot.code/deobfuscators/dotNET_Reactor/v4/MethodsDecrypter.cs b/de4dot.code/deobfuscators/dotNET_Reactor/v4/MethodsDecrypter.cs index d0588984..83390106 100644 --- a/de4dot.code/deobfuscators/dotNET_Reactor/v4/MethodsDecrypter.cs +++ b/de4dot.code/deobfuscators/dotNET_Reactor/v4/MethodsDecrypter.cs @@ -168,7 +168,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 { } } else { - // DNR 4.0 - 4.4 (jitter is hooked) + // DNR 4.0 - 4.5 (jitter is hooked) var methodDef = peImage.DotNetFile.MetaData.TablesStream.MethodTable; var rvaToIndex = new Dictionary((int)methodDef.Rows); diff --git a/de4dot.code/deobfuscators/dotNET_Reactor/v4/NativeImageUnpacker.cs b/de4dot.code/deobfuscators/dotNET_Reactor/v4/NativeImageUnpacker.cs index a87b8a32..e7cea77b 100644 --- a/de4dot.code/deobfuscators/dotNET_Reactor/v4/NativeImageUnpacker.cs +++ b/de4dot.code/deobfuscators/dotNET_Reactor/v4/NativeImageUnpacker.cs @@ -22,11 +22,13 @@ using System.IO; using ICSharpCode.SharpZipLib.Zip.Compression; using dot10.PE; using dot10.IO; +using dot10.DotNet; namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 { class NativeImageUnpacker { MyPEImage peImage; bool isNet1x; + const int loaderHeaderSizeV45 = 14; public NativeImageUnpacker(IPEImage peImage) { this.peImage = new MyPEImage(peImage); @@ -60,18 +62,44 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 { return null; } - if (BitConverter.ToInt16(inflatedData, 0) != 0x5A4D) - return null; + // CLR 1.x or DNR v4.0 - v4.4 + if (BitConverter.ToInt16(inflatedData, 0) == 0x5A4D) + return inflatedData; - return inflatedData; + // DNR v4.5 + if (BitConverter.ToInt16(inflatedData, loaderHeaderSizeV45) == 0x5A4D) + return unpackLoader(inflatedData); + + return null; } - static uint[] baseOffsets = new uint[] { + static byte[] unpackLoader(byte[] loaderData) { + var loaderBytes = new byte[loaderData.Length - loaderHeaderSizeV45]; + Array.Copy(loaderData, loaderHeaderSizeV45, loaderBytes, 0, loaderBytes.Length); + + try { + using (var asmLoader = ModuleDefMD.Load(loaderBytes)) { + if (asmLoader.Resources.Count == 0) + return null; + var resource = asmLoader.Resources[0] as EmbeddedResource; + if (resource == null) + return null; + + return resource.Data.ReadAllBytes(); + } + } + catch { + return null; + } + } + + static readonly uint[] baseOffsets = new uint[] { 0x1C00, // DNR 4.0 & 4.1 0x1900, // DNR 4.2.7.5 - 0x1B60, // DNR 4.2.8.4, 4.3 & 4.4 + 0x1B60, // DNR 4.2.8.4, 4.3, 4.4, 4.5 + 0x700, // DNR 4.5.0.0 }; - static short[] decryptMethodPattern = new short[] { + static readonly short[] decryptMethodPattern = new short[] { /* 00 */ 0x83, 0xEC, 0x38, // sub esp, 38h /* 03 */ 0x53, // push ebx /* 04 */ 0xB0, -1, // mov al, ??h @@ -84,7 +112,7 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 { /* 1C */ 0x55, // push ebp /* 1D */ 0x56, // push esi }; - static short[] startMethodNet1xPattern = new short[] { + static readonly short[] startMethodNet1xPattern = new short[] { /* 00 */ 0x55, // push ebp /* 01 */ 0x8B, 0xEC, // mov ebp, esp /* 03 */ 0xB9, 0x14, 0x00, 0x00, 0x00, // mov ecx, 14h