Support .NET Reactor 4.5 (an updated version) and 4.6
This commit is contained in:
parent
8dc7249033
commit
689635cf69
|
@ -157,6 +157,7 @@
|
|||
<Compile Include="deobfuscators\DeobUtils.cs" />
|
||||
<Compile Include="deobfuscators\Dotfuscator\Deobfuscator.cs" />
|
||||
<Compile Include="deobfuscators\Dotfuscator\StringDecrypter.cs" />
|
||||
<Compile Include="deobfuscators\dotNET_Reactor\v4\DnrMethodCallInliner.cs" />
|
||||
<Compile Include="deobfuscators\Eazfuscator_NET\Dynocode.cs" />
|
||||
<Compile Include="deobfuscators\MyPEImage.cs" />
|
||||
<Compile Include="deobfuscators\dotNET_Reactor\v3\AntiStrongName.cs" />
|
||||
|
|
|
@ -26,6 +26,7 @@ using dnlib.DotNet;
|
|||
using dnlib.DotNet.Emit;
|
||||
using dnlib.DotNet.Writer;
|
||||
using de4dot.blocks;
|
||||
using de4dot.blocks.cflow;
|
||||
|
||||
namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||
public class DeobfuscatorInfo : DeobfuscatorInfoBase {
|
||||
|
@ -142,6 +143,15 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
|||
get { return startedDeobfuscating ? options.InlineMethods : true; }
|
||||
}
|
||||
|
||||
public override IEnumerable<IBlocksDeobfuscator> BlocksDeobfuscators {
|
||||
get {
|
||||
var list = new List<IBlocksDeobfuscator>();
|
||||
if (CanInlineMethods)
|
||||
list.Add(new DnrMethodCallInliner());
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
public Deobfuscator(Options options)
|
||||
: base(options) {
|
||||
this.options = options;
|
||||
|
@ -333,8 +343,12 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
|||
}
|
||||
|
||||
var compileMethod = MethodsDecrypter.FindDnrCompileMethod(methodsDecrypter.Method.DeclaringType);
|
||||
if (compileMethod == null)
|
||||
if (compileMethod == null) {
|
||||
DeobfuscatedFile.Deobfuscate(methodsDecrypter.Method);
|
||||
if (!MethodsDecrypter.IsNewer45Decryption(methodsDecrypter.Method))
|
||||
return DeobfuscatorInfo.THE_NAME + " < 4.0";
|
||||
return DeobfuscatorInfo.THE_NAME + " 4.5+";
|
||||
}
|
||||
DeobfuscatedFile.Deobfuscate(compileMethod);
|
||||
bool compileMethodHasConstant_0x70000000 = DeobUtils.HasInteger(compileMethod, 0x70000000); // 4.0-4.1
|
||||
DeobfuscatedFile.Deobfuscate(methodsDecrypter.Method);
|
||||
|
@ -346,11 +360,27 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
|||
return DeobfuscatorInfo.THE_NAME + " 4.0";
|
||||
}
|
||||
if (!hasCorEnableProfilingString) {
|
||||
// 4.x or 4.5
|
||||
// 4.x or 4.5 - 4.6
|
||||
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";
|
||||
return DeobfuscatorInfo.THE_NAME + " 4.0 - 4.4";
|
||||
|
||||
int numIntPtrSizeCompares = CountCompareSystemIntPtrSize(methodsDecrypter.Method);
|
||||
if (module.IsClr40) {
|
||||
switch (numIntPtrSizeCompares) {
|
||||
case 9: return DeobfuscatorInfo.THE_NAME + " 4.5";
|
||||
case 10:return DeobfuscatorInfo.THE_NAME + " 4.6";
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (numIntPtrSizeCompares) {
|
||||
case 8: return DeobfuscatorInfo.THE_NAME + " 4.5";
|
||||
case 9: return DeobfuscatorInfo.THE_NAME + " 4.6";
|
||||
}
|
||||
}
|
||||
|
||||
// Should never be reached unless it's a new version
|
||||
return DeobfuscatorInfo.THE_NAME + " 4.5+";
|
||||
}
|
||||
|
||||
// 4.2-4.4
|
||||
|
@ -364,6 +394,29 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
|||
return DeobfuscatorInfo.THE_NAME + " 4.3";
|
||||
}
|
||||
|
||||
static int CountCompareSystemIntPtrSize(MethodDef method) {
|
||||
if (method == null || method.Body == null)
|
||||
return 0;
|
||||
int count = 0;
|
||||
var instrs = method.Body.Instructions;
|
||||
for (int i = 1; i < instrs.Count - 1; i++) {
|
||||
var ldci4 = instrs[i];
|
||||
if (!ldci4.IsLdcI4() || ldci4.GetLdcI4Value() != 4)
|
||||
continue;
|
||||
if (!instrs[i + 1].IsConditionalBranch())
|
||||
continue;
|
||||
var call = instrs[i - 1];
|
||||
if (call.OpCode.Code != Code.Call)
|
||||
continue;
|
||||
var calledMethod = call.Operand as MemberRef;
|
||||
if (calledMethod == null || calledMethod.FullName != "System.Int32 System.IntPtr::get_Size()")
|
||||
continue;
|
||||
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static bool FindString(MethodDef method, string s) {
|
||||
foreach (var cs in DotNetUtils.GetCodeStrings(method)) {
|
||||
if (cs == s)
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
Copyright (C) 2011-2013 de4dot@gmail.com
|
||||
|
||||
This file is part of de4dot.
|
||||
|
||||
de4dot is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
de4dot is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using dnlib.DotNet.Emit;
|
||||
using de4dot.blocks;
|
||||
using de4dot.blocks.cflow;
|
||||
|
||||
namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
||||
class DnrMethodCallInliner : MethodCallInliner {
|
||||
public DnrMethodCallInliner()
|
||||
: base(false) {
|
||||
}
|
||||
|
||||
protected override Instruction GetFirstInstruction(IList<Instruction> instrs, ref int index) {
|
||||
var instr = GetFirstInstruction(instrs, index);
|
||||
if (instr != null)
|
||||
index = instrs.IndexOf(instr);
|
||||
return DotNetUtils.GetInstruction(instrs, ref index);
|
||||
}
|
||||
|
||||
Instruction GetFirstInstruction(IList<Instruction> instrs, int index) {
|
||||
try {
|
||||
var instr = instrs[index];
|
||||
if (!instr.IsBr())
|
||||
return null;
|
||||
instr = instr.Operand as Instruction;
|
||||
if (instr == null)
|
||||
return null;
|
||||
if (!instr.IsLdcI4() || instr.GetLdcI4Value() != 0)
|
||||
return null;
|
||||
instr = instrs[instrs.IndexOf(instr) + 1];
|
||||
if (!instr.IsBrtrue())
|
||||
return null;
|
||||
return instrs[instrs.IndexOf(instr) + 1];
|
||||
}
|
||||
catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -121,8 +121,8 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
|||
}
|
||||
}
|
||||
|
||||
static short[] nativeLdci4 = new short[] { 0x55, 0x8B, 0xEC, 0xB8, -1, -1, -1, -1, 0x5D, 0xC3 };
|
||||
static short[] nativeLdci4_0 = new short[] { 0x55, 0x8B, 0xEC, 0x33, 0xC0, 0x5D, 0xC3 };
|
||||
readonly static short[] nativeLdci4 = new short[] { 0x55, 0x8B, 0xEC, 0xB8, -1, -1, -1, -1, 0x5D, 0xC3 };
|
||||
readonly static short[] nativeLdci4_0 = new short[] { 0x55, 0x8B, 0xEC, 0x33, 0xC0, 0x5D, 0xC3 };
|
||||
public bool Decrypt(MyPEImage peImage, ISimpleDeobfuscator simpleDeobfuscator, ref DumpedMethods dumpedMethods, Dictionary<uint, byte[]> tokenToNativeCode, bool unpackedNativeFile) {
|
||||
if (encryptedResource.Method == null)
|
||||
return false;
|
||||
|
@ -157,27 +157,29 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
|||
}
|
||||
}
|
||||
else if (!hooksJitter || mode == 1) {
|
||||
// DNR 3.9.8.0, 4.0, 4.1, 4.2, 4.3, 4.4
|
||||
|
||||
// If it's .NET 1.x, then offsets are used, not RVAs.
|
||||
bool useOffsets = unpackedNativeFile && module.IsClr1x;
|
||||
// DNR 3.9.8.0, 4.0+
|
||||
|
||||
PatchDwords(peImage, methodsDataReader, patchCount);
|
||||
bool oldCode = !IsNewer45Decryption(encryptedResource.Method);
|
||||
while (methodsDataReader.Position < methodsData.Length - 1) {
|
||||
uint rva = methodsDataReader.ReadUInt32();
|
||||
uint token = methodsDataReader.ReadUInt32(); // token, unknown, or index
|
||||
int size = methodsDataReader.ReadInt32();
|
||||
if (size > 0) {
|
||||
int size;
|
||||
if (oldCode) {
|
||||
methodsDataReader.ReadUInt32(); // token, unknown, or index
|
||||
size = methodsDataReader.ReadInt32();
|
||||
}
|
||||
else
|
||||
size = methodsDataReader.ReadInt32() * 4;
|
||||
|
||||
var newData = methodsDataReader.ReadBytes(size);
|
||||
if (useOffsets)
|
||||
if (unpackedNativeFile)
|
||||
peImage.DotNetSafeWriteOffset(rva, newData);
|
||||
else
|
||||
peImage.DotNetSafeWrite(rva, newData);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// DNR 4.0 - 4.5 (jitter is hooked)
|
||||
// DNR 4.0+ (jitter is hooked)
|
||||
|
||||
var methodDef = peImage.DotNetFile.MetaData.TablesStream.MethodTable;
|
||||
var rvaToIndex = new Dictionary<uint, int>((int)methodDef.Rows);
|
||||
|
@ -258,6 +260,33 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
|||
return true;
|
||||
}
|
||||
|
||||
public static bool IsNewer45Decryption(MethodDef method) {
|
||||
if (method == null || method.Body == null)
|
||||
return false;
|
||||
|
||||
var instrs = method.Body.Instructions;
|
||||
for (int i = 0; i < instrs.Count - 4; i++) {
|
||||
var ldci4 = instrs[i];
|
||||
if (!ldci4.IsLdcI4() || ldci4.GetLdcI4Value() != 4)
|
||||
continue;
|
||||
if (instrs[i + 1].OpCode.Code != Code.Mul)
|
||||
continue;
|
||||
ldci4 = instrs[i + 2];
|
||||
if (!ldci4.IsLdcI4() || ldci4.GetLdcI4Value() != 4)
|
||||
continue;
|
||||
if (instrs[i + 3].OpCode.Code != Code.Ldloca_S && instrs[i + 3].OpCode.Code != Code.Ldloca)
|
||||
continue;
|
||||
var call = instrs[i + 4];
|
||||
if (call.OpCode.Code != Code.Call)
|
||||
continue;
|
||||
if (!DotNetUtils.IsPinvokeMethod(call.Operand as MethodDef, "kernel32", "VirtualProtect"))
|
||||
continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void PatchDwords(MyPEImage peImage, IBinaryReader reader, int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
uint rva = reader.ReadUInt32();
|
||||
|
@ -363,6 +392,12 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
|||
Array.Copy(encrypted, resourceData, resourceData.Length);
|
||||
}
|
||||
|
||||
enum CompileMethodType {
|
||||
Unknown,
|
||||
V1, // <= DNR 4.5.0.0 (2012-11-06 <= endDate < 2013-01-31)
|
||||
V2, // >= DNR 4.5.0.0 (2012-11-06 < startDate <= 2013-01-31)
|
||||
}
|
||||
|
||||
public static MethodDef FindDnrCompileMethod(TypeDef type) {
|
||||
foreach (var method in type.Methods) {
|
||||
if (!method.IsStatic || method.Body == null)
|
||||
|
@ -370,11 +405,19 @@ namespace de4dot.code.deobfuscators.dotNET_Reactor.v4 {
|
|||
var sig = method.MethodSig;
|
||||
if (sig == null || sig.Params.Count != 6)
|
||||
continue;
|
||||
if (!DotNetUtils.IsMethod(method, "System.UInt32", "(System.UInt64&,System.IntPtr,System.IntPtr,System.UInt32,System.IntPtr&,System.UInt32&)"))
|
||||
if (GetCompileMethodType(method) == CompileMethodType.Unknown)
|
||||
continue;
|
||||
return method;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static CompileMethodType GetCompileMethodType(MethodDef method) {
|
||||
if (DotNetUtils.IsMethod(method, "System.UInt32", "(System.UInt64&,System.IntPtr,System.IntPtr,System.UInt32,System.IntPtr&,System.UInt32&)"))
|
||||
return CompileMethodType.V1;
|
||||
if (DotNetUtils.IsMethod(method, "System.UInt32", "(System.IntPtr,System.IntPtr,System.IntPtr,System.UInt32,System.IntPtr,System.UInt32&)"))
|
||||
return CompileMethodType.V2;
|
||||
return CompileMethodType.Unknown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user