From 583d4201f563a8f89b0bb70e9a01cf0c74470878 Mon Sep 17 00:00:00 2001 From: de4dot Date: Wed, 7 Nov 2012 05:17:45 +0100 Subject: [PATCH] Port Agile.NET deobfuscator --- blocks/DotNetUtils.cs | 13 +- blocks/cflow/MethodCallInlinerBase.cs | 4 +- de4dot.code/de4dot.code.csproj | 38 +++--- .../Agile_NET/CliSecureRtType.cs | 41 ++----- .../deobfuscators/Agile_NET/Deobfuscator.cs | 28 +++-- .../Agile_NET/MethodsDecrypter.cs | 13 +- .../deobfuscators/Agile_NET/ProxyCallFixer.cs | 24 ++-- .../Agile_NET/ResourceDecrypter.cs | 33 +++--- .../Agile_NET/StackFrameHelper.cs | 19 ++- .../Agile_NET/StringDecrypter.cs | 8 +- .../vm/CilOperandInstructionRestorer.cs | 63 +++++----- .../deobfuscators/Agile_NET/vm/Csvm.cs | 35 +++--- .../Agile_NET/vm/CsvmDataReader.cs | 7 +- .../Agile_NET/vm/CsvmToCilMethodConverter.cs | 111 ++++++++---------- .../deobfuscators/Agile_NET/vm/FieldsInfo.cs | 8 +- .../Agile_NET/vm/OpCodeHandler.cs | 7 +- .../Agile_NET/vm/UnknownHandlerInfo.cs | 8 +- .../Agile_NET/vm/VmOpCodeHandlerDetector.cs | 28 +++-- de4dot.cui/Program.cs | 2 +- dot10 | 2 +- 20 files changed, 235 insertions(+), 257 deletions(-) diff --git a/blocks/DotNetUtils.cs b/blocks/DotNetUtils.cs index 96f066fa..350f5251 100644 --- a/blocks/DotNetUtils.cs +++ b/blocks/DotNetUtils.cs @@ -202,7 +202,7 @@ namespace de4dot.blocks { var sig = method.MethodSig; if (sig == null || !method.HasBody || !sig.IsDefault) continue; - if (method.IsStatic != isStatic || method.Parameters.Count != argsTypes.Length) + if (method.IsStatic != isStatic || sig.Params.Count != argsTypes.Length) continue; if (sig.GenParamCount > 0) continue; @@ -248,23 +248,24 @@ namespace de4dot.blocks { return dll; } -#if PORT - public static bool hasPinvokeMethod(TypeDefinition type, string methodName) { + public static bool hasPinvokeMethod(TypeDef type, string methodName) { return getPInvokeMethod(type, methodName) != null; } - public static MethodDef getPInvokeMethod(TypeDefinition type, string methodName) { + public static MethodDef getPInvokeMethod(TypeDef type, string methodName) { if (type == null) return null; + var mname = new UTF8String(methodName); foreach (var method in type.Methods) { - if (method.PInvokeInfo == null) + if (method.ImplMap == null) continue; - if (method.PInvokeInfo.EntryPoint == methodName) + if (UTF8String.Equals(method.ImplMap.Name, mname)) return method; } return null; } +#if PORT public static MethodDef getPInvokeMethod(TypeDefinition type, string dll, string funcName) { foreach (var method in type.Methods) { if (isPinvokeMethod(method, dll, funcName)) diff --git a/blocks/cflow/MethodCallInlinerBase.cs b/blocks/cflow/MethodCallInlinerBase.cs index e647890b..970d87b1 100644 --- a/blocks/cflow/MethodCallInlinerBase.cs +++ b/blocks/cflow/MethodCallInlinerBase.cs @@ -165,10 +165,10 @@ namespace de4dot.blocks.cflow { var methodArgs = methodToInline.Parameters; var calledMethodArgs = DotNetUtils.getArgs(ctor); - if (methodArgs.Count + 1 - popLastArgs != calledMethodArgs.Count) + if (methodArgs.Count - popLastArgs != calledMethodArgs.Count) return null; for (int i = 1; i < calledMethodArgs.Count; i++) { - if (!isCompatibleType(i, calledMethodArgs[i], methodArgs[i - 1].Type)) + if (!isCompatibleType(i, calledMethodArgs[i], methodArgs[i].Type)) return null; } diff --git a/de4dot.code/de4dot.code.csproj b/de4dot.code/de4dot.code.csproj index a5f5fc42..2480c28d 100644 --- a/de4dot.code/de4dot.code.csproj +++ b/de4dot.code/de4dot.code.csproj @@ -57,25 +57,25 @@ - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/de4dot.code/deobfuscators/Agile_NET/CliSecureRtType.cs b/de4dot.code/deobfuscators/Agile_NET/CliSecureRtType.cs index 0a712abb..cb92be22 100644 --- a/de4dot.code/deobfuscators/Agile_NET/CliSecureRtType.cs +++ b/de4dot.code/deobfuscators/Agile_NET/CliSecureRtType.cs @@ -26,7 +26,7 @@ using de4dot.PE; namespace de4dot.code.deobfuscators.Agile_NET { class CliSecureRtType { - ModuleDefinition module; + ModuleDefMD module; TypeDef cliSecureRtType; MethodDef postInitializeMethod; MethodDef initializeMethod; @@ -58,27 +58,11 @@ namespace de4dot.code.deobfuscators.Agile_NET { get { return loadMethod; } } - public IEnumerable DecryptModuleReferences { - get { - var list = new List(); - addModuleReference(list, "_Initialize"); - addModuleReference(list, "_Initialize64"); - return list; - } - } - - void addModuleReference(List list, string methodName) { - var method = DotNetUtils.getPInvokeMethod(cliSecureRtType, methodName); - if (method == null) - return; - list.Add(method.PInvokeInfo.Module); - } - - public CliSecureRtType(ModuleDefinition module) { + public CliSecureRtType(ModuleDefMD module) { this.module = module; } - public CliSecureRtType(ModuleDefinition module, CliSecureRtType oldOne) { + public CliSecureRtType(ModuleDefMD module, CliSecureRtType oldOne) { this.module = module; cliSecureRtType = lookup(oldOne.cliSecureRtType, "Could not find CliSecureRt type"); postInitializeMethod = lookup(oldOne.postInitializeMethod, "Could not find postInitializeMethod method"); @@ -88,7 +72,7 @@ namespace de4dot.code.deobfuscators.Agile_NET { foundSig = oldOne.foundSig; } - T lookup(T def, string errorMessage) where T : MemberReference { + T lookup(T def, string errorMessage) where T : class, ICodedToken { return DeobUtils.lookup(module, def, errorMessage); } @@ -147,13 +131,13 @@ namespace de4dot.code.deobfuscators.Agile_NET { foreach (var type in module.Types) { if (type.Fields.Count != 1) continue; - if (type.Fields[0].FieldType.FullName != "System.Byte[]") + if (type.Fields[0].FieldSig.GetFieldType().GetFullName() != "System.Byte[]") continue; if (type.Methods.Count != 2) continue; - if (DotNetUtils.getMethod(type, ".cctor") == null) + if (type.FindClassConstructor() == null) continue; - var cs = DotNetUtils.getMethod(type, "cs"); + var cs = type.FindMethod("cs"); if (cs == null) continue; @@ -196,12 +180,13 @@ namespace de4dot.code.deobfuscators.Agile_NET { var method = DotNetUtils.getPInvokeMethod(type, name); if (method == null) return false; - if (method.Parameters.Count != 1) + var sig = method.MethodSig; + if (sig.Params.Count != 1) return false; - if (method.Parameters[0].ParameterType.FullName != "System.IntPtr") + if (sig.Params[0].GetElementType() != ElementType.I) return false; - var retType = method.MethodReturnType.ReturnType.FullName; - if (retType != "System.Void" && retType != "System.Int32") + var retType = sig.RetType.GetElementType(); + if (retType != ElementType.Void && retType != ElementType.I4) return false; return true; } @@ -209,7 +194,7 @@ namespace de4dot.code.deobfuscators.Agile_NET { bool findNativeCode(byte[] moduleBytes) { var stream = moduleBytes != null ? (Stream)new MemoryStream(moduleBytes) : - (Stream)new FileStream(module.FullyQualifiedName, FileMode.Open, FileAccess.Read, FileShare.Read); + (Stream)new FileStream(module.Location, FileMode.Open, FileAccess.Read, FileShare.Read); using (stream) { var peImage = new PeImage(stream); return foundSig = MethodsDecrypter.detect(peImage); diff --git a/de4dot.code/deobfuscators/Agile_NET/Deobfuscator.cs b/de4dot.code/deobfuscators/Agile_NET/Deobfuscator.cs index 52af594e..216bbfc5 100644 --- a/de4dot.code/deobfuscators/Agile_NET/Deobfuscator.cs +++ b/de4dot.code/deobfuscators/Agile_NET/Deobfuscator.cs @@ -19,8 +19,9 @@ using System; using System.Collections.Generic; +using dot10.PE; using dot10.DotNet; -using Mono.MyStuff; +using dot10.DotNet.MD; using de4dot.blocks; using de4dot.PE; @@ -112,16 +113,17 @@ namespace de4dot.code.deobfuscators.Agile_NET { this.options = options; } - public override void init(ModuleDefinition module) { + public override void init(ModuleDefMD module) { base.init(module); } - public override byte[] unpackNativeFile(PeImage peImage) { + public override byte[] unpackNativeFile(PEImage peImage) { return unpackNativeFile1(peImage) ?? unpackNativeFile2(peImage); } // Old CS versions - byte[] unpackNativeFile1(PeImage peImage) { + byte[] unpackNativeFile1(PEImage peImage) { +#if PORT const int dataDirNum = 6; // debug dir const int dotNetDirNum = 14; @@ -139,10 +141,14 @@ namespace de4dot.code.deobfuscators.Agile_NET { writeUInt32(fileData, dataDir + 4, 0); ModuleBytes = fileData; return fileData; +#else + return null; +#endif } // CS 1.x - byte[] unpackNativeFile2(PeImage peImage) { + byte[] unpackNativeFile2(PEImage peImage) { +#if PORT var dir = peImage.Resources.getRoot(); if ((dir = dir.getDirectory("ASSEMBLY")) == null) return null; @@ -153,6 +159,9 @@ namespace de4dot.code.deobfuscators.Agile_NET { return null; return ModuleBytes = peImage.readBytes(data.RVA, (int)data.Size); +#else + return null; +#endif } static void writeUInt32(byte[] data, int offset, uint value) { @@ -221,7 +230,7 @@ namespace de4dot.code.deobfuscators.Agile_NET { return true; } - public override IDeobfuscator moduleReloaded(ModuleDefinition module) { + public override IDeobfuscator moduleReloaded(ModuleDefMD module) { var newOne = new Deobfuscator(options); newOne.setModule(module); newOne.cliSecureAttributes = lookup(module, cliSecureAttributes, "Could not find CliSecure attribute"); @@ -233,7 +242,7 @@ namespace de4dot.code.deobfuscators.Agile_NET { return newOne; } - static List lookup(ModuleDefinition module, List types, string errorMsg) { + static List lookup(ModuleDefMD module, List types, string errorMsg) { var list = new List(types.Count); foreach (var type in types) list.Add(DeobUtils.lookup(module, type, errorMsg)); @@ -274,7 +283,6 @@ namespace de4dot.code.deobfuscators.Agile_NET { if (options.RestoreVmCode) { csvm.restore(); - addAssemblyReferenceToBeRemoved(csvm.VmAssemblyReference, "CSVM assembly reference"); addResourceToBeRemoved(csvm.Resource, "CSVM data resource"); } } @@ -308,11 +316,9 @@ namespace de4dot.code.deobfuscators.Agile_NET { } if (options.DecryptMethods) { addResources("Obfuscator protection files"); - addModuleReferencesToBeRemoved(cliSecureRtType.DecryptModuleReferences, "Obfuscator protection files"); - addModuleReferences("Obfuscator protection files"); } - module.Attributes |= ModuleAttributes.ILOnly; + module.Cor20HeaderFlags |= ComImageFlags.ILOnly; base.deobfuscateEnd(); } diff --git a/de4dot.code/deobfuscators/Agile_NET/MethodsDecrypter.cs b/de4dot.code/deobfuscators/Agile_NET/MethodsDecrypter.cs index 9a05b472..2e07f7e2 100644 --- a/de4dot.code/deobfuscators/Agile_NET/MethodsDecrypter.cs +++ b/de4dot.code/deobfuscators/Agile_NET/MethodsDecrypter.cs @@ -20,7 +20,8 @@ using System; using System.Collections.Generic; using System.IO; -using Mono.MyStuff; +using dot10.DotNet; +using dot10.DotNet.MD; using de4dot.PE; using de4dot.blocks; @@ -62,7 +63,7 @@ namespace de4dot.code.deobfuscators.Agile_NET { } PeImage peImage; - Mono.Cecil.ModuleDefinition module; + ModuleDefMD module; CliSecureRtType csRtType; CodeHeader codeHeader = new CodeHeader(); IDecrypter decrypter; @@ -155,7 +156,7 @@ namespace de4dot.code.deobfuscators.Agile_NET { public Decrypter5(PeImage peImage, CodeHeader codeHeader, uint codeHeaderSize) : base(peImage, codeHeader) { - this.codeHeaderSize = codeHeaderSize; + this.codeHeaderSize = codeHeaderSize; } public override MethodBodyHeader decrypt(MethodInfo methodInfo, out byte[] code, out byte[] extraSections) { @@ -434,7 +435,7 @@ namespace de4dot.code.deobfuscators.Agile_NET { Error, } - public bool decrypt(PeImage peImage, Mono.Cecil.ModuleDefinition module, CliSecureRtType csRtType, ref DumpedMethods dumpedMethods) { + public bool decrypt(PeImage peImage, ModuleDefMD module, CliSecureRtType csRtType, ref DumpedMethods dumpedMethods) { this.peImage = peImage; this.csRtType = csRtType; this.module = module; @@ -446,7 +447,7 @@ namespace de4dot.code.deobfuscators.Agile_NET { case DecryptResult.Error: Log.w("Using dynamic method decryption"); byte[] moduleCctorBytes = getModuleCctorBytes(csRtType); - dumpedMethods = de4dot.code.deobfuscators.MethodsDecrypter.decrypt(module.FullyQualifiedName, moduleCctorBytes); + dumpedMethods = de4dot.code.deobfuscators.MethodsDecrypter.decrypt(module.Location, moduleCctorBytes); return true; default: @@ -542,7 +543,7 @@ namespace de4dot.code.deobfuscators.Agile_NET { var dm = new DumpedMethod(); dm.token = 0x06000001 + (uint)i; - var method = (Mono.Cecil.MethodDef)module.LookupToken((int)dm.token); + var method = (MethodDef)module.ResolveMethod(MDToken.ToRID(dm.token)); if (method == null || method.DeclaringType == DotNetUtils.getModuleType(module)) continue; diff --git a/de4dot.code/deobfuscators/Agile_NET/ProxyCallFixer.cs b/de4dot.code/deobfuscators/Agile_NET/ProxyCallFixer.cs index 1883e78f..09aaaae5 100644 --- a/de4dot.code/deobfuscators/Agile_NET/ProxyCallFixer.cs +++ b/de4dot.code/deobfuscators/Agile_NET/ProxyCallFixer.cs @@ -25,13 +25,11 @@ using de4dot.blocks; namespace de4dot.code.deobfuscators.Agile_NET { class ProxyCallFixer : ProxyCallFixer1 { - IList memberReferences; - - public ProxyCallFixer(ModuleDefinition module) + public ProxyCallFixer(ModuleDefMD module) : base(module) { } - public ProxyCallFixer(ModuleDefinition module, ProxyCallFixer oldOne) + public ProxyCallFixer(ModuleDefMD module, ProxyCallFixer oldOne) : base(module) { foreach (var method in oldOne.delegateCreatorMethods) setDelegateCreatorMethod(lookup(method, "Could not find delegate creator method")); @@ -53,14 +51,14 @@ namespace de4dot.code.deobfuscators.Agile_NET { var instrs = cctor.Body.Instructions; if (instrs.Count != 3) return null; - if (!DotNetUtils.isLdcI4(instrs[0].OpCode.Code)) + if (!instrs[0].IsLdcI4()) return null; if (instrs[1].OpCode != OpCodes.Call || !isDelegateCreatorMethod(instrs[1].Operand as MethodDef)) return null; if (instrs[2].OpCode != OpCodes.Ret) return null; - int delegateToken = 0x02000001 + DotNetUtils.getLdcI4Value(instrs[0]); + int delegateToken = 0x02000001 + instrs[0].GetLdcI4Value(); if (type.MDToken.ToInt32() != delegateToken) { Log.w("Delegate token is not current type"); return null; @@ -69,11 +67,8 @@ namespace de4dot.code.deobfuscators.Agile_NET { return new object(); } - protected override void getCallInfo(object context, FieldDef field, out MethodReference calledMethod, out OpCode callOpcode) { - if (memberReferences == null) - memberReferences = new List(module.GetMemberReferences()); - - var name = field.Name; + protected override void getCallInfo(object context, FieldDef field, out IMethod calledMethod, out OpCode callOpcode) { + var name = field.Name.String; callOpcode = OpCodes.Call; if (name.EndsWith("%", StringComparison.Ordinal)) { callOpcode = OpCodes.Callvirt; @@ -81,9 +76,10 @@ namespace de4dot.code.deobfuscators.Agile_NET { } byte[] value = Convert.FromBase64String(name); int methodIndex = BitConverter.ToInt32(value, 0); // 0-based memberRef index - if (methodIndex >= memberReferences.Count) - throw new ApplicationException(string.Format("methodIndex ({0}) >= memberReferences.Count ({1})", methodIndex, memberReferences.Count)); - calledMethod = memberReferences[methodIndex] as MethodReference; + var mr = module.ResolveMemberRef((uint)methodIndex + 1); + if (mr == null || !mr.IsMethodRef) + throw new ApplicationException(string.Format("Invalid MemberRef index: {0}", methodIndex)); + calledMethod = mr; } } } diff --git a/de4dot.code/deobfuscators/Agile_NET/ResourceDecrypter.cs b/de4dot.code/deobfuscators/Agile_NET/ResourceDecrypter.cs index 9f4b5166..3766aff1 100644 --- a/de4dot.code/deobfuscators/Agile_NET/ResourceDecrypter.cs +++ b/de4dot.code/deobfuscators/Agile_NET/ResourceDecrypter.cs @@ -20,12 +20,13 @@ using System.IO; using System.Security.Cryptography; using System.Text; +using dot10.IO; using dot10.DotNet; using de4dot.blocks; namespace de4dot.code.deobfuscators.Agile_NET { class ResourceDecrypter { - ModuleDefinition module; + ModuleDefMD module; TypeDef rsrcType; MethodDef rsrcRrrMethod; MethodDef rsrcResolveMethod; @@ -42,18 +43,18 @@ namespace de4dot.code.deobfuscators.Agile_NET { get { return rsrcRrrMethod; } } - public ResourceDecrypter(ModuleDefinition module) { + public ResourceDecrypter(ModuleDefMD module) { this.module = module; } - public ResourceDecrypter(ModuleDefinition module, ResourceDecrypter oldOne) { + public ResourceDecrypter(ModuleDefMD module, ResourceDecrypter oldOne) { this.module = module; rsrcType = lookup(oldOne.rsrcType, "Could not find rsrcType"); rsrcRrrMethod = lookup(oldOne.rsrcRrrMethod, "Could not find rsrcRrrMethod"); rsrcResolveMethod = lookup(oldOne.rsrcResolveMethod, "Could not find rsrcResolveMethod"); } - T lookup(T def, string errorMessage) where T : MemberReference { + T lookup(T def, string errorMessage) where T : class, ICodedToken { return DeobUtils.lookup(module, def, errorMessage); } @@ -99,23 +100,21 @@ namespace de4dot.code.deobfuscators.Agile_NET { var resource = DotNetUtils.getResource(module, DotNetUtils.getCodeStrings(rsrcResolveMethod)) as EmbeddedResource; if (resource == null) return null; - DeobUtils.decryptAndAddResources(module, resource.Name, () => decryptResource(resource)); + DeobUtils.decryptAndAddResources(module, resource.Name.String, () => decryptResource(resource)); return resource; } byte[] decryptResource(EmbeddedResource resource) { - using (var rsrcStream = resource.GetResourceStream()) { - using (var reader = new BinaryReader(rsrcStream)) { - var key = reader.ReadString(); - var data = reader.ReadBytes((int)(rsrcStream.Length - rsrcStream.Position)); - var cryptoTransform = new DESCryptoServiceProvider { - Key = Encoding.ASCII.GetBytes(key), - IV = Encoding.ASCII.GetBytes(key), - }.CreateDecryptor(); - var memStream = new MemoryStream(data); - using (var reader2 = new BinaryReader(new CryptoStream(memStream, cryptoTransform, CryptoStreamMode.Read))) { - return reader2.ReadBytes((int)memStream.Length); - } + using (var reader = resource.Data) { + var key = reader.ReadString(); + var data = reader.ReadBytes((int)(reader.Length - reader.Position)); + var cryptoTransform = new DESCryptoServiceProvider { + Key = Encoding.ASCII.GetBytes(key), + IV = Encoding.ASCII.GetBytes(key), + }.CreateDecryptor(); + var memStream = new MemoryStream(data); + using (var reader2 = new BinaryReader(new CryptoStream(memStream, cryptoTransform, CryptoStreamMode.Read))) { + return reader2.ReadBytes((int)memStream.Length); } } } diff --git a/de4dot.code/deobfuscators/Agile_NET/StackFrameHelper.cs b/de4dot.code/deobfuscators/Agile_NET/StackFrameHelper.cs index f4ef0696..7313c5e9 100644 --- a/de4dot.code/deobfuscators/Agile_NET/StackFrameHelper.cs +++ b/de4dot.code/deobfuscators/Agile_NET/StackFrameHelper.cs @@ -23,7 +23,7 @@ using de4dot.blocks; namespace de4dot.code.deobfuscators.Agile_NET { class StackFrameHelper { - ModuleDefinition module; + ModuleDefMD module; TypeDef stackFrameHelperType; ExceptionLoggerRemover exceptionLoggerRemover = new ExceptionLoggerRemover(); @@ -35,7 +35,7 @@ namespace de4dot.code.deobfuscators.Agile_NET { get { return exceptionLoggerRemover; } } - public StackFrameHelper(ModuleDefinition module) { + public StackFrameHelper(ModuleDefMD module) { this.module = module; } @@ -48,17 +48,16 @@ namespace de4dot.code.deobfuscators.Agile_NET { MethodDef errorMethod = null; foreach (var method in type.Methods) { - if (method.IsRuntimeSpecialName && method.Name == ".ctor" && !method.HasParameters) + if (method.Name == ".ctor") continue; // .ctor is allowed - if (method.IsRuntimeSpecialName && method.Name == ".cctor" && !method.HasParameters) + if (method.Name == ".cctor") continue; // .cctor is allowed - if (method.IsStatic && method.CallingConvention == MethodCallingConvention.Default && - method.ExplicitThis == false && method.HasThis == false && - method.HasBody && method.IsManaged && method.IsIL && method.HasParameters && - method.Parameters.Count == 2 && !method.HasGenericParameters && + var sig = method.MethodSig; + if (sig != null && method.IsStatic && method.HasBody && + sig.Params.Count == 2 && !method.HasGenericParameters && !DotNetUtils.hasReturnValue(method) && - method.Parameters[0].ParameterType.FullName == "System.Exception" && - method.Parameters[1].ParameterType.FullName == "System.Object[]") { + sig.Params[0].GetFullName() == "System.Exception" && + sig.Params[1].GetFullName() == "System.Object[]") { errorMethod = method; } else diff --git a/de4dot.code/deobfuscators/Agile_NET/StringDecrypter.cs b/de4dot.code/deobfuscators/Agile_NET/StringDecrypter.cs index 1d67c966..c7b858d6 100644 --- a/de4dot.code/deobfuscators/Agile_NET/StringDecrypter.cs +++ b/de4dot.code/deobfuscators/Agile_NET/StringDecrypter.cs @@ -23,7 +23,7 @@ using dot10.DotNet; namespace de4dot.code.deobfuscators.Agile_NET { class StringDecrypter { - ModuleDefinition module; + ModuleDefMD module; TypeDef stringDecrypterType; MethodDef stringDecrypterMethod; byte[] stringDecrypterKey; @@ -41,19 +41,19 @@ namespace de4dot.code.deobfuscators.Agile_NET { set { stringDecrypterMethod = value; } } - public StringDecrypter(ModuleDefinition module, MethodDef stringDecrypterMethod) { + public StringDecrypter(ModuleDefMD module, MethodDef stringDecrypterMethod) { this.module = module; this.stringDecrypterMethod = stringDecrypterMethod; } - public StringDecrypter(ModuleDefinition module, StringDecrypter oldOne) { + public StringDecrypter(ModuleDefMD module, StringDecrypter oldOne) { this.module = module; stringDecrypterType = lookup(oldOne.stringDecrypterType, "Could not find stringDecrypterType"); stringDecrypterMethod = lookup(oldOne.stringDecrypterMethod, "Could not find stringDecrypterMethod"); stringDecrypterKey = oldOne.stringDecrypterKey; } - T lookup(T def, string errorMessage) where T : MemberReference { + T lookup(T def, string errorMessage) where T : class, ICodedToken { return DeobUtils.lookup(module, def, errorMessage); } diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/CilOperandInstructionRestorer.cs b/de4dot.code/deobfuscators/Agile_NET/vm/CilOperandInstructionRestorer.cs index 65465f7a..4a5e9d4d 100644 --- a/de4dot.code/deobfuscators/Agile_NET/vm/CilOperandInstructionRestorer.cs +++ b/de4dot.code/deobfuscators/Agile_NET/vm/CilOperandInstructionRestorer.cs @@ -19,7 +19,6 @@ using dot10.DotNet; using dot10.DotNet.Emit; -using Mono.Cecil.Metadata; using de4dot.blocks; namespace de4dot.code.deobfuscators.Agile_NET.vm { @@ -43,13 +42,13 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { if (instr.Operand != null) continue; - TypeReference operandType = null; + TypeSig operandType = null; switch (instr.OpCode.Code) { case Code.Ldelema: - var arrayType = MethodStack.getLoadedType(method, instrs, i, 1) as ArrayType; + var arrayType = MethodStack.getLoadedType(method, instrs, i, 1) as SZArraySig; if (arrayType == null) break; - operandType = arrayType.ElementType; + operandType = arrayType.Next; break; case Code.Ldobj: @@ -70,58 +69,58 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { continue; } - instr.Operand = operandType; + instr.Operand = operandType.ToTypeDefOrRef(); } return !atLeastOneFailed; } - static TypeReference getPtrElementType(TypeReference type) { + static TypeSig getPtrElementType(TypeSig type) { if (type == null) return null; - var pt = type as PointerType; - if (pt != null) - return pt.ElementType; - var bt = type as ByReferenceType; - if (bt != null) - return bt.ElementType; + if (type.IsPointer || type.IsByRef) + return type.Next; return null; } - bool isValidType(TypeReference type) { + bool isValidType(TypeSig type) { + type = type.RemovePinnedAndModifiers(); if (type == null) return false; - if (type.EType == ElementType.Void) + if (type.ElementType == ElementType.Void) return false; while (type != null) { - switch (MemberReferenceHelper.getMemberReferenceType(type)) { - case CecilType.ArrayType: - case CecilType.GenericInstanceType: - case CecilType.PointerType: - case CecilType.TypeDef: - case CecilType.TypeReference: - case CecilType.FunctionPointerType: + switch (type.ElementType) { + case ElementType.SZArray: + case ElementType.Array: + case ElementType.GenericInst: + case ElementType.Ptr: + case ElementType.Class: + case ElementType.ValueType: + case ElementType.FnPtr: break; - case CecilType.GenericParam: - var gp = (GenericParam)type; - if (method.DeclaringType != gp.Owner && method != gp.Owner) + case ElementType.MVar: + var gmvar = (GenericMVar)type; + if (gmvar.Number >= method.MethodSig.GetGenParamCount()) return false; break; - case CecilType.ByReferenceType: - case CecilType.OptionalModifierType: - case CecilType.PinnedType: - case CecilType.RequiredModifierType: - case CecilType.SentinelType: + case ElementType.Var: + var gvar = (GenericVar)type; + var dt = method.DeclaringType; + if (dt == null || gvar.Number >= dt.GenericParams.Count) + return false; + break; + + case ElementType.ByRef: default: return false; } - - if (!(type is TypeSpecification)) + if (type.Next == null) break; - type = ((TypeSpecification)type).ElementType; + type = type.Next; } return type != null; diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/Csvm.cs b/de4dot.code/deobfuscators/Agile_NET/vm/Csvm.cs index 44bbe92f..5d22f5b4 100644 --- a/de4dot.code/deobfuscators/Agile_NET/vm/Csvm.cs +++ b/de4dot.code/deobfuscators/Agile_NET/vm/Csvm.cs @@ -26,9 +26,9 @@ using de4dot.blocks; namespace de4dot.code.deobfuscators.Agile_NET.vm { class Csvm { IDeobfuscatorContext deobfuscatorContext; - ModuleDefinition module; + ModuleDefMD module; EmbeddedResource resource; - AssemblyNameReference vmAssemblyReference; + AssemblyRef vmAssemblyReference; public bool Detected { get { return resource != null && vmAssemblyReference != null; } @@ -38,22 +38,22 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { get { return Detected ? resource : null; } } - public AssemblyNameReference VmAssemblyReference { + public AssemblyRef VmAssemblyReference { get { return Detected ? vmAssemblyReference : null; } } - public Csvm(IDeobfuscatorContext deobfuscatorContext, ModuleDefinition module) { + public Csvm(IDeobfuscatorContext deobfuscatorContext, ModuleDefMD module) { this.deobfuscatorContext = deobfuscatorContext; this.module = module; } - public Csvm(IDeobfuscatorContext deobfuscatorContext, ModuleDefinition module, Csvm oldOne) { + public Csvm(IDeobfuscatorContext deobfuscatorContext, ModuleDefMD module, Csvm oldOne) { this.deobfuscatorContext = deobfuscatorContext; this.module = module; if (oldOne.resource != null) this.resource = (EmbeddedResource)module.Resources[oldOne.module.Resources.IndexOf(oldOne.resource)]; if (oldOne.vmAssemblyReference != null) - this.vmAssemblyReference = module.AssemblyReferences[oldOne.module.AssemblyReferences.IndexOf(oldOne.vmAssemblyReference)]; + this.vmAssemblyReference = module.ResolveAssemblyRef(oldOne.vmAssemblyReference.Rid); } public void find() { @@ -61,13 +61,12 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { vmAssemblyReference = findVmAssemblyReference(); } - AssemblyNameReference findVmAssemblyReference() { - foreach (var memberRef in module.GetMemberReferences()) { - var method = memberRef as MethodReference; - if (method == null) + AssemblyRef findVmAssemblyReference() { + foreach (var memberRef in module.GetMemberRefs()) { + if (!memberRef.IsMethodRef) continue; - if (method.FullName == "System.Object VMRuntime.Libraries.CSVMRuntime::RunMethod(System.String,System.Object[])") - return method.DeclaringType.Scope as AssemblyNameReference; + if (memberRef.FullName == "System.Object VMRuntime.Libraries.CSVMRuntime::RunMethod(System.String,System.Object[])") + return memberRef.DeclaringType.Scope as AssemblyRef; } return null; } @@ -94,11 +93,11 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { Log.indent(); var opcodeDetector = getVmOpCodeHandlerDetector(); - var csvmMethods = new CsvmDataReader(resource.GetResourceStream()).read(); + var csvmMethods = new CsvmDataReader(resource.Data).read(); var converter = new CsvmToCilMethodConverter(deobfuscatorContext, module, opcodeDetector); var methodPrinter = new MethodPrinter(); foreach (var csvmMethod in csvmMethods) { - var cilMethod = module.LookupToken(csvmMethod.Token) as MethodDef; + var cilMethod = module.ResolveToken(csvmMethod.Token) as MethodDef; if (cilMethod == null) throw new ApplicationException(string.Format("Could not find method {0:X8}", csvmMethod.Token)); converter.convert(cilMethod, csvmMethod); @@ -117,8 +116,8 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { Log.v("Locals:"); Log.indent(); - for (int i = 0; i < method.Body.Variables.Count; i++) - Log.v("#{0}: {1}", i, method.Body.Variables[i].VariableType); + for (int i = 0; i < method.Body.LocalList.Count; i++) + Log.v("#{0}: {1}", i, method.Body.LocalList[i].Type); Log.deIndent(); Log.v("Code:"); @@ -131,7 +130,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { VmOpCodeHandlerDetector getVmOpCodeHandlerDetector() { var vmFilename = vmAssemblyReference.Name + ".dll"; - var vmModulePath = Path.Combine(Path.GetDirectoryName(module.FullyQualifiedName), vmFilename); + var vmModulePath = Path.Combine(Path.GetDirectoryName(module.Location), vmFilename); Log.v("CSVM filename: {0}", vmFilename); var dataKey = "cs cached VmOpCodeHandlerDetector"; @@ -141,7 +140,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { VmOpCodeHandlerDetector detector; if (dict.TryGetValue(vmModulePath, out detector)) return detector; - dict[vmModulePath] = detector = new VmOpCodeHandlerDetector(ModuleDefinition.ReadModule(vmModulePath)); + dict[vmModulePath] = detector = new VmOpCodeHandlerDetector(ModuleDefMD.Load(vmModulePath)); detector.findHandlers(); Log.v("CSVM opcodes:"); diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/CsvmDataReader.cs b/de4dot.code/deobfuscators/Agile_NET/vm/CsvmDataReader.cs index 1efea978..c4201947 100644 --- a/de4dot.code/deobfuscators/Agile_NET/vm/CsvmDataReader.cs +++ b/de4dot.code/deobfuscators/Agile_NET/vm/CsvmDataReader.cs @@ -20,15 +20,16 @@ using System; using System.Collections.Generic; using System.IO; +using dot10.IO; using dot10.DotNet; using de4dot.blocks; namespace de4dot.code.deobfuscators.Agile_NET.vm { class CsvmDataReader { - BinaryReader reader; + IBinaryReader reader; - public CsvmDataReader(Stream stream) { - reader = new BinaryReader(stream); + public CsvmDataReader(IBinaryReader reader) { + this.reader = reader; } public List read() { diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/CsvmToCilMethodConverter.cs b/de4dot.code/deobfuscators/Agile_NET/vm/CsvmToCilMethodConverter.cs index 227bb866..ce8aa469 100644 --- a/de4dot.code/deobfuscators/Agile_NET/vm/CsvmToCilMethodConverter.cs +++ b/de4dot.code/deobfuscators/Agile_NET/vm/CsvmToCilMethodConverter.cs @@ -22,17 +22,16 @@ using System.Collections.Generic; using System.IO; using dot10.DotNet; using dot10.DotNet.Emit; -using Mono.Cecil.Metadata; using de4dot.blocks; namespace de4dot.code.deobfuscators.Agile_NET.vm { class CsvmToCilMethodConverter { IDeobfuscatorContext deobfuscatorContext; - ModuleDefinition module; + ModuleDefMD module; VmOpCodeHandlerDetector opCodeDetector; CilOperandInstructionRestorer operandRestorer = new CilOperandInstructionRestorer(); - public CsvmToCilMethodConverter(IDeobfuscatorContext deobfuscatorContext, ModuleDefinition module, VmOpCodeHandlerDetector opCodeDetector) { + public CsvmToCilMethodConverter(IDeobfuscatorContext deobfuscatorContext, ModuleDefMD module, VmOpCodeHandlerDetector opCodeDetector) { this.deobfuscatorContext = deobfuscatorContext; this.module = module; this.opCodeDetector = opCodeDetector; @@ -44,7 +43,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { var newExceptions = readExceptions(cilMethod, csvmMethod, newInstructions); fixInstructionOperands(newInstructions); - fixLocals(newInstructions, cilMethod.Body.Variables); + fixLocals(newInstructions, cilMethod.Body.LocalList); fixArgs(newInstructions, cilMethod); DotNetUtils.restoreBody(cilMethod, newInstructions, newExceptions); @@ -54,7 +53,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { restoreConstrainedPrefix(cilMethod); } - void fixLocals(IList instrs, IList locals) { + void fixLocals(IList instrs, IList locals) { foreach (var instr in instrs) { var op = instr.Operand as LocalOperand; if (op == null) @@ -64,7 +63,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { } } - static void updateLocalInstruction(Instruction instr, VariableDefinition local, int index) { + static void updateLocalInstruction(Instruction instr, Local local, int index) { object operand = null; OpCode opcode; @@ -135,19 +134,11 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { if (op == null) continue; - int argIndex = op.arg; - if (method.HasImplicitThis) - argIndex--; - ParameterDefinition arg; - if (argIndex == -1) - arg = method.Body.ThisParameter; - else - arg = method.Parameters[argIndex]; - updateArgInstruction(instr, arg, op.arg); + updateArgInstruction(instr, method.Parameters[op.arg], op.arg); } } - static void updateArgInstruction(Instruction instr, ParameterDefinition arg, int index) { + static void updateArgInstruction(Instruction instr, Parameter arg, int index) { switch (instr.OpCode.Code) { case Code.Ldarg: case Code.Ldarg_S: @@ -209,12 +200,12 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { List readInstructions(MethodDef cilMethod, CsvmMethodData csvmMethod) { var reader = new BinaryReader(new MemoryStream(csvmMethod.Instructions)); var instrs = new List(); - int offset = 0; + uint offset = 0; while (reader.BaseStream.Position < reader.BaseStream.Length) { int vmOpCode = reader.ReadUInt16(); var instr = opCodeDetector.Handlers[vmOpCode].Read(reader); instr.Offset = offset; - offset += getInstructionSize(instr); + offset += (uint)getInstructionSize(instr); instrs.Add(instr); } return instrs; @@ -230,8 +221,8 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { return instr.OpCode.Size + (op.targetDisplacements.Length + 1) * 4; } - List readLocals(MethodDef cilMethod, CsvmMethodData csvmMethod) { - var locals = new List(); + List readLocals(MethodDef cilMethod, CsvmMethodData csvmMethod) { + var locals = new List(); var reader = new BinaryReader(new MemoryStream(csvmMethod.Locals)); if (csvmMethod.Locals.Length == 0) @@ -243,63 +234,58 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { throw new ApplicationException("Invalid number of locals"); for (int i = 0; i < numLocals; i++) - locals.Add(new VariableDefinition(readTypeReference(reader))); + locals.Add(new Local(readTypeReference(reader))); return locals; } - TypeReference readTypeReference(BinaryReader reader) { + TypeSig readTypeReference(BinaryReader reader) { var etype = (ElementType)reader.ReadInt32(); switch (etype) { - case ElementType.Void: return module.TypeSystem.Void; - case ElementType.Boolean: return module.TypeSystem.Boolean; - case ElementType.Char: return module.TypeSystem.Char; - case ElementType.I1: return module.TypeSystem.SByte; - case ElementType.U1: return module.TypeSystem.Byte; - case ElementType.I2: return module.TypeSystem.Int16; - case ElementType.U2: return module.TypeSystem.UInt16; - case ElementType.I4: return module.TypeSystem.Int32; - case ElementType.U4: return module.TypeSystem.UInt32; - case ElementType.I8: return module.TypeSystem.Int64; - case ElementType.U8: return module.TypeSystem.UInt64; - case ElementType.R4: return module.TypeSystem.Single; - case ElementType.R8: return module.TypeSystem.Double; - case ElementType.String: return module.TypeSystem.String; - case ElementType.TypedByRef: return module.TypeSystem.TypedReference; - case ElementType.I: return module.TypeSystem.IntPtr; - case ElementType.U: return module.TypeSystem.UIntPtr; - case ElementType.Object: return module.TypeSystem.Object; + case ElementType.Void: return module.CorLibTypes.Void; + case ElementType.Boolean: return module.CorLibTypes.Boolean; + case ElementType.Char: return module.CorLibTypes.Char; + case ElementType.I1: return module.CorLibTypes.SByte; + case ElementType.U1: return module.CorLibTypes.Byte; + case ElementType.I2: return module.CorLibTypes.Int16; + case ElementType.U2: return module.CorLibTypes.UInt16; + case ElementType.I4: return module.CorLibTypes.Int32; + case ElementType.U4: return module.CorLibTypes.UInt32; + case ElementType.I8: return module.CorLibTypes.Int64; + case ElementType.U8: return module.CorLibTypes.UInt64; + case ElementType.R4: return module.CorLibTypes.Single; + case ElementType.R8: return module.CorLibTypes.Double; + case ElementType.String: return module.CorLibTypes.String; + case ElementType.TypedByRef: return module.CorLibTypes.TypedReference; + case ElementType.I: return module.CorLibTypes.IntPtr; + case ElementType.U: return module.CorLibTypes.UIntPtr; + case ElementType.Object: return module.CorLibTypes.Object; case ElementType.ValueType: case ElementType.Var: case ElementType.MVar: - return (TypeReference)module.LookupToken(reader.ReadInt32()); + return (module.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef).ToTypeSig(); case ElementType.GenericInst: etype = (ElementType)reader.ReadInt32(); if (etype == ElementType.ValueType) - return (TypeReference)module.LookupToken(reader.ReadInt32()); + return (module.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef).ToTypeSig(); // ElementType.Class - return module.TypeSystem.Object; + return module.CorLibTypes.Object; case ElementType.Ptr: case ElementType.Class: case ElementType.Array: case ElementType.FnPtr: - case ElementType.SzArray: + case ElementType.SZArray: case ElementType.ByRef: - case ElementType.CModReqD: + case ElementType.CModReqd: case ElementType.CModOpt: case ElementType.Internal: - case ElementType.Modifier: case ElementType.Sentinel: case ElementType.Pinned: - case ElementType.Type: - case ElementType.Boxed: - case ElementType.Enum: - case ElementType.None: default: - return module.TypeSystem.Object; + return module.CorLibTypes.Object; } } @@ -321,7 +307,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { eh.HandlerStart = getInstruction(cilInstructions, reader.ReadInt32()); eh.HandlerEnd = getInstructionEnd(cilInstructions, reader.ReadInt32()); if (eh.HandlerType == ExceptionHandlerType.Catch) - eh.CatchType = (TypeReference)module.LookupToken(reader.ReadInt32()); + eh.CatchType = module.ResolveToken(reader.ReadUInt32()) as ITypeDefOrRef; else if (eh.HandlerType == ExceptionHandlerType.Filter) eh.FilterStart = getInstruction(cilInstructions, reader.ReadInt32()); @@ -387,9 +373,9 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { throw new ApplicationException(string.Format("Unknown operand type: {0}", vmOperand.GetType())); } - FieldReference fixLoadStoreFieldInstruction(Instruction instr, int token, OpCode staticInstr, OpCode instanceInstr) { - var fieldRef = (FieldReference)module.LookupToken(token); - var field = deobfuscatorContext.resolve(fieldRef); + IField fixLoadStoreFieldInstruction(Instruction instr, int token, OpCode staticInstr, OpCode instanceInstr) { + var fieldRef = module.ResolveToken(token) as IField; + var field = deobfuscatorContext.resolveField(fieldRef); bool isStatic; if (field == null) { Log.w("Could not resolve field {0:X8}. Assuming it's not static.", token); @@ -401,8 +387,8 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { return fieldRef; } - MemberReference getMemberReference(int token) { - var memberRef = module.LookupToken(token) as MemberReference; + ITokenOperand getMemberReference(int token) { + var memberRef = module.ResolveToken(token) as ITokenOperand; if (memberRef == null) throw new ApplicationException(string.Format("Could not find member ref: {0:X8}", token)); return memberRef; @@ -418,15 +404,18 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { if (instr.OpCode.Code != Code.Callvirt) continue; - var calledMethod = instr.Operand as MethodReference; - if (calledMethod == null || !calledMethod.HasThis) + var calledMethod = instr.Operand as IMethod; + if (calledMethod == null) continue; - var thisType = MethodStack.getLoadedType(method, instrs, i, calledMethod.Parameters.Count) as ByReferenceType; + var sig = calledMethod.MethodSig; + if (sig == null || !sig.HasThis) + continue; + var thisType = MethodStack.getLoadedType(method, instrs, i, sig.Params.Count) as ByRefSig; if (thisType == null) continue; if (hasPrefix(instrs, i, Code.Constrained)) continue; - instrs.Insert(i, Instruction.Create(OpCodes.Constrained, thisType.ElementType)); + instrs.Insert(i, Instruction.Create(OpCodes.Constrained, thisType.Next.ToTypeDefOrRef())); i++; } } diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/FieldsInfo.cs b/de4dot.code/deobfuscators/Agile_NET/vm/FieldsInfo.cs index cb96c93b..1d12513c 100644 --- a/de4dot.code/deobfuscators/Agile_NET/vm/FieldsInfo.cs +++ b/de4dot.code/deobfuscators/Agile_NET/vm/FieldsInfo.cs @@ -33,11 +33,11 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { public FieldsInfo(IEnumerable fields) { foreach (var field in fields) { - var fieldTypeDef = field.FieldType as TypeDef; + var fieldTypeDef = field.FieldSig.GetFieldType().TryGetTypeDef(); if (fieldTypeDef != null && fieldTypeDef.IsEnum) addEnum(); else - add(field.FieldType); + add(field.FieldSig.GetFieldType()); } } @@ -50,8 +50,8 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { } } - void add(TypeReference type) { - add(type.FullName); + void add(TypeSig type) { + add(type.GetFullName()); } void add(string typeFullName) { diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/OpCodeHandler.cs b/de4dot.code/deobfuscators/Agile_NET/vm/OpCodeHandler.cs index 016d51eb..b9cc6b31 100644 --- a/de4dot.code/deobfuscators/Agile_NET/vm/OpCodeHandler.cs +++ b/de4dot.code/deobfuscators/Agile_NET/vm/OpCodeHandler.cs @@ -23,7 +23,6 @@ using System.IO; using de4dot.blocks; using dot10.DotNet; using dot10.DotNet.Emit; -using Mono.Cecil.Metadata; namespace de4dot.code.deobfuscators.Agile_NET.vm { partial class OpCodeHandler { @@ -248,7 +247,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { new InstructionInfo2 { First = false, Second = true, Value = 12, OpCode = OpCodes.Stelem_R4 }, new InstructionInfo2 { First = false, Second = true, Value = 13, OpCode = OpCodes.Stelem_R8 }, new InstructionInfo2 { First = false, Second = true, Value = 28, OpCode = OpCodes.Stelem_Ref }, - new InstructionInfo2 { First = false, Second = false, Value = 0, OpCode = OpCodes.Stelem_Any }, + new InstructionInfo2 { First = false, Second = false, Value = 0, OpCode = OpCodes.Stelem }, new InstructionInfo2 { First = true, Second = true, Value = 24, OpCode = OpCodes.Ldelem_I }, new InstructionInfo2 { First = true, Second = true, Value = 4, OpCode = OpCodes.Ldelem_I1 }, @@ -261,7 +260,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { new InstructionInfo2 { First = true, Second = true, Value = 12, OpCode = OpCodes.Ldelem_R4 }, new InstructionInfo2 { First = true, Second = true, Value = 13, OpCode = OpCodes.Ldelem_R8 }, new InstructionInfo2 { First = true, Second = true, Value = 28, OpCode = OpCodes.Ldelem_Ref }, - new InstructionInfo2 { First = true, Second = false, Value = 0, OpCode = OpCodes.Ldelem_Any }, + new InstructionInfo2 { First = true, Second = false, Value = 0, OpCode = OpCodes.Ldelem }, }; static Instruction ldelem_read(BinaryReader reader) { Instruction instr = null; @@ -463,7 +462,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { } static bool rethrow_check(UnknownHandlerInfo info) { - return info.ExecuteMethod.Body.Variables.Count == 0; + return info.ExecuteMethod.Body.LocalList.Count == 0; } static Instruction rethrow_read(BinaryReader reader) { diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/UnknownHandlerInfo.cs b/de4dot.code/deobfuscators/Agile_NET/vm/UnknownHandlerInfo.cs index ac2127a0..f2d923e1 100644 --- a/de4dot.code/deobfuscators/Agile_NET/vm/UnknownHandlerInfo.cs +++ b/de4dot.code/deobfuscators/Agile_NET/vm/UnknownHandlerInfo.cs @@ -83,7 +83,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { if (method.Body == null) continue; foreach (var instr in method.Body.Instructions) { - var fieldRef = instr.Operand as FieldReference; + var fieldRef = instr.Operand as IField; if (fieldRef == null) continue; var field = typeFields.find(fieldRef); @@ -119,7 +119,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { throw new ApplicationException("Found another read method"); readMethod = method; } - else if (!DotNetUtils.hasReturnValue(method) && method.Parameters.Count == 1) { + else if (!DotNetUtils.hasReturnValue(method) && method.MethodSig.GetParamCount() == 1) { if (executeMethod != null) throw new ApplicationException("Found another execute method"); executeMethod = method; @@ -146,8 +146,8 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { foreach (var instr in method.Body.Instructions) { if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt) continue; - var calledMethod = instr.Operand as MethodReference; - if (!MemberReferenceHelper.compareMethodReferenceAndDeclaringType(calledMethod, csvmInfo.PopMethod)) + var calledMethod = instr.Operand as IMethod; + if (!MethodEqualityComparer.CompareDeclaringTypes.Equals(calledMethod, csvmInfo.PopMethod)) continue; count++; diff --git a/de4dot.code/deobfuscators/Agile_NET/vm/VmOpCodeHandlerDetector.cs b/de4dot.code/deobfuscators/Agile_NET/vm/VmOpCodeHandlerDetector.cs index 6b556be2..dafb6917 100644 --- a/de4dot.code/deobfuscators/Agile_NET/vm/VmOpCodeHandlerDetector.cs +++ b/de4dot.code/deobfuscators/Agile_NET/vm/VmOpCodeHandlerDetector.cs @@ -44,14 +44,14 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { } class VmOpCodeHandlerDetector { - ModuleDefinition module; + ModuleDefMD module; List opCodeHandlers; public List Handlers { get { return opCodeHandlers; } } - public VmOpCodeHandlerDetector(ModuleDefinition module) { + public VmOpCodeHandlerDetector(ModuleDefMD module) { this.module = module; } @@ -88,10 +88,10 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { int enumTypes = 0; int objectTypes = 0; foreach (var field in type.Fields) { - var fieldType = field.FieldType as TypeDef; + var fieldType = field.FieldSig.GetFieldType().TryGetTypeDef(); if (fieldType != null && fieldType.IsEnum) enumTypes++; - if (field.FieldType.FullName == "System.Object") + if (field.FieldSig.GetFieldType().GetElementType() == ElementType.Object) objectTypes++; } if (enumTypes != 1 || objectTypes != 1) @@ -109,7 +109,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { } bool isStackType(TypeDef type, TypeDef stackValueType) { - if (type.Interfaces.Count != 2) + if (type.InterfaceImpls.Count != 2) return false; if (!implementsInterface(type, "System.Collections.ICollection")) return false; @@ -124,11 +124,14 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { foreach (var field in type.Fields) { if (field.IsLiteral) continue; - if (field.FieldType is ArrayType && ((ArrayType)field.FieldType).ElementType == stackValueType) + var fieldType = field.FieldSig.GetFieldType(); + if (fieldType == null) + continue; + if (fieldType.IsSZArray && fieldType.Next.TryGetTypeDef() == stackValueType) stackValueTypes++; - if (field.FieldType.FullName == "System.Int32") + if (fieldType.ElementType == ElementType.I4) int32Types++; - if (field.FieldType.FullName == "System.Object") + if (fieldType.ElementType == ElementType.Object) objectTypes++; } if (stackValueTypes != 2 || int32Types != 2 || objectTypes != 1) @@ -138,8 +141,8 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { } static bool implementsInterface(TypeDef type, string ifaceName) { - foreach (var iface in type.Interfaces) { - if (iface.FullName == ifaceName) + foreach (var iface in type.InterfaceImpls) { + if (iface.Interface.FullName == ifaceName) return true; } return false; @@ -147,7 +150,8 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { void initStackTypeMethods(CsvmInfo csvmInfo) { foreach (var method in csvmInfo.Stack.Methods) { - if (method.Parameters.Count == 0 && method.MethodReturnType.ReturnType == csvmInfo.StackValue) { + var sig = method.MethodSig; + if (sig != null && sig.Params.Count == 0 && sig.RetType.TryGetTypeDef() == csvmInfo.StackValue) { if (hasAdd(method)) csvmInfo.PopMethod = method; else @@ -172,7 +176,7 @@ namespace de4dot.code.deobfuscators.Agile_NET.vm { }; var cflowDeobfuscator = new CflowDeobfuscator(); foreach (var type in module.Types) { - var cctor = DotNetUtils.getMethod(type, ".cctor"); + var cctor = type.FindClassConstructor(); if (cctor == null) continue; requiredFields[0] = type.FullName; diff --git a/de4dot.cui/Program.cs b/de4dot.cui/Program.cs index 1f8340a5..a487156a 100644 --- a/de4dot.cui/Program.cs +++ b/de4dot.cui/Program.cs @@ -37,9 +37,9 @@ namespace de4dot.cui { static IList createDeobfuscatorInfos() { return new List { new de4dot.code.deobfuscators.Unknown.DeobfuscatorInfo(), + new de4dot.code.deobfuscators.Agile_NET.DeobfuscatorInfo(), #if PORT new de4dot.code.deobfuscators.Babel_NET.DeobfuscatorInfo(), - new de4dot.code.deobfuscators.Agile_NET.DeobfuscatorInfo(), new de4dot.code.deobfuscators.CodeFort.DeobfuscatorInfo(), new de4dot.code.deobfuscators.CodeVeil.DeobfuscatorInfo(), new de4dot.code.deobfuscators.CodeWall.DeobfuscatorInfo(), diff --git a/dot10 b/dot10 index cf50ec12..13f15527 160000 --- a/dot10 +++ b/dot10 @@ -1 +1 @@ -Subproject commit cf50ec12f7cc258eb23cad730eee638b65e8dfc8 +Subproject commit 13f15527e9b8f99c2fddfd386714835a0f4b9d0b