de4dot-cex/de4dot.code/deobfuscators/DeobfuscatorBase.cs

795 lines
22 KiB
C#
Raw Normal View History

2011-09-22 10:55:30 +08:00
/*
2012-01-10 06:02:47 +08:00
Copyright (C) 2011-2012 de4dot@gmail.com
2011-09-22 10:55:30 +08:00
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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
2012-11-01 18:28:09 +08:00
using dot10.DotNet;
using dot10.DotNet.Emit;
using dot10.DotNet.Writer;
2012-11-01 14:51:08 +08:00
using dot10.PE;
2011-09-22 10:55:30 +08:00
using de4dot.blocks;
2012-01-11 11:38:02 +08:00
using de4dot.blocks.cflow;
2011-09-22 10:55:30 +08:00
2012-11-01 21:39:39 +08:00
namespace de4dot.code.deobfuscators {
abstract class DeobfuscatorBase : IDeobfuscator, IModuleWriterListener {
2011-09-22 10:55:30 +08:00
public const string DEFAULT_VALID_NAME_REGEX = @"^[a-zA-Z_<{$][a-zA-Z_0-9<>{}$.`-]*$";
class RemoveInfo<T> {
public T obj;
public string reason;
public RemoveInfo(T obj, string reason) {
this.obj = obj;
this.reason = reason;
}
}
OptionsBase optionsBase;
2012-11-01 18:28:09 +08:00
protected ModuleDefMD module;
2012-01-20 02:16:44 +08:00
protected StaticStringInliner staticStringInliner = new StaticStringInliner();
2012-11-01 18:28:09 +08:00
IList<RemoveInfo<TypeDef>> typesToRemove = new List<RemoveInfo<TypeDef>>();
IList<RemoveInfo<MethodDef>> methodsToRemove = new List<RemoveInfo<MethodDef>>();
IList<RemoveInfo<FieldDef>> fieldsToRemove = new List<RemoveInfo<FieldDef>>();
IList<RemoveInfo<TypeDef>> attrsToRemove = new List<RemoveInfo<TypeDef>>();
2011-09-22 10:55:30 +08:00
IList<RemoveInfo<Resource>> resourcesToRemove = new List<RemoveInfo<Resource>>();
List<string> namesToPossiblyRemove = new List<string>();
2011-10-23 14:41:33 +08:00
MethodCallRemover methodCallRemover = new MethodCallRemover();
byte[] moduleBytes;
protected InitializedDataCreator initializedDataCreator;
protected byte[] ModuleBytes {
get { return moduleBytes; }
set { moduleBytes = value; }
}
2011-09-22 10:55:30 +08:00
internal class OptionsBase : IDeobfuscatorOptions {
public bool RenameResourcesInCode { get; set; }
public NameRegexes ValidNameRegex { get; set; }
public bool DecryptStrings { get; set; }
public OptionsBase() {
RenameResourcesInCode = true;
}
}
public IDeobfuscatorOptions TheOptions {
get { return optionsBase; }
}
public IOperations Operations { get; set; }
public IDeobfuscatedFile DeobfuscatedFile { get; set; }
public virtual StringFeatures StringFeatures { get; set; }
public virtual RenamingOptions RenamingOptions { get; set; }
public DecrypterType DefaultDecrypterType { get; set; }
2011-09-22 10:55:30 +08:00
public abstract string Type { get; }
2011-11-12 18:31:07 +08:00
public abstract string TypeLong { get; }
2011-09-22 10:55:30 +08:00
public abstract string Name { get; }
2012-01-11 11:38:02 +08:00
protected virtual bool CanInlineMethods {
2011-11-01 21:19:53 +08:00
get { return false; }
}
protected virtual bool KeepTypes {
get { return false; }
}
protected bool CanRemoveTypes {
get { return !Operations.KeepObfuscatorTypes && !KeepTypes; }
}
protected bool CanRemoveStringDecrypterType {
get { return Operations.DecryptStrings != OpDecryptString.None && staticStringInliner.InlinedAllCalls; }
}
public virtual IEnumerable<IBlocksDeobfuscator> BlocksDeobfuscators {
2012-01-11 11:38:02 +08:00
get {
var list = new List<IBlocksDeobfuscator>();
2012-01-11 11:38:02 +08:00
if (CanInlineMethods)
list.Add(new MethodCallInliner(false));
return list;
2012-01-11 11:38:02 +08:00
}
}
2011-09-22 10:55:30 +08:00
public DeobfuscatorBase(OptionsBase optionsBase) {
this.optionsBase = optionsBase;
StringFeatures = StringFeatures.AllowAll;
DefaultDecrypterType = DecrypterType.Static;
2011-09-22 10:55:30 +08:00
}
public virtual byte[] unpackNativeFile(IPEImage peImage) {
return null;
}
2012-11-01 18:28:09 +08:00
public virtual void init(ModuleDefMD module) {
setModule(module);
}
2012-11-01 18:28:09 +08:00
protected void setModule(ModuleDefMD module) {
2011-09-22 10:55:30 +08:00
this.module = module;
initializedDataCreator = new InitializedDataCreator(module);
2011-09-22 10:55:30 +08:00
}
2011-11-10 07:47:22 +08:00
protected virtual bool checkValidName(string name) {
return optionsBase.ValidNameRegex.isMatch(name);
}
public virtual int detect() {
scanForObfuscator();
return detectInternal();
2011-09-22 10:55:30 +08:00
}
protected abstract void scanForObfuscator();
protected abstract int detectInternal();
public virtual bool getDecryptedModule(int count, ref byte[] newFileData, ref DumpedMethods dumpedMethods) {
return false;
2011-09-22 10:55:30 +08:00
}
2012-11-01 18:28:09 +08:00
public virtual IDeobfuscator moduleReloaded(ModuleDefMD module) {
throw new ApplicationException("moduleReloaded() must be overridden by the deobfuscator");
}
2011-09-22 10:55:30 +08:00
public virtual void deobfuscateBegin() {
ModuleBytes = null;
2011-09-22 10:55:30 +08:00
}
public virtual void deobfuscateMethodBegin(Blocks blocks) {
}
public virtual void deobfuscateMethodEnd(Blocks blocks) {
2011-10-23 14:41:33 +08:00
removeMethodCalls(blocks);
2011-09-22 10:55:30 +08:00
}
public virtual void deobfuscateStrings(Blocks blocks) {
2012-01-20 02:16:44 +08:00
staticStringInliner.decrypt(blocks);
2011-09-22 10:55:30 +08:00
}
public virtual bool deobfuscateOther(Blocks blocks) {
return false;
}
2011-09-22 10:55:30 +08:00
public virtual void deobfuscateEnd() {
if (CanRemoveTypes) {
2012-02-25 12:28:32 +08:00
removeTypesWithInvalidBaseTypes();
2011-09-22 10:55:30 +08:00
deleteEmptyCctors();
deleteMethods();
deleteFields();
deleteCustomAttributes();
deleteOtherAttributes();
deleteTypes();
deleteDllResources();
}
restoreBaseType();
}
2012-11-01 18:28:09 +08:00
static bool isTypeWithInvalidBaseType(TypeDef moduleType, TypeDef type) {
return type.BaseType == null && !type.IsInterface && type != moduleType;
}
void restoreBaseType() {
2012-01-09 01:46:23 +08:00
var moduleType = DotNetUtils.getModuleType(module);
foreach (var type in module.GetTypes()) {
if (!isTypeWithInvalidBaseType(moduleType, type))
continue;
Logger.v("Adding System.Object as base type: {0} ({1:X8})",
Utils.removeNewlines(type),
2012-11-01 18:28:09 +08:00
type.MDToken.ToInt32());
type.BaseType = module.CorLibTypes.Object.TypeDefOrRef;
}
2011-09-22 10:55:30 +08:00
}
2012-02-25 12:28:32 +08:00
void removeTypesWithInvalidBaseTypes() {
var moduleType = DotNetUtils.getModuleType(module);
foreach (var type in module.GetTypes()) {
if (!isTypeWithInvalidBaseType(moduleType, type))
continue;
addTypeToBeRemoved(type, "Invalid type with no base type (anti-reflection)");
}
}
protected void fixEnumTypes() {
foreach (var type in module.GetTypes()) {
if (!type.IsEnum)
continue;
foreach (var field in type.Fields) {
if (field.IsStatic)
continue;
2012-11-17 06:50:52 +08:00
field.IsRuntimeSpecialName = true;
field.IsSpecialName = true;
}
}
}
2012-02-29 06:57:48 +08:00
protected void fixInterfaces() {
foreach (var type in module.GetTypes()) {
if (!type.IsInterface)
continue;
type.IsSealed = false;
}
}
2012-02-25 13:25:40 +08:00
public abstract IEnumerable<int> getStringDecrypterMethods();
2011-09-22 10:55:30 +08:00
2011-10-23 14:41:33 +08:00
class MethodCallRemover {
2011-12-31 23:32:57 +08:00
Dictionary<string, MethodDefinitionAndDeclaringTypeDict<bool>> methodNameInfos = new Dictionary<string, MethodDefinitionAndDeclaringTypeDict<bool>>();
MethodDefinitionAndDeclaringTypeDict<MethodDefinitionAndDeclaringTypeDict<bool>> methodRefInfos = new MethodDefinitionAndDeclaringTypeDict<MethodDefinitionAndDeclaringTypeDict<bool>>();
2011-09-22 10:55:30 +08:00
2012-11-01 18:28:09 +08:00
void checkMethod(IMethod methodToBeRemoved) {
var sig = methodToBeRemoved.MethodSig;
if (sig.Params.Count != 0)
2011-10-23 14:41:33 +08:00
throw new ApplicationException(string.Format("Method takes params: {0}", methodToBeRemoved));
2012-11-01 18:28:09 +08:00
if (sig.RetType.ElementType != ElementType.Void)
2011-10-23 14:41:33 +08:00
throw new ApplicationException(string.Format("Method has a return value: {0}", methodToBeRemoved));
}
2012-11-01 18:28:09 +08:00
public void add(string method, MethodDef methodToBeRemoved) {
2011-10-23 14:41:33 +08:00
if (methodToBeRemoved == null)
return;
checkMethod(methodToBeRemoved);
2011-12-31 23:32:57 +08:00
MethodDefinitionAndDeclaringTypeDict<bool> dict;
2011-10-23 14:41:33 +08:00
if (!methodNameInfos.TryGetValue(method, out dict))
2011-12-31 23:32:57 +08:00
methodNameInfos[method] = dict = new MethodDefinitionAndDeclaringTypeDict<bool>();
dict.add(methodToBeRemoved, true);
2011-10-23 14:41:33 +08:00
}
2012-11-01 18:28:09 +08:00
public void add(MethodDef method, MethodDef methodToBeRemoved) {
2011-10-23 14:41:33 +08:00
if (method == null || methodToBeRemoved == null)
return;
checkMethod(methodToBeRemoved);
2011-12-31 23:32:57 +08:00
var dict = methodRefInfos.find(method);
if (dict == null)
methodRefInfos.add(method, dict = new MethodDefinitionAndDeclaringTypeDict<bool>());
dict.add(methodToBeRemoved, true);
2011-10-23 14:41:33 +08:00
}
public void removeAll(Blocks blocks) {
var allBlocks = blocks.MethodBlocks.getAllBlocks();
2012-11-01 18:28:09 +08:00
removeAll(allBlocks, blocks, blocks.Method.Name.String);
2011-10-23 14:41:33 +08:00
removeAll(allBlocks, blocks, blocks.Method);
}
void removeAll(IList<Block> allBlocks, Blocks blocks, string method) {
2011-12-31 23:32:57 +08:00
MethodDefinitionAndDeclaringTypeDict<bool> info;
2011-10-23 14:41:33 +08:00
if (!methodNameInfos.TryGetValue(method, out info))
return;
2011-09-22 10:55:30 +08:00
2011-10-23 14:41:33 +08:00
removeCalls(allBlocks, blocks, info);
}
2012-11-01 18:28:09 +08:00
void removeAll(IList<Block> allBlocks, Blocks blocks, MethodDef method) {
2011-12-31 23:32:57 +08:00
var info = methodRefInfos.find(method);
if (info == null)
2011-10-23 14:41:33 +08:00
return;
removeCalls(allBlocks, blocks, info);
}
2011-12-31 23:32:57 +08:00
void removeCalls(IList<Block> allBlocks, Blocks blocks, MethodDefinitionAndDeclaringTypeDict<bool> info) {
2011-09-22 10:55:30 +08:00
var instrsToDelete = new List<int>();
2011-10-23 14:41:33 +08:00
foreach (var block in allBlocks) {
instrsToDelete.Clear();
for (int i = 0; i < block.Instructions.Count; i++) {
var instr = block.Instructions[i];
if (instr.OpCode != OpCodes.Call)
continue;
2012-11-01 18:28:09 +08:00
var destMethod = instr.Operand as IMethod;
2011-09-22 10:55:30 +08:00
if (destMethod == null)
continue;
2011-10-23 14:41:33 +08:00
2011-12-31 23:32:57 +08:00
if (info.find(destMethod)) {
Logger.v("Removed call to {0}", Utils.removeNewlines(destMethod));
2011-09-22 10:55:30 +08:00
instrsToDelete.Add(i);
}
}
2011-10-23 14:41:33 +08:00
block.remove(instrsToDelete);
2011-09-22 10:55:30 +08:00
}
}
}
2012-11-01 18:28:09 +08:00
public void addCctorInitCallToBeRemoved(MethodDef methodToBeRemoved) {
2011-10-23 14:41:33 +08:00
methodCallRemover.add(".cctor", methodToBeRemoved);
}
2012-11-01 18:28:09 +08:00
public void addModuleCctorInitCallToBeRemoved(MethodDef methodToBeRemoved) {
2012-03-15 16:35:44 +08:00
methodCallRemover.add(DotNetUtils.getModuleTypeCctor(module), methodToBeRemoved);
2011-10-23 14:41:33 +08:00
}
2012-11-01 18:28:09 +08:00
public void addCtorInitCallToBeRemoved(MethodDef methodToBeRemoved) {
2011-11-24 17:44:01 +08:00
methodCallRemover.add(".ctor", methodToBeRemoved);
}
2012-11-01 18:28:09 +08:00
public void addCallToBeRemoved(MethodDef method, MethodDef methodToBeRemoved) {
2011-10-23 14:41:33 +08:00
methodCallRemover.add(method, methodToBeRemoved);
}
void removeMethodCalls(Blocks blocks) {
methodCallRemover.removeAll(blocks);
}
2012-11-01 18:28:09 +08:00
protected void addMethodsToBeRemoved(IEnumerable<MethodDef> methods, string reason) {
2011-09-22 10:55:30 +08:00
foreach (var method in methods)
addMethodToBeRemoved(method, reason);
}
2012-11-01 18:28:09 +08:00
protected void addMethodToBeRemoved(MethodDef method, string reason) {
2012-04-05 23:06:27 +08:00
if (method != null)
2012-11-01 18:28:09 +08:00
methodsToRemove.Add(new RemoveInfo<MethodDef>(method, reason));
2011-09-22 10:55:30 +08:00
}
2012-11-01 18:28:09 +08:00
protected void addFieldsToBeRemoved(IEnumerable<FieldDef> fields, string reason) {
2011-09-22 10:55:30 +08:00
foreach (var field in fields)
addFieldToBeRemoved(field, reason);
}
2012-11-01 18:28:09 +08:00
protected void addFieldToBeRemoved(FieldDef field, string reason) {
2012-04-05 23:06:27 +08:00
if (field != null)
2012-11-01 18:28:09 +08:00
fieldsToRemove.Add(new RemoveInfo<FieldDef>(field, reason));
2011-09-22 10:55:30 +08:00
}
2012-11-01 18:28:09 +08:00
protected void addAttributesToBeRemoved(IEnumerable<TypeDef> attrs, string reason) {
2012-04-26 22:08:39 +08:00
foreach (var attr in attrs)
addAttributeToBeRemoved(attr, reason);
}
2012-11-01 18:28:09 +08:00
protected void addAttributeToBeRemoved(TypeDef attr, string reason) {
2012-04-05 23:06:27 +08:00
if (attr == null)
return;
2011-09-22 10:55:30 +08:00
addTypeToBeRemoved(attr, reason);
2012-11-01 18:28:09 +08:00
attrsToRemove.Add(new RemoveInfo<TypeDef>(attr, reason));
2011-09-22 10:55:30 +08:00
}
2012-11-01 18:28:09 +08:00
protected void addTypesToBeRemoved(IEnumerable<TypeDef> types, string reason) {
2011-09-22 10:55:30 +08:00
foreach (var type in types)
addTypeToBeRemoved(type, reason);
}
2012-11-01 18:28:09 +08:00
protected void addTypeToBeRemoved(TypeDef type, string reason) {
2012-04-05 23:06:27 +08:00
if (type != null)
2012-11-01 18:28:09 +08:00
typesToRemove.Add(new RemoveInfo<TypeDef>(type, reason));
2011-09-22 10:55:30 +08:00
}
protected void addResourceToBeRemoved(Resource resource, string reason) {
2012-04-05 23:06:27 +08:00
if (resource != null)
resourcesToRemove.Add(new RemoveInfo<Resource>(resource, reason));
2011-09-22 10:55:30 +08:00
}
void deleteEmptyCctors() {
2012-11-01 18:28:09 +08:00
var emptyCctorsToRemove = new List<MethodDef>();
2011-09-22 10:55:30 +08:00
foreach (var type in module.GetTypes()) {
2012-11-17 06:50:52 +08:00
var cctor = type.FindStaticConstructor();
2011-09-22 10:55:30 +08:00
if (cctor != null && DotNetUtils.isEmpty(cctor))
emptyCctorsToRemove.Add(cctor);
}
if (emptyCctorsToRemove.Count == 0)
return;
Logger.v("Removing empty .cctor methods");
Logger.Instance.indent();
2011-09-22 10:55:30 +08:00
foreach (var cctor in emptyCctorsToRemove) {
var type = cctor.DeclaringType;
if (type == null)
continue;
2011-09-22 10:55:30 +08:00
if (type.Methods.Remove(cctor))
Logger.v("{0:X8}, type: {1} ({2:X8})",
2012-11-01 18:28:09 +08:00
cctor.MDToken.ToUInt32(),
Utils.removeNewlines(type),
2012-11-01 18:28:09 +08:00
type.MDToken.ToUInt32());
2011-09-22 10:55:30 +08:00
}
Logger.Instance.deIndent();
2011-09-22 10:55:30 +08:00
}
void deleteMethods() {
if (methodsToRemove.Count == 0)
return;
Logger.v("Removing methods");
Logger.Instance.indent();
2011-09-22 10:55:30 +08:00
foreach (var info in methodsToRemove) {
var method = info.obj;
if (method == null)
continue;
var type = method.DeclaringType;
2012-01-24 06:16:01 +08:00
if (type == null)
continue;
2011-09-22 10:55:30 +08:00
if (type.Methods.Remove(method))
Logger.v("Removed method {0} ({1:X8}) (Type: {2}) (reason: {3})",
Utils.removeNewlines(method),
2012-11-01 18:28:09 +08:00
method.MDToken.ToUInt32(),
Utils.removeNewlines(type),
info.reason);
2011-09-22 10:55:30 +08:00
}
Logger.Instance.deIndent();
2011-09-22 10:55:30 +08:00
}
void deleteFields() {
if (fieldsToRemove.Count == 0)
return;
Logger.v("Removing fields");
Logger.Instance.indent();
2011-09-22 10:55:30 +08:00
foreach (var info in fieldsToRemove) {
var field = info.obj;
if (field == null)
continue;
var type = field.DeclaringType;
if (type == null)
continue;
2011-09-22 10:55:30 +08:00
if (type.Fields.Remove(field))
Logger.v("Removed field {0} ({1:X8}) (Type: {2}) (reason: {3})",
Utils.removeNewlines(field),
2012-11-01 18:28:09 +08:00
field.MDToken.ToUInt32(),
Utils.removeNewlines(type),
info.reason);
2011-09-22 10:55:30 +08:00
}
Logger.Instance.deIndent();
2011-09-22 10:55:30 +08:00
}
void deleteTypes() {
var types = module.Types;
if (types == null || typesToRemove.Count == 0)
return;
Logger.v("Removing types");
Logger.Instance.indent();
2012-07-27 14:02:27 +08:00
var moduleType = DotNetUtils.getModuleType(module);
2011-09-22 10:55:30 +08:00
foreach (var info in typesToRemove) {
var typeDef = info.obj;
2012-07-27 14:02:27 +08:00
if (typeDef == null || typeDef == moduleType)
2011-09-22 10:55:30 +08:00
continue;
bool removed;
2012-11-01 18:28:09 +08:00
if (typeDef.DeclaringType != null)
removed = typeDef.DeclaringType.NestedTypes.Remove(typeDef);
else
removed = types.Remove(typeDef);
if (removed)
Logger.v("Removed type {0} ({1:X8}) (reason: {2})",
Utils.removeNewlines(typeDef),
2012-11-01 18:28:09 +08:00
typeDef.MDToken.ToUInt32(),
info.reason);
2011-09-22 10:55:30 +08:00
}
Logger.Instance.deIndent();
2011-09-22 10:55:30 +08:00
}
void deleteCustomAttributes() {
if (attrsToRemove.Count == 0)
return;
Logger.v("Removing custom attributes");
Logger.Instance.indent();
2011-09-22 10:55:30 +08:00
deleteCustomAttributes(module.CustomAttributes);
2011-10-05 14:20:32 +08:00
if (module.Assembly != null)
deleteCustomAttributes(module.Assembly.CustomAttributes);
Logger.Instance.deIndent();
2011-09-22 10:55:30 +08:00
}
void deleteCustomAttributes(IList<CustomAttribute> customAttrs) {
if (customAttrs == null)
return;
foreach (var info in attrsToRemove) {
var typeDef = info.obj;
if (typeDef == null)
continue;
for (int i = 0; i < customAttrs.Count; i++) {
2012-11-01 21:39:39 +08:00
if (new SigComparer().Equals(typeDef, customAttrs[i].AttributeType)) {
2011-09-22 10:55:30 +08:00
customAttrs.RemoveAt(i);
2012-11-01 21:39:39 +08:00
i--;
Logger.v("Removed custom attribute {0} ({1:X8}) (reason: {2})",
Utils.removeNewlines(typeDef),
2012-11-01 18:28:09 +08:00
typeDef.MDToken.ToUInt32(),
info.reason);
2011-09-22 10:55:30 +08:00
break;
}
}
}
}
void deleteOtherAttributes() {
Logger.v("Removing other attributes");
Logger.Instance.indent();
2011-09-22 10:55:30 +08:00
deleteOtherAttributes(module.CustomAttributes);
2011-10-05 14:20:32 +08:00
if (module.Assembly != null)
deleteOtherAttributes(module.Assembly.CustomAttributes);
Logger.Instance.deIndent();
2011-09-22 10:55:30 +08:00
}
void deleteOtherAttributes(IList<CustomAttribute> customAttributes) {
for (int i = customAttributes.Count - 1; i >= 0; i--) {
2012-11-01 18:28:09 +08:00
var attr = customAttributes[i].TypeFullName;
if (attr == "System.Runtime.CompilerServices.SuppressIldasmAttribute") {
Logger.v("Removed attribute {0}", Utils.removeNewlines(attr));
2011-09-22 10:55:30 +08:00
customAttributes.RemoveAt(i);
}
}
}
void deleteDllResources() {
if (!module.HasResources || resourcesToRemove.Count == 0)
return;
Logger.v("Removing resources");
Logger.Instance.indent();
2011-09-22 10:55:30 +08:00
foreach (var info in resourcesToRemove) {
var resource = info.obj;
if (resource == null)
continue;
if (module.Resources.Remove(resource))
Logger.v("Removed resource {0} (reason: {1})", Utils.toCsharpString(resource.Name), info.reason);
2011-09-22 10:55:30 +08:00
}
Logger.Instance.deIndent();
2011-09-22 10:55:30 +08:00
}
protected void setInitLocals() {
foreach (var type in module.GetTypes()) {
foreach (var method in type.Methods) {
if (isFatHeader(method))
method.Body.InitLocals = true;
}
}
}
2012-11-01 18:28:09 +08:00
static bool isFatHeader(MethodDef method) {
if (method == null || method.Body == null)
return false;
var body = method.Body;
2012-11-01 18:28:09 +08:00
if (body.InitLocals || body.MaxStack > 8)
return true;
if (body.Variables.Count > 0)
return true;
if (body.ExceptionHandlers.Count > 0)
return true;
if (getCodeSize(method) > 63)
return true;
return false;
}
2012-11-01 18:28:09 +08:00
static int getCodeSize(MethodDef method) {
if (method == null || method.Body == null)
return 0;
int size = 0;
foreach (var instr in method.Body.Instructions)
size += instr.GetSize();
return size;
}
2011-09-22 10:55:30 +08:00
public override string ToString() {
return Name;
}
2012-11-01 18:28:09 +08:00
protected void findPossibleNamesToRemove(MethodDef method) {
if (method == null || !method.HasBody)
2011-09-22 10:55:30 +08:00
return;
foreach (var instr in method.Body.Instructions) {
2011-09-22 10:55:30 +08:00
if (instr.OpCode == OpCodes.Ldstr)
namesToPossiblyRemove.Add((string)instr.Operand);
}
}
protected void addResources(string reason) {
if (!module.HasResources)
return;
foreach (var name in namesToPossiblyRemove) {
foreach (var resource in module.Resources) {
if (resource.Name == name) {
addResourceToBeRemoved(resource, reason);
break;
}
}
}
}
2012-07-27 14:02:27 +08:00
protected bool removeProxyDelegates(ProxyCallFixerBase proxyCallFixer) {
return removeProxyDelegates(proxyCallFixer, true);
2012-07-07 13:11:32 +08:00
}
2012-07-27 14:02:27 +08:00
protected bool removeProxyDelegates(ProxyCallFixerBase proxyCallFixer, bool removeCreators) {
2012-05-29 17:13:39 +08:00
if (proxyCallFixer.Errors != 0) {
Logger.v("Not removing proxy delegates and creator type since errors were detected.");
2012-07-27 14:02:27 +08:00
return false;
}
2012-05-29 17:13:39 +08:00
addTypesToBeRemoved(proxyCallFixer.DelegateTypes, "Proxy delegate type");
2012-07-27 14:02:27 +08:00
if (removeCreators && proxyCallFixer.RemovedDelegateCreatorCalls > 0) {
2012-05-29 17:13:39 +08:00
addTypesToBeRemoved(proxyCallFixer.DelegateCreatorTypes, "Proxy delegate creator type");
2012-07-27 14:02:27 +08:00
foreach (var tuple in proxyCallFixer.OtherMethods)
addMethodToBeRemoved(tuple.Item1, tuple.Item2);
}
return true;
2011-09-22 10:55:30 +08:00
}
protected Resource getResource(IEnumerable<string> strings) {
return DotNetUtils.getResource(module, strings);
}
2012-11-01 21:39:39 +08:00
protected CustomAttribute getAssemblyAttribute(IType attr) {
if (module.Assembly == null)
return null;
return module.Assembly.CustomAttributes.Find(attr);
2011-09-22 10:55:30 +08:00
}
2011-11-17 11:17:03 +08:00
2012-11-01 21:39:39 +08:00
protected CustomAttribute getModuleAttribute(IType attr) {
return module.CustomAttributes.Find(attr);
2012-08-16 01:33:57 +08:00
}
2011-11-24 14:49:50 +08:00
protected bool hasMetadataStream(string name) {
2012-11-01 18:28:09 +08:00
foreach (var stream in module.MetaData.AllStreams) {
if (stream.Name == name)
2011-11-24 14:49:50 +08:00
return true;
}
return false;
}
2012-11-01 21:39:39 +08:00
List<T> getObjectsToRemove<T>(IList<RemoveInfo<T>> removeThese) where T : class, ICodedToken {
var list = new List<T>(removeThese.Count);
foreach (var info in removeThese) {
if (info.obj != null)
list.Add(info.obj);
}
return list;
}
2012-11-01 18:28:09 +08:00
protected List<TypeDef> getTypesToRemove() {
return getObjectsToRemove(typesToRemove);
}
2012-11-01 18:28:09 +08:00
protected List<MethodDef> getMethodsToRemove() {
return getObjectsToRemove(methodsToRemove);
}
2011-11-23 12:28:57 +08:00
public virtual bool isValidNamespaceName(string ns) {
if (ns == null)
return false;
foreach (var part in ns.Split(new char[] { '.' })) {
if (!checkValidName(part))
return false;
}
return true;
2011-11-17 11:17:03 +08:00
}
2011-11-23 12:28:57 +08:00
public virtual bool isValidTypeName(string name) {
2011-11-21 18:03:45 +08:00
return name != null && checkValidName(name);
2011-11-17 11:17:03 +08:00
}
2011-11-23 12:28:57 +08:00
public virtual bool isValidMethodName(string name) {
2011-11-21 18:03:45 +08:00
return name != null && checkValidName(name);
2011-11-17 11:17:03 +08:00
}
2011-11-23 12:28:57 +08:00
public virtual bool isValidPropertyName(string name) {
2011-11-21 18:03:45 +08:00
return name != null && checkValidName(name);
2011-11-17 11:17:03 +08:00
}
2011-11-23 12:28:57 +08:00
public virtual bool isValidEventName(string name) {
2011-11-21 18:03:45 +08:00
return name != null && checkValidName(name);
2011-11-17 11:17:03 +08:00
}
2011-11-23 12:28:57 +08:00
public virtual bool isValidFieldName(string name) {
2011-11-21 18:03:45 +08:00
return name != null && checkValidName(name);
2011-11-17 11:17:03 +08:00
}
2011-11-23 12:28:57 +08:00
public virtual bool isValidGenericParamName(string name) {
2011-11-21 18:03:45 +08:00
return name != null && checkValidName(name);
2011-11-17 11:17:03 +08:00
}
2011-11-23 12:28:57 +08:00
public virtual bool isValidMethodArgName(string name) {
2011-11-21 18:03:45 +08:00
return name != null && checkValidName(name);
2011-11-17 11:17:03 +08:00
}
2012-11-04 18:45:04 +08:00
public virtual bool isValidMethodReturnArgName(string name) {
return string.IsNullOrEmpty(name) || checkValidName(name);
}
2012-05-03 20:53:01 +08:00
public virtual bool isValidResourceKeyName(string name) {
return name != null && checkValidName(name);
}
public virtual void OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt) {
}
2011-12-21 04:47:45 +08:00
2012-01-22 05:16:07 +08:00
protected void findAndRemoveInlinedMethods() {
removeInlinedMethods(InlinedMethodsFinder.find(module));
}
2012-11-01 18:28:09 +08:00
protected void removeInlinedMethods(List<MethodDef> inlinedMethods) {
addMethodsToBeRemoved(new UnusedMethodsFinder(module, inlinedMethods, getRemovedMethods()).find(), "Inlined method");
}
2012-02-03 13:33:54 +08:00
protected MethodCollection getRemovedMethods() {
var removedMethods = new MethodCollection();
removedMethods.add(getMethodsToRemove());
removedMethods.addAndNested(getTypesToRemove());
return removedMethods;
2011-12-21 04:47:45 +08:00
}
2011-12-21 07:30:17 +08:00
2012-11-01 18:28:09 +08:00
protected bool isTypeCalled(TypeDef decrypterType) {
2011-12-21 07:30:17 +08:00
if (decrypterType == null)
return false;
var decrypterMethods = new MethodCollection();
decrypterMethods.addAndNested(decrypterType);
2011-12-21 07:30:17 +08:00
var removedMethods = getRemovedMethods();
2011-12-21 07:30:17 +08:00
foreach (var type in module.GetTypes()) {
foreach (var method in type.Methods) {
if (method.Body == null)
2011-12-21 07:30:17 +08:00
continue;
if (decrypterMethods.exists(method))
2011-12-21 07:30:17 +08:00
break; // decrypter type / nested type method
if (removedMethods.exists(method))
2011-12-21 07:30:17 +08:00
continue;
foreach (var instr in method.Body.Instructions) {
2011-12-21 07:30:17 +08:00
switch (instr.OpCode.Code) {
case Code.Call:
case Code.Callvirt:
case Code.Newobj:
2012-11-01 18:28:09 +08:00
var calledMethod = instr.Operand as IMethod;
2011-12-21 07:30:17 +08:00
if (calledMethod == null)
break;
if (decrypterMethods.exists(calledMethod))
2011-12-21 07:30:17 +08:00
return true;
break;
default:
break;
}
}
}
}
return false;
}
protected bool hasNativeMethods() {
if (module.VTableFixups != null)
return true;
foreach (var type in module.GetTypes()) {
foreach (var method in type.Methods) {
var mb = method.MethodBody;
if (mb == null)
continue;
if (mb is CilBody)
continue;
return true;
}
}
return false;
}
2012-10-31 23:54:20 +08:00
protected static int toInt32(bool b) {
2011-12-22 02:21:06 +08:00
return b ? 1 : 0;
}
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing) {
}
2011-09-22 10:55:30 +08:00
}
}