diff --git a/de4dot.code/de4dot.code.csproj b/de4dot.code/de4dot.code.csproj index 7525dd6b..56fdba30 100644 --- a/de4dot.code/de4dot.code.csproj +++ b/de4dot.code/de4dot.code.csproj @@ -155,12 +155,12 @@ - + - + @@ -181,6 +181,7 @@ + diff --git a/de4dot.code/deobfuscators/CodeVeil/ResourceDecrypter.cs b/de4dot.code/deobfuscators/CodeVeil/ResourceDecrypter.cs index e19396c7..26d3b14b 100644 --- a/de4dot.code/deobfuscators/CodeVeil/ResourceDecrypter.cs +++ b/de4dot.code/deobfuscators/CodeVeil/ResourceDecrypter.cs @@ -36,7 +36,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { MethodDefinition resTypeCtor; TypeDefinition resourceFlagsType; TypeDefinition resourceEnumeratorType; - GetManifestResourceRestorerBase getManifestResourceRestorer; + ResourceMethodsRestorerBase resourceMethodsRestorer; public bool CanRemoveTypes { get { @@ -78,7 +78,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { } public void initialize() { - getManifestResourceRestorer = new GetManifestResourceRestorerBase(module); + resourceMethodsRestorer = new ResourceMethodsRestorerBase(module); findEncryptedResourceStreamType(); findEncryptedResourceSet(); findEncryptedResourceReader(); @@ -264,8 +264,8 @@ namespace de4dot.code.deobfuscators.CodeVeil { if (!findManifestResourceStreamMethods(type, out getManifestResourceStreamMethodTmp1, out getManifestResourceStreamMethodTmp2)) continue; - getManifestResourceRestorer.GetStream1Method = getManifestResourceStreamMethodTmp1; - getManifestResourceRestorer.GetStream2Method = getManifestResourceStreamMethodTmp2; + resourceMethodsRestorer.createGetManifestResourceStream1(getManifestResourceStreamMethodTmp1); + resourceMethodsRestorer.createGetManifestResourceStream2(getManifestResourceStreamMethodTmp2); encryptedResourceStreamType = type; return; } @@ -355,7 +355,7 @@ namespace de4dot.code.deobfuscators.CodeVeil { if (encryptedResourceStreamType == null) return; - getManifestResourceRestorer.deobfuscate(blocks); + resourceMethodsRestorer.deobfuscate(blocks); } } } diff --git a/de4dot.code/deobfuscators/Eazfuscator_NET/Deobfuscator.cs b/de4dot.code/deobfuscators/Eazfuscator_NET/Deobfuscator.cs index 9f20e78d..0d21f5ef 100644 --- a/de4dot.code/deobfuscators/Eazfuscator_NET/Deobfuscator.cs +++ b/de4dot.code/deobfuscators/Eazfuscator_NET/Deobfuscator.cs @@ -54,7 +54,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET { StringDecrypter stringDecrypter; AssemblyResolver assemblyResolver; ResourceResolver resourceResolver; - GetManifestResourceRestorer getManifestResourceRestorer; + ResourceMethodsRestorer resourceMethodsRestorer; internal class Options : OptionsBase { } @@ -129,8 +129,8 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET { addResourceToBeRemoved(info.Resource, "Encrypted resources"); addModuleCctorInitCallToBeRemoved(resourceResolver.InitMethod); - getManifestResourceRestorer = new GetManifestResourceRestorer(module); - getManifestResourceRestorer.find(DeobfuscatedFile, this); + resourceMethodsRestorer = new ResourceMethodsRestorer(module); + resourceMethodsRestorer.find(DeobfuscatedFile, this); dumpEmbeddedAssemblies(); } @@ -143,7 +143,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET { } public override void deobfuscateMethodEnd(Blocks blocks) { - getManifestResourceRestorer.deobfuscate(blocks); + resourceMethodsRestorer.deobfuscate(blocks); base.deobfuscateMethodEnd(blocks); } @@ -156,8 +156,8 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET { addTypeToBeRemoved(assemblyResolver.Type, "Assembly resolver type"); addTypeToBeRemoved(assemblyResolver.OtherType, "Assembly resolver other type"); addTypeToBeRemoved(resourceResolver.Type, "Resource resolver type"); - addTypeToBeRemoved(getManifestResourceRestorer.Type, "GetManifestResourceStream type"); - addResourceToBeRemoved(getManifestResourceRestorer.Resource, "GetManifestResourceStream type resource"); + addTypeToBeRemoved(resourceMethodsRestorer.Type, "GetManifestResourceStream type"); + addResourceToBeRemoved(resourceMethodsRestorer.Resource, "GetManifestResourceStream type resource"); fixInterfaces(); base.deobfuscateEnd(); diff --git a/de4dot.code/deobfuscators/Eazfuscator_NET/GetManifestResourceRestorer.cs b/de4dot.code/deobfuscators/Eazfuscator_NET/ResourceMethodsRestorer.cs similarity index 92% rename from de4dot.code/deobfuscators/Eazfuscator_NET/GetManifestResourceRestorer.cs rename to de4dot.code/deobfuscators/Eazfuscator_NET/ResourceMethodsRestorer.cs index 0278f6fc..e256d88d 100644 --- a/de4dot.code/deobfuscators/Eazfuscator_NET/GetManifestResourceRestorer.cs +++ b/de4dot.code/deobfuscators/Eazfuscator_NET/ResourceMethodsRestorer.cs @@ -21,7 +21,7 @@ using Mono.Cecil; using de4dot.blocks; namespace de4dot.code.deobfuscators.Eazfuscator_NET { - class GetManifestResourceRestorer : GetManifestResourceRestorerBase { + class ResourceMethodsRestorer : ResourceMethodsRestorerBase { TypeDefinition getManifestResourceStreamType; EmbeddedResource getManifestResourceStreamTypeResource; @@ -33,7 +33,7 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET { get { return getManifestResourceStreamTypeResource; } } - public GetManifestResourceRestorer(ModuleDefinition module) + public ResourceMethodsRestorer(ModuleDefinition module) : base(module) { } @@ -58,9 +58,8 @@ namespace de4dot.code.deobfuscators.Eazfuscator_NET { continue; getManifestResourceStreamType = type; - getManifestResourceStream1Method = null; - getManifestResourceStream2Method = getStream2; - getManifestResourceNamesMethod = getNames; + createGetManifestResourceStream2(getStream2); + createGetManifestResourceNames(getNames); getManifestResourceStreamTypeResource = resource; break; } diff --git a/de4dot.code/deobfuscators/GetManifestResourceRestorerBase.cs b/de4dot.code/deobfuscators/GetManifestResourceRestorerBase.cs deleted file mode 100644 index fcc796ca..00000000 --- a/de4dot.code/deobfuscators/GetManifestResourceRestorerBase.cs +++ /dev/null @@ -1,96 +0,0 @@ -/* - Copyright (C) 2011-2012 de4dot@gmail.com - - This file is part of de4dot. - - de4dot is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - de4dot is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with de4dot. If not, see . -*/ - -using Mono.Cecil; -using Mono.Cecil.Cil; -using de4dot.blocks; - -namespace de4dot.code.deobfuscators { - class GetManifestResourceRestorerBase { - protected ModuleDefinition module; - protected MethodDefinition getManifestResourceStream1Method; - protected MethodDefinition getManifestResourceStream2Method; - protected MethodDefinition getManifestResourceNamesMethod; - protected MethodReference Assembly_GetManifestResourceStream1; - protected MethodReference Assembly_GetManifestResourceStream2; - protected MethodReference Assembly_GetManifestResourceNames; - - public MethodDefinition GetStream1Method { - set { getManifestResourceStream1Method = value; } - } - - public MethodDefinition GetStream2Method { - set { getManifestResourceStream2Method = value; } - } - - public MethodDefinition GetNamesMethod { - set { getManifestResourceNamesMethod = value; } - } - - public GetManifestResourceRestorerBase(ModuleDefinition module) { - this.module = module; - createGetManifestResourceStreamMethods(); - } - - void createGetManifestResourceStreamMethods() { - var assemblyType = new TypeReference("System.Reflection", "Assembly", module, module.TypeSystem.Corlib); - var typeType = new TypeReference("System", "Type", module, module.TypeSystem.Corlib); - var streamType = new TypeReference("System.IO", "Stream", module, module.TypeSystem.Corlib); - var stringArrayType = new ArrayType(module.TypeSystem.String); - - Assembly_GetManifestResourceStream1 = new MethodReference("GetManifestResourceStream", streamType, assemblyType); - Assembly_GetManifestResourceStream1.HasThis = true; - Assembly_GetManifestResourceStream1.Parameters.Add(new ParameterDefinition(module.TypeSystem.String)); - - Assembly_GetManifestResourceStream2 = new MethodReference("GetManifestResourceStream", streamType, assemblyType); - Assembly_GetManifestResourceStream2.HasThis = true; - Assembly_GetManifestResourceStream2.Parameters.Add(new ParameterDefinition(typeType)); - Assembly_GetManifestResourceStream2.Parameters.Add(new ParameterDefinition(module.TypeSystem.String)); - - Assembly_GetManifestResourceNames = new MethodReference("GetManifestResourceNames", stringArrayType, assemblyType); - Assembly_GetManifestResourceNames.HasThis = true; - } - - public void deobfuscate(Blocks blocks) { - foreach (var block in blocks.MethodBlocks.getAllBlocks()) { - var instrs = block.Instructions; - for (int i = 0; i < instrs.Count; i++) { - var call = instrs[i]; - if (call.OpCode.Code != Code.Call) - continue; - var calledMethod = call.Operand as MethodDefinition; - if (calledMethod == null) - continue; - - MethodReference newMethod = null; - if (calledMethod == getManifestResourceStream1Method) - newMethod = Assembly_GetManifestResourceStream1; - else if (calledMethod == getManifestResourceStream2Method) - newMethod = Assembly_GetManifestResourceStream2; - else if (calledMethod == getManifestResourceNamesMethod) - newMethod = Assembly_GetManifestResourceNames; - if (newMethod == null) - continue; - - instrs[i] = new Instr(Instruction.Create(OpCodes.Callvirt, newMethod)); - } - } - } - } -} diff --git a/de4dot.code/deobfuscators/MemberReferenceBuilder.cs b/de4dot.code/deobfuscators/MemberReferenceBuilder.cs new file mode 100644 index 00000000..623945e0 --- /dev/null +++ b/de4dot.code/deobfuscators/MemberReferenceBuilder.cs @@ -0,0 +1,192 @@ +/* + Copyright (C) 2011-2012 de4dot@gmail.com + + This file is part of de4dot. + + de4dot is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + de4dot is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with de4dot. If not, see . +*/ + +using System; +using System.Collections.Generic; +using Mono.Cecil; +using de4dot.blocks; + +namespace de4dot.code.deobfuscators { + class MemberReferenceBuilder { + ModuleDefinition module; + Dictionary createdTypes = new Dictionary(); + + public MemberReferenceBuilder(ModuleDefinition module) { + this.module = module; + } + + public IMetadataScope CorLib { + get { return module.TypeSystem.Corlib; } + } + + public TypeReference Object { + get { return module.TypeSystem.Object; } + } + + public TypeReference Void { + get { return module.TypeSystem.Void; } + } + + public TypeReference Boolean { + get { return module.TypeSystem.Boolean; } + } + + public TypeReference Char { + get { return module.TypeSystem.Char; } + } + + public TypeReference SByte { + get { return module.TypeSystem.SByte; } + } + + public TypeReference Byte { + get { return module.TypeSystem.Byte; } + } + + public TypeReference Int16 { + get { return module.TypeSystem.Int16; } + } + + public TypeReference UInt16 { + get { return module.TypeSystem.UInt16; } + } + + public TypeReference Int32 { + get { return module.TypeSystem.Int32; } + } + + public TypeReference UInt32 { + get { return module.TypeSystem.UInt32; } + } + + public TypeReference Int64 { + get { return module.TypeSystem.Int64; } + } + + public TypeReference UInt64 { + get { return module.TypeSystem.UInt64; } + } + + public TypeReference Single { + get { return module.TypeSystem.Single; } + } + + public TypeReference Double { + get { return module.TypeSystem.Double; } + } + + public TypeReference IntPtr { + get { return module.TypeSystem.IntPtr; } + } + + public TypeReference UIntPtr { + get { return module.TypeSystem.UIntPtr; } + } + + public TypeReference String { + get { return module.TypeSystem.String; } + } + + public TypeReference TypedReference { + get { return module.TypeSystem.TypedReference; } + } + + public TypeReference type(string ns, string name, string asmSimpleName) { + return type(ns, name, findAssemblyReference(asmSimpleName)); + } + + public TypeReference type(string ns, string name) { + return type(ns, name, CorLib); + } + + public TypeReference type(string ns, string name, IMetadataScope asmRef) { + return type(false, ns, name, asmRef); + } + + public TypeReference valueType(string ns, string name, string asmSimpleName) { + return valueType(ns, name, findAssemblyReference(asmSimpleName)); + } + + public TypeReference valueType(string ns, string name) { + return valueType(ns, name, CorLib); + } + + public TypeReference valueType(string ns, string name, IMetadataScope asmRef) { + return type(true, ns, name, asmRef); + } + + public TypeReference type(bool isValueType, string ns, string name, IMetadataScope asmRef) { + var typeRef = new TypeReference(ns, name, module, asmRef); + typeRef.IsValueType = isValueType; + return add(isValueType, typeRef); + } + + public TypeReference array(TypeReference typeRef) { + return add(false, new ArrayType(typeRef)); + } + + TypeReference add(bool isValueType, TypeReference typeRef) { + var key = new TypeReferenceKey(typeRef); + TypeReference createdTypeRef; + if (createdTypes.TryGetValue(key, out createdTypeRef)) { + if (createdTypeRef.IsValueType != isValueType) + throw new ApplicationException(string.Format("Type {0}'s IsValueType is not correct", createdTypeRef)); + return createdTypeRef; + } + createdTypes[key] = typeRef; + return typeRef; + } + + public MethodReference instanceMethod(string name, TypeReference declaringType, TypeReference returnType, params TypeReference[] args) { + return method(true, name, declaringType, returnType, args); + } + + public MethodReference staticMethod(string name, TypeReference declaringType, TypeReference returnType, params TypeReference[] args) { + return method(false, name, declaringType, returnType, args); + } + + public MethodReference method(bool isInstance, string name, TypeReference declaringType, TypeReference returnType, params TypeReference[] args) { + var method = new MethodReference(name, returnType, declaringType); + method.HasThis = isInstance; + foreach (var arg in args) + method.Parameters.Add(new ParameterDefinition(arg)); + return method; + } + + AssemblyNameReference findAssemblyReference(string asmSimpleName) { + AssemblyNameReference asmRef = null; + foreach (var asmRef2 in findAssemblyReferences(asmSimpleName)) { + if (asmRef == null || asmRef.Version == null || (asmRef2.Version != null && asmRef2.Version > asmRef.Version)) + asmRef = asmRef2; + } + if (asmRef == null) + throw new ApplicationException(string.Format("Could not find assembly {0} in assembly references", asmSimpleName)); + return asmRef; + } + + List findAssemblyReferences(string asmSimpleName) { + var asmRefs = new List(); + foreach (var asmRef in module.AssemblyReferences) { + if (asmRef.Name == asmSimpleName) + asmRefs.Add(asmRef); + } + return asmRefs; + } + } +} diff --git a/de4dot.code/deobfuscators/ResourceMethodsRestorerBase.cs b/de4dot.code/deobfuscators/ResourceMethodsRestorerBase.cs new file mode 100644 index 00000000..ce42c453 --- /dev/null +++ b/de4dot.code/deobfuscators/ResourceMethodsRestorerBase.cs @@ -0,0 +1,85 @@ +/* + Copyright (C) 2011-2012 de4dot@gmail.com + + This file is part of de4dot. + + de4dot is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + de4dot is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with de4dot. If not, see . +*/ + +using System.Collections.Generic; +using Mono.Cecil; +using Mono.Cecil.Cil; +using de4dot.blocks; + +namespace de4dot.code.deobfuscators { + class ResourceMethodsRestorerBase { + protected MemberReferenceBuilder builder; + protected ModuleDefinition module; + + MethodDefinitionAndDeclaringTypeDict oldToNewMethod = new MethodDefinitionAndDeclaringTypeDict(); + + public ResourceMethodsRestorerBase(ModuleDefinition module) { + this.module = module; + this.builder = new MemberReferenceBuilder(module); + } + + public void createGetManifestResourceStream1(MethodDefinition oldMethod) { + var assemblyType = builder.type("System.Reflection", "Assembly", builder.CorLib); + var streamType = builder.type("System.IO", "Stream", builder.CorLib); + var newMethod = builder.instanceMethod("GetManifestResourceStream", assemblyType, streamType, builder.String); + add(oldMethod, newMethod); + } + + public void createGetManifestResourceStream2(MethodDefinition oldMethod) { + var assemblyType = builder.type("System.Reflection", "Assembly", builder.CorLib); + var typeType = builder.type("System", "Type", builder.CorLib); + var streamType = builder.type("System.IO", "Stream", builder.CorLib); + var newMethod = builder.instanceMethod("GetManifestResourceStream", assemblyType, streamType, typeType, builder.String); + add(oldMethod, newMethod); + } + + public void createGetManifestResourceNames(MethodDefinition oldMethod) { + var assemblyType = builder.type("System.Reflection", "Assembly", builder.CorLib); + var stringArrayType = builder.array(builder.String); + var newMethod = builder.instanceMethod("GetManifestResourceNames", assemblyType, stringArrayType); + add(oldMethod, newMethod); + } + + void add(MethodDefinition oldMethod, MethodReference newMethod) { + if (oldMethod == null) + return; + oldToNewMethod.add(oldMethod, newMethod); + } + + public void deobfuscate(Blocks blocks) { + foreach (var block in blocks.MethodBlocks.getAllBlocks()) { + var instrs = block.Instructions; + for (int i = 0; i < instrs.Count; i++) { + var call = instrs[i]; + if (call.OpCode.Code != Code.Call) + continue; + var calledMethod = call.Operand as MethodDefinition; + if (calledMethod == null) + continue; + + var newMethod = oldToNewMethod.find(calledMethod); + if (newMethod == null) + continue; + + instrs[i] = new Instr(Instruction.Create(OpCodes.Callvirt, newMethod)); + } + } + } + } +}