Update renamer code so it's less likely to use an existing name

This commit is contained in:
de4dot 2011-11-04 13:59:43 +01:00
parent e6a8d50d03
commit df507526ba
7 changed files with 127 additions and 37 deletions

View File

@ -103,6 +103,7 @@
<Compile Include="Option.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="renamer\CurrentNames.cs" />
<Compile Include="renamer\DefinitionsRenamer.cs" />
<Compile Include="renamer\ExternalAssemblies.cs" />
<Compile Include="renamer\MemberRefFinder.cs" />

View 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 CurrentNames {
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 newName(string oldName, INameCreator nameCreator) {
return newName(oldName, () => nameCreator.newName());
}
public string newName(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 CurrentNames clone() {
var cn = new CurrentNames();
foreach (var key in allNames.Keys)
cn.allNames[key] = true;
return cn;
}
}
}

View File

@ -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;

View File

@ -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<string, bool>(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;
}

View File

@ -125,17 +125,6 @@ namespace de4dot.renamer {
string newName(TypeDefinition typeDefinition, string newBaseTypeName = null);
}
class PinvokeNameCreator {
Dictionary<string, NameCreator2> nameCreators = new Dictionary<string, NameCreator2>(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<NameInfo> nameInfos = new List<NameInfo>();
@ -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));
}

View File

@ -23,10 +23,11 @@ using de4dot.deobfuscators;
namespace de4dot.renamer {
class TypeNameState {
IDictionary<string, string> namespaceToNewName = new Dictionary<string, string>(StringComparer.Ordinal);
INameCreator createNamespaceName = new GlobalNameCreator(new NameCreator("ns"));
public ITypeNameCreator globalTypeNameCreator = new GlobalTypeNameCreator();
public ITypeNameCreator internalTypeNameCreator = new TypeNameCreator();
public CurrentNames currentNames;
IDictionary<string, string> namespaceToNewName;
INameCreator createNamespaceName;
public ITypeNameCreator globalTypeNameCreator;
public ITypeNameCreator internalTypeNameCreator;
Func<string, bool> isValidName;
public Func<string, bool> IsValidName {
@ -34,6 +35,14 @@ namespace de4dot.renamer {
set { isValidName = value; }
}
public TypeNameState() {
currentNames = new CurrentNames();
namespaceToNewName = new Dictionary<string, string>(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))

View File

@ -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<string, bool> isValidName;
public Func<string, bool> 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);
}
}