2011-09-22 10:55:30 +08:00
|
|
|
|
/*
|
2013-01-02 00:03:16 +08:00
|
|
|
|
Copyright (C) 2011-2013 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-12-20 09:06:09 +08:00
|
|
|
|
using dnlib.DotNet;
|
|
|
|
|
using dnlib.DotNet.Emit;
|
|
|
|
|
using dnlib.DotNet.Writer;
|
|
|
|
|
using dnlib.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 {
|
2012-11-05 02:40:36 +08:00
|
|
|
|
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();
|
2011-12-01 03:19:50 +08:00
|
|
|
|
byte[] moduleBytes;
|
2011-12-29 15:23:46 +08:00
|
|
|
|
protected InitializedDataCreator initializedDataCreator;
|
2012-12-14 23:50:06 +08:00
|
|
|
|
bool keepTypes;
|
|
|
|
|
MetaDataFlags? mdFlags;
|
2011-12-01 03:19:50 +08:00
|
|
|
|
|
|
|
|
|
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; }
|
2011-11-09 19:08:48 +08:00
|
|
|
|
public virtual RenamingOptions RenamingOptions { get; set; }
|
2011-09-28 22:06:10 +08:00
|
|
|
|
public DecrypterType DefaultDecrypterType { get; set; }
|
2011-09-22 10:55:30 +08:00
|
|
|
|
|
2012-12-01 10:24:12 +08:00
|
|
|
|
public virtual MetaDataFlags MetaDataFlags {
|
2012-12-14 23:50:06 +08:00
|
|
|
|
get { return mdFlags ?? Operations.MetaDataFlags; }
|
2012-12-01 10:24:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
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; }
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-14 23:50:06 +08:00
|
|
|
|
protected bool KeepTypes {
|
|
|
|
|
get { return keepTypes; }
|
|
|
|
|
set { keepTypes = value; }
|
2012-01-14 19:27:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
2012-11-09 09:15:28 +08:00
|
|
|
|
protected bool CanRemoveTypes {
|
|
|
|
|
get { return !Operations.KeepObfuscatorTypes && !KeepTypes; }
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-21 23:56:29 +08:00
|
|
|
|
protected bool CanRemoveStringDecrypterType {
|
|
|
|
|
get { return Operations.DecryptStrings != OpDecryptString.None && staticStringInliner.InlinedAllCalls; }
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-30 04:22:43 +08:00
|
|
|
|
public virtual IEnumerable<IBlocksDeobfuscator> BlocksDeobfuscators {
|
2012-01-11 11:38:02 +08:00
|
|
|
|
get {
|
2012-04-30 04:22:43 +08:00
|
|
|
|
var list = new List<IBlocksDeobfuscator>();
|
2012-01-11 11:38:02 +08:00
|
|
|
|
if (CanInlineMethods)
|
2012-04-30 04:22:43 +08:00
|
|
|
|
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;
|
2011-09-28 22:06:10 +08:00
|
|
|
|
DefaultDecrypterType = DecrypterType.Static;
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public virtual byte[] UnpackNativeFile(IPEImage peImage) {
|
2011-12-01 01:26:36 +08:00
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public virtual void Initialize(ModuleDefMD module) {
|
|
|
|
|
SetModule(module);
|
2011-10-26 20:29:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected void SetModule(ModuleDefMD module) {
|
2011-09-22 10:55:30 +08:00
|
|
|
|
this.module = module;
|
2011-12-29 15:23:46 +08:00
|
|
|
|
initializedDataCreator = new InitializedDataCreator(module);
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected void PreserveTokensAndTypes() {
|
2012-12-14 23:50:06 +08:00
|
|
|
|
keepTypes = true;
|
|
|
|
|
mdFlags = Operations.MetaDataFlags;
|
|
|
|
|
mdFlags |= MetaDataFlags.PreserveRids |
|
|
|
|
|
MetaDataFlags.PreserveUSOffsets |
|
|
|
|
|
MetaDataFlags.PreserveBlobOffsets |
|
|
|
|
|
MetaDataFlags.PreserveExtraSignatureData;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected virtual bool CheckValidName(string name) {
|
|
|
|
|
return optionsBase.ValidNameRegex.IsMatch(name);
|
2011-11-10 07:47:22 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public virtual int Detect() {
|
|
|
|
|
ScanForObfuscator();
|
|
|
|
|
return DetectInternal();
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected abstract void ScanForObfuscator();
|
|
|
|
|
protected abstract int DetectInternal();
|
2011-10-26 20:29:12 +08:00
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public virtual bool GetDecryptedModule(int count, ref byte[] newFileData, ref DumpedMethods dumpedMethods) {
|
2011-10-29 08:23:48 +08:00
|
|
|
|
return false;
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public virtual IDeobfuscator ModuleReloaded(ModuleDefMD module) {
|
2011-10-26 20:29:12 +08:00
|
|
|
|
throw new ApplicationException("moduleReloaded() must be overridden by the deobfuscator");
|
|
|
|
|
}
|
2011-09-22 10:55:30 +08:00
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public virtual void DeobfuscateBegin() {
|
2011-12-01 03:19:50 +08:00
|
|
|
|
ModuleBytes = null;
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public virtual void DeobfuscateMethodBegin(Blocks blocks) {
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public virtual void DeobfuscateMethodEnd(Blocks blocks) {
|
|
|
|
|
RemoveMethodCalls(blocks);
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public virtual void DeobfuscateStrings(Blocks blocks) {
|
|
|
|
|
staticStringInliner.Decrypt(blocks);
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public virtual bool DeobfuscateOther(Blocks blocks) {
|
2011-10-27 04:16:51 +08:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public virtual void DeobfuscateEnd() {
|
2012-11-09 09:15:28 +08:00
|
|
|
|
if (CanRemoveTypes) {
|
2013-01-19 20:03:57 +08:00
|
|
|
|
RemoveTypesWithInvalidBaseTypes();
|
2012-02-25 12:28:32 +08:00
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
DeleteEmptyCctors();
|
|
|
|
|
DeleteMethods();
|
|
|
|
|
DeleteFields();
|
|
|
|
|
DeleteCustomAttributes();
|
|
|
|
|
DeleteOtherAttributes();
|
|
|
|
|
DeleteTypes();
|
|
|
|
|
DeleteDllResources();
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
2012-01-04 03:14:28 +08:00
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
RestoreBaseType();
|
|
|
|
|
FixMDHeaderVersion();
|
2012-01-04 03:14:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
static bool IsTypeWithInvalidBaseType(TypeDef moduleType, TypeDef type) {
|
2012-02-12 18:35:18 +08:00
|
|
|
|
return type.BaseType == null && !type.IsInterface && type != moduleType;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
void RestoreBaseType() {
|
|
|
|
|
var moduleType = DotNetUtils.GetModuleType(module);
|
2012-01-04 03:14:28 +08:00
|
|
|
|
foreach (var type in module.GetTypes()) {
|
2013-01-19 20:03:57 +08:00
|
|
|
|
if (!IsTypeWithInvalidBaseType(moduleType, type))
|
2012-01-04 03:14:28 +08:00
|
|
|
|
continue;
|
2012-12-28 19:07:11 +08:00
|
|
|
|
var corSig = module.CorLibTypes.GetCorLibTypeSig(type);
|
|
|
|
|
if (corSig != null && corSig.ElementType == ElementType.Object)
|
|
|
|
|
continue;
|
2012-11-11 12:31:11 +08:00
|
|
|
|
Logger.v("Adding System.Object as base type: {0} ({1:X8})",
|
2013-01-19 20:03:57 +08:00
|
|
|
|
Utils.RemoveNewlines(type),
|
2012-11-01 18:28:09 +08:00
|
|
|
|
type.MDToken.ToInt32());
|
|
|
|
|
type.BaseType = module.CorLibTypes.Object.TypeDefOrRef;
|
2012-01-04 03:14:28 +08:00
|
|
|
|
}
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
void FixMDHeaderVersion() {
|
2012-12-20 08:45:50 +08:00
|
|
|
|
// Version 1.1 supports generics but it's a little different. Most tools
|
|
|
|
|
// will have a problem reading the MD tables, so switch to the standard v2.0.
|
|
|
|
|
if (module.TablesHeaderVersion == 0x0101)
|
|
|
|
|
module.TablesHeaderVersion = 0x0200;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
void RemoveTypesWithInvalidBaseTypes() {
|
|
|
|
|
var moduleType = DotNetUtils.GetModuleType(module);
|
2012-02-12 18:35:18 +08:00
|
|
|
|
foreach (var type in module.GetTypes()) {
|
2013-01-19 20:03:57 +08:00
|
|
|
|
if (!IsTypeWithInvalidBaseType(moduleType, type))
|
2012-02-12 18:35:18 +08:00
|
|
|
|
continue;
|
2013-01-19 20:03:57 +08:00
|
|
|
|
AddTypeToBeRemoved(type, "Invalid type with no base type (anti-reflection)");
|
2012-02-12 18:35:18 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected void FixEnumTypes() {
|
2012-02-25 12:15:42 +08:00
|
|
|
|
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;
|
2012-02-25 12:15:42 +08:00
|
|
|
|
field.IsSpecialName = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-02-29 06:57:48 +08:00
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected void FixInterfaces() {
|
2012-02-29 06:57:48 +08:00
|
|
|
|
foreach (var type in module.GetTypes()) {
|
|
|
|
|
if (!type.IsInterface)
|
|
|
|
|
continue;
|
|
|
|
|
type.IsSealed = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-02-25 12:15:42 +08:00
|
|
|
|
|
2013-01-19 20:03:57 +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 {
|
2012-11-22 16:14:51 +08:00
|
|
|
|
Dictionary<string, MethodDefAndDeclaringTypeDict<bool>> methodNameInfos = new Dictionary<string, MethodDefAndDeclaringTypeDict<bool>>();
|
|
|
|
|
MethodDefAndDeclaringTypeDict<MethodDefAndDeclaringTypeDict<bool>> methodRefInfos = new MethodDefAndDeclaringTypeDict<MethodDefAndDeclaringTypeDict<bool>>();
|
2011-09-22 10:55:30 +08:00
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
void CheckMethod(IMethod methodToBeRemoved) {
|
2012-11-01 18:28:09 +08:00
|
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public void Add(string method, MethodDef methodToBeRemoved) {
|
2011-10-23 14:41:33 +08:00
|
|
|
|
if (methodToBeRemoved == null)
|
|
|
|
|
return;
|
2013-01-19 20:03:57 +08:00
|
|
|
|
CheckMethod(methodToBeRemoved);
|
2011-10-23 14:41:33 +08:00
|
|
|
|
|
2012-11-22 16:14:51 +08:00
|
|
|
|
MethodDefAndDeclaringTypeDict<bool> dict;
|
2011-10-23 14:41:33 +08:00
|
|
|
|
if (!methodNameInfos.TryGetValue(method, out dict))
|
2012-11-22 16:14:51 +08:00
|
|
|
|
methodNameInfos[method] = dict = new MethodDefAndDeclaringTypeDict<bool>();
|
2013-01-19 20:03:57 +08:00
|
|
|
|
dict.Add(methodToBeRemoved, true);
|
2011-10-23 14:41:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public void Add(MethodDef method, MethodDef methodToBeRemoved) {
|
2011-10-23 14:41:33 +08:00
|
|
|
|
if (method == null || methodToBeRemoved == null)
|
|
|
|
|
return;
|
2013-01-19 20:03:57 +08:00
|
|
|
|
CheckMethod(methodToBeRemoved);
|
2011-10-23 14:41:33 +08:00
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
var dict = methodRefInfos.Find(method);
|
2011-12-31 23:32:57 +08:00
|
|
|
|
if (dict == null)
|
2013-01-19 20:03:57 +08:00
|
|
|
|
methodRefInfos.Add(method, dict = new MethodDefAndDeclaringTypeDict<bool>());
|
|
|
|
|
dict.Add(methodToBeRemoved, true);
|
2011-10-23 14:41:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public void RemoveAll(Blocks blocks) {
|
|
|
|
|
var allBlocks = blocks.MethodBlocks.GetAllBlocks();
|
2011-10-23 14:41:33 +08:00
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
RemoveAll(allBlocks, blocks, blocks.Method.Name.String);
|
|
|
|
|
RemoveAll(allBlocks, blocks, blocks.Method);
|
2011-10-23 14:41:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
void RemoveAll(IList<Block> allBlocks, Blocks blocks, string method) {
|
2012-11-22 16:14:51 +08:00
|
|
|
|
MethodDefAndDeclaringTypeDict<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
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
RemoveCalls(allBlocks, blocks, info);
|
2011-10-23 14:41:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
void RemoveAll(IList<Block> allBlocks, Blocks blocks, MethodDef method) {
|
|
|
|
|
var info = methodRefInfos.Find(method);
|
2011-12-31 23:32:57 +08:00
|
|
|
|
if (info == null)
|
2011-10-23 14:41:33 +08:00
|
|
|
|
return;
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
RemoveCalls(allBlocks, blocks, info);
|
2011-10-23 14:41:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
void RemoveCalls(IList<Block> allBlocks, Blocks blocks, MethodDefAndDeclaringTypeDict<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
|
|
|
|
|
2013-01-19 20:03: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);
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-01-19 20:03:57 +08:00
|
|
|
|
block.Remove(instrsToDelete);
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public void AddCctorInitCallToBeRemoved(MethodDef methodToBeRemoved) {
|
|
|
|
|
methodCallRemover.Add(".cctor", methodToBeRemoved);
|
2011-10-23 14:41:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public void AddModuleCctorInitCallToBeRemoved(MethodDef methodToBeRemoved) {
|
|
|
|
|
methodCallRemover.Add(DotNetUtils.GetModuleTypeCctor(module), methodToBeRemoved);
|
2011-10-23 14:41:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public void AddCtorInitCallToBeRemoved(MethodDef methodToBeRemoved) {
|
|
|
|
|
methodCallRemover.Add(".ctor", methodToBeRemoved);
|
2011-11-24 17:44:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public void AddCallToBeRemoved(MethodDef method, MethodDef methodToBeRemoved) {
|
|
|
|
|
methodCallRemover.Add(method, methodToBeRemoved);
|
2011-10-23 14:41:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
void RemoveMethodCalls(Blocks blocks) {
|
|
|
|
|
methodCallRemover.RemoveAll(blocks);
|
2011-10-23 14:41:33 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected void AddMethodsToBeRemoved(IEnumerable<MethodDef> methods, string reason) {
|
2011-09-22 10:55:30 +08:00
|
|
|
|
foreach (var method in methods)
|
2013-01-19 20:03:57 +08:00
|
|
|
|
AddMethodToBeRemoved(method, reason);
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +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
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected void AddFieldsToBeRemoved(IEnumerable<FieldDef> fields, string reason) {
|
2011-09-22 10:55:30 +08:00
|
|
|
|
foreach (var field in fields)
|
2013-01-19 20:03:57 +08:00
|
|
|
|
AddFieldToBeRemoved(field, reason);
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +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
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected void AddAttributesToBeRemoved(IEnumerable<TypeDef> attrs, string reason) {
|
2012-04-26 22:08:39 +08:00
|
|
|
|
foreach (var attr in attrs)
|
2013-01-19 20:03:57 +08:00
|
|
|
|
AddAttributeToBeRemoved(attr, reason);
|
2012-04-26 22:08:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected void AddAttributeToBeRemoved(TypeDef attr, string reason) {
|
2012-04-05 23:06:27 +08:00
|
|
|
|
if (attr == null)
|
|
|
|
|
return;
|
2013-01-19 20:03:57 +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
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected void AddTypesToBeRemoved(IEnumerable<TypeDef> types, string reason) {
|
2011-09-22 10:55:30 +08:00
|
|
|
|
foreach (var type in types)
|
2013-01-19 20:03:57 +08:00
|
|
|
|
AddTypeToBeRemoved(type, reason);
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +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
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +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
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +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();
|
2013-01-19 20:03:57 +08:00
|
|
|
|
if (cctor != null && DotNetUtils.IsEmpty(cctor))
|
2011-09-22 10:55:30 +08:00
|
|
|
|
emptyCctorsToRemove.Add(cctor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (emptyCctorsToRemove.Count == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
2012-11-11 12:31:11 +08:00
|
|
|
|
Logger.v("Removing empty .cctor methods");
|
2013-01-19 20:03:57 +08:00
|
|
|
|
Logger.Instance.Indent();
|
2011-09-22 10:55:30 +08:00
|
|
|
|
foreach (var cctor in emptyCctorsToRemove) {
|
|
|
|
|
var type = cctor.DeclaringType;
|
2012-07-31 10:40:06 +08:00
|
|
|
|
if (type == null)
|
|
|
|
|
continue;
|
2011-09-22 10:55:30 +08:00
|
|
|
|
if (type.Methods.Remove(cctor))
|
2012-11-11 12:31:11 +08:00
|
|
|
|
Logger.v("{0:X8}, type: {1} ({2:X8})",
|
2012-11-01 18:28:09 +08:00
|
|
|
|
cctor.MDToken.ToUInt32(),
|
2013-01-19 20:03:57 +08:00
|
|
|
|
Utils.RemoveNewlines(type),
|
2012-11-01 18:28:09 +08:00
|
|
|
|
type.MDToken.ToUInt32());
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
2013-01-19 20:03:57 +08:00
|
|
|
|
Logger.Instance.DeIndent();
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
void DeleteMethods() {
|
2011-09-22 10:55:30 +08:00
|
|
|
|
if (methodsToRemove.Count == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
2012-11-11 12:31:11 +08:00
|
|
|
|
Logger.v("Removing methods");
|
2013-01-19 20:03:57 +08:00
|
|
|
|
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))
|
2012-11-11 12:31:11 +08:00
|
|
|
|
Logger.v("Removed method {0} ({1:X8}) (Type: {2}) (reason: {3})",
|
2013-01-19 20:03:57 +08:00
|
|
|
|
Utils.RemoveNewlines(method),
|
2012-11-01 18:28:09 +08:00
|
|
|
|
method.MDToken.ToUInt32(),
|
2013-01-19 20:03:57 +08:00
|
|
|
|
Utils.RemoveNewlines(type),
|
2012-01-04 02:52:40 +08:00
|
|
|
|
info.reason);
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
2013-01-19 20:03:57 +08:00
|
|
|
|
Logger.Instance.DeIndent();
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
void DeleteFields() {
|
2011-09-22 10:55:30 +08:00
|
|
|
|
if (fieldsToRemove.Count == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
2012-11-11 12:31:11 +08:00
|
|
|
|
Logger.v("Removing fields");
|
2013-01-19 20:03:57 +08:00
|
|
|
|
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;
|
2012-07-31 10:40:06 +08:00
|
|
|
|
if (type == null)
|
|
|
|
|
continue;
|
2011-09-22 10:55:30 +08:00
|
|
|
|
if (type.Fields.Remove(field))
|
2012-11-11 12:31:11 +08:00
|
|
|
|
Logger.v("Removed field {0} ({1:X8}) (Type: {2}) (reason: {3})",
|
2013-01-19 20:03:57 +08:00
|
|
|
|
Utils.RemoveNewlines(field),
|
2012-11-01 18:28:09 +08:00
|
|
|
|
field.MDToken.ToUInt32(),
|
2013-01-19 20:03:57 +08:00
|
|
|
|
Utils.RemoveNewlines(type),
|
2012-01-04 02:52:40 +08:00
|
|
|
|
info.reason);
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
2013-01-19 20:03:57 +08:00
|
|
|
|
Logger.Instance.DeIndent();
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
void DeleteTypes() {
|
2011-09-22 10:55:30 +08:00
|
|
|
|
var types = module.Types;
|
|
|
|
|
if (types == null || typesToRemove.Count == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
2012-11-11 12:31:11 +08:00
|
|
|
|
Logger.v("Removing types");
|
2013-01-19 20:03:57 +08:00
|
|
|
|
Logger.Instance.Indent();
|
|
|
|
|
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;
|
2011-12-28 20:30:44 +08:00
|
|
|
|
bool removed;
|
2012-11-01 18:28:09 +08:00
|
|
|
|
if (typeDef.DeclaringType != null)
|
2011-12-28 20:30:44 +08:00
|
|
|
|
removed = typeDef.DeclaringType.NestedTypes.Remove(typeDef);
|
|
|
|
|
else
|
|
|
|
|
removed = types.Remove(typeDef);
|
|
|
|
|
if (removed)
|
2012-11-11 12:31:11 +08:00
|
|
|
|
Logger.v("Removed type {0} ({1:X8}) (reason: {2})",
|
2013-01-19 20:03:57 +08:00
|
|
|
|
Utils.RemoveNewlines(typeDef),
|
2012-11-01 18:28:09 +08:00
|
|
|
|
typeDef.MDToken.ToUInt32(),
|
2012-01-04 02:52:40 +08:00
|
|
|
|
info.reason);
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
2013-01-19 20:03:57 +08:00
|
|
|
|
Logger.Instance.DeIndent();
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
void DeleteCustomAttributes() {
|
2011-09-22 10:55:30 +08:00
|
|
|
|
if (attrsToRemove.Count == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
2012-11-11 12:31:11 +08:00
|
|
|
|
Logger.v("Removing custom attributes");
|
2013-01-19 20:03:57 +08:00
|
|
|
|
Logger.Instance.Indent();
|
|
|
|
|
DeleteCustomAttributes(module.CustomAttributes);
|
2011-10-05 14:20:32 +08:00
|
|
|
|
if (module.Assembly != null)
|
2013-01-19 20:03:57 +08:00
|
|
|
|
DeleteCustomAttributes(module.Assembly.CustomAttributes);
|
|
|
|
|
Logger.Instance.DeIndent();
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
void DeleteCustomAttributes(IList<CustomAttribute> customAttrs) {
|
2011-09-22 10:55:30 +08:00
|
|
|
|
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--;
|
2012-11-11 12:31:11 +08:00
|
|
|
|
Logger.v("Removed custom attribute {0} ({1:X8}) (reason: {2})",
|
2013-01-19 20:03:57 +08:00
|
|
|
|
Utils.RemoveNewlines(typeDef),
|
2012-11-01 18:28:09 +08:00
|
|
|
|
typeDef.MDToken.ToUInt32(),
|
2012-01-04 02:52:40 +08:00
|
|
|
|
info.reason);
|
2011-09-22 10:55:30 +08:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
void DeleteOtherAttributes() {
|
2012-11-11 12:31:11 +08:00
|
|
|
|
Logger.v("Removing other attributes");
|
2013-01-19 20:03:57 +08:00
|
|
|
|
Logger.Instance.Indent();
|
|
|
|
|
DeleteOtherAttributes(module.CustomAttributes);
|
2011-10-05 14:20:32 +08:00
|
|
|
|
if (module.Assembly != null)
|
2013-01-19 20:03:57 +08:00
|
|
|
|
DeleteOtherAttributes(module.Assembly.CustomAttributes);
|
|
|
|
|
Logger.Instance.DeIndent();
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
void DeleteOtherAttributes(IList<CustomAttribute> customAttributes) {
|
2011-09-22 10:55:30 +08:00
|
|
|
|
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") {
|
2013-01-19 20:03:57 +08:00
|
|
|
|
Logger.v("Removed attribute {0}", Utils.RemoveNewlines(attr));
|
2011-09-22 10:55:30 +08:00
|
|
|
|
customAttributes.RemoveAt(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
void DeleteDllResources() {
|
2011-09-22 10:55:30 +08:00
|
|
|
|
if (!module.HasResources || resourcesToRemove.Count == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
2012-11-11 12:31:11 +08:00
|
|
|
|
Logger.v("Removing resources");
|
2013-01-19 20:03:57 +08:00
|
|
|
|
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))
|
2013-01-19 20:03:57 +08:00
|
|
|
|
Logger.v("Removed resource {0} (reason: {1})", Utils.ToCsharpString(resource.Name), info.reason);
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
2013-01-19 20:03:57 +08:00
|
|
|
|
Logger.Instance.DeIndent();
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected void SetInitLocals() {
|
2012-04-29 12:16:53 +08:00
|
|
|
|
foreach (var type in module.GetTypes()) {
|
|
|
|
|
foreach (var method in type.Methods) {
|
2013-01-19 20:03:57 +08:00
|
|
|
|
if (IsFatHeader(method))
|
2012-11-06 22:58:55 +08:00
|
|
|
|
method.Body.InitLocals = true;
|
2012-04-29 12:16:53 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
static bool IsFatHeader(MethodDef method) {
|
2012-11-06 22:58:55 +08:00
|
|
|
|
if (method == null || method.Body == null)
|
2012-04-29 12:16:53 +08:00
|
|
|
|
return false;
|
2012-11-06 22:58:55 +08:00
|
|
|
|
var body = method.Body;
|
2012-11-01 18:28:09 +08:00
|
|
|
|
if (body.InitLocals || body.MaxStack > 8)
|
2012-04-29 12:16:53 +08:00
|
|
|
|
return true;
|
2012-11-20 00:58:34 +08:00
|
|
|
|
if (body.Variables.Count > 0)
|
2012-04-29 12:16:53 +08:00
|
|
|
|
return true;
|
|
|
|
|
if (body.ExceptionHandlers.Count > 0)
|
|
|
|
|
return true;
|
2013-01-19 20:03:57 +08:00
|
|
|
|
if (GetCodeSize(method) > 63)
|
2012-04-29 12:16:53 +08:00
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
static int GetCodeSize(MethodDef method) {
|
2012-11-06 22:58:55 +08:00
|
|
|
|
if (method == null || method.Body == null)
|
2012-04-29 12:16:53 +08:00
|
|
|
|
return 0;
|
|
|
|
|
int size = 0;
|
2012-11-06 22:58:55 +08:00
|
|
|
|
foreach (var instr in method.Body.Instructions)
|
2012-04-29 12:16:53 +08:00
|
|
|
|
size += instr.GetSize();
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-22 10:55:30 +08:00
|
|
|
|
public override string ToString() {
|
|
|
|
|
return Name;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected void FindPossibleNamesToRemove(MethodDef method) {
|
2012-11-06 22:58:55 +08:00
|
|
|
|
if (method == null || !method.HasBody)
|
2011-09-22 10:55:30 +08:00
|
|
|
|
return;
|
|
|
|
|
|
2012-11-06 22:58:55 +08:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected void AddResources(string reason) {
|
2011-09-22 10:55:30 +08:00
|
|
|
|
if (!module.HasResources)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
foreach (var name in namesToPossiblyRemove) {
|
|
|
|
|
foreach (var resource in module.Resources) {
|
|
|
|
|
if (resource.Name == name) {
|
2013-01-19 20:03:57 +08:00
|
|
|
|
AddResourceToBeRemoved(resource, reason);
|
2011-09-22 10:55:30 +08:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected bool RemoveProxyDelegates(ProxyCallFixerBase proxyCallFixer) {
|
|
|
|
|
return RemoveProxyDelegates(proxyCallFixer, true);
|
2012-07-07 13:11:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected bool RemoveProxyDelegates(ProxyCallFixerBase proxyCallFixer, bool removeCreators) {
|
2012-05-29 17:13:39 +08:00
|
|
|
|
if (proxyCallFixer.Errors != 0) {
|
2012-11-11 12:31:11 +08:00
|
|
|
|
Logger.v("Not removing proxy delegates and creator type since errors were detected.");
|
2012-07-27 14:02:27 +08:00
|
|
|
|
return false;
|
2011-11-28 18:45:48 +08:00
|
|
|
|
}
|
2013-01-19 20:03:57 +08:00
|
|
|
|
AddTypesToBeRemoved(proxyCallFixer.DelegateTypes, "Proxy delegate type");
|
2012-07-27 14:02:27 +08:00
|
|
|
|
if (removeCreators && proxyCallFixer.RemovedDelegateCreatorCalls > 0) {
|
2013-01-19 20:03:57 +08:00
|
|
|
|
AddTypesToBeRemoved(proxyCallFixer.DelegateCreatorTypes, "Proxy delegate creator type");
|
2012-07-27 14:02:27 +08:00
|
|
|
|
foreach (var tuple in proxyCallFixer.OtherMethods)
|
2013-01-19 20:03:57 +08:00
|
|
|
|
AddMethodToBeRemoved(tuple.Item1, tuple.Item2);
|
2012-07-27 14:02:27 +08:00
|
|
|
|
}
|
|
|
|
|
return true;
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected Resource GetResource(IEnumerable<string> strings) {
|
|
|
|
|
return DotNetUtils.GetResource(module, strings);
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected CustomAttribute GetAssemblyAttribute(IType attr) {
|
2012-11-01 21:39:39 +08:00
|
|
|
|
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
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected CustomAttribute GetModuleAttribute(IType attr) {
|
2012-11-01 21:39:39 +08:00
|
|
|
|
return module.CustomAttributes.Find(attr);
|
2012-08-16 01:33:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected bool HasMetadataStream(string name) {
|
2012-11-01 18:28:09 +08:00
|
|
|
|
foreach (var stream in module.MetaData.AllStreams) {
|
2011-11-25 22:19:56 +08:00
|
|
|
|
if (stream.Name == name)
|
2011-11-24 14:49:50 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
List<T> GetObjectsToRemove<T>(IList<RemoveInfo<T>> removeThese) where T : class, ICodedToken {
|
2011-11-26 19:21:18 +08:00
|
|
|
|
var list = new List<T>(removeThese.Count);
|
|
|
|
|
foreach (var info in removeThese) {
|
|
|
|
|
if (info.obj != null)
|
|
|
|
|
list.Add(info.obj);
|
|
|
|
|
}
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected List<TypeDef> GetTypesToRemove() {
|
|
|
|
|
return GetObjectsToRemove(typesToRemove);
|
2011-11-26 19:21:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected List<MethodDef> GetMethodsToRemove() {
|
|
|
|
|
return GetObjectsToRemove(methodsToRemove);
|
2011-11-26 19:21:18 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public virtual bool IsValidNamespaceName(string ns) {
|
2011-11-23 18:50:34 +08:00
|
|
|
|
if (ns == null)
|
|
|
|
|
return false;
|
|
|
|
|
foreach (var part in ns.Split(new char[] { '.' })) {
|
2013-01-19 20:03:57 +08:00
|
|
|
|
if (!CheckValidName(part))
|
2011-11-23 18:50:34 +08:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
2011-11-17 11:17:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public virtual bool IsValidTypeName(string name) {
|
|
|
|
|
return name != null && CheckValidName(name);
|
2011-11-17 11:17:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public virtual bool IsValidMethodName(string name) {
|
|
|
|
|
return name != null && CheckValidName(name);
|
2011-11-17 11:17:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public virtual bool IsValidPropertyName(string name) {
|
|
|
|
|
return name != null && CheckValidName(name);
|
2011-11-17 11:17:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public virtual bool IsValidEventName(string name) {
|
|
|
|
|
return name != null && CheckValidName(name);
|
2011-11-17 11:17:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public virtual bool IsValidFieldName(string name) {
|
|
|
|
|
return name != null && CheckValidName(name);
|
2011-11-17 11:17:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public virtual bool IsValidGenericParamName(string name) {
|
|
|
|
|
return name != null && CheckValidName(name);
|
2011-11-17 11:17:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public virtual bool IsValidMethodArgName(string name) {
|
|
|
|
|
return name != null && CheckValidName(name);
|
2011-11-17 11:17:03 +08:00
|
|
|
|
}
|
2011-11-25 22:19:56 +08:00
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public virtual bool IsValidMethodReturnArgName(string name) {
|
|
|
|
|
return string.IsNullOrEmpty(name) || CheckValidName(name);
|
2012-11-04 18:45:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
public virtual bool IsValidResourceKeyName(string name) {
|
|
|
|
|
return name != null && CheckValidName(name);
|
2012-05-03 20:53:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
2012-11-13 05:06:13 +08:00
|
|
|
|
public virtual void OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt) {
|
2011-11-25 22:19:56 +08:00
|
|
|
|
}
|
2011-12-21 04:47:45 +08:00
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected void FindAndRemoveInlinedMethods() {
|
|
|
|
|
RemoveInlinedMethods(InlinedMethodsFinder.Find(module));
|
2012-01-22 05:16:07 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected void RemoveInlinedMethods(List<MethodDef> inlinedMethods) {
|
|
|
|
|
AddMethodsToBeRemoved(new UnusedMethodsFinder(module, inlinedMethods, GetRemovedMethods()).Find(), "Inlined method");
|
2011-12-28 20:30:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected MethodCollection GetRemovedMethods() {
|
2011-12-28 20:30:44 +08:00
|
|
|
|
var removedMethods = new MethodCollection();
|
2013-01-19 20:03:57 +08:00
|
|
|
|
removedMethods.Add(GetMethodsToRemove());
|
|
|
|
|
removedMethods.AddAndNested(GetTypesToRemove());
|
2011-12-28 20:30:44 +08:00
|
|
|
|
return removedMethods;
|
2011-12-21 04:47:45 +08:00
|
|
|
|
}
|
2011-12-21 07:30:17 +08:00
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected bool IsTypeCalled(TypeDef decrypterType) {
|
2011-12-21 07:30:17 +08:00
|
|
|
|
if (decrypterType == null)
|
|
|
|
|
return false;
|
|
|
|
|
|
2011-12-28 20:30:44 +08:00
|
|
|
|
var decrypterMethods = new MethodCollection();
|
2013-01-19 20:03:57 +08:00
|
|
|
|
decrypterMethods.AddAndNested(decrypterType);
|
2011-12-21 07:30:17 +08:00
|
|
|
|
|
2013-01-19 20:03:57 +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) {
|
2012-11-06 22:58:55 +08:00
|
|
|
|
if (method.Body == null)
|
2011-12-21 07:30:17 +08:00
|
|
|
|
continue;
|
2013-01-19 20:03:57 +08:00
|
|
|
|
if (decrypterMethods.Exists(method))
|
2011-12-21 07:30:17 +08:00
|
|
|
|
break; // decrypter type / nested type method
|
2013-01-19 20:03:57 +08:00
|
|
|
|
if (removedMethods.Exists(method))
|
2011-12-21 07:30:17 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
2012-11-06 22:58:55 +08:00
|
|
|
|
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;
|
2013-01-19 20:03:57 +08:00
|
|
|
|
if (decrypterMethods.Exists(calledMethod))
|
2011-12-21 07:30:17 +08:00
|
|
|
|
return true;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected bool HasNativeMethods() {
|
2012-11-14 18:29:22 +08:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-19 20:03:57 +08:00
|
|
|
|
protected static int ToInt32(bool b) {
|
2011-12-22 02:21:06 +08:00
|
|
|
|
return b ? 1 : 0;
|
|
|
|
|
}
|
2012-11-21 20:57:13 +08:00
|
|
|
|
|
|
|
|
|
public void Dispose() {
|
|
|
|
|
Dispose(true);
|
|
|
|
|
GC.SuppressFinalize(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual void Dispose(bool disposing) {
|
|
|
|
|
}
|
2011-09-22 10:55:30 +08:00
|
|
|
|
}
|
|
|
|
|
}
|