Update renamer code so it's less likely to use an existing name
This commit is contained in:
parent
e6a8d50d03
commit
df507526ba
|
@ -103,6 +103,7 @@
|
||||||
<Compile Include="Option.cs" />
|
<Compile Include="Option.cs" />
|
||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="renamer\CurrentNames.cs" />
|
||||||
<Compile Include="renamer\DefinitionsRenamer.cs" />
|
<Compile Include="renamer\DefinitionsRenamer.cs" />
|
||||||
<Compile Include="renamer\ExternalAssemblies.cs" />
|
<Compile Include="renamer\ExternalAssemblies.cs" />
|
||||||
<Compile Include="renamer\MemberRefFinder.cs" />
|
<Compile Include="renamer\MemberRefFinder.cs" />
|
||||||
|
|
62
de4dot.code/renamer/CurrentNames.cs
Normal file
62
de4dot.code/renamer/CurrentNames.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 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -209,6 +209,8 @@ namespace de4dot.renamer {
|
||||||
void renameTypeDefinitions() {
|
void renameTypeDefinitions() {
|
||||||
Log.v("Renaming obfuscated type definitions");
|
Log.v("Renaming obfuscated type definitions");
|
||||||
typeNameState = new TypeNameState();
|
typeNameState = new TypeNameState();
|
||||||
|
foreach (var typeDef in allTypes)
|
||||||
|
typeNameState.currentNames.add(typeDef.OldName);
|
||||||
prepareRenameTypeDefinitions(baseTypes);
|
prepareRenameTypeDefinitions(baseTypes);
|
||||||
typeNameState = null;
|
typeNameState = null;
|
||||||
|
|
||||||
|
|
|
@ -635,6 +635,13 @@ namespace de4dot.renamer {
|
||||||
if (MemberRenameState == null)
|
if (MemberRenameState == null)
|
||||||
MemberRenameState = baseType.typeDef.MemberRenameState.clone();
|
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,
|
// 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
|
// and events if the type is a non-renamable type (eg. it's from mscorlib or some other
|
||||||
// non-deobfuscated assembly).
|
// non-deobfuscated assembly).
|
||||||
|
@ -947,15 +954,20 @@ namespace de4dot.renamer {
|
||||||
|
|
||||||
if (canRenameName) {
|
if (canRenameName) {
|
||||||
var nameCreator = getMethodNameCreator(methodDef, suggestedName);
|
var nameCreator = getMethodNameCreator(methodDef, suggestedName);
|
||||||
if (!methodDef.MethodDefinition.IsRuntimeSpecialName && !variableNameState.IsValidName(methodDef.OldName))
|
if (!methodDef.MethodDefinition.IsRuntimeSpecialName && !variableNameState.IsValidName(methodDef.OldName)) {
|
||||||
methodDef.NewName = nameCreator.newName();
|
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) {
|
if (methodDef.ParamDefs.Count > 0) {
|
||||||
var newVariableNameState = variableNameState.clone();
|
var newVariableNameState = variableNameState.clone();
|
||||||
foreach (var paramDef in methodDef.ParamDefs) {
|
foreach (var paramDef in methodDef.ParamDefs) {
|
||||||
if (!newVariableNameState.IsValidName(paramDef.OldName)) {
|
if (!newVariableNameState.IsValidName(paramDef.OldName)) {
|
||||||
paramDef.NewName = newVariableNameState.getNewParamName(paramDef.ParameterDefinition);
|
paramDef.NewName = newVariableNameState.getNewParamName(paramDef.OldName, paramDef.ParameterDefinition);
|
||||||
paramDef.Renamed = true;
|
paramDef.Renamed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -968,18 +980,10 @@ namespace de4dot.renamer {
|
||||||
}
|
}
|
||||||
|
|
||||||
string getPinvokeName(MethodDef methodDef) {
|
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;
|
var entryPoint = methodDef.MethodDefinition.PInvokeInfo.EntryPoint;
|
||||||
if (Regex.IsMatch(entryPoint, @"^#\d+$"))
|
if (Regex.IsMatch(entryPoint, @"^#\d+$"))
|
||||||
entryPoint = DotNetUtils.getDllName(methodDef.MethodDefinition.PInvokeInfo.Module.Name) + "_" + entryPoint.Substring(1);
|
entryPoint = DotNetUtils.getDllName(methodDef.MethodDefinition.PInvokeInfo.Module.Name) + "_" + entryPoint.Substring(1);
|
||||||
while (true) {
|
return entryPoint;
|
||||||
var newName = MemberRenameState.variableNameState.pinvokeNameCreator.newName(entryPoint);
|
|
||||||
if (!methodNames.ContainsKey(newName))
|
|
||||||
return newName;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INameCreator getMethodNameCreator(MethodDef methodDef, string suggestedName) {
|
INameCreator getMethodNameCreator(MethodDef methodDef, string suggestedName) {
|
||||||
|
@ -1011,8 +1015,12 @@ namespace de4dot.renamer {
|
||||||
|
|
||||||
if (newName == null)
|
if (newName == null)
|
||||||
newName = suggestedName;
|
newName = suggestedName;
|
||||||
if (newName != null)
|
if (newName != null) {
|
||||||
nameCreator = new OneNameCreator(newName);
|
if (methodDef.isVirtual())
|
||||||
|
nameCreator = new OneNameCreator(newName); // It must have this name
|
||||||
|
else
|
||||||
|
nameCreator = new NameCreator2(newName);
|
||||||
|
}
|
||||||
|
|
||||||
return nameCreator;
|
return nameCreator;
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,17 +125,6 @@ namespace de4dot.renamer {
|
||||||
string newName(TypeDefinition typeDefinition, string newBaseTypeName = null);
|
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 {
|
class NameInfos {
|
||||||
IList<NameInfo> nameInfos = new List<NameInfo>();
|
IList<NameInfo> nameInfos = new List<NameInfo>();
|
||||||
|
|
||||||
|
@ -163,6 +152,7 @@ namespace de4dot.renamer {
|
||||||
}
|
}
|
||||||
|
|
||||||
class TypeNameCreator : ITypeNameCreator {
|
class TypeNameCreator : ITypeNameCreator {
|
||||||
|
CurrentNames currentNames;
|
||||||
INameCreator createUnknownTypeName;
|
INameCreator createUnknownTypeName;
|
||||||
INameCreator createEnumName;
|
INameCreator createEnumName;
|
||||||
INameCreator createStructName;
|
INameCreator createStructName;
|
||||||
|
@ -171,7 +161,8 @@ namespace de4dot.renamer {
|
||||||
INameCreator createInterfaceName;
|
INameCreator createInterfaceName;
|
||||||
NameInfos nameInfos = new NameInfos();
|
NameInfos nameInfos = new NameInfos();
|
||||||
|
|
||||||
public TypeNameCreator() {
|
public TypeNameCreator(CurrentNames currentNames) {
|
||||||
|
this.currentNames = currentNames;
|
||||||
createUnknownTypeName = createNameCreator("Type");
|
createUnknownTypeName = createNameCreator("Type");
|
||||||
createEnumName = createNameCreator("Enum");
|
createEnumName = createNameCreator("Enum");
|
||||||
createStructName = createNameCreator("Struct");
|
createStructName = createNameCreator("Struct");
|
||||||
|
@ -197,7 +188,7 @@ namespace de4dot.renamer {
|
||||||
|
|
||||||
public string newName(TypeDefinition typeDefinition, string newBaseTypeName = null) {
|
public string newName(TypeDefinition typeDefinition, string newBaseTypeName = null) {
|
||||||
var nameCreator = getNameCreator(typeDefinition, newBaseTypeName);
|
var nameCreator = getNameCreator(typeDefinition, newBaseTypeName);
|
||||||
return nameCreator.newName();
|
return currentNames.newName(typeDefinition.Name, nameCreator);
|
||||||
}
|
}
|
||||||
|
|
||||||
INameCreator getNameCreator(TypeDefinition typeDefinition, string newBaseTypeName) {
|
INameCreator getNameCreator(TypeDefinition typeDefinition, string newBaseTypeName) {
|
||||||
|
@ -228,6 +219,10 @@ namespace de4dot.renamer {
|
||||||
}
|
}
|
||||||
|
|
||||||
class GlobalTypeNameCreator : TypeNameCreator {
|
class GlobalTypeNameCreator : TypeNameCreator {
|
||||||
|
public GlobalTypeNameCreator(CurrentNames currentNames)
|
||||||
|
: base(currentNames) {
|
||||||
|
}
|
||||||
|
|
||||||
protected override INameCreator createNameCreator(string prefix) {
|
protected override INameCreator createNameCreator(string prefix) {
|
||||||
return new GlobalNameCreator(base.createNameCreator("G" + prefix));
|
return new GlobalNameCreator(base.createNameCreator("G" + prefix));
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,10 +23,11 @@ using de4dot.deobfuscators;
|
||||||
|
|
||||||
namespace de4dot.renamer {
|
namespace de4dot.renamer {
|
||||||
class TypeNameState {
|
class TypeNameState {
|
||||||
IDictionary<string, string> namespaceToNewName = new Dictionary<string, string>(StringComparer.Ordinal);
|
public CurrentNames currentNames;
|
||||||
INameCreator createNamespaceName = new GlobalNameCreator(new NameCreator("ns"));
|
IDictionary<string, string> namespaceToNewName;
|
||||||
public ITypeNameCreator globalTypeNameCreator = new GlobalTypeNameCreator();
|
INameCreator createNamespaceName;
|
||||||
public ITypeNameCreator internalTypeNameCreator = new TypeNameCreator();
|
public ITypeNameCreator globalTypeNameCreator;
|
||||||
|
public ITypeNameCreator internalTypeNameCreator;
|
||||||
Func<string, bool> isValidName;
|
Func<string, bool> isValidName;
|
||||||
|
|
||||||
public Func<string, bool> IsValidName {
|
public Func<string, bool> IsValidName {
|
||||||
|
@ -34,6 +35,14 @@ namespace de4dot.renamer {
|
||||||
set { isValidName = value; }
|
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) {
|
public bool isValidNamespace(string ns) {
|
||||||
foreach (var part in ns.Split(new char[] { '.' })) {
|
foreach (var part in ns.Split(new char[] { '.' })) {
|
||||||
if (!isValidName(part))
|
if (!isValidName(part))
|
||||||
|
|
|
@ -18,11 +18,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using Mono.Cecil;
|
using Mono.Cecil;
|
||||||
using de4dot.deobfuscators;
|
|
||||||
|
|
||||||
namespace de4dot.renamer {
|
namespace de4dot.renamer {
|
||||||
// State when renaming type members
|
// State when renaming type members
|
||||||
class VariableNameState {
|
class VariableNameState {
|
||||||
|
CurrentNames currentVariableNames = new CurrentNames();
|
||||||
|
CurrentNames currentMethodNames = new CurrentNames();
|
||||||
protected TypeNames variableNameCreator = new VariableNameCreator(); // For fields and method args
|
protected TypeNames variableNameCreator = new VariableNameCreator(); // For fields and method args
|
||||||
protected TypeNames propertyNameCreator = new PropertyNameCreator();
|
protected TypeNames propertyNameCreator = new PropertyNameCreator();
|
||||||
protected INameCreator eventNameCreator = new NameCreator("Event_");
|
protected INameCreator eventNameCreator = new NameCreator("Event_");
|
||||||
|
@ -30,7 +31,6 @@ namespace de4dot.renamer {
|
||||||
public INameCreator virtualMethodNameCreator = new NameCreator("vmethod_");
|
public INameCreator virtualMethodNameCreator = new NameCreator("vmethod_");
|
||||||
public INameCreator instanceMethodNameCreator = new NameCreator("method_");
|
public INameCreator instanceMethodNameCreator = new NameCreator("method_");
|
||||||
protected INameCreator genericPropertyNameCreator = new NameCreator("Prop_");
|
protected INameCreator genericPropertyNameCreator = new NameCreator("Prop_");
|
||||||
public PinvokeNameCreator pinvokeNameCreator = new PinvokeNameCreator();
|
|
||||||
Func<string, bool> isValidName;
|
Func<string, bool> isValidName;
|
||||||
|
|
||||||
public Func<string, bool> IsValidName {
|
public Func<string, bool> IsValidName {
|
||||||
|
@ -44,7 +44,17 @@ namespace de4dot.renamer {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addFieldName(string fieldName) {
|
||||||
|
currentVariableNames.add(fieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addMethodName(string methodName) {
|
||||||
|
currentMethodNames.add(methodName);
|
||||||
|
}
|
||||||
|
|
||||||
protected void cloneInit(VariableNameState variableNameState) {
|
protected void cloneInit(VariableNameState variableNameState) {
|
||||||
|
variableNameState.currentVariableNames = new CurrentNames();
|
||||||
|
variableNameState.currentMethodNames = new CurrentNames();
|
||||||
variableNameState.variableNameCreator = variableNameCreator.clone();
|
variableNameState.variableNameCreator = variableNameCreator.clone();
|
||||||
variableNameState.propertyNameCreator = propertyNameCreator.clone();
|
variableNameState.propertyNameCreator = propertyNameCreator.clone();
|
||||||
variableNameState.eventNameCreator = eventNameCreator.clone();
|
variableNameState.eventNameCreator = eventNameCreator.clone();
|
||||||
|
@ -52,7 +62,6 @@ namespace de4dot.renamer {
|
||||||
variableNameState.virtualMethodNameCreator = virtualMethodNameCreator.clone();
|
variableNameState.virtualMethodNameCreator = virtualMethodNameCreator.clone();
|
||||||
variableNameState.instanceMethodNameCreator = instanceMethodNameCreator.clone();
|
variableNameState.instanceMethodNameCreator = instanceMethodNameCreator.clone();
|
||||||
variableNameState.genericPropertyNameCreator = genericPropertyNameCreator.clone();
|
variableNameState.genericPropertyNameCreator = genericPropertyNameCreator.clone();
|
||||||
variableNameState.pinvokeNameCreator = new PinvokeNameCreator();
|
|
||||||
variableNameState.isValidName = isValidName;
|
variableNameState.isValidName = isValidName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,11 +77,15 @@ namespace de4dot.renamer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public string getNewFieldName(FieldDefinition field) {
|
public string getNewFieldName(FieldDefinition field) {
|
||||||
return variableNameCreator.newName(field.FieldType);
|
return currentVariableNames.newName(field.Name, () => variableNameCreator.newName(field.FieldType));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string getNewParamName(ParameterDefinition param) {
|
public string getNewParamName(string oldName, ParameterDefinition param) {
|
||||||
return variableNameCreator.newName(param.ParameterType);
|
return currentVariableNames.newName(oldName, () => variableNameCreator.newName(param.ParameterType));
|
||||||
|
}
|
||||||
|
|
||||||
|
public string getNewMethodName(string oldName, INameCreator nameCreator) {
|
||||||
|
return currentMethodNames.newName(oldName, nameCreator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user