Rename types
This commit is contained in:
parent
b58c3843e3
commit
195c7194cb
|
@ -20,6 +20,7 @@
|
|||
using System.Collections.Generic;
|
||||
using de4dot.deobfuscators;
|
||||
using Mono.Cecil;
|
||||
using de4dot.renamer;
|
||||
|
||||
namespace de4dot {
|
||||
interface IObfuscatedFile {
|
||||
|
@ -27,7 +28,7 @@ namespace de4dot {
|
|||
IDeobfuscator Deobfuscator { get; }
|
||||
string Filename { get; }
|
||||
string NewFilename { get; }
|
||||
Func<string, bool> IsValidName { get; }
|
||||
INameChecker NameChecker { get; }
|
||||
bool RenameResourcesInCode { get; }
|
||||
bool RenameSymbols { get; }
|
||||
bool RemoveNamespaceWithOneType { get; }
|
||||
|
|
|
@ -29,6 +29,7 @@ using de4dot.deobfuscators;
|
|||
using de4dot.blocks;
|
||||
using de4dot.blocks.cflow;
|
||||
using de4dot.AssemblyClient;
|
||||
using de4dot.renamer;
|
||||
|
||||
namespace de4dot {
|
||||
class ObfuscatedFile : IObfuscatedFile, IDeobfuscatedFile {
|
||||
|
@ -106,8 +107,8 @@ namespace de4dot {
|
|||
get { return module; }
|
||||
}
|
||||
|
||||
public Func<string, bool> IsValidName {
|
||||
get { return deob.IsValidName; }
|
||||
public INameChecker NameChecker {
|
||||
get { return deob; }
|
||||
}
|
||||
|
||||
public bool RenameResourcesInCode {
|
||||
|
|
|
@ -156,6 +156,7 @@
|
|||
<Compile Include="renamer\asmmodules\EventDef.cs" />
|
||||
<Compile Include="renamer\asmmodules\ExternalAssemblies.cs" />
|
||||
<Compile Include="renamer\asmmodules\FieldDef.cs" />
|
||||
<Compile Include="renamer\asmmodules\GenericParamDef.cs" />
|
||||
<Compile Include="renamer\asmmodules\IResolver.cs" />
|
||||
<Compile Include="renamer\asmmodules\MemberRefFinder.cs" />
|
||||
<Compile Include="renamer\asmmodules\MethodDef.cs" />
|
||||
|
@ -166,7 +167,12 @@
|
|||
<Compile Include="renamer\asmmodules\Ref.cs" />
|
||||
<Compile Include="renamer\asmmodules\RefDict.cs" />
|
||||
<Compile Include="renamer\asmmodules\TypeDef.cs" />
|
||||
<Compile Include="renamer\DerivedFrom.cs" />
|
||||
<Compile Include="renamer\ExistingNames.cs" />
|
||||
<Compile Include="renamer\INameChecker.cs" />
|
||||
<Compile Include="renamer\NameCreators.cs" />
|
||||
<Compile Include="renamer\Renamer.cs" />
|
||||
<Compile Include="renamer\TypeRenamerState.cs" />
|
||||
<Compile Include="StringDecrypter.cs" />
|
||||
<Compile Include="UserException.cs" />
|
||||
<Compile Include="Utils.cs" />
|
||||
|
|
|
@ -77,10 +77,6 @@ namespace de4dot.deobfuscators {
|
|||
get { return false; }
|
||||
}
|
||||
|
||||
public Func<string, bool> IsValidName {
|
||||
get { return (name) => checkValidName(name); }
|
||||
}
|
||||
|
||||
public DeobfuscatorBase(OptionsBase optionsBase) {
|
||||
this.optionsBase = optionsBase;
|
||||
StringFeatures = StringFeatures.AllowAll;
|
||||
|
@ -502,5 +498,37 @@ namespace de4dot.deobfuscators {
|
|||
var list = new List<CustomAttribute>(DotNetUtils.findAttributes(module.Assembly, attr));
|
||||
return list.Count == 0 ? null : list[0];
|
||||
}
|
||||
|
||||
public bool isValidNamespaceName(string ns) {
|
||||
return checkValidName(ns);
|
||||
}
|
||||
|
||||
public bool isValidTypeName(string name) {
|
||||
return checkValidName(name);
|
||||
}
|
||||
|
||||
public bool isValidMethodName(string name) {
|
||||
return checkValidName(name);
|
||||
}
|
||||
|
||||
public bool isValidPropertyName(string name) {
|
||||
return checkValidName(name);
|
||||
}
|
||||
|
||||
public bool isValidEventName(string name) {
|
||||
return checkValidName(name);
|
||||
}
|
||||
|
||||
public bool isValidFieldName(string name) {
|
||||
return checkValidName(name);
|
||||
}
|
||||
|
||||
public bool isValidGenericParamName(string name) {
|
||||
return checkValidName(name);
|
||||
}
|
||||
|
||||
public bool isValidMethodArgName(string name) {
|
||||
return checkValidName(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ using System.Collections.Generic;
|
|||
using Mono.Cecil;
|
||||
using Mono.MyStuff;
|
||||
using de4dot.blocks;
|
||||
using de4dot.renamer;
|
||||
|
||||
namespace de4dot.deobfuscators {
|
||||
interface IDeobfuscatorOptions {
|
||||
|
@ -49,11 +50,10 @@ namespace de4dot.deobfuscators {
|
|||
RemoveNamespaceIfOneType = 1,
|
||||
}
|
||||
|
||||
interface IDeobfuscator {
|
||||
interface IDeobfuscator : INameChecker {
|
||||
string Type { get; }
|
||||
string TypeLong { get; }
|
||||
string Name { get; }
|
||||
Func<string, bool> IsValidName { get; }
|
||||
IDeobfuscatorOptions TheOptions { get; }
|
||||
IOperations Operations { get; set; }
|
||||
StringFeatures StringFeatures { get; }
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace de4dot.old_renamer {
|
|||
List<MethodDefinition> allMethods;
|
||||
|
||||
public Func<string, bool> IsValidName {
|
||||
get { return obfuscatedFile.IsValidName; }
|
||||
get { return null; }
|
||||
}
|
||||
|
||||
class RefToDef<R, D> where R : MemberReference where D : R {
|
||||
|
|
62
de4dot.code/renamer/DerivedFrom.cs
Normal file
62
de4dot.code/renamer/DerivedFrom.cs
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
Copyright (C) 2011 de4dot@gmail.com
|
||||
|
||||
This file is part of de4dot.
|
||||
|
||||
de4dot is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
de4dot is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using de4dot.renamer.asmmodules;
|
||||
|
||||
namespace de4dot.renamer {
|
||||
class DerivedFrom {
|
||||
Dictionary<string, bool> classNames = new Dictionary<string, bool>(StringComparer.Ordinal);
|
||||
Dictionary<TypeDef, bool> results = new Dictionary<TypeDef, bool>();
|
||||
|
||||
public DerivedFrom(string className) {
|
||||
addName(className);
|
||||
}
|
||||
|
||||
public DerivedFrom(string[] classNames) {
|
||||
foreach (var className in classNames)
|
||||
addName(className);
|
||||
}
|
||||
|
||||
void addName(string className) {
|
||||
classNames[className] = true;
|
||||
}
|
||||
|
||||
public bool check(TypeDef type) {
|
||||
if (results.ContainsKey(type))
|
||||
return results[type];
|
||||
|
||||
bool val;
|
||||
if (classNames.ContainsKey(type.TypeDefinition.FullName))
|
||||
val = true;
|
||||
else if (type.baseType == null) {
|
||||
if (type.TypeDefinition.BaseType != null)
|
||||
val = classNames.ContainsKey(type.TypeDefinition.BaseType.FullName);
|
||||
else
|
||||
val = false;
|
||||
}
|
||||
else
|
||||
val = check(type.baseType.typeDef);
|
||||
|
||||
results[type] = val;
|
||||
return val;
|
||||
}
|
||||
}
|
||||
}
|
62
de4dot.code/renamer/ExistingNames.cs
Normal file
62
de4dot.code/renamer/ExistingNames.cs
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
Copyright (C) 2011 de4dot@gmail.com
|
||||
|
||||
This file is part of de4dot.
|
||||
|
||||
de4dot is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
de4dot is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace de4dot.renamer {
|
||||
class ExistingNames {
|
||||
Dictionary<string, bool> allNames = new Dictionary<string, bool>(StringComparer.Ordinal);
|
||||
|
||||
public void add(string name) {
|
||||
allNames[name] = true;
|
||||
}
|
||||
|
||||
bool exists(string name) {
|
||||
return allNames.ContainsKey(name);
|
||||
}
|
||||
|
||||
public string getName(string oldName, INameCreator nameCreator) {
|
||||
return getName(oldName, () => nameCreator.create());
|
||||
}
|
||||
|
||||
public string getName(string oldName, Func<string> createNewName) {
|
||||
string prevName = null;
|
||||
while (true) {
|
||||
var name = createNewName();
|
||||
if (name == prevName)
|
||||
throw new ApplicationException(string.Format("Could not rename symbol to {0}", Utils.toCsharpString(name)));
|
||||
|
||||
if (!exists(name) || name == oldName) {
|
||||
allNames[name] = true;
|
||||
return name;
|
||||
}
|
||||
|
||||
prevName = name;
|
||||
}
|
||||
}
|
||||
|
||||
public ExistingNames clone() {
|
||||
var cn = new ExistingNames();
|
||||
foreach (var key in allNames.Keys)
|
||||
cn.allNames[key] = true;
|
||||
return cn;
|
||||
}
|
||||
}
|
||||
}
|
31
de4dot.code/renamer/INameChecker.cs
Normal file
31
de4dot.code/renamer/INameChecker.cs
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
Copyright (C) 2011 de4dot@gmail.com
|
||||
|
||||
This file is part of de4dot.
|
||||
|
||||
de4dot is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
de4dot is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace de4dot.renamer {
|
||||
interface INameChecker {
|
||||
bool isValidNamespaceName(string ns);
|
||||
bool isValidTypeName(string name);
|
||||
bool isValidMethodName(string name);
|
||||
bool isValidPropertyName(string name);
|
||||
bool isValidEventName(string name);
|
||||
bool isValidFieldName(string name);
|
||||
bool isValidGenericParamName(string name);
|
||||
bool isValidMethodArgName(string name);
|
||||
}
|
||||
}
|
229
de4dot.code/renamer/NameCreators.cs
Normal file
229
de4dot.code/renamer/NameCreators.cs
Normal file
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
Copyright (C) 2011 de4dot@gmail.com
|
||||
|
||||
This file is part of de4dot.
|
||||
|
||||
de4dot is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
de4dot is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Mono.Cecil;
|
||||
using de4dot.blocks;
|
||||
|
||||
namespace de4dot.renamer {
|
||||
interface INameCreator {
|
||||
INameCreator clone();
|
||||
string create();
|
||||
}
|
||||
|
||||
class OneNameCreator : INameCreator {
|
||||
string name;
|
||||
|
||||
public OneNameCreator(string name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public INameCreator clone() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public string create() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
class GlobalNameCreator : INameCreator {
|
||||
INameCreator other;
|
||||
|
||||
public GlobalNameCreator(INameCreator other) {
|
||||
this.other = other;
|
||||
}
|
||||
|
||||
public INameCreator clone() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public string create() {
|
||||
return other.create();
|
||||
}
|
||||
}
|
||||
|
||||
class GenericParamNameCreator : INameCreator {
|
||||
static string[] names = new string[] { "T", "U", "V", "W", "X", "Y", "Z" };
|
||||
int index = 0;
|
||||
|
||||
public string create() {
|
||||
if (index < names.Length)
|
||||
return names[index++];
|
||||
return string.Format("T{0}", index++);
|
||||
}
|
||||
|
||||
public INameCreator clone() {
|
||||
var rv = new GenericParamNameCreator();
|
||||
rv.index = index;
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
class NameCreator : INameCreator {
|
||||
string prefix;
|
||||
int num;
|
||||
|
||||
public NameCreator(string prefix, int num = 0) {
|
||||
this.prefix = prefix;
|
||||
this.num = num;
|
||||
}
|
||||
|
||||
public INameCreator clone() {
|
||||
return new NameCreator(prefix, num);
|
||||
}
|
||||
|
||||
public string create() {
|
||||
return prefix + num++;
|
||||
}
|
||||
}
|
||||
|
||||
// Like NameCreator but don't add the counter the first time
|
||||
class NameCreator2 : INameCreator {
|
||||
string prefix;
|
||||
int num;
|
||||
const string separator = "_";
|
||||
|
||||
public NameCreator2(string prefix, int num = 0) {
|
||||
this.prefix = prefix;
|
||||
this.num = num;
|
||||
}
|
||||
|
||||
public INameCreator clone() {
|
||||
return new NameCreator2(prefix, num);
|
||||
}
|
||||
|
||||
public string create() {
|
||||
string rv;
|
||||
if (num == 0)
|
||||
rv = prefix;
|
||||
else
|
||||
rv = prefix + separator + num;
|
||||
num++;
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
interface ITypeNameCreator {
|
||||
string create(TypeDefinition typeDefinition, string newBaseTypeName = null);
|
||||
}
|
||||
|
||||
class NameInfos {
|
||||
IList<NameInfo> nameInfos = new List<NameInfo>();
|
||||
|
||||
class NameInfo {
|
||||
public string name;
|
||||
public INameCreator nameCreator;
|
||||
public NameInfo(string name, INameCreator nameCreator) {
|
||||
this.name = name;
|
||||
this.nameCreator = nameCreator;
|
||||
}
|
||||
}
|
||||
|
||||
public void add(string name, INameCreator nameCreator) {
|
||||
nameInfos.Add(new NameInfo(name, nameCreator));
|
||||
}
|
||||
|
||||
public INameCreator find(string typeName) {
|
||||
foreach (var nameInfo in nameInfos) {
|
||||
if (typeName.Contains(nameInfo.name))
|
||||
return nameInfo.nameCreator;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class TypeNameCreator : ITypeNameCreator {
|
||||
ExistingNames existingNames;
|
||||
INameCreator createUnknownTypeName;
|
||||
INameCreator createEnumName;
|
||||
INameCreator createStructName;
|
||||
INameCreator createDelegateName;
|
||||
INameCreator createClassName;
|
||||
INameCreator createInterfaceName;
|
||||
NameInfos nameInfos = new NameInfos();
|
||||
|
||||
public TypeNameCreator(ExistingNames existingNames) {
|
||||
this.existingNames = existingNames;
|
||||
createUnknownTypeName = createNameCreator("Type");
|
||||
createEnumName = createNameCreator("Enum");
|
||||
createStructName = createNameCreator("Struct");
|
||||
createDelegateName = createNameCreator("Delegate");
|
||||
createClassName = createNameCreator("Class");
|
||||
createInterfaceName = createNameCreator("Interface");
|
||||
|
||||
var names = new string[] {
|
||||
"Exception",
|
||||
"EventArgs",
|
||||
"Attribute",
|
||||
"Form",
|
||||
"Dialog",
|
||||
"Control",
|
||||
};
|
||||
foreach (var name in names)
|
||||
nameInfos.add(name, createNameCreator(name));
|
||||
}
|
||||
|
||||
protected virtual INameCreator createNameCreator(string prefix) {
|
||||
return new NameCreator(prefix);
|
||||
}
|
||||
|
||||
public string create(TypeDefinition typeDefinition, string newBaseTypeName = null) {
|
||||
var nameCreator = getNameCreator(typeDefinition, newBaseTypeName);
|
||||
return existingNames.getName(typeDefinition.Name, nameCreator);
|
||||
}
|
||||
|
||||
INameCreator getNameCreator(TypeDefinition typeDefinition, string newBaseTypeName) {
|
||||
var nameCreator = createUnknownTypeName;
|
||||
if (typeDefinition.IsEnum)
|
||||
nameCreator = createEnumName;
|
||||
else if (typeDefinition.IsValueType)
|
||||
nameCreator = createStructName;
|
||||
else if (typeDefinition.IsClass) {
|
||||
if (typeDefinition.BaseType != null) {
|
||||
if (MemberReferenceHelper.verifyType(typeDefinition.BaseType, "mscorlib", "System.Delegate"))
|
||||
nameCreator = createDelegateName;
|
||||
else if (MemberReferenceHelper.verifyType(typeDefinition.BaseType, "mscorlib", "System.MulticastDelegate"))
|
||||
nameCreator = createDelegateName;
|
||||
else {
|
||||
nameCreator = nameInfos.find(newBaseTypeName ?? typeDefinition.BaseType.Name);
|
||||
if (nameCreator == null)
|
||||
nameCreator = createClassName;
|
||||
}
|
||||
}
|
||||
else
|
||||
nameCreator = createClassName;
|
||||
}
|
||||
else if (typeDefinition.IsInterface)
|
||||
nameCreator = createInterfaceName;
|
||||
return nameCreator;
|
||||
}
|
||||
}
|
||||
|
||||
class GlobalTypeNameCreator : TypeNameCreator {
|
||||
public GlobalTypeNameCreator(ExistingNames existingNames)
|
||||
: base(existingNames) {
|
||||
}
|
||||
|
||||
protected override INameCreator createNameCreator(string prefix) {
|
||||
return new GlobalNameCreator(base.createNameCreator("G" + prefix));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,21 +17,177 @@
|
|||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Mono.Cecil;
|
||||
using Mono.Cecil.Cil;
|
||||
using de4dot.blocks;
|
||||
using de4dot.renamer.asmmodules;
|
||||
|
||||
namespace de4dot.renamer {
|
||||
class MemberInfo {
|
||||
Ref memberRef;
|
||||
public string oldFullName;
|
||||
public string oldName;
|
||||
public string newName;
|
||||
public bool renamed;
|
||||
|
||||
public MemberInfo(Ref memberRef) {
|
||||
this.memberRef = memberRef;
|
||||
oldFullName = memberRef.memberReference.FullName;
|
||||
oldName = memberRef.memberReference.Name;
|
||||
newName = memberRef.memberReference.Name;
|
||||
}
|
||||
|
||||
public void rename(string newTypeName) {
|
||||
renamed = true;
|
||||
newName = newTypeName;
|
||||
}
|
||||
|
||||
public bool gotNewName() {
|
||||
return oldName != newName;
|
||||
}
|
||||
}
|
||||
|
||||
class TypeInfo : MemberInfo {
|
||||
public string oldNamespace;
|
||||
public string newNamespace;
|
||||
|
||||
public TypeInfo(TypeDef type)
|
||||
: base(type) {
|
||||
oldNamespace = type.TypeDefinition.Namespace;
|
||||
}
|
||||
}
|
||||
|
||||
class GenericParamInfo : MemberInfo {
|
||||
public GenericParamInfo(GenericParamDef genericParamDef)
|
||||
: base(genericParamDef) {
|
||||
}
|
||||
}
|
||||
|
||||
class Renamer {
|
||||
bool renameSymbols = true;
|
||||
bool renameFields = true;
|
||||
bool renameProperties = true;
|
||||
bool renameEvents = true;
|
||||
bool renameMethods = true;
|
||||
public bool RenameNamespaces { get; set; }
|
||||
public bool RenameTypes { get; set; }
|
||||
public bool RenameProperties { get; set; }
|
||||
public bool RenameEvents { get; set; }
|
||||
public bool RenameFields { get; set; }
|
||||
public bool RenameGenericParams { get; set; }
|
||||
public bool RenameMethodArgs { get; set; }
|
||||
Modules modules = new Modules();
|
||||
DerivedFrom isWinFormsClass;
|
||||
Dictionary<TypeDef, TypeInfo> allTypeInfos = new Dictionary<TypeDef, TypeInfo>();
|
||||
Dictionary<GenericParamDef, GenericParamInfo> allGenericParamInfos = new Dictionary<GenericParamDef, GenericParamInfo>();
|
||||
Dictionary<MethodDef, string> suggestedMethodNames = new Dictionary<MethodDef, string>();
|
||||
|
||||
static string[] WINFORMS_CLASSES = new string[] {
|
||||
#region Win Forms class names
|
||||
"System.Windows.Forms.Control",
|
||||
"System.Windows.Forms.AxHost",
|
||||
"System.Windows.Forms.ButtonBase",
|
||||
"System.Windows.Forms.Button",
|
||||
"System.Windows.Forms.CheckBox",
|
||||
"System.Windows.Forms.RadioButton",
|
||||
"System.Windows.Forms.DataGrid",
|
||||
"System.Windows.Forms.DataGridView",
|
||||
"System.Windows.Forms.DataVisualization.Charting.Chart",
|
||||
"System.Windows.Forms.DateTimePicker",
|
||||
"System.Windows.Forms.GroupBox",
|
||||
"System.Windows.Forms.Integration.ElementHost",
|
||||
"System.Windows.Forms.Label",
|
||||
"System.Windows.Forms.LinkLabel",
|
||||
"System.Windows.Forms.ListControl",
|
||||
"System.Windows.Forms.ComboBox",
|
||||
"Microsoft.VisualBasic.Compatibility.VB6.DriveListBox",
|
||||
"System.Windows.Forms.DataGridViewComboBoxEditingControl",
|
||||
"System.Windows.Forms.ListBox",
|
||||
"Microsoft.VisualBasic.Compatibility.VB6.DirListBox",
|
||||
"Microsoft.VisualBasic.Compatibility.VB6.FileListBox",
|
||||
"System.Windows.Forms.CheckedListBox",
|
||||
"System.Windows.Forms.ListView",
|
||||
"System.Windows.Forms.MdiClient",
|
||||
"System.Windows.Forms.MonthCalendar",
|
||||
"System.Windows.Forms.PictureBox",
|
||||
"System.Windows.Forms.PrintPreviewControl",
|
||||
"System.Windows.Forms.ProgressBar",
|
||||
"System.Windows.Forms.ScrollableControl",
|
||||
"System.Windows.Forms.ContainerControl",
|
||||
"System.Windows.Forms.Form",
|
||||
"System.ComponentModel.Design.CollectionEditor.CollectionForm",
|
||||
"System.Messaging.Design.QueuePathDialog",
|
||||
"System.ServiceProcess.Design.ServiceInstallerDialog",
|
||||
"System.Web.UI.Design.WebControls.CalendarAutoFormatDialog",
|
||||
"System.Web.UI.Design.WebControls.RegexEditorDialog",
|
||||
"System.Windows.Forms.Design.ComponentEditorForm",
|
||||
"System.Windows.Forms.PrintPreviewDialog",
|
||||
"System.Windows.Forms.ThreadExceptionDialog",
|
||||
"System.Workflow.Activities.Rules.Design.RuleConditionDialog",
|
||||
"System.Workflow.Activities.Rules.Design.RuleSetDialog",
|
||||
"System.Workflow.ComponentModel.Design.ThemeConfigurationDialog",
|
||||
"System.Workflow.ComponentModel.Design.TypeBrowserDialog",
|
||||
"System.Workflow.ComponentModel.Design.WorkflowPageSetupDialog",
|
||||
"System.Windows.Forms.PropertyGrid",
|
||||
"System.Windows.Forms.SplitContainer",
|
||||
"System.Windows.Forms.ToolStripContainer",
|
||||
"System.Windows.Forms.ToolStripPanel",
|
||||
"System.Windows.Forms.UpDownBase",
|
||||
"System.Windows.Forms.DomainUpDown",
|
||||
"System.Windows.Forms.NumericUpDown",
|
||||
"System.Windows.Forms.UserControl",
|
||||
"Microsoft.VisualBasic.Compatibility.VB6.ADODC",
|
||||
"System.Web.UI.Design.WebControls.ParameterEditorUserControl",
|
||||
"System.Workflow.ComponentModel.Design.WorkflowOutline",
|
||||
"System.Workflow.ComponentModel.Design.WorkflowView",
|
||||
"System.Windows.Forms.Design.ComponentTray",
|
||||
"System.Windows.Forms.Panel",
|
||||
"System.Windows.Forms.Design.ComponentEditorPage",
|
||||
"System.Windows.Forms.FlowLayoutPanel",
|
||||
"System.Windows.Forms.SplitterPanel",
|
||||
"System.Windows.Forms.TableLayoutPanel",
|
||||
"System.ComponentModel.Design.ByteViewer",
|
||||
"System.Windows.Forms.TabPage",
|
||||
"System.Windows.Forms.ToolStripContentPanel",
|
||||
"System.Windows.Forms.ToolStrip",
|
||||
"System.Windows.Forms.BindingNavigator",
|
||||
"System.Windows.Forms.MenuStrip",
|
||||
"System.Windows.Forms.StatusStrip",
|
||||
"System.Windows.Forms.ToolStripDropDown",
|
||||
"System.Windows.Forms.ToolStripDropDownMenu",
|
||||
"System.Windows.Forms.ContextMenuStrip",
|
||||
"System.Windows.Forms.ToolStripOverflow",
|
||||
"System.Windows.Forms.ScrollBar",
|
||||
"System.Windows.Forms.HScrollBar",
|
||||
"System.Windows.Forms.VScrollBar",
|
||||
"System.Windows.Forms.Splitter",
|
||||
"System.Windows.Forms.StatusBar",
|
||||
"System.Windows.Forms.TabControl",
|
||||
"System.Windows.Forms.TextBoxBase",
|
||||
"System.Windows.Forms.MaskedTextBox",
|
||||
"System.Windows.Forms.RichTextBox",
|
||||
"System.Windows.Forms.TextBox",
|
||||
"System.Windows.Forms.DataGridTextBox",
|
||||
"System.Windows.Forms.DataGridViewTextBoxEditingControl",
|
||||
"System.Windows.Forms.ToolBar",
|
||||
"System.Windows.Forms.TrackBar",
|
||||
"System.Windows.Forms.TreeView",
|
||||
"System.ComponentModel.Design.ObjectSelectorEditor.Selector",
|
||||
"System.Windows.Forms.WebBrowserBase",
|
||||
"System.Windows.Forms.WebBrowser",
|
||||
#endregion
|
||||
};
|
||||
|
||||
public Renamer(IEnumerable<IObfuscatedFile> files) {
|
||||
RenameNamespaces = true;
|
||||
RenameTypes = true;
|
||||
RenameProperties = true;
|
||||
RenameEvents = true;
|
||||
RenameFields = true;
|
||||
RenameGenericParams = true;
|
||||
RenameMethodArgs = true;
|
||||
|
||||
foreach (var file in files)
|
||||
modules.add(new Module(file));
|
||||
|
||||
isWinFormsClass = new DerivedFrom(WINFORMS_CLASSES);
|
||||
}
|
||||
|
||||
public void rename() {
|
||||
|
@ -41,7 +197,224 @@ namespace de4dot.renamer {
|
|||
|
||||
modules.initialize();
|
||||
modules.initializeVirtualMembers();
|
||||
renameTypeDefinitions();
|
||||
modules.cleanUp();
|
||||
}
|
||||
|
||||
void renameTypeDefinitions() {
|
||||
Log.v("Renaming obfuscated type definitions");
|
||||
|
||||
prepareRenameTypes();
|
||||
}
|
||||
|
||||
void prepareRenameTypes() {
|
||||
foreach (var type in modules.AllTypes)
|
||||
allTypeInfos[type] = new TypeInfo(type);
|
||||
|
||||
var state = new TypeRenamerState();
|
||||
prepareRenameTypes(modules.BaseTypes, state);
|
||||
fixClsTypeNames();
|
||||
renameTypeDefinitions(modules.NonNestedTypes);
|
||||
}
|
||||
|
||||
void renameTypeDefinitions(IEnumerable<TypeDef> typeDefs) {
|
||||
Log.indent();
|
||||
foreach (var typeDef in typeDefs) {
|
||||
rename(typeDef);
|
||||
renameTypeDefinitions(typeDef.NestedTypes);
|
||||
}
|
||||
Log.deIndent();
|
||||
}
|
||||
|
||||
void rename(TypeDef type) {
|
||||
var typeDefinition = type.TypeDefinition;
|
||||
var info = allTypeInfos[type];
|
||||
|
||||
Log.v("Type: {0} ({1:X8})", typeDefinition.FullName, typeDefinition.MetadataToken.ToUInt32());
|
||||
Log.indent();
|
||||
|
||||
renameGenericParams(type.GenericParams);
|
||||
|
||||
if (RenameTypes && info.gotNewName()) {
|
||||
var old = typeDefinition.Name;
|
||||
typeDefinition.Name = info.newName;
|
||||
Log.v("Name: {0} => {1}", old, typeDefinition.Name);
|
||||
}
|
||||
|
||||
if (RenameNamespaces && info.newNamespace != null) {
|
||||
var old = typeDefinition.Namespace;
|
||||
typeDefinition.Namespace = info.newNamespace;
|
||||
Log.v("Namespace: {0} => {1}", old, typeDefinition.Namespace);
|
||||
}
|
||||
|
||||
Log.deIndent();
|
||||
}
|
||||
|
||||
void renameGenericParams(IEnumerable<GenericParamDef> genericParams) {
|
||||
if (!RenameGenericParams)
|
||||
return;
|
||||
foreach (var param in genericParams) {
|
||||
var info = allGenericParamInfos[param];
|
||||
if (!info.gotNewName())
|
||||
continue;
|
||||
param.GenericParameter.Name = info.newName;
|
||||
Log.v("GenParam: {0} => {1}", info.oldFullName, param.GenericParameter.FullName);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the renamed types are using valid CLS names. That means renaming all
|
||||
// generic types from eg. Class1 to Class1`2. If we don't do this, some decompilers
|
||||
// (eg. ILSpy v1.0) won't produce correct output.
|
||||
void fixClsTypeNames() {
|
||||
foreach (var type in modules.NonNestedTypes)
|
||||
fixClsTypeNames(null, type);
|
||||
}
|
||||
|
||||
void fixClsTypeNames(TypeDef nesting, TypeDef nested) {
|
||||
int nestingCount = nesting == null ? 0 : nesting.GenericParams.Count;
|
||||
int arity = nested.GenericParams.Count - nestingCount;
|
||||
var nestedInfo = allTypeInfos[nested];
|
||||
if (nestedInfo.renamed && arity > 0)
|
||||
nestedInfo.newName += "`" + arity;
|
||||
foreach (var nestedType in nested.NestedTypes)
|
||||
fixClsTypeNames(nested, nestedType);
|
||||
}
|
||||
|
||||
void prepareRenameTypes(IEnumerable<TypeDef> types, TypeRenamerState state) {
|
||||
foreach (var typeDef in types) {
|
||||
prepareRenameTypes(typeDef, state);
|
||||
prepareRenameTypes(typeDef.derivedTypes, state);
|
||||
}
|
||||
}
|
||||
|
||||
void prepareRenameTypes(TypeDef type, TypeRenamerState state) {
|
||||
var info = allTypeInfos[type];
|
||||
var checker = type.Module.ObfuscatedFile.NameChecker;
|
||||
|
||||
if (RenameNamespaces) {
|
||||
if (info.newNamespace == null && info.oldNamespace != "") {
|
||||
if (!checker.isValidNamespaceName(info.oldNamespace)) {
|
||||
info.newNamespace = state.createNamespace(info.oldNamespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (RenameTypes) {
|
||||
if (info.oldFullName != "<Module>" && !checker.isValidTypeName(info.oldName)) {
|
||||
string origClassName = null;
|
||||
if (isWinFormsClass.check(type))
|
||||
origClassName = findWindowsFormsClassName(type);
|
||||
if (origClassName != null && checker.isValidTypeName(origClassName))
|
||||
info.rename(state.getTypeName(info.oldName, origClassName));
|
||||
else {
|
||||
ITypeNameCreator nameCreator = type.isGlobalType() ?
|
||||
state.globalTypeNameCreator :
|
||||
state.internalTypeNameCreator;
|
||||
string newBaseType = null;
|
||||
TypeInfo baseInfo;
|
||||
if (type.baseType != null && allTypeInfos.TryGetValue(type.baseType.typeDef, out baseInfo)) {
|
||||
if (baseInfo.renamed)
|
||||
newBaseType = baseInfo.newName;
|
||||
}
|
||||
info.rename(nameCreator.create(type.TypeDefinition, newBaseType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (RenameGenericParams)
|
||||
prepareRenameGenericParams(type.GenericParams, checker);
|
||||
}
|
||||
|
||||
void prepareRenameGenericParams(IEnumerable<GenericParamDef> genericParams, INameChecker checker, IEnumerable<GenericParamDef> otherGenericParams = null) {
|
||||
var usedNames = new Dictionary<string, bool>(StringComparer.Ordinal);
|
||||
var nameCreator = new GenericParamNameCreator();
|
||||
|
||||
foreach (var gp in genericParams)
|
||||
allGenericParamInfos[gp] = new GenericParamInfo(gp);
|
||||
|
||||
if (otherGenericParams != null) {
|
||||
foreach (var param in otherGenericParams) {
|
||||
var gpInfo = allGenericParamInfos[param];
|
||||
usedNames[gpInfo.newName] = true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var param in genericParams) {
|
||||
var gpInfo = allGenericParamInfos[param];
|
||||
if (!checker.isValidGenericParamName(gpInfo.oldName) || usedNames.ContainsKey(gpInfo.oldName)) {
|
||||
string newName;
|
||||
do {
|
||||
newName = nameCreator.create();
|
||||
} while (usedNames.ContainsKey(newName));
|
||||
usedNames[newName] = true;
|
||||
gpInfo.rename(newName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string findWindowsFormsClassName(TypeDef type) {
|
||||
foreach (var methodDef in type.getAllMethods()) {
|
||||
if (methodDef.MethodDefinition.Body == null)
|
||||
continue;
|
||||
if (methodDef.MethodDefinition.IsStatic || methodDef.MethodDefinition.IsVirtual)
|
||||
continue;
|
||||
var instructions = methodDef.MethodDefinition.Body.Instructions;
|
||||
for (int i = 2; i < instructions.Count; i++) {
|
||||
var call = instructions[i];
|
||||
if (call.OpCode.Code != Code.Call && call.OpCode.Code != Code.Callvirt)
|
||||
continue;
|
||||
if (!isWindowsFormsSetNameMethod(call.Operand as MethodReference))
|
||||
continue;
|
||||
|
||||
var ldstr = instructions[i - 1];
|
||||
if (ldstr.OpCode.Code != Code.Ldstr)
|
||||
continue;
|
||||
var className = ldstr.Operand as string;
|
||||
if (className == null)
|
||||
continue;
|
||||
|
||||
if (DotNetUtils.getArgIndex(methodDef.MethodDefinition, instructions[i - 2]) != 0)
|
||||
continue;
|
||||
|
||||
findInitializeComponentMethod(type, methodDef);
|
||||
return className;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void findInitializeComponentMethod(TypeDef type, MethodDef possibleInitMethod) {
|
||||
foreach (var methodDef in type.getAllMethods()) {
|
||||
if (methodDef.MethodDefinition.Name != ".ctor")
|
||||
continue;
|
||||
if (methodDef.MethodDefinition.Body == null)
|
||||
continue;
|
||||
foreach (var instr in methodDef.MethodDefinition.Body.Instructions) {
|
||||
if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt)
|
||||
continue;
|
||||
if (!MemberReferenceHelper.compareMethodReferenceAndDeclaringType(possibleInitMethod.MethodDefinition, instr.Operand as MethodReference))
|
||||
continue;
|
||||
|
||||
suggestedMethodNames[possibleInitMethod] = "InitializeComponent";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool isWindowsFormsSetNameMethod(MethodReference method) {
|
||||
if (method == null)
|
||||
return false;
|
||||
if (method.Name != "set_Name")
|
||||
return false;
|
||||
if (method.MethodReturnType.ReturnType.FullName != "System.Void")
|
||||
return false;
|
||||
if (method.Parameters.Count != 1)
|
||||
return false;
|
||||
if (method.Parameters[0].ParameterType.FullName != "System.String")
|
||||
return false;
|
||||
if (!method.DeclaringType.FullName.StartsWith("System.Windows.Forms.", StringComparison.Ordinal))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
50
de4dot.code/renamer/TypeRenamerState.cs
Normal file
50
de4dot.code/renamer/TypeRenamerState.cs
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
Copyright (C) 2011 de4dot@gmail.com
|
||||
|
||||
This file is part of de4dot.
|
||||
|
||||
de4dot is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
de4dot is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace de4dot.renamer {
|
||||
class TypeRenamerState {
|
||||
ExistingNames existingNames;
|
||||
Dictionary<string, string> namespaceToNewName;
|
||||
INameCreator createNamespaceName;
|
||||
public ITypeNameCreator globalTypeNameCreator;
|
||||
public ITypeNameCreator internalTypeNameCreator;
|
||||
|
||||
public TypeRenamerState() {
|
||||
existingNames = new ExistingNames();
|
||||
namespaceToNewName = new Dictionary<string, string>(StringComparer.Ordinal);
|
||||
createNamespaceName = new GlobalNameCreator(new NameCreator("ns"));
|
||||
globalTypeNameCreator = new GlobalTypeNameCreator(existingNames);
|
||||
internalTypeNameCreator = new TypeNameCreator(existingNames);
|
||||
}
|
||||
|
||||
public string getTypeName(string oldName, string newName) {
|
||||
return existingNames.getName(oldName, new NameCreator2(newName));
|
||||
}
|
||||
|
||||
public string createNamespace(string ns) {
|
||||
string newName;
|
||||
if (namespaceToNewName.TryGetValue(ns, out newName))
|
||||
return newName;
|
||||
return namespaceToNewName[ns] = createNamespaceName.create();
|
||||
}
|
||||
}
|
||||
}
|
43
de4dot.code/renamer/asmmodules/GenericParamDef.cs
Normal file
43
de4dot.code/renamer/asmmodules/GenericParamDef.cs
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
Copyright (C) 2011 de4dot@gmail.com
|
||||
|
||||
This file is part of de4dot.
|
||||
|
||||
de4dot is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
de4dot is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Mono.Cecil;
|
||||
|
||||
namespace de4dot.renamer.asmmodules {
|
||||
class GenericParamDef : Ref {
|
||||
public GenericParameter GenericParameter {
|
||||
get { return (GenericParameter)memberReference; }
|
||||
}
|
||||
|
||||
public GenericParamDef(GenericParameter genericParameter, int index)
|
||||
: base(genericParameter, null, index) {
|
||||
}
|
||||
|
||||
public static List<GenericParamDef> createGenericParamDefList(IEnumerable<GenericParameter> parameters) {
|
||||
var list = new List<GenericParamDef>();
|
||||
if (parameters == null)
|
||||
return list;
|
||||
int i = 0;
|
||||
foreach (var param in parameters)
|
||||
list.Add(new GenericParamDef(param, i++));
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,16 +17,20 @@
|
|||
along with de4dot. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Mono.Cecil;
|
||||
|
||||
namespace de4dot.renamer.asmmodules {
|
||||
class MethodDef : Ref {
|
||||
IList<GenericParamDef> genericParams;
|
||||
|
||||
public MethodDefinition MethodDefinition {
|
||||
get { return (MethodDefinition)memberReference; }
|
||||
}
|
||||
|
||||
public MethodDef(MethodDefinition methodDefinition, TypeDef owner, int index)
|
||||
: base(methodDefinition, owner, index) {
|
||||
genericParams = GenericParamDef.createGenericParamDefList(MethodDefinition.GenericParameters);
|
||||
}
|
||||
|
||||
public bool isPublic() {
|
||||
|
|
|
@ -40,6 +40,10 @@ namespace de4dot.renamer.asmmodules {
|
|||
}
|
||||
}
|
||||
|
||||
public IObfuscatedFile ObfuscatedFile {
|
||||
get { return obfuscatedFile; }
|
||||
}
|
||||
|
||||
public string Filename {
|
||||
get { return obfuscatedFile.Filename; }
|
||||
}
|
||||
|
|
|
@ -30,8 +30,20 @@ namespace de4dot.renamer.asmmodules {
|
|||
AssemblyHash assemblyHash = new AssemblyHash();
|
||||
|
||||
List<TypeDef> allTypes = new List<TypeDef>();
|
||||
List<TypeDef> baseTypes = new List<TypeDef>(); //TODO: Do we need this?
|
||||
List<TypeDef> nonNestedTypes; //TODO: Do we need this?
|
||||
List<TypeDef> baseTypes = new List<TypeDef>();
|
||||
List<TypeDef> nonNestedTypes;
|
||||
|
||||
public IEnumerable<TypeDef> AllTypes {
|
||||
get { return allTypes; }
|
||||
}
|
||||
|
||||
public IEnumerable<TypeDef> BaseTypes {
|
||||
get { return baseTypes; }
|
||||
}
|
||||
|
||||
public List<TypeDef> NonNestedTypes {
|
||||
get { return nonNestedTypes; }
|
||||
}
|
||||
|
||||
class AssemblyHash {
|
||||
IDictionary<string, ModuleHash> assemblyHash = new Dictionary<string, ModuleHash>(StringComparer.Ordinal);
|
||||
|
|
|
@ -21,7 +21,7 @@ using Mono.Cecil;
|
|||
|
||||
namespace de4dot.renamer.asmmodules {
|
||||
abstract class Ref {
|
||||
protected readonly MemberReference memberReference;
|
||||
public readonly MemberReference memberReference;
|
||||
public int Index { get; set; }
|
||||
public TypeDef Owner { get; set; }
|
||||
|
||||
|
|
|
@ -204,6 +204,7 @@ namespace de4dot.renamer.asmmodules {
|
|||
MethodDefDict methods = new MethodDefDict();
|
||||
PropertyDefDict properties = new PropertyDefDict();
|
||||
TypeDefDict types = new TypeDefDict();
|
||||
List<GenericParamDef> genericParams;
|
||||
internal TypeInfo baseType = null;
|
||||
internal IList<TypeInfo> interfaces = new List<TypeInfo>(); // directly implemented interfaces
|
||||
internal IList<TypeDef> derivedTypes = new List<TypeDef>();
|
||||
|
@ -214,10 +215,18 @@ namespace de4dot.renamer.asmmodules {
|
|||
Dictionary<TypeInfo, bool> allImplementedInterfaces = new Dictionary<TypeInfo, bool>();
|
||||
InterfaceMethodInfos interfaceMethodInfos = new InterfaceMethodInfos();
|
||||
|
||||
public Module Module {
|
||||
get { return module; }
|
||||
}
|
||||
|
||||
public bool HasModule {
|
||||
get { return module != null; }
|
||||
}
|
||||
|
||||
public IList<GenericParamDef> GenericParams {
|
||||
get { return genericParams; }
|
||||
}
|
||||
|
||||
public IEnumerable<TypeDef> NestedTypes {
|
||||
get { return types.getSorted(); }
|
||||
}
|
||||
|
@ -231,6 +240,7 @@ namespace de4dot.renamer.asmmodules {
|
|||
public TypeDef(TypeDefinition typeDefinition, Module module, int index)
|
||||
: base(typeDefinition, null, index) {
|
||||
this.module = module;
|
||||
genericParams = GenericParamDef.createGenericParamDefList(TypeDefinition.GenericParameters);
|
||||
}
|
||||
|
||||
public void addInterface(TypeDef ifaceDef, TypeReference iface) {
|
||||
|
@ -290,6 +300,28 @@ namespace de4dot.renamer.asmmodules {
|
|||
add(new PropertyDef(type.Properties[i], this, i));
|
||||
}
|
||||
|
||||
public bool isNested() {
|
||||
return NestingType != null;
|
||||
}
|
||||
|
||||
public bool isGlobalType() {
|
||||
if (!isNested())
|
||||
return TypeDefinition.IsPublic;
|
||||
var mask = TypeDefinition.Attributes & TypeAttributes.VisibilityMask;
|
||||
switch (mask) {
|
||||
case TypeAttributes.NestedPrivate:
|
||||
case TypeAttributes.NestedAssembly:
|
||||
case TypeAttributes.NestedFamANDAssem:
|
||||
return false;
|
||||
case TypeAttributes.NestedPublic:
|
||||
case TypeAttributes.NestedFamily:
|
||||
case TypeAttributes.NestedFamORAssem:
|
||||
return NestingType.isGlobalType();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void initializeVirtualMembers(MethodNameScopes scopes, IResolver resolver) {
|
||||
if (initializeVirtualMembersCalled)
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue
Block a user