From f6b5a3117f2a4163f82f64ddc6bab05c12829156 Mon Sep 17 00:00:00 2001 From: de4dot Date: Thu, 8 Nov 2012 09:48:05 +0100 Subject: [PATCH] Port CodeVeil deobfuscator --- blocks/DotNetUtils.cs | 14 ++-- de4dot.code/de4dot.code.csproj | 30 ++++---- .../CodeVeil/AssemblyResolver.cs | 40 ++++++----- .../deobfuscators/CodeVeil/Deobfuscator.cs | 3 +- .../CodeVeil/ErexResourceReader.cs | 24 +++---- .../CodeVeil/InvalidMethodsFinder.cs | 16 +++-- .../deobfuscators/CodeVeil/MainType.cs | 22 +++--- .../CodeVeil/MethodsDecrypter.cs | 4 +- .../deobfuscators/CodeVeil/ProxyCallFixer.cs | 51 +++++++------- .../CodeVeil/ResourceConverter.cs | 7 +- .../CodeVeil/ResourceDecrypter.cs | 70 ++++++++++--------- .../deobfuscators/CodeVeil/ResourceInfo.cs | 4 +- .../deobfuscators/CodeVeil/ResourceReader.cs | 18 ++--- .../deobfuscators/CodeVeil/StringDecrypter.cs | 27 +++---- .../deobfuscators/CodeVeil/TamperDetection.cs | 11 ++- de4dot.code/deobfuscators/DeobUtils.cs | 13 ++++ de4dot.cui/Program.cs | 2 +- dot10 | 2 +- 18 files changed, 189 insertions(+), 169 deletions(-) diff --git a/blocks/DotNetUtils.cs b/blocks/DotNetUtils.cs index 3b00dd69..f72b4a80 100644 --- a/blocks/DotNetUtils.cs +++ b/blocks/DotNetUtils.cs @@ -265,8 +265,7 @@ namespace de4dot.blocks { return null; } -#if PORT - public static MethodDef getPInvokeMethod(TypeDefinition type, string dll, string funcName) { + public static MethodDef getPInvokeMethod(TypeDef type, string dll, string funcName) { foreach (var method in type.Methods) { if (isPinvokeMethod(method, dll, funcName)) return method; @@ -277,11 +276,12 @@ namespace de4dot.blocks { public static bool isPinvokeMethod(MethodDef method, string dll, string funcName) { if (method == null) return false; - if (method.PInvokeInfo == null || method.PInvokeInfo.EntryPoint != funcName) + if (method.ImplMap == null || method.ImplMap.Name.String != funcName) return false; - return getDllName(dll).Equals(getDllName(method.PInvokeInfo.Module.Name), StringComparison.OrdinalIgnoreCase); + return getDllName(dll).Equals(getDllName(method.ImplMap.Scope.Name.String), StringComparison.OrdinalIgnoreCase); } +#if PORT public static MethodDef getMethod(TypeDefinition type, string name) { if (type == null) return null; @@ -418,17 +418,17 @@ namespace de4dot.blocks { return type.FindField(fieldReference.Name, fieldReference.FieldSig); } -#if PORT - public static FieldDefinition getField(TypeDefinition type, string typeFullName) { + public static FieldDef getField(TypeDef type, string typeFullName) { if (type == null) return null; foreach (var field in type.Fields) { - if (field.FieldType.FullName == typeFullName) + if (field.FieldSig.GetFieldType().GetFullName() == typeFullName) return field; } return null; } +#if PORT public static FieldDefinition getFieldByName(TypeDefinition type, string name) { if (type == null) return null; diff --git a/de4dot.code/de4dot.code.csproj b/de4dot.code/de4dot.code.csproj index 6cf04e0f..ace0b2d3 100644 --- a/de4dot.code/de4dot.code.csproj +++ b/de4dot.code/de4dot.code.csproj @@ -100,21 +100,21 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/de4dot.code/deobfuscators/CodeVeil/AssemblyResolver.cs b/de4dot.code/deobfuscators/CodeVeil/AssemblyResolver.cs index 5ad69231..b1be506c 100644 --- a/de4dot.code/deobfuscators/CodeVeil/AssemblyResolver.cs +++ b/de4dot.code/deobfuscators/CodeVeil/AssemblyResolver.cs @@ -20,13 +20,14 @@ using System.Collections.Generic; using System.IO; using System.Xml; +using dot10.IO; using dot10.DotNet; using dot10.DotNet.Emit; using de4dot.blocks; namespace de4dot.code.deobfuscators.CodeVeil { class AssemblyResolver { - ModuleDefinition module; + ModuleDefMD module; EmbeddedResource bundleData; EmbeddedResource bundleXmlFile; TypeDef bundleType; @@ -95,7 +96,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { get { return bundleXmlFile; } } - public AssemblyResolver(ModuleDefinition module) { + public AssemblyResolver(ModuleDefMD module) { this.module = module; } @@ -124,10 +125,10 @@ namespace de4dot.code.deobfuscators.CodeVeil { } void findEmbeddedAssemblies() { - var data = bundleData.GetResourceData(); + var data = bundleData.Data.ReadAllBytes(); var doc = new XmlDocument(); - doc.Load(XmlReader.Create(bundleXmlFile.GetResourceStream())); + doc.Load(XmlReader.Create(new MemoryStream(bundleXmlFile.Data.ReadAllBytes()))); var manifest = doc.DocumentElement; if (manifest.Name.ToLowerInvariant() != "manifest") { Log.w("Could not find Manifest element"); @@ -150,7 +151,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { } var assemblyData = DeobUtils.inflate(data, offset, data.Length - offset, true); - var mod = ModuleDefinition.ReadModule(new MemoryStream(assemblyData)); + var mod = ModuleDefMD.Load(assemblyData); infos.Add(new AssemblyInfo(mod.Assembly.FullName, DeobUtils.getExtension(mod.Kind), assemblyData)); } } @@ -174,7 +175,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { if (type.Fields.Count != 2) continue; - var ctor = DotNetUtils.getMethod(type, ".ctor"); + var ctor = type.FindMethod(".ctor"); if (ctor == null || !ctor.IsPrivate) continue; if (!DotNetUtils.isMethod(ctor, "System.Void", "(System.Reflection.Assembly)")) @@ -234,7 +235,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { return; foreach (var field in bundleType.Fields) { - var type = field.FieldType as TypeDef; + var type = field.FieldSig.GetFieldType().TryGetTypeDef(); if (type == null) continue; if (type == bundleType) @@ -242,10 +243,13 @@ namespace de4dot.code.deobfuscators.CodeVeil { if (type.Fields.Count != 2) continue; - var ctor = DotNetUtils.getMethod(type, ".ctor"); - if (ctor == null || ctor.Parameters.Count != 2) + var ctor = type.FindMethod(".ctor"); + if (ctor == null) continue; - var iface = ctor.Parameters[1].ParameterType as TypeDef; + var sig = ctor.MethodSig; + if (sig == null || sig.Params.Count != 2) + continue; + var iface = sig.Params[1].TryGetTypeDef(); if (iface == null || !iface.IsInterface) continue; @@ -259,22 +263,22 @@ namespace de4dot.code.deobfuscators.CodeVeil { if (assemblyManagerType == null) return; foreach (var field in assemblyManagerType.Fields) { - var type = field.FieldType as TypeDef; + var type = field.FieldSig.GetFieldType().TryGetTypeDef(); if (type == null || type.IsInterface) continue; - var ctor = DotNetUtils.getMethod(type, ".ctor"); + var ctor = type.FindMethod(".ctor"); if (!DotNetUtils.isMethod(ctor, "System.Void", "()")) continue; if (type.Fields.Count != 1) continue; - var git = type.Fields[0].FieldType as GenericInstanceType; + var git = type.Fields[0].FieldSig.GetFieldType().ToGenericInstSig(); if (git == null) continue; - if (git.ElementType.FullName != "System.Collections.Generic.List`1") + if (git.GenericType.FullName != "System.Collections.Generic.List`1") continue; if (git.GenericArguments.Count != 1) continue; - var type2 = git.GenericArguments[0] as TypeDef; + var type2 = git.GenericArguments[0].TryGetTypeDef(); if (type2 == null) continue; @@ -287,7 +291,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { void findStreamProviderType() { if (bundleType == null) return; - var ctor = DotNetUtils.getMethod(bundleType, ".ctor"); + var ctor = bundleType.FindMethod(".ctor"); if (!DotNetUtils.isMethod(ctor, "System.Void", "(System.Reflection.Assembly)")) return; foreach (var instr in ctor.Body.Instructions) { @@ -301,9 +305,9 @@ namespace de4dot.code.deobfuscators.CodeVeil { if (!DotNetUtils.isMethod(newobjCtor, "System.Void", "(System.Reflection.Assembly,System.String)")) continue; var type = newobjCtor.DeclaringType; - if (type.Interfaces.Count != 1) + if (type.InterfaceImpls.Count != 1) continue; - if (type.Interfaces[0] != bundleStreamProviderIFace) + if (type.InterfaceImpls[0].Interface != bundleStreamProviderIFace) continue; streamProviderType = type; diff --git a/de4dot.code/deobfuscators/CodeVeil/Deobfuscator.cs b/de4dot.code/deobfuscators/CodeVeil/Deobfuscator.cs index c9b9ea6d..cd036737 100644 --- a/de4dot.code/deobfuscators/CodeVeil/Deobfuscator.cs +++ b/de4dot.code/deobfuscators/CodeVeil/Deobfuscator.cs @@ -20,7 +20,6 @@ using System; using System.Collections.Generic; using dot10.DotNet; -using Mono.MyStuff; using de4dot.blocks; namespace de4dot.code.deobfuscators.CodeVeil { @@ -161,7 +160,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { return true; } - public override IDeobfuscator moduleReloaded(ModuleDefinition module) { + public override IDeobfuscator moduleReloaded(ModuleDefMD module) { var newOne = new Deobfuscator(options); newOne.setModule(module); newOne.mainType = new MainType(module, mainType); diff --git a/de4dot.code/deobfuscators/CodeVeil/ErexResourceReader.cs b/de4dot.code/deobfuscators/CodeVeil/ErexResourceReader.cs index 49ddba94..80eb5c7d 100644 --- a/de4dot.code/deobfuscators/CodeVeil/ErexResourceReader.cs +++ b/de4dot.code/deobfuscators/CodeVeil/ErexResourceReader.cs @@ -19,14 +19,15 @@ using System; using System.IO; +using dot10.IO; namespace de4dot.code.deobfuscators.CodeVeil { class ErexResourceReader { - BinaryReader reader; + IBinaryReader reader; uint[] key; - public ErexResourceReader(Stream stream) { - reader = new BinaryReader(stream); + public ErexResourceReader(IBinaryReader reader) { + this.reader = reader; } public byte[] decrypt() { @@ -47,10 +48,10 @@ namespace de4dot.code.deobfuscators.CodeVeil { readKey(); if (isDeflated) - reader = new BinaryReader(inflate(length)); + reader = inflate(length); if (isEncrypted) - reader = new BinaryReader(decrypt(length)); + reader = decrypt(length); return reader.ReadBytes(length); } @@ -61,17 +62,17 @@ namespace de4dot.code.deobfuscators.CodeVeil { key[i] = reader.ReadUInt32(); } - Stream inflate(int length) { - var data = reader.ReadBytes((int)(reader.BaseStream.Length - reader.BaseStream.Position)); - return new MemoryStream(DeobUtils.inflate(data, true)); + IBinaryReader inflate(int length) { + var data = reader.ReadRemainingBytes(); + return MemoryImageStream.Create(DeobUtils.inflate(data, true)); } - Stream decrypt(int length) { + IBinaryReader decrypt(int length) { var block = new uint[4]; var decrypted = new byte[16]; var outStream = new MemoryStream(length); - while (reader.BaseStream.Position < reader.BaseStream.Length) { + while (reader.Position < reader.Length) { block[0] = reader.ReadUInt32(); block[1] = reader.ReadUInt32(); block[2] = reader.ReadUInt32(); @@ -81,8 +82,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { outStream.Write(decrypted, 0, decrypted.Length); } - outStream.Position = 0; - return outStream; + return MemoryImageStream.Create(outStream.ToArray()); } } } diff --git a/de4dot.code/deobfuscators/CodeVeil/InvalidMethodsFinder.cs b/de4dot.code/deobfuscators/CodeVeil/InvalidMethodsFinder.cs index a9603fa7..7cce295f 100644 --- a/de4dot.code/deobfuscators/CodeVeil/InvalidMethodsFinder.cs +++ b/de4dot.code/deobfuscators/CodeVeil/InvalidMethodsFinder.cs @@ -22,7 +22,7 @@ using dot10.DotNet; namespace de4dot.code.deobfuscators.CodeVeil { class InvalidMethodsFinder { - public static List findAll(ModuleDefinition module) { + public static List findAll(ModuleDefMD module) { var list = new List(); foreach (var type in module.GetTypes()) { foreach (var method in type.Methods) { @@ -34,17 +34,19 @@ namespace de4dot.code.deobfuscators.CodeVeil { } public static bool isInvalidMethod(MethodDef method) { - if (method == null) + if (method == null || method.IsStatic) return false; - if (method.IsStatic) + var sig = method.MethodSig; + if (sig == null || sig.Params.Count != 0) return false; - if (method.Parameters.Count != 0) - return false; - var retType = method.MethodReturnType.ReturnType as GenericParam; + var retType = sig.RetType as GenericSig; if (retType == null) return false; - return retType.Owner == null; + if (retType.IsMethodVar) + return retType.Number >= sig.GenParamCount; + var dt = method.DeclaringType; + return dt == null || retType.Number >= dt.GenericParams.Count; } } } diff --git a/de4dot.code/deobfuscators/CodeVeil/MainType.cs b/de4dot.code/deobfuscators/CodeVeil/MainType.cs index 53270418..7c79ae46 100644 --- a/de4dot.code/deobfuscators/CodeVeil/MainType.cs +++ b/de4dot.code/deobfuscators/CodeVeil/MainType.cs @@ -20,18 +20,17 @@ using System.Collections.Generic; using dot10.DotNet; using dot10.DotNet.Emit; -using Mono.Cecil.Metadata; using de4dot.blocks; namespace de4dot.code.deobfuscators.CodeVeil { // Detects the type CV adds to the assembly that gets called from ::.cctor. class MainType { - ModuleDefinition module; + ModuleDefMD module; TypeDef theType; MethodDef initMethod; MethodDef tamperCheckMethod; ObfuscatorVersion obfuscatorVersion = ObfuscatorVersion.Unknown; - List rvas = new List(); // _stub and _executive + List rvas = new List(); // _stub and _executive List otherInitMethods = new List(); public bool Detected { @@ -58,15 +57,15 @@ namespace de4dot.code.deobfuscators.CodeVeil { get { return tamperCheckMethod; } } - public List Rvas { + public List Rvas { get { return rvas; } } - public MainType(ModuleDefinition module) { + public MainType(ModuleDefMD module) { this.module = module; } - public MainType(ModuleDefinition module, MainType oldOne) { + public MainType(ModuleDefMD module, MainType oldOne) { this.module = module; this.theType = lookup(oldOne.theType, "Could not find main type"); this.initMethod = lookup(oldOne.initMethod, "Could not find main type init method"); @@ -89,11 +88,11 @@ namespace de4dot.code.deobfuscators.CodeVeil { var instrs = cctor.Body.Instructions; for (int i = 0; i < instrs.Count - 2; i++) { var ldci4_1 = instrs[i]; - if (!DotNetUtils.isLdcI4(ldci4_1)) + if (!ldci4_1.IsLdcI4()) continue; var ldci4_2 = instrs[i + 1]; - if (!DotNetUtils.isLdcI4(ldci4_2)) + if (!ldci4_2.IsLdcI4()) continue; var call = instrs[i + 2]; @@ -155,21 +154,22 @@ namespace de4dot.code.deobfuscators.CodeVeil { } bool checkMethodsType(TypeDef type) { - rvas = new List(); + rvas = new List(); var fields = getRvaFields(type); if (fields.Count < 2) // RVAs for executive and stub are always present if encrypted methods return true; foreach (var field in fields) - rvas.Add(field.RVA); + rvas.Add((uint)field.RVA); return true; } static List getRvaFields(TypeDef type) { var fields = new List(); foreach (var field in type.Fields) { - if (field.FieldType.EType != ElementType.U1 && field.FieldType.EType != ElementType.U4) + var etype = field.FieldSig.GetFieldType().GetElementType(); + if (etype != ElementType.U1 && etype != ElementType.U4) continue; if (field.RVA == 0) continue; diff --git a/de4dot.code/deobfuscators/CodeVeil/MethodsDecrypter.cs b/de4dot.code/deobfuscators/CodeVeil/MethodsDecrypter.cs index d9888304..dc6e1af7 100644 --- a/de4dot.code/deobfuscators/CodeVeil/MethodsDecrypter.cs +++ b/de4dot.code/deobfuscators/CodeVeil/MethodsDecrypter.cs @@ -22,8 +22,6 @@ using System.Collections.Generic; using System.IO; using dot10.DotNet; using dot10.DotNet.Emit; -using Mono.Cecil.Metadata; -using Mono.MyStuff; using de4dot.blocks; using de4dot.PE; @@ -226,7 +224,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { return null; // rva is 0 when the assembly has been embedded - int rva = BitConverter.ToInt32(fileData, offset + RVA_EXECUTIVE_OFFSET); + uint rva = BitConverter.ToUInt32(fileData, offset + RVA_EXECUTIVE_OFFSET); if (rva != 0 && mainType.Rvas.IndexOf(rva) < 0) continue; diff --git a/de4dot.code/deobfuscators/CodeVeil/ProxyCallFixer.cs b/de4dot.code/deobfuscators/CodeVeil/ProxyCallFixer.cs index df3b3429..df3c9ba9 100644 --- a/de4dot.code/deobfuscators/CodeVeil/ProxyCallFixer.cs +++ b/de4dot.code/deobfuscators/CodeVeil/ProxyCallFixer.cs @@ -20,16 +20,16 @@ using System; using System.Collections.Generic; using System.IO; +using dot10.IO; using dot10.DotNet; using dot10.DotNet.Emit; -using Mono.Cecil.Metadata; using de4dot.blocks; namespace de4dot.code.deobfuscators.CodeVeil { class ProxyCallFixer : ProxyCallFixer1 { MainType mainType; Info info = new Info(); - BinaryReader reader; + IBinaryReader reader; class Info { public TypeDef proxyType; @@ -73,12 +73,12 @@ namespace de4dot.code.deobfuscators.CodeVeil { get { return info.methodInfoType; } } - public ProxyCallFixer(ModuleDefinition module, MainType mainType) + public ProxyCallFixer(ModuleDefMD module, MainType mainType) : base(module) { this.mainType = mainType; } - public ProxyCallFixer(ModuleDefinition module, MainType mainType, ProxyCallFixer oldOne) + public ProxyCallFixer(ModuleDefMD module, MainType mainType, ProxyCallFixer oldOne) : base(module, oldOne) { this.mainType = mainType; info.proxyType = lookup(oldOne.info.proxyType, "Could not find proxyType"); @@ -93,7 +93,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { var instrs = cctor.Body.Instructions; for (int i = 0; i < instrs.Count - 1; i++) { var ldci4 = instrs[i]; - if (!DotNetUtils.isLdcI4(ldci4)) + if (!ldci4.IsLdcI4()) continue; var call = instrs[i + 1]; @@ -102,24 +102,24 @@ namespace de4dot.code.deobfuscators.CodeVeil { if (call.Operand != info.initMethod) continue; - int offset = DotNetUtils.getLdcI4Value(ldci4); - reader.BaseStream.Position = offset; - int rid = DeobUtils.readVariableLengthInt32(reader); - if (rid != type.MDToken.RID) + int offset = ldci4.GetLdcI4Value(); + reader.Position = offset; + uint rid = reader.ReadCompressedUInt32(); + if (rid != type.Rid) throw new ApplicationException("Invalid RID"); return string.Empty; // It's non-null } return null; } - protected override void getCallInfo(object context, FieldDef field, out MethodReference calledMethod, out OpCode callOpcode) { + protected override void getCallInfo(object context, FieldDef field, out IMethod calledMethod, out OpCode callOpcode) { byte flags = reader.ReadByte(); - int methodToken = 0x06000000 + ((flags & 0x3F) << 24) + DeobUtils.readVariableLengthInt32(reader); - int genericTypeToken = (flags & 0x40) == 0 ? -1 : 0x1B000000 + DeobUtils.readVariableLengthInt32(reader); + int methodToken = 0x06000000 + ((flags & 0x3F) << 24) + (int)reader.ReadCompressedUInt32(); + int genericTypeToken = (flags & 0x40) == 0 ? -1 : 0x1B000000 + (int)reader.ReadCompressedUInt32(); callOpcode = (flags & 0x80) != 0 ? OpCodes.Callvirt : OpCodes.Call; - calledMethod = module.LookupToken(methodToken) as MethodReference; + calledMethod = module.ResolveToken(methodToken) as IMethod; if (calledMethod == null) throw new ApplicationException("Could not find method"); if (genericTypeToken != -1 && calledMethod.DeclaringType.MDToken.ToInt32() != genericTypeToken) @@ -140,7 +140,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { bool initializeInfo(Info infoTmp, TypeDef type) { foreach (var dtype in type.NestedTypes) { - var cctor = DotNetUtils.getMethod(dtype, ".cctor"); + var cctor = dtype.FindMethod(".cctor"); if (cctor == null) continue; if (!initProxyType(infoTmp, cctor)) @@ -186,7 +186,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { if (fields.Count != 1) return false; var field = fields[0]; - var fieldType = DotNetUtils.getType(module, field.FieldType); + var fieldType = DotNetUtils.getType(module, field.FieldSig.GetFieldType()); if (type.NestedTypes.IndexOf(fieldType) < 0) return false; if (field.InitialValue == null || field.InitialValue.Length == 0) @@ -218,8 +218,8 @@ namespace de4dot.code.deobfuscators.CodeVeil { findOtherTypes(); var decompressed = DeobUtils.inflate(info.dataField.InitialValue, true); - reader = new BinaryReader(new MemoryStream(decompressed)); - info.dataField.FieldType = module.TypeSystem.Byte; + reader = MemoryImageStream.Create(decompressed); + info.dataField.FieldSig.Type = module.CorLibTypes.Byte; info.dataField.InitialValue = new byte[1]; } @@ -228,14 +228,15 @@ namespace de4dot.code.deobfuscators.CodeVeil { return; foreach (var method in info.proxyType.Methods) { - if (method.Parameters.Count != 4) + var sig = method.MethodSig; + if (sig == null || sig.Params.Count != 4) continue; - if (method.Parameters[2].ParameterType.FullName != "System.Type[]") + if (sig.Params[2].GetFullName() != "System.Type[]") continue; - var methodType = method.Parameters[0].ParameterType as TypeDef; - var fieldType = method.Parameters[1].ParameterType as TypeDef; - var ilgType = method.Parameters[3].ParameterType as TypeDef; + var methodType = sig.Params[0].TryGetTypeDef(); + var fieldType = sig.Params[1].TryGetTypeDef(); + var ilgType = sig.Params[3].TryGetTypeDef(); if (!checkMethodType(methodType)) continue; if (!checkFieldType(fieldType)) @@ -250,7 +251,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { } bool checkMethodType(TypeDef type) { - if (type == null || type.BaseType == null || type.BaseType.EType != ElementType.Object) + if (type == null || type.BaseType == null || type.BaseType.FullName != "System.Object") return false; if (type.Fields.Count != 1) return false; @@ -261,7 +262,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { } bool checkFieldType(TypeDef type) { - if (type == null || type.BaseType == null || type.BaseType.EType != ElementType.Object) + if (type == null || type.BaseType == null || type.BaseType.FullName != "System.Object") return false; if (DotNetUtils.getField(type, "System.Reflection.FieldInfo") == null) return false; @@ -270,7 +271,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { } bool checkIlGeneratorType(TypeDef type) { - if (type == null || type.BaseType == null || type.BaseType.EType != ElementType.Object) + if (type == null || type.BaseType == null || type.BaseType.FullName != "System.Object") return false; if (type.Fields.Count != 1) return false; diff --git a/de4dot.code/deobfuscators/CodeVeil/ResourceConverter.cs b/de4dot.code/deobfuscators/CodeVeil/ResourceConverter.cs index 9a05275f..34d2c3cf 100644 --- a/de4dot.code/deobfuscators/CodeVeil/ResourceConverter.cs +++ b/de4dot.code/deobfuscators/CodeVeil/ResourceConverter.cs @@ -19,16 +19,17 @@ using System; using System.IO; +using dot10.IO; using dot10.DotNet; using de4dot.code.resources; namespace de4dot.code.deobfuscators.CodeVeil { class ResourceConverter { - ModuleDefinition module; + ModuleDefMD module; ResourceInfo[] infos; ResourceDataCreator dataCreator; - public ResourceConverter(ModuleDefinition module, ResourceInfo[] infos) { + public ResourceConverter(ModuleDefMD module, ResourceInfo[] infos) { this.module = module; this.dataCreator = new ResourceDataCreator(module); this.infos = infos; @@ -46,7 +47,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { ResourceElement convert(ResourceInfo info) { var reader = info.dataReader; - reader.BaseStream.Position = info.offset; + reader.Position = info.offset; IResourceData resourceData; int type = (info.flags & 0x7F); diff --git a/de4dot.code/deobfuscators/CodeVeil/ResourceDecrypter.cs b/de4dot.code/deobfuscators/CodeVeil/ResourceDecrypter.cs index 650cc868..b086d0d8 100644 --- a/de4dot.code/deobfuscators/CodeVeil/ResourceDecrypter.cs +++ b/de4dot.code/deobfuscators/CodeVeil/ResourceDecrypter.cs @@ -19,19 +19,19 @@ using System; using System.IO; +using dot10.IO; using dot10.DotNet; using dot10.DotNet.Emit; -using Mono.Cecil.Metadata; using de4dot.blocks; namespace de4dot.code.deobfuscators.CodeVeil { class ResourceDecrypter { - ModuleDefinition module; + ModuleDefMD module; TypeDef encryptedResourceStreamType; TypeDef encryptedResourceSetType; MethodDef encryptedResourceSet_GetDefaultReader; TypeDef encryptedResourceReaderType; - GenericInstanceType encryptedResourceReaderTypeDict; + GenericInstSig encryptedResourceReaderTypeDict; TypeDef resType; MethodDef resTypeCtor; TypeDef resourceFlagsType; @@ -73,7 +73,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { get { return resourceEnumeratorType; } } - public ResourceDecrypter(ModuleDefinition module) { + public ResourceDecrypter(ModuleDefMD module) { this.module = module; } @@ -100,18 +100,19 @@ namespace de4dot.code.deobfuscators.CodeVeil { foreach (var type in module.Types) { if (type.Namespace != "") continue; - if (type.BaseType == null || type.BaseType.EType != ElementType.Object) + if (type.BaseType == null || type.BaseType.FullName != "System.Object") continue; if (!hasInterface(type, "System.Collections.IDictionaryEnumerator")) continue; if (!new FieldTypes(type).all(resourceEnumeratorType_fields)) continue; - var ctor = DotNetUtils.getMethod(type, ".ctor"); + var ctor = type.FindMethod(".ctor"); if (ctor == null) continue; - if (ctor.Parameters.Count != 1) + var sig = ctor.MethodSig; + if (sig == null || sig.Params.Count != 1) continue; - if (ctor.Parameters[0].ParameterType != encryptedResourceReaderType) + if (sig.Params[0].TryGetTypeDef() != encryptedResourceReaderType) continue; resourceEnumeratorType = type; @@ -120,9 +121,12 @@ namespace de4dot.code.deobfuscators.CodeVeil { } void findResourceFlags() { - if (resTypeCtor == null || resTypeCtor.Parameters.Count != 4) + if (resTypeCtor == null) return; - var type = resTypeCtor.Parameters[2].ParameterType as TypeDef; + var sig = resTypeCtor.MethodSig; + if (sig == null || sig.Params.Count != 4) + return; + var type = sig.Params[2].TryGetTypeDef(); if (type == null || !type.IsEnum) return; @@ -137,13 +141,16 @@ namespace de4dot.code.deobfuscators.CodeVeil { void findResType() { if (encryptedResourceReaderTypeDict == null) return; - var type = encryptedResourceReaderTypeDict.GenericArguments[1] as TypeDef; + var type = encryptedResourceReaderTypeDict.GenericArguments[1].TryGetTypeDef(); if (type == null) return; - if (type.BaseType == null || type.BaseType.EType != ElementType.Object) + if (type.BaseType == null || type.BaseType.FullName != "System.Object") return; - var ctor = DotNetUtils.getMethod(type, ".ctor"); - if (ctor == null || ctor.Parameters.Count != 4) + var ctor = type.FindMethod(".ctor"); + if (ctor == null) + return; + var sig = ctor.MethodSig; + if (sig == null || sig.Params.Count != 4) return; resTypeCtor = ctor; @@ -176,25 +183,25 @@ namespace de4dot.code.deobfuscators.CodeVeil { } static bool hasInterface(TypeDef type, string interfaceFullName) { - foreach (var iface in type.Interfaces) { - if (iface.FullName == interfaceFullName) + foreach (var iface in type.InterfaceImpls) { + if (iface.Interface.FullName == interfaceFullName) return true; } return false; } - static GenericInstanceType getDlxResDict(TypeDef type) { + static GenericInstSig getDlxResDict(TypeDef type) { foreach (var field in type.Fields) { - var fieldType = field.FieldType as GenericInstanceType; + var fieldType = field.FieldSig.GetFieldType().ToGenericInstSig(); if (fieldType == null) continue; - if (fieldType.ElementType.FullName != "System.Collections.Generic.Dictionary`2") + if (fieldType.GenericType.FullName != "System.Collections.Generic.Dictionary`2") continue; if (fieldType.GenericArguments.Count != 2) continue; if (fieldType.GenericArguments[0].FullName != "System.String") continue; - if (!(fieldType.GenericArguments[1] is TypeDef)) + if (fieldType.GenericArguments[1].TryGetTypeDef() == null) continue; return fieldType; } @@ -221,10 +228,10 @@ namespace de4dot.code.deobfuscators.CodeVeil { continue; if (type.BaseType == null || type.BaseType.FullName != "System.Resources.ResourceSet") continue; - var ctor = DotNetUtils.getMethod(type, ".ctor"); + var ctor = type.FindMethod(".ctor"); if (!DotNetUtils.isMethod(ctor, "System.Void", "(System.Resources.IResourceReader)")) continue; - var method = DotNetUtils.getMethod(type, "GetDefaultReader"); + var method = type.FindMethod("GetDefaultReader"); if (!DotNetUtils.isMethod(method, "System.Type", "()")) continue; if (method.Body == null || method.IsStatic || !method.IsVirtual) @@ -252,7 +259,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { continue; if (type.BaseType == null || type.BaseType.FullName != "System.IO.Stream") continue; - var ctor = DotNetUtils.getMethod(type, ".ctor"); + var ctor = type.FindMethod(".ctor"); if (!DotNetUtils.isMethod(ctor, "System.Void", "(System.IO.Stream)")) continue; if (!new FieldTypes(type).all(encryptedResourceStreamType_fields)) @@ -312,21 +319,20 @@ namespace de4dot.code.deobfuscators.CodeVeil { if (resource == null) continue; - var decrypted = decrypt(resource.GetResourceStream()); + var decrypted = decrypt(resource.Data); if (decrypted == null) continue; Log.v("Decrypted resource {0}", Utils.toCsharpString(resource.Name)); - module.Resources[i] = new EmbeddedResource(resource.Name, resource.Attributes, decrypted); + module.Resources[i] = new EmbeddedResource(resource.Name, decrypted, resource.Flags); } } - byte[] decrypt(Stream stream) { + byte[] decrypt(IBinaryReader reader) { try { - stream.Position = 0; - var reader = new BinaryReader(stream); + reader.Position = 0; uint sig = reader.ReadUInt32(); - stream.Position = 0; + reader.Position = 0; if (sig == 0xBEEFCACE) return decryptBeefcace(reader); if (sig == 0x58455245) @@ -342,13 +348,13 @@ namespace de4dot.code.deobfuscators.CodeVeil { } } - byte[] decryptBeefcace(BinaryReader reader) { + byte[] decryptBeefcace(IBinaryReader reader) { var resourceReader = new ResourceReader(reader); return new ResourceConverter(module, resourceReader.read()).convert(); } - byte[] decryptErex(BinaryReader reader) { - return new ErexResourceReader(reader.BaseStream).decrypt(); + byte[] decryptErex(IBinaryReader reader) { + return new ErexResourceReader(reader).decrypt(); } public void deobfuscate(Blocks blocks) { diff --git a/de4dot.code/deobfuscators/CodeVeil/ResourceInfo.cs b/de4dot.code/deobfuscators/CodeVeil/ResourceInfo.cs index 291c5765..65698343 100644 --- a/de4dot.code/deobfuscators/CodeVeil/ResourceInfo.cs +++ b/de4dot.code/deobfuscators/CodeVeil/ResourceInfo.cs @@ -18,7 +18,7 @@ */ using System; -using System.IO; +using dot10.IO; namespace de4dot.code.deobfuscators.CodeVeil { class ResourceInfo { @@ -26,7 +26,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { public byte flags; public int offset; public int length; - public BinaryReader dataReader; + public IBinaryReader dataReader; public ResourceInfo(string name, byte flags, int offset, int length) { this.name = name; this.flags = flags; diff --git a/de4dot.code/deobfuscators/CodeVeil/ResourceReader.cs b/de4dot.code/deobfuscators/CodeVeil/ResourceReader.cs index 84b33378..ec286192 100644 --- a/de4dot.code/deobfuscators/CodeVeil/ResourceReader.cs +++ b/de4dot.code/deobfuscators/CodeVeil/ResourceReader.cs @@ -21,10 +21,11 @@ using System; using System.Collections.Generic; using System.IO; using System.Text; +using dot10.IO; namespace de4dot.code.deobfuscators.CodeVeil { class ResourceReader { - BinaryReader reader; + IBinaryReader reader; string resourceReader; string resourceSet; @@ -36,12 +37,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { get { return resourceSet; } } - public ResourceReader(Stream stream) { - stream.Position = 0; - reader = new BinaryReader(stream); - } - - public ResourceReader(BinaryReader reader) { + public ResourceReader(IBinaryReader reader) { this.reader = reader; } @@ -93,13 +89,13 @@ namespace de4dot.code.deobfuscators.CodeVeil { DeobUtils.xxteaDecrypt(encryptedData, key); byte[] decryptedData = new byte[encryptedData.Length * 4]; Buffer.BlockCopy(encryptedData, 0, decryptedData, 0, decryptedData.Length); - dataReader = new BinaryReader(new MemoryStream(decryptedData)); + dataReader = MemoryImageStream.Create(decryptedData); } if (inflateData) { - var data = dataReader.ReadBytes((int)(dataReader.BaseStream.Length - dataReader.BaseStream.Position)); + var data = dataReader.ReadRemainingBytes(); data = DeobUtils.inflate(data, true); - dataReader = new BinaryReader(new MemoryStream(data)); + dataReader = MemoryImageStream.Create(data); } foreach (var info in infos) @@ -108,7 +104,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { return infos; } - static string readResourceName(BinaryReader reader, bool encrypted) { + static string readResourceName(IBinaryReader reader, bool encrypted) { if (!encrypted) return reader.ReadString(); diff --git a/de4dot.code/deobfuscators/CodeVeil/StringDecrypter.cs b/de4dot.code/deobfuscators/CodeVeil/StringDecrypter.cs index 811a2886..cab30692 100644 --- a/de4dot.code/deobfuscators/CodeVeil/StringDecrypter.cs +++ b/de4dot.code/deobfuscators/CodeVeil/StringDecrypter.cs @@ -19,13 +19,14 @@ using System; using System.IO; +using dot10.IO; using dot10.DotNet; using dot10.DotNet.Emit; using de4dot.blocks; namespace de4dot.code.deobfuscators.CodeVeil { class StringDecrypter { - ModuleDefinition module; + ModuleDefMD module; MainType mainType; TypeDef decrypterType; FieldDef stringDataField; @@ -49,12 +50,12 @@ namespace de4dot.code.deobfuscators.CodeVeil { get { return decrypterMethod; } } - public StringDecrypter(ModuleDefinition module, MainType mainType) { + public StringDecrypter(ModuleDefMD module, MainType mainType) { this.module = module; this.mainType = mainType; } - public StringDecrypter(ModuleDefinition module, MainType mainType, StringDecrypter oldOne) { + public StringDecrypter(ModuleDefMD module, MainType mainType, StringDecrypter oldOne) { this.module = module; this.mainType = mainType; this.decrypterType = lookup(oldOne.decrypterType, "Could not find string decrypter type"); @@ -121,7 +122,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { var stringDataFieldTmp = checkFields(type); if (stringDataFieldTmp == null) return false; - var fieldType = DotNetUtils.getType(module, stringDataFieldTmp.FieldType); + var fieldType = DotNetUtils.getType(module, stringDataFieldTmp.FieldSig.GetFieldType()); if (fieldType == null || type.NestedTypes.IndexOf(fieldType) < 0) return false; @@ -189,7 +190,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { decryptStrings(key); - stringDataField.FieldType = module.TypeSystem.Byte; + stringDataField.FieldSig.Type = module.CorLibTypes.Byte; stringDataField.InitialValue = new byte[1]; } @@ -197,9 +198,9 @@ namespace de4dot.code.deobfuscators.CodeVeil { var instrs = method.Body.Instructions; for (int i = 0; i < instrs.Count - 1; i++) { var ldci4 = instrs[i]; - if (!DotNetUtils.isLdcI4(ldci4)) + if (!ldci4.IsLdcI4()) continue; - if (DotNetUtils.getLdcI4Value(ldci4) != 4) + if (ldci4.GetLdcI4Value() != 4) continue; if (instrs[i + 1].OpCode.Code != Code.Newarr) @@ -225,16 +226,16 @@ namespace de4dot.code.deobfuscators.CodeVeil { Buffer.BlockCopy(encryptedData, 0, decryptedData, 0, data.Length); var inflated = DeobUtils.inflate(decryptedData, 0, decryptedData.Length, true); - var reader = new BinaryReader(new MemoryStream(inflated)); - int deflatedLength = DeobUtils.readVariableLengthInt32(reader); - int numStrings = DeobUtils.readVariableLengthInt32(reader); + var reader = MemoryImageStream.Create(inflated); + int deflatedLength = (int)reader.ReadCompressedUInt32(); + int numStrings = (int)reader.ReadCompressedUInt32(); decryptedStrings = new string[numStrings]; var offsets = new int[numStrings]; for (int i = 0; i < numStrings; i++) - offsets[i] = DeobUtils.readVariableLengthInt32(reader); - int startOffset = (int)reader.BaseStream.Position; + offsets[i] = (int)reader.ReadCompressedUInt32(); + int startOffset = (int)reader.Position; for (int i = 0; i < numStrings; i++) { - reader.BaseStream.Position = startOffset + offsets[i]; + reader.Position = startOffset + offsets[i]; decryptedStrings[i] = reader.ReadString(); } } diff --git a/de4dot.code/deobfuscators/CodeVeil/TamperDetection.cs b/de4dot.code/deobfuscators/CodeVeil/TamperDetection.cs index 92b2df88..db49dee2 100644 --- a/de4dot.code/deobfuscators/CodeVeil/TamperDetection.cs +++ b/de4dot.code/deobfuscators/CodeVeil/TamperDetection.cs @@ -20,12 +20,11 @@ using System.Collections.Generic; using dot10.DotNet; using dot10.DotNet.Emit; -using Mono.Cecil.Metadata; using de4dot.blocks; namespace de4dot.code.deobfuscators.CodeVeil { class TamperDetection { - ModuleDefinition module; + ModuleDefMD module; MainType mainType; TypeDef tamperDetectionType; List tamperDetectionMethods = new List(); @@ -38,7 +37,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { get { return tamperDetectionMethods; } } - public TamperDetection(ModuleDefinition module, MainType mainType) { + public TamperDetection(ModuleDefMD module, MainType mainType) { this.module = module; this.mainType = mainType; } @@ -57,7 +56,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { foreach (var type in module.Types) { if (!type.HasNestedTypes) continue; - if ((type.Attributes & ~TypeAttributes.Sealed) != 0) + if ((type.Flags & ~TypeAttributes.Sealed) != 0) continue; if (!checkTamperDetectionClasses(type.NestedTypes)) @@ -91,9 +90,9 @@ namespace de4dot.code.deobfuscators.CodeVeil { } bool isTamperDetectionClass(TypeDef type) { - if (type.BaseType == null || type.BaseType.EType != ElementType.Object) + if (type.BaseType == null || type.BaseType.FullName != "System.Object") return false; - if ((type.Attributes & ~TypeAttributes.Sealed) != TypeAttributes.NestedAssembly) + if ((type.Flags & ~TypeAttributes.Sealed) != TypeAttributes.NestedAssembly) return false; MethodDef cctor = null, initMethod = null; diff --git a/de4dot.code/deobfuscators/DeobUtils.cs b/de4dot.code/deobfuscators/DeobUtils.cs index 4dd6c6cb..22e8fefa 100644 --- a/de4dot.code/deobfuscators/DeobUtils.cs +++ b/de4dot.code/deobfuscators/DeobUtils.cs @@ -189,6 +189,19 @@ namespace de4dot.code.deobfuscators { return null; } + //TODO: Remove this method + public static int readVariableLengthInt32(BinaryReader reader) { + byte b = reader.ReadByte(); + if ((b & 0x80) == 0) + return b; + if ((b & 0x40) == 0) + return (((int)b & 0x3F) << 8) + reader.ReadByte(); + return (((int)b & 0x3F) << 24) + + ((int)reader.ReadByte() << 16) + + ((int)reader.ReadByte() << 8) + + reader.ReadByte(); + } + public static int readVariableLengthInt32(byte[] data, ref int index) { byte b = data[index++]; if ((b & 0x80) == 0) diff --git a/de4dot.cui/Program.cs b/de4dot.cui/Program.cs index 93bad5f5..0db4dc10 100644 --- a/de4dot.cui/Program.cs +++ b/de4dot.cui/Program.cs @@ -40,8 +40,8 @@ namespace de4dot.cui { new de4dot.code.deobfuscators.Agile_NET.DeobfuscatorInfo(), new de4dot.code.deobfuscators.Babel_NET.DeobfuscatorInfo(), new de4dot.code.deobfuscators.CodeFort.DeobfuscatorInfo(), -#if PORT new de4dot.code.deobfuscators.CodeVeil.DeobfuscatorInfo(), +#if PORT new de4dot.code.deobfuscators.CodeWall.DeobfuscatorInfo(), new de4dot.code.deobfuscators.CryptoObfuscator.DeobfuscatorInfo(), new de4dot.code.deobfuscators.DeepSea.DeobfuscatorInfo(), diff --git a/dot10 b/dot10 index 5844915b..8cd1f845 160000 --- a/dot10 +++ b/dot10 @@ -1 +1 @@ -Subproject commit 5844915b880f422af17a3bcd234829ba32dcb6e5 +Subproject commit 8cd1f845241489cfafd6011c91e6516910600979