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