diff --git a/blocks/DotNetUtils.cs b/blocks/DotNetUtils.cs index 58459ada..bb69e215 100644 --- a/blocks/DotNetUtils.cs +++ b/blocks/DotNetUtils.cs @@ -26,6 +26,7 @@ using Mono.Cecil.Metadata; //TODO: Remove these using DN = dot10.DotNet; using DNE = dot10.DotNet.Emit; +using DNM = dot10.DotNet.MD; namespace de4dot.blocks { public enum FrameworkType { @@ -315,6 +316,40 @@ namespace de4dot.blocks { return null; } + public static DN.MethodDef getMethod2(DN.ModuleDef module, DN.IMethod method) { + if (method == null) + return null; + return getMethod(module, method, method.DeclaringType.ScopeType); + } + + static DN.TypeDef getType(DN.ModuleDef module, DN.ITypeDefOrRef type) { + var td = type as DN.TypeDef; + if (td != null) + return td; + + var tr = type as DN.TypeRef; + if (tr != null) + return tr.Resolve(); + + return null; + } + + static DN.MethodDef getMethod(DN.ModuleDef module, DN.IMethod method, DN.ITypeDefOrRef declaringType) { + if (method == null) + return null; + if (method is DN.MethodDef) + return (DN.MethodDef)method; + return getMethod(getType(module, declaringType), method); + } + + public static DN.MethodDef getMethod(DN.TypeDef type, DN.IMethod methodRef) { + if (type == null || methodRef == null) + return null; + if (methodRef is DN.MethodDef) + return (DN.MethodDef)methodRef; + return type.FindMethod(methodRef.Name, methodRef.MethodSig); + } + public static IEnumerable getNormalMethods(TypeDefinition type) { foreach (var method in type.Methods) { if (method.HasPInvokeInfo) @@ -413,11 +448,11 @@ namespace de4dot.blocks { return strings; } - public static Resource getResource(ModuleDefinition module, string name) { + public static DN.Resource getResource(DN.ModuleDef module, string name) { return getResource(module, new List { name }); } - public static Resource getResource(ModuleDefinition module, IEnumerable strings) { + public static DN.Resource getResource(DN.ModuleDef module, IEnumerable strings) { if (!module.HasResources) return null; @@ -426,8 +461,9 @@ namespace de4dot.blocks { var resourceName = removeFromNullChar(tmp); if (resourceName == null) continue; + var name = new DNM.UTF8String(resourceName); foreach (var resource in resources) { - if (resource.Name == resourceName) + if (DNM.UTF8String.Equals(resource.Name, name)) return resource; } } @@ -1052,6 +1088,14 @@ namespace de4dot.blocks { return typeRef; } + public static DN.TypeDefOrRefSig findOrCreateTypeReference(DN.ModuleDef module, DN.AssemblyRef asmRef, string ns, string name, bool isValueType) { + var typeRef = module.UpdateRowId(new DN.TypeRefUser(module, ns, name, asmRef)); + if (isValueType) + return new DN.ValueTypeSig(typeRef); + else + return new DN.ClassSig(typeRef); + } + public static FrameworkType getFrameworkType(ModuleDefinition module) { foreach (var modRef in module.AssemblyReferences) { if (modRef.Name != "mscorlib") diff --git a/de4dot.code/Utils.cs b/de4dot.code/Utils.cs index 6ece6e7b..7f440ab0 100644 --- a/de4dot.code/Utils.cs +++ b/de4dot.code/Utils.cs @@ -21,6 +21,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Text; +using dot10.DotNet.MD; namespace de4dot.code { // These are in .NET 3.5 and later... @@ -61,6 +62,10 @@ namespace de4dot.code { return dict.Keys; } + public static string toCsharpString(UTF8String s) { + return toCsharpString(UTF8String.ToSystemStringOrEmpty(s)); + } + public static string toCsharpString(string s) { var sb = new StringBuilder(s.Length + 2); sb.Append('"'); diff --git a/de4dot.code/deobfuscators/Babel_NET/ConstantsDecrypter.cs b/de4dot.code/deobfuscators/Babel_NET/ConstantsDecrypter.cs index 3ac7059b..49c1a6ff 100644 --- a/de4dot.code/deobfuscators/Babel_NET/ConstantsDecrypter.cs +++ b/de4dot.code/deobfuscators/Babel_NET/ConstantsDecrypter.cs @@ -254,7 +254,7 @@ namespace de4dot.code.deobfuscators.Babel_NET { var arrayType = castclass.Operand as ArrayType; if (arrayType == null) continue; - if (arrayType.ElementType.PrimitiveSize == -1) { + if (arrayType.ElementType.GetPrimitiveSize() == -1) { Log.w("Can't decrypt non-primitive type array in method {0}", blocks.Method.MetadataToken.ToInt32()); continue; } @@ -264,7 +264,7 @@ namespace de4dot.code.deobfuscators.Babel_NET { infos.Reverse(); foreach (var info in infos) { - var elemSize = info.arrayType.ElementType.PrimitiveSize; + var elemSize = info.arrayType.ElementType.GetPrimitiveSize(); var decrypted = decryptArray(info.encryptedField.InitialValue, elemSize); initializedDataCreator.addInitializeArrayCode(block, info.start, info.len, info.arrayType.ElementType, decrypted); diff --git a/de4dot.code/deobfuscators/DeobfuscatorBase.cs b/de4dot.code/deobfuscators/DeobfuscatorBase.cs index c99c05cc..fd30566d 100644 --- a/de4dot.code/deobfuscators/DeobfuscatorBase.cs +++ b/de4dot.code/deobfuscators/DeobfuscatorBase.cs @@ -19,14 +19,23 @@ using System; using System.Collections.Generic; -using Mono.Cecil; -using Mono.Cecil.Cil; -using Mono.MyStuff; +using dot10.DotNet; +using dot10.DotNet.Emit; using dot10.PE; using de4dot.blocks; using de4dot.blocks.cflow; namespace de4dot.code.deobfuscators { + //TODO: I added this iface to Cecil but now you must add something similar to dot10 + interface IWriterListener { + internal class MetadataBuilder { + //TODO: Dummy class. Don't use + } + + // Called before adding resources, and after adding types, methods, etc. + void OnBeforeAddingResources(MetadataBuilder builder); + } + abstract class DeobfuscatorBase : IDeobfuscator, IWriterListener { public const string DEFAULT_VALID_NAME_REGEX = @"^[a-zA-Z_<{$][a-zA-Z_0-9<>{}$.`-]*$"; @@ -40,15 +49,13 @@ namespace de4dot.code.deobfuscators { } OptionsBase optionsBase; - protected ModuleDefinition module; + protected ModuleDefMD module; protected StaticStringInliner staticStringInliner = new StaticStringInliner(); - IList> typesToRemove = new List>(); - IList> methodsToRemove = new List>(); - IList> fieldsToRemove = new List>(); - IList> attrsToRemove = new List>(); + IList> typesToRemove = new List>(); + IList> methodsToRemove = new List>(); + IList> fieldsToRemove = new List>(); + IList> attrsToRemove = new List>(); IList> resourcesToRemove = new List>(); - IList> modrefsToRemove = new List>(); - IList> asmrefsToRemove = new List>(); List namesToPossiblyRemove = new List(); MethodCallRemover methodCallRemover = new MethodCallRemover(); byte[] moduleBytes; @@ -95,7 +102,6 @@ namespace de4dot.code.deobfuscators { get { return Operations.DecryptStrings != OpDecryptString.None && staticStringInliner.InlinedAllCalls; } } -#if PORT public virtual IEnumerable BlocksDeobfuscators { get { var list = new List(); @@ -104,7 +110,6 @@ namespace de4dot.code.deobfuscators { return list; } } -#endif public DeobfuscatorBase(OptionsBase optionsBase) { this.optionsBase = optionsBase; @@ -116,11 +121,11 @@ namespace de4dot.code.deobfuscators { return null; } - public virtual void init(ModuleDefinition module) { + public virtual void init(ModuleDefMD module) { setModule(module); } - protected void setModule(ModuleDefinition module) { + protected void setModule(ModuleDefMD module) { this.module = module; initializedDataCreator = new InitializedDataCreator(module); } @@ -141,7 +146,7 @@ namespace de4dot.code.deobfuscators { return false; } - public virtual IDeobfuscator moduleReloaded(ModuleDefinition module) { + public virtual IDeobfuscator moduleReloaded(ModuleDefMD module) { throw new ApplicationException("moduleReloaded() must be overridden by the deobfuscator"); } @@ -173,21 +178,14 @@ namespace de4dot.code.deobfuscators { deleteFields(); deleteCustomAttributes(); deleteOtherAttributes(); - - // Delete types after removing methods, fields, and attributes. The reason is - // that the Scope property will be null if we remove a type. Comparing a - // typeref with a typedef will then fail. deleteTypes(); - deleteDllResources(); - deleteModuleReferences(); - deleteAssemblyReferences(); } restoreBaseType(); } - static bool isTypeWithInvalidBaseType(TypeDefinition moduleType, TypeDefinition type) { + static bool isTypeWithInvalidBaseType(TypeDef moduleType, TypeDef type) { return type.BaseType == null && !type.IsInterface && type != moduleType; } @@ -198,8 +196,8 @@ namespace de4dot.code.deobfuscators { continue; Log.v("Adding System.Object as base type: {0} ({1:X8})", Utils.removeNewlines(type), - type.MetadataToken.ToInt32()); - type.BaseType = module.TypeSystem.Object; + type.MDToken.ToInt32()); + type.BaseType = module.CorLibTypes.Object.TypeDefOrRef; } } @@ -219,7 +217,7 @@ namespace de4dot.code.deobfuscators { foreach (var field in type.Fields) { if (field.IsStatic) continue; - field.IsRuntimeSpecialName = true; + field.IsRTSpecialName = true; field.IsSpecialName = true; } } @@ -239,14 +237,15 @@ namespace de4dot.code.deobfuscators { Dictionary> methodNameInfos = new Dictionary>(); MethodDefinitionAndDeclaringTypeDict> methodRefInfos = new MethodDefinitionAndDeclaringTypeDict>(); - void checkMethod(MethodReference methodToBeRemoved) { - if (methodToBeRemoved.Parameters.Count != 0) + void checkMethod(IMethod methodToBeRemoved) { + var sig = methodToBeRemoved.MethodSig; + if (sig.Params.Count != 0) throw new ApplicationException(string.Format("Method takes params: {0}", methodToBeRemoved)); - if (DotNetUtils.hasReturnValue(methodToBeRemoved)) + if (sig.RetType.ElementType != ElementType.Void) throw new ApplicationException(string.Format("Method has a return value: {0}", methodToBeRemoved)); } - public void add(string method, MethodDefinition methodToBeRemoved) { + public void add(string method, MethodDef methodToBeRemoved) { if (methodToBeRemoved == null) return; checkMethod(methodToBeRemoved); @@ -257,7 +256,7 @@ namespace de4dot.code.deobfuscators { dict.add(methodToBeRemoved, true); } - public void add(MethodDefinition method, MethodDefinition methodToBeRemoved) { + public void add(MethodDef method, MethodDef methodToBeRemoved) { if (method == null || methodToBeRemoved == null) return; checkMethod(methodToBeRemoved); @@ -271,7 +270,7 @@ namespace de4dot.code.deobfuscators { public void removeAll(Blocks blocks) { var allBlocks = blocks.MethodBlocks.getAllBlocks(); - removeAll(allBlocks, blocks, blocks.Method.Name); + removeAll(allBlocks, blocks, blocks.Method.Name.String); removeAll(allBlocks, blocks, blocks.Method); } @@ -283,7 +282,7 @@ namespace de4dot.code.deobfuscators { removeCalls(allBlocks, blocks, info); } - void removeAll(IList allBlocks, Blocks blocks, MethodDefinition method) { + void removeAll(IList allBlocks, Blocks blocks, MethodDef method) { var info = methodRefInfos.find(method); if (info == null) return; @@ -299,7 +298,7 @@ namespace de4dot.code.deobfuscators { var instr = block.Instructions[i]; if (instr.OpCode != OpCodes.Call) continue; - var destMethod = instr.Operand as MethodReference; + var destMethod = instr.Operand as IMethod; if (destMethod == null) continue; @@ -313,19 +312,19 @@ namespace de4dot.code.deobfuscators { } } - public void addCctorInitCallToBeRemoved(MethodDefinition methodToBeRemoved) { + public void addCctorInitCallToBeRemoved(MethodDef methodToBeRemoved) { methodCallRemover.add(".cctor", methodToBeRemoved); } - public void addModuleCctorInitCallToBeRemoved(MethodDefinition methodToBeRemoved) { + public void addModuleCctorInitCallToBeRemoved(MethodDef methodToBeRemoved) { methodCallRemover.add(DotNetUtils.getModuleTypeCctor(module), methodToBeRemoved); } - public void addCtorInitCallToBeRemoved(MethodDefinition methodToBeRemoved) { + public void addCtorInitCallToBeRemoved(MethodDef methodToBeRemoved) { methodCallRemover.add(".ctor", methodToBeRemoved); } - public void addCallToBeRemoved(MethodDefinition method, MethodDefinition methodToBeRemoved) { + public void addCallToBeRemoved(MethodDef method, MethodDef methodToBeRemoved) { methodCallRemover.add(method, methodToBeRemoved); } @@ -333,46 +332,46 @@ namespace de4dot.code.deobfuscators { methodCallRemover.removeAll(blocks); } - protected void addMethodsToBeRemoved(IEnumerable methods, string reason) { + protected void addMethodsToBeRemoved(IEnumerable methods, string reason) { foreach (var method in methods) addMethodToBeRemoved(method, reason); } - protected void addMethodToBeRemoved(MethodDefinition method, string reason) { + protected void addMethodToBeRemoved(MethodDef method, string reason) { if (method != null) - methodsToRemove.Add(new RemoveInfo(method, reason)); + methodsToRemove.Add(new RemoveInfo(method, reason)); } - protected void addFieldsToBeRemoved(IEnumerable fields, string reason) { + protected void addFieldsToBeRemoved(IEnumerable fields, string reason) { foreach (var field in fields) addFieldToBeRemoved(field, reason); } - protected void addFieldToBeRemoved(FieldDefinition field, string reason) { + protected void addFieldToBeRemoved(FieldDef field, string reason) { if (field != null) - fieldsToRemove.Add(new RemoveInfo(field, reason)); + fieldsToRemove.Add(new RemoveInfo(field, reason)); } - protected void addAttributesToBeRemoved(IEnumerable attrs, string reason) { + protected void addAttributesToBeRemoved(IEnumerable attrs, string reason) { foreach (var attr in attrs) addAttributeToBeRemoved(attr, reason); } - protected void addAttributeToBeRemoved(TypeDefinition attr, string reason) { + protected void addAttributeToBeRemoved(TypeDef attr, string reason) { if (attr == null) return; addTypeToBeRemoved(attr, reason); - attrsToRemove.Add(new RemoveInfo(attr, reason)); + attrsToRemove.Add(new RemoveInfo(attr, reason)); } - protected void addTypesToBeRemoved(IEnumerable types, string reason) { + protected void addTypesToBeRemoved(IEnumerable types, string reason) { foreach (var type in types) addTypeToBeRemoved(type, reason); } - protected void addTypeToBeRemoved(TypeDefinition type, string reason) { + protected void addTypeToBeRemoved(TypeDef type, string reason) { if (type != null) - typesToRemove.Add(new RemoveInfo(type, reason)); + typesToRemove.Add(new RemoveInfo(type, reason)); } protected void addResourceToBeRemoved(Resource resource, string reason) { @@ -380,25 +379,10 @@ namespace de4dot.code.deobfuscators { resourcesToRemove.Add(new RemoveInfo(resource, reason)); } - protected void addModuleReferencesToBeRemoved(IEnumerable modrefs, string reason) { - foreach (var modref in modrefs) - addModuleReferenceToBeRemoved(modref, reason); - } - - protected void addModuleReferenceToBeRemoved(ModuleReference modref, string reason) { - if (modref != null) - modrefsToRemove.Add(new RemoveInfo(modref, reason)); - } - - protected void addAssemblyReferenceToBeRemoved(AssemblyNameReference asmRef, string reason) { - if (asmRef != null) - asmrefsToRemove.Add(new RemoveInfo(asmRef, reason)); - } - void deleteEmptyCctors() { - var emptyCctorsToRemove = new List(); + var emptyCctorsToRemove = new List(); foreach (var type in module.GetTypes()) { - var cctor = DotNetUtils.getMethod(type, ".cctor"); + var cctor = type.FindClassConstructor(); if (cctor != null && DotNetUtils.isEmpty(cctor)) emptyCctorsToRemove.Add(cctor); } @@ -414,9 +398,9 @@ namespace de4dot.code.deobfuscators { continue; if (type.Methods.Remove(cctor)) Log.v("{0:X8}, type: {1} ({2:X8})", - cctor.MetadataToken.ToUInt32(), + cctor.MDToken.ToUInt32(), Utils.removeNewlines(type), - type.MetadataToken.ToUInt32()); + type.MDToken.ToUInt32()); } Log.deIndent(); } @@ -437,7 +421,7 @@ namespace de4dot.code.deobfuscators { if (type.Methods.Remove(method)) Log.v("Removed method {0} ({1:X8}) (Type: {2}) (reason: {3})", Utils.removeNewlines(method), - method.MetadataToken.ToUInt32(), + method.MDToken.ToUInt32(), Utils.removeNewlines(type), info.reason); } @@ -460,7 +444,7 @@ namespace de4dot.code.deobfuscators { if (type.Fields.Remove(field)) Log.v("Removed field {0} ({1:X8}) (Type: {2}) (reason: {3})", Utils.removeNewlines(field), - field.MetadataToken.ToUInt32(), + field.MDToken.ToUInt32(), Utils.removeNewlines(type), info.reason); } @@ -480,14 +464,14 @@ namespace de4dot.code.deobfuscators { if (typeDef == null || typeDef == moduleType) continue; bool removed; - if (typeDef.IsNested) + if (typeDef.DeclaringType != null) removed = typeDef.DeclaringType.NestedTypes.Remove(typeDef); else removed = types.Remove(typeDef); if (removed) Log.v("Removed type {0} ({1:X8}) (reason: {2})", Utils.removeNewlines(typeDef), - typeDef.MetadataToken.ToUInt32(), + typeDef.MDToken.ToUInt32(), info.reason); } Log.deIndent(); @@ -517,7 +501,7 @@ namespace de4dot.code.deobfuscators { customAttrs.RemoveAt(i); Log.v("Removed custom attribute {0} ({1:X8}) (reason: {2})", Utils.removeNewlines(typeDef), - typeDef.MetadataToken.ToUInt32(), + typeDef.MDToken.ToUInt32(), info.reason); break; } @@ -536,9 +520,9 @@ namespace de4dot.code.deobfuscators { void deleteOtherAttributes(IList customAttributes) { for (int i = customAttributes.Count - 1; i >= 0; i--) { - var attr = customAttributes[i].AttributeType; - if (attr.FullName == "System.Runtime.CompilerServices.SuppressIldasmAttribute") { - Log.v("Removed attribute {0}", Utils.removeNewlines(attr.FullName)); + var attr = customAttributes[i].TypeFullName; + if (attr == "System.Runtime.CompilerServices.SuppressIldasmAttribute") { + Log.v("Removed attribute {0}", Utils.removeNewlines(attr)); customAttributes.RemoveAt(i); } } @@ -560,54 +544,22 @@ namespace de4dot.code.deobfuscators { Log.deIndent(); } - void deleteModuleReferences() { - if (!module.HasModuleReferences || modrefsToRemove.Count == 0) - return; - - Log.v("Removing module references"); - Log.indent(); - foreach (var info in modrefsToRemove) { - var modref = info.obj; - if (modref == null) - continue; - if (module.ModuleReferences.Remove(modref)) - Log.v("Removed module reference {0} (reason: {1})", modref, info.reason); - } - Log.deIndent(); - } - - void deleteAssemblyReferences() { - if (!module.HasAssemblyReferences || asmrefsToRemove.Count == 0) - return; - - Log.v("Removing assembly references"); - Log.indent(); - foreach (var info in asmrefsToRemove) { - var asmRef = info.obj; - if (asmRef == null) - continue; - if (module.AssemblyReferences.Remove(asmRef)) - Log.v("Removed assembly reference {0} (reason: {1})", asmRef, info.reason); - } - Log.deIndent(); - } - protected void setInitLocals() { foreach (var type in module.GetTypes()) { foreach (var method in type.Methods) { if (isFatHeader(method)) - method.Body.InitLocals = true; + method.CilBody.InitLocals = true; } } } - static bool isFatHeader(MethodDefinition method) { - if (method == null || method.Body == null) + static bool isFatHeader(MethodDef method) { + if (method == null || method.CilBody == null) return false; - var body = method.Body; - if (body.InitLocals || body.MaxStackSize > 8) + var body = method.CilBody; + if (body.InitLocals || body.MaxStack > 8) return true; - if (body.Variables.Count > 0) + if (body.LocalList.Length > 0) return true; if (body.ExceptionHandlers.Count > 0) return true; @@ -617,11 +569,11 @@ namespace de4dot.code.deobfuscators { return false; } - static int getCodeSize(MethodDefinition method) { - if (method == null || method.Body == null) + static int getCodeSize(MethodDef method) { + if (method == null || method.CilBody == null) return 0; int size = 0; - foreach (var instr in method.Body.Instructions) + foreach (var instr in method.CilBody.Instructions) size += instr.GetSize(); return size; } @@ -630,11 +582,11 @@ namespace de4dot.code.deobfuscators { return Name; } - protected void findPossibleNamesToRemove(MethodDefinition method) { - if (method == null || !method.HasBody) + protected void findPossibleNamesToRemove(MethodDef method) { + if (method == null || !method.HasCilBody) return; - foreach (var instr in method.Body.Instructions) { + foreach (var instr in method.CilBody.Instructions) { if (instr.OpCode == OpCodes.Ldstr) namesToPossiblyRemove.Add((string)instr.Operand); } @@ -654,18 +606,6 @@ namespace de4dot.code.deobfuscators { } } - protected void addModuleReferences(string reason) { - if (!module.HasModuleReferences) - return; - - foreach (var name in namesToPossiblyRemove) { - foreach (var moduleRef in module.ModuleReferences) { - if (Utils.StartsWith(moduleRef.Name, name, StringComparison.OrdinalIgnoreCase)) - addModuleReferenceToBeRemoved(moduleRef, reason); - } - } - } - protected bool removeProxyDelegates(ProxyCallFixerBase proxyCallFixer) { return removeProxyDelegates(proxyCallFixer, true); } @@ -699,7 +639,7 @@ namespace de4dot.code.deobfuscators { } protected bool hasMetadataStream(string name) { - foreach (var stream in module.MetadataStreams) { + foreach (var stream in module.MetaData.AllStreams) { if (stream.Name == name) return true; } @@ -715,11 +655,11 @@ namespace de4dot.code.deobfuscators { return list; } - protected List getTypesToRemove() { + protected List getTypesToRemove() { return getObjectsToRemove(typesToRemove); } - protected List getMethodsToRemove() { + protected List getMethodsToRemove() { return getObjectsToRemove(methodsToRemove); } @@ -765,14 +705,14 @@ namespace de4dot.code.deobfuscators { return name != null && checkValidName(name); } - public virtual void OnBeforeAddingResources(MetadataBuilder builder) { + public virtual void OnBeforeAddingResources(IWriterListener.MetadataBuilder builder) { } protected void findAndRemoveInlinedMethods() { removeInlinedMethods(InlinedMethodsFinder.find(module)); } - protected void removeInlinedMethods(List inlinedMethods) { + protected void removeInlinedMethods(List inlinedMethods) { addMethodsToBeRemoved(new UnusedMethodsFinder(module, inlinedMethods, getRemovedMethods()).find(), "Inlined method"); } @@ -783,7 +723,7 @@ namespace de4dot.code.deobfuscators { return removedMethods; } - protected bool isTypeCalled(TypeDefinition decrypterType) { + protected bool isTypeCalled(TypeDef decrypterType) { if (decrypterType == null) return false; @@ -794,19 +734,19 @@ namespace de4dot.code.deobfuscators { foreach (var type in module.GetTypes()) { foreach (var method in type.Methods) { - if (method.Body == null) + if (method.CilBody == null) continue; if (decrypterMethods.exists(method)) break; // decrypter type / nested type method if (removedMethods.exists(method)) continue; - foreach (var instr in method.Body.Instructions) { + foreach (var instr in method.CilBody.Instructions) { switch (instr.OpCode.Code) { case Code.Call: case Code.Callvirt: case Code.Newobj: - var calledMethod = instr.Operand as MethodReference; + var calledMethod = instr.Operand as IMethod; if (calledMethod == null) break; if (decrypterMethods.exists(calledMethod)) diff --git a/de4dot.code/deobfuscators/InitializedDataCreator.cs b/de4dot.code/deobfuscators/InitializedDataCreator.cs index 3628ca42..a45b3b4f 100644 --- a/de4dot.code/deobfuscators/InitializedDataCreator.cs +++ b/de4dot.code/deobfuscators/InitializedDataCreator.cs @@ -21,56 +21,55 @@ using System; using System.Collections.Generic; using System.IO; using System.Security.Cryptography; -using Mono.Cecil; -using Mono.Cecil.Cil; +using dot10.DotNet; +using dot10.DotNet.Emit; using de4dot.blocks; namespace de4dot.code.deobfuscators { class InitializedDataCreator { - ModuleDefinition module; - Dictionary sizeToArrayType = new Dictionary(); - TypeDefinition ourType; - TypeReference valueType; + ModuleDef module; + Dictionary sizeToArrayType = new Dictionary(); + TypeDef ourType; + TypeDefOrRefSig valueType; int unique = 0; - MethodReference initializeArrayMethod; + MemberRef initializeArrayMethod; - public MethodReference InitializeArrayMethod { + public MemberRef InitializeArrayMethod { get { return createInitializeArrayMethod(); } } - public InitializedDataCreator(ModuleDefinition module) { + public InitializedDataCreator(ModuleDef module) { this.module = module; } - MethodReference createInitializeArrayMethod() { + MemberRef createInitializeArrayMethod() { if (initializeArrayMethod == null) { - var runtimeHelpersType = DotNetUtils.findOrCreateTypeReference(module, module.TypeSystem.Corlib as AssemblyNameReference, "System.Runtime.CompilerServices", "RuntimeHelpers", false); - initializeArrayMethod = new MethodReference("InitializeArray", module.TypeSystem.Void, runtimeHelpersType); - var systemArrayType = DotNetUtils.findOrCreateTypeReference(module, module.TypeSystem.Corlib as AssemblyNameReference, "System", "Array", false); - var runtimeFieldHandleType = DotNetUtils.findOrCreateTypeReference(module, module.TypeSystem.Corlib as AssemblyNameReference, "System", "RuntimeFieldHandle", true); - initializeArrayMethod.Parameters.Add(new ParameterDefinition(systemArrayType)); - initializeArrayMethod.Parameters.Add(new ParameterDefinition(runtimeFieldHandleType)); + var runtimeHelpersType = DotNetUtils.findOrCreateTypeReference(module, module.CorLibTypes.AssemblyRef, "System.Runtime.CompilerServices", "RuntimeHelpers", false); + var systemArrayType = DotNetUtils.findOrCreateTypeReference(module, module.CorLibTypes.AssemblyRef, "System", "Array", false); + var runtimeFieldHandleType = DotNetUtils.findOrCreateTypeReference(module, module.CorLibTypes.AssemblyRef, "System", "RuntimeFieldHandle", true); + var methodSig = MethodSig.CreateStatic(module.CorLibTypes.Void, systemArrayType, runtimeFieldHandleType); + initializeArrayMethod = module.UpdateRowId(new MemberRefUser(module, "InitializeArray", methodSig, runtimeHelpersType.TypeDefOrRef)); } return initializeArrayMethod; } - public void addInitializeArrayCode(Block block, int start, int numToRemove, TypeReference elementType, byte[] data) { + public void addInitializeArrayCode(Block block, int start, int numToRemove, ITypeDefOrRef elementType, byte[] data) { int index = start; - block.replace(index++, numToRemove, DotNetUtils.createLdci4(data.Length / elementType.PrimitiveSize)); + block.replace(index++, numToRemove, Instruction.CreateLdcI4(data.Length / elementType.ToTypeSig().ElementType.GetPrimitiveSize())); block.insert(index++, Instruction.Create(OpCodes.Newarr, elementType)); block.insert(index++, Instruction.Create(OpCodes.Dup)); - block.insert(index++, Instruction.Create(OpCodes.Ldtoken, create(data))); - block.insert(index++, Instruction.Create(OpCodes.Call, InitializeArrayMethod)); + block.insert(index++, Instruction.Create(OpCodes.Ldtoken, (IField)create(data))); + block.insert(index++, Instruction.Create(OpCodes.Call, (IMethod)InitializeArrayMethod)); } void createOurType() { if (ourType != null) return; - var attrs = TypeAttributes.NotPublic | TypeAttributes.AutoLayout | - TypeAttributes.Class | TypeAttributes.AnsiClass; - ourType = new TypeDefinition("", string.Format("{0}", getModuleId()), attrs, module.TypeSystem.Object); - ourType.MetadataToken = DotNetUtils.nextTypeDefToken(); + ourType = new TypeDefUser("", string.Format("{0}", getModuleId()), module.CorLibTypes.Object.TypeDefOrRef); + ourType.Flags = TypeAttributes.NotPublic | TypeAttributes.AutoLayout | + TypeAttributes.Class | TypeAttributes.AnsiClass; + module.UpdateRowId(ourType); module.Types.Add(ourType); } @@ -78,8 +77,8 @@ namespace de4dot.code.deobfuscators { var memoryStream = new MemoryStream(); var writer = new BinaryWriter(memoryStream); if (module.Assembly != null) - writer.Write(module.Assembly.Name.FullName); - writer.Write(module.Mvid.ToByteArray()); + writer.Write(module.Assembly.FullName); + writer.Write((module.Mvid ?? Guid.Empty).ToByteArray()); var hash = new SHA1Managed().ComputeHash(memoryStream.GetBuffer()); var guid = new Guid(BitConverter.ToInt32(hash, 0), BitConverter.ToInt16(hash, 4), @@ -89,33 +88,32 @@ namespace de4dot.code.deobfuscators { return guid.ToString("B"); } - TypeDefinition getArrayType(long size) { + TypeDef getArrayType(long size) { createOurType(); - TypeDefinition arrayType; + TypeDef arrayType; if (sizeToArrayType.TryGetValue(size, out arrayType)) return arrayType; if (valueType == null) - valueType = DotNetUtils.findOrCreateTypeReference(module, module.TypeSystem.Corlib as AssemblyNameReference, "System", "ValueType", false); - var attrs = TypeAttributes.NestedPrivate | TypeAttributes.ExplicitLayout | - TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.AnsiClass; - arrayType = new TypeDefinition("", string.Format("__StaticArrayInitTypeSize={0}", size), attrs, valueType); - arrayType.MetadataToken = DotNetUtils.nextTypeDefToken(); + valueType = DotNetUtils.findOrCreateTypeReference(module, module.CorLibTypes.AssemblyRef, "System", "ValueType", false); + arrayType = new TypeDefUser("", string.Format("__StaticArrayInitTypeSize={0}", size), valueType.TypeDefOrRef); + module.UpdateRowId(arrayType); + arrayType.Flags = TypeAttributes.NestedPrivate | TypeAttributes.ExplicitLayout | + TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.AnsiClass; ourType.NestedTypes.Add(arrayType); sizeToArrayType[size] = arrayType; - arrayType.ClassSize = (int)size; - arrayType.PackingSize = 1; - arrayType.IsValueType = true; + arrayType.ClassLayout = new ClassLayoutUser(1, (uint)size); return arrayType; } - public FieldDefinition create(byte[] data) { + public FieldDef create(byte[] data) { var arrayType = getArrayType(data.LongLength); + var fieldSig = new FieldSig(new ValueTypeSig(arrayType)); var attrs = FieldAttributes.Assembly | FieldAttributes.Static; - var field = new FieldDefinition(string.Format("field_{0}", unique++), attrs, arrayType); - field.Attributes |= FieldAttributes.HasFieldRVA; - field.MetadataToken = DotNetUtils.nextFieldToken(); + var field = new FieldDefUser(string.Format("field_{0}", unique++), fieldSig, attrs); + module.UpdateRowId(field); + field.HasFieldRVA = true; ourType.Fields.Add(field); var iv = new byte[data.Length]; Array.Copy(data, iv, data.Length); diff --git a/de4dot.code/deobfuscators/InlinedMethodsFinder.cs b/de4dot.code/deobfuscators/InlinedMethodsFinder.cs index c8f6fb49..1c732d9e 100644 --- a/de4dot.code/deobfuscators/InlinedMethodsFinder.cs +++ b/de4dot.code/deobfuscators/InlinedMethodsFinder.cs @@ -18,31 +18,31 @@ */ using System.Collections.Generic; -using Mono.Cecil; -using Mono.Cecil.Cil; +using dot10.DotNet; +using dot10.DotNet.Emit; using de4dot.blocks; namespace de4dot.code.deobfuscators { static class InlinedMethodsFinder { - public static List find(ModuleDefinition module) { + public static List find(ModuleDef module) { // Not all garbage methods are inlined, possibly because we remove some code that calls // the garbage method before the methods inliner has a chance to inline it. Try to find // all garbage methods and other code will figure out if there are any calls left. - var inlinedMethods = new List(); + var inlinedMethods = new List(); foreach (var type in module.GetTypes()) { foreach (var method in type.Methods) { if (!method.IsStatic) continue; - if (!method.IsAssembly && !method.IsCompilerControlled && !method.IsPrivate) + if (!method.IsAssembly && !method.IsPrivateScope && !method.IsPrivate) continue; - if (method.GenericParameters.Count > 0) + if (method.GenericParams.Count > 0) continue; if (method.Name == ".cctor") continue; - if (method.Body == null) + if (method.CilBody == null) continue; - var instrs = method.Body.Instructions; + var instrs = method.CilBody.Instructions; if (instrs.Count < 2) continue; @@ -97,10 +97,10 @@ namespace de4dot.code.deobfuscators { return inlinedMethods; } - static bool isCallMethod(MethodDefinition method) { + static bool isCallMethod(MethodDef method) { int loadIndex = 0; int methodArgsCount = DotNetUtils.getArgsCount(method); - var instrs = method.Body.Instructions; + var instrs = method.CilBody.Instructions; int i = 0; for (; i < instrs.Count && i < methodArgsCount; i++) { var instr = instrs[i]; @@ -113,7 +113,7 @@ namespace de4dot.code.deobfuscators { case Code.Ldarg_3: case Code.Ldarga: case Code.Ldarga_S: - if (DotNetUtils.getArgIndex(instr) != loadIndex) + if (instr.GetParameterIndex() != loadIndex) return false; loadIndex++; continue; diff --git a/de4dot.code/deobfuscators/MethodCollection.cs b/de4dot.code/deobfuscators/MethodCollection.cs index 99b558cc..2b2e2b26 100644 --- a/de4dot.code/deobfuscators/MethodCollection.cs +++ b/de4dot.code/deobfuscators/MethodCollection.cs @@ -18,7 +18,7 @@ */ using System.Collections.Generic; -using Mono.Cecil; +using dot10.DotNet; using de4dot.blocks; namespace de4dot.code.deobfuscators { @@ -26,7 +26,7 @@ namespace de4dot.code.deobfuscators { TypeDefinitionDict types = new TypeDefinitionDict(); MethodDefinitionAndDeclaringTypeDict methods = new MethodDefinitionAndDeclaringTypeDict(); - public bool exists(MethodReference method) { + public bool exists(IMethod method) { if (method == null) return false; if (method.DeclaringType != null && types.find(method.DeclaringType)) @@ -34,26 +34,27 @@ namespace de4dot.code.deobfuscators { return methods.find(method); } - public void add(MethodDefinition method) { + public void add(MethodDef method) { methods.add(method, true); } - public void add(IEnumerable methods) { + public void add(IEnumerable methods) { foreach (var method in methods) add(method); } - public void add(TypeDefinition type) { + public void add(TypeDef type) { types.add(type, true); } - public void addAndNested(TypeDefinition type) { - foreach (var t in TypeDefinition.GetTypes(new List { type })) - add(type); + public void addAndNested(TypeDef type) { + add(type); + foreach (var t in type.GetTypes()) + add(t); } - public void addAndNested(IList types) { - foreach (var type in TypeDefinition.GetTypes(types)) + public void addAndNested(IList types) { + foreach (var type in AllTypesHelper.Types(types)) add(type); } } diff --git a/de4dot.code/deobfuscators/UnusedMethodsFinder.cs b/de4dot.code/deobfuscators/UnusedMethodsFinder.cs index 8fbc37f6..83cb535e 100644 --- a/de4dot.code/deobfuscators/UnusedMethodsFinder.cs +++ b/de4dot.code/deobfuscators/UnusedMethodsFinder.cs @@ -18,18 +18,18 @@ */ using System.Collections.Generic; -using Mono.Cecil; -using Mono.Cecil.Cil; +using dot10.DotNet; +using dot10.DotNet.Emit; using de4dot.blocks; namespace de4dot.code.deobfuscators { class UnusedMethodsFinder { - ModuleDefinition module; + ModuleDef module; MethodCollection removedMethods; - Dictionary possiblyUnusedMethods = new Dictionary(); - Stack notUnusedStack = new Stack(); + Dictionary possiblyUnusedMethods = new Dictionary(); + Stack notUnusedStack = new Stack(); - public UnusedMethodsFinder(ModuleDefinition module, IEnumerable possiblyUnusedMethods, MethodCollection removedMethods) { + public UnusedMethodsFinder(ModuleDef module, IEnumerable possiblyUnusedMethods, MethodCollection removedMethods) { this.module = module; this.removedMethods = removedMethods; foreach (var method in possiblyUnusedMethods) { @@ -38,7 +38,7 @@ namespace de4dot.code.deobfuscators { } } - public IEnumerable find() { + public IEnumerable find() { if (possiblyUnusedMethods.Count == 0) return possiblyUnusedMethods.Keys; @@ -57,15 +57,15 @@ namespace de4dot.code.deobfuscators { return possiblyUnusedMethods.Keys; } - void check(MethodDefinition method) { - if (method.Body == null) + void check(MethodDef method) { + if (method.CilBody == null) return; if (possiblyUnusedMethods.ContainsKey(method)) return; if (removedMethods.exists(method)) return; - foreach (var instr in method.Body.Instructions) { + foreach (var instr in method.CilBody.Instructions) { switch (instr.OpCode.Code) { case Code.Call: case Code.Calli: @@ -79,7 +79,7 @@ namespace de4dot.code.deobfuscators { continue; } - var calledMethod = DotNetUtils.getMethod2(module, instr.Operand as MethodReference); + var calledMethod = DotNetUtils.getMethod2(module, instr.Operand as IMethod); if (calledMethod == null) continue; if (possiblyUnusedMethods.ContainsKey(calledMethod)) diff --git a/dot10 b/dot10 index a0b16e31..c12a2f59 160000 --- a/dot10 +++ b/dot10 @@ -1 +1 @@ -Subproject commit a0b16e316fee176a704b8701df38793ed7411ed5 +Subproject commit c12a2f599e25b32dfee2cc42be4f13dc2edc06d4