diff --git a/de4dot.code/de4dot.code.csproj b/de4dot.code/de4dot.code.csproj
index 8baee5b9..9b5dc4f6 100644
--- a/de4dot.code/de4dot.code.csproj
+++ b/de4dot.code/de4dot.code.csproj
@@ -103,6 +103,7 @@
+
diff --git a/de4dot.code/renamer/CurrentNames.cs b/de4dot.code/renamer/CurrentNames.cs
new file mode 100644
index 00000000..894fb3d1
--- /dev/null
+++ b/de4dot.code/renamer/CurrentNames.cs
@@ -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 .
+*/
+
+using System;
+using System.Collections.Generic;
+
+namespace de4dot.renamer {
+ class CurrentNames {
+ Dictionary allNames = new Dictionary(StringComparer.Ordinal);
+
+ public void add(string name) {
+ allNames[name] = true;
+ }
+
+ bool exists(string name) {
+ return allNames.ContainsKey(name);
+ }
+
+ public string newName(string oldName, INameCreator nameCreator) {
+ return newName(oldName, () => nameCreator.newName());
+ }
+
+ public string newName(string oldName, Func 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 CurrentNames clone() {
+ var cn = new CurrentNames();
+ foreach (var key in allNames.Keys)
+ cn.allNames[key] = true;
+ return cn;
+ }
+ }
+}
diff --git a/de4dot.code/renamer/DefinitionsRenamer.cs b/de4dot.code/renamer/DefinitionsRenamer.cs
index 7f307ca5..d3b58621 100644
--- a/de4dot.code/renamer/DefinitionsRenamer.cs
+++ b/de4dot.code/renamer/DefinitionsRenamer.cs
@@ -209,6 +209,8 @@ namespace de4dot.renamer {
void renameTypeDefinitions() {
Log.v("Renaming obfuscated type definitions");
typeNameState = new TypeNameState();
+ foreach (var typeDef in allTypes)
+ typeNameState.currentNames.add(typeDef.OldName);
prepareRenameTypeDefinitions(baseTypes);
typeNameState = null;
diff --git a/de4dot.code/renamer/MemberRefs.cs b/de4dot.code/renamer/MemberRefs.cs
index 34f674d6..c8ad0426 100644
--- a/de4dot.code/renamer/MemberRefs.cs
+++ b/de4dot.code/renamer/MemberRefs.cs
@@ -635,6 +635,13 @@ namespace de4dot.renamer {
if (MemberRenameState == null)
MemberRenameState = baseType.typeDef.MemberRenameState.clone();
+ if (IsRenamable) {
+ foreach (var fieldDef in fields.getAll())
+ MemberRenameState.variableNameState.addFieldName(fieldDef.OldName);
+ foreach (var methodDef in methods.getAll())
+ MemberRenameState.variableNameState.addMethodName(methodDef.OldName);
+ }
+
// For each base type and interface it implements, add all its virtual methods, props,
// and events if the type is a non-renamable type (eg. it's from mscorlib or some other
// non-deobfuscated assembly).
@@ -947,15 +954,20 @@ namespace de4dot.renamer {
if (canRenameName) {
var nameCreator = getMethodNameCreator(methodDef, suggestedName);
- if (!methodDef.MethodDefinition.IsRuntimeSpecialName && !variableNameState.IsValidName(methodDef.OldName))
- methodDef.NewName = nameCreator.newName();
+ if (!methodDef.MethodDefinition.IsRuntimeSpecialName && !variableNameState.IsValidName(methodDef.OldName)) {
+ bool useNameCreator = methodDef.isVirtual() || methodDef.Property != null || methodDef.Event != null;
+ if (useNameCreator)
+ methodDef.NewName = nameCreator.newName();
+ else
+ methodDef.NewName = variableNameState.getNewMethodName(methodDef.OldName, nameCreator);
+ }
}
if (methodDef.ParamDefs.Count > 0) {
var newVariableNameState = variableNameState.clone();
foreach (var paramDef in methodDef.ParamDefs) {
if (!newVariableNameState.IsValidName(paramDef.OldName)) {
- paramDef.NewName = newVariableNameState.getNewParamName(paramDef.ParameterDefinition);
+ paramDef.NewName = newVariableNameState.getNewParamName(paramDef.OldName, paramDef.ParameterDefinition);
paramDef.Renamed = true;
}
}
@@ -968,18 +980,10 @@ namespace de4dot.renamer {
}
string getPinvokeName(MethodDef methodDef) {
- var methodNames = new Dictionary(StringComparer.Ordinal);
- foreach (var method in methods.getAll())
- methodNames[method.NewName] = true;
-
var entryPoint = methodDef.MethodDefinition.PInvokeInfo.EntryPoint;
if (Regex.IsMatch(entryPoint, @"^#\d+$"))
entryPoint = DotNetUtils.getDllName(methodDef.MethodDefinition.PInvokeInfo.Module.Name) + "_" + entryPoint.Substring(1);
- while (true) {
- var newName = MemberRenameState.variableNameState.pinvokeNameCreator.newName(entryPoint);
- if (!methodNames.ContainsKey(newName))
- return newName;
- }
+ return entryPoint;
}
INameCreator getMethodNameCreator(MethodDef methodDef, string suggestedName) {
@@ -1011,8 +1015,12 @@ namespace de4dot.renamer {
if (newName == null)
newName = suggestedName;
- if (newName != null)
- nameCreator = new OneNameCreator(newName);
+ if (newName != null) {
+ if (methodDef.isVirtual())
+ nameCreator = new OneNameCreator(newName); // It must have this name
+ else
+ nameCreator = new NameCreator2(newName);
+ }
return nameCreator;
}
diff --git a/de4dot.code/renamer/NameCreators.cs b/de4dot.code/renamer/NameCreators.cs
index 438c6498..e4a08c2e 100644
--- a/de4dot.code/renamer/NameCreators.cs
+++ b/de4dot.code/renamer/NameCreators.cs
@@ -125,17 +125,6 @@ namespace de4dot.renamer {
string newName(TypeDefinition typeDefinition, string newBaseTypeName = null);
}
- class PinvokeNameCreator {
- Dictionary nameCreators = new Dictionary(StringComparer.Ordinal);
-
- public string newName(string name) {
- NameCreator2 nameCreator;
- if (!nameCreators.TryGetValue(name, out nameCreator))
- nameCreators[name] = nameCreator = new NameCreator2(name);
- return nameCreator.newName();
- }
- }
-
class NameInfos {
IList nameInfos = new List();
@@ -163,6 +152,7 @@ namespace de4dot.renamer {
}
class TypeNameCreator : ITypeNameCreator {
+ CurrentNames currentNames;
INameCreator createUnknownTypeName;
INameCreator createEnumName;
INameCreator createStructName;
@@ -171,7 +161,8 @@ namespace de4dot.renamer {
INameCreator createInterfaceName;
NameInfos nameInfos = new NameInfos();
- public TypeNameCreator() {
+ public TypeNameCreator(CurrentNames currentNames) {
+ this.currentNames = currentNames;
createUnknownTypeName = createNameCreator("Type");
createEnumName = createNameCreator("Enum");
createStructName = createNameCreator("Struct");
@@ -197,7 +188,7 @@ namespace de4dot.renamer {
public string newName(TypeDefinition typeDefinition, string newBaseTypeName = null) {
var nameCreator = getNameCreator(typeDefinition, newBaseTypeName);
- return nameCreator.newName();
+ return currentNames.newName(typeDefinition.Name, nameCreator);
}
INameCreator getNameCreator(TypeDefinition typeDefinition, string newBaseTypeName) {
@@ -228,6 +219,10 @@ namespace de4dot.renamer {
}
class GlobalTypeNameCreator : TypeNameCreator {
+ public GlobalTypeNameCreator(CurrentNames currentNames)
+ : base(currentNames) {
+ }
+
protected override INameCreator createNameCreator(string prefix) {
return new GlobalNameCreator(base.createNameCreator("G" + prefix));
}
diff --git a/de4dot.code/renamer/TypeNameState.cs b/de4dot.code/renamer/TypeNameState.cs
index a20240b5..12999ae7 100644
--- a/de4dot.code/renamer/TypeNameState.cs
+++ b/de4dot.code/renamer/TypeNameState.cs
@@ -23,10 +23,11 @@ using de4dot.deobfuscators;
namespace de4dot.renamer {
class TypeNameState {
- IDictionary namespaceToNewName = new Dictionary(StringComparer.Ordinal);
- INameCreator createNamespaceName = new GlobalNameCreator(new NameCreator("ns"));
- public ITypeNameCreator globalTypeNameCreator = new GlobalTypeNameCreator();
- public ITypeNameCreator internalTypeNameCreator = new TypeNameCreator();
+ public CurrentNames currentNames;
+ IDictionary namespaceToNewName;
+ INameCreator createNamespaceName;
+ public ITypeNameCreator globalTypeNameCreator;
+ public ITypeNameCreator internalTypeNameCreator;
Func isValidName;
public Func IsValidName {
@@ -34,6 +35,14 @@ namespace de4dot.renamer {
set { isValidName = value; }
}
+ public TypeNameState() {
+ currentNames = new CurrentNames();
+ namespaceToNewName = new Dictionary(StringComparer.Ordinal);
+ createNamespaceName = new GlobalNameCreator(new NameCreator("ns"));
+ globalTypeNameCreator = new GlobalTypeNameCreator(currentNames);
+ internalTypeNameCreator = new TypeNameCreator(currentNames);
+ }
+
public bool isValidNamespace(string ns) {
foreach (var part in ns.Split(new char[] { '.' })) {
if (!isValidName(part))
diff --git a/de4dot.code/renamer/VariableNameState.cs b/de4dot.code/renamer/VariableNameState.cs
index 47ba167a..d9c44da3 100644
--- a/de4dot.code/renamer/VariableNameState.cs
+++ b/de4dot.code/renamer/VariableNameState.cs
@@ -18,11 +18,12 @@
*/
using Mono.Cecil;
-using de4dot.deobfuscators;
namespace de4dot.renamer {
// State when renaming type members
class VariableNameState {
+ CurrentNames currentVariableNames = new CurrentNames();
+ CurrentNames currentMethodNames = new CurrentNames();
protected TypeNames variableNameCreator = new VariableNameCreator(); // For fields and method args
protected TypeNames propertyNameCreator = new PropertyNameCreator();
protected INameCreator eventNameCreator = new NameCreator("Event_");
@@ -30,7 +31,6 @@ namespace de4dot.renamer {
public INameCreator virtualMethodNameCreator = new NameCreator("vmethod_");
public INameCreator instanceMethodNameCreator = new NameCreator("method_");
protected INameCreator genericPropertyNameCreator = new NameCreator("Prop_");
- public PinvokeNameCreator pinvokeNameCreator = new PinvokeNameCreator();
Func isValidName;
public Func IsValidName {
@@ -44,7 +44,17 @@ namespace de4dot.renamer {
return rv;
}
+ public void addFieldName(string fieldName) {
+ currentVariableNames.add(fieldName);
+ }
+
+ public void addMethodName(string methodName) {
+ currentMethodNames.add(methodName);
+ }
+
protected void cloneInit(VariableNameState variableNameState) {
+ variableNameState.currentVariableNames = new CurrentNames();
+ variableNameState.currentMethodNames = new CurrentNames();
variableNameState.variableNameCreator = variableNameCreator.clone();
variableNameState.propertyNameCreator = propertyNameCreator.clone();
variableNameState.eventNameCreator = eventNameCreator.clone();
@@ -52,7 +62,6 @@ namespace de4dot.renamer {
variableNameState.virtualMethodNameCreator = virtualMethodNameCreator.clone();
variableNameState.instanceMethodNameCreator = instanceMethodNameCreator.clone();
variableNameState.genericPropertyNameCreator = genericPropertyNameCreator.clone();
- variableNameState.pinvokeNameCreator = new PinvokeNameCreator();
variableNameState.isValidName = isValidName;
}
@@ -68,11 +77,15 @@ namespace de4dot.renamer {
}
public string getNewFieldName(FieldDefinition field) {
- return variableNameCreator.newName(field.FieldType);
+ return currentVariableNames.newName(field.Name, () => variableNameCreator.newName(field.FieldType));
}
- public string getNewParamName(ParameterDefinition param) {
- return variableNameCreator.newName(param.ParameterType);
+ public string getNewParamName(string oldName, ParameterDefinition param) {
+ return currentVariableNames.newName(oldName, () => variableNameCreator.newName(param.ParameterType));
+ }
+
+ public string getNewMethodName(string oldName, INameCreator nameCreator) {
+ return currentMethodNames.newName(oldName, nameCreator);
}
}