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="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" />
|
||||
|
|
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() {
|
||||
Log.v("Renaming obfuscated type definitions");
|
||||
typeNameState = new TypeNameState();
|
||||
foreach (var typeDef in allTypes)
|
||||
typeNameState.currentNames.add(typeDef.OldName);
|
||||
prepareRenameTypeDefinitions(baseTypes);
|
||||
typeNameState = null;
|
||||
|
||||
|
|
|
@ -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))
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user