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); } }