Merge branch 'master' into dnr

This commit is contained in:
de4dot 2011-11-05 14:27:40 +01:00
commit 75a464a7f4
18 changed files with 616 additions and 71 deletions

View File

@ -305,7 +305,7 @@ namespace de4dot.blocks {
public static bool isPinvokeMethod(MethodDefinition method, string dll, string funcName) {
if (method == null)
return false;
if (!method.HasPInvokeInfo || method.PInvokeInfo.EntryPoint != funcName)
if (method.PInvokeInfo == null || method.PInvokeInfo.EntryPoint != funcName)
return false;
return getDllName(dll).Equals(getDllName(method.PInvokeInfo.Module.Name), StringComparison.OrdinalIgnoreCase);
}

View File

@ -45,8 +45,11 @@ namespace de4dot {
return module;
}
public void save(string newFilename) {
module.Write(newFilename);
public void save(string newFilename, bool updateMaxStack) {
var writerParams = new WriterParameters() {
UpdateMaxStack = updateMaxStack,
};
module.Write(newFilename, writerParams);
}
public ModuleDefinition reload(byte[] newModuleData, Dictionary<uint, DumpedMethod> dumpedMethods) {
@ -63,7 +66,7 @@ namespace de4dot {
}
void readMethodsFile() {
if (new FileInfo(methodsFilename).Exists) {
if (Utils.fileExists(methodsFilename)) {
using (var reader = new BinaryReader(File.Open(methodsFilename, FileMode.Open, FileAccess.Read, FileShare.Read))) {
dumpedMethods = new DumpedMethodsReader(reader).read();
}

View File

@ -20,6 +20,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using Mono.Cecil;
namespace de4dot {
@ -31,6 +32,51 @@ namespace de4dot {
static AssemblyResolver() {
// Make sure there's only ONE assembly resolver
GlobalAssemblyResolver.Instance = Instance;
addOtherAssemblySearchPaths();
}
static void addOtherAssemblySearchPaths() {
addOtherAssemblySearchPaths(Environment.GetEnvironmentVariable("ProgramFiles"));
addOtherAssemblySearchPaths(Environment.GetEnvironmentVariable("ProgramFiles(x86)"));
}
static void addOtherAssemblySearchPaths(string path) {
if (string.IsNullOrEmpty(path))
return;
addSilverlightDirs(Path.Combine(path, @"Microsoft Silverlight"));
addIfExists(path, @"Microsoft SDKs\Silverlight\v3.0\Libraries\Client");
addIfExists(path, @"Microsoft SDKs\Silverlight\v3.0\Libraries\Server");
addIfExists(path, @"Microsoft SDKs\Silverlight\v4.0\Libraries\Client");
addIfExists(path, @"Microsoft SDKs\Silverlight\v4.0\Libraries\Server");
addIfExists(path, @"Reference Assemblies\Microsoft\Framework\Silverlight\v3.0");
addIfExists(path, @"Reference Assemblies\Microsoft\Framework\Silverlight\v4.0");
addIfExists(path, @"Microsoft Visual Studio .NET\Common7\IDE\PublicAssemblies");
addIfExists(path, @"Microsoft Visual Studio 8.0\Common7\IDE\PublicAssemblies");
addIfExists(path, @"Microsoft Visual Studio 9.0\Common7\IDE\PublicAssemblies");
addIfExists(path, @"Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies");
}
// basePath is eg. "C:\Program Files (x86)\Microsoft Silverlight"
static void addSilverlightDirs(string basePath) {
try {
var di = new DirectoryInfo(basePath);
foreach (var dir in di.GetDirectories()) {
if (Regex.IsMatch(dir.Name, @"^\d+(?:\.\d+){3}$"))
addIfExists(basePath, dir.Name);
}
}
catch (Exception) {
}
}
static void addIfExists(string basePath, string extraPath) {
try {
var path = Path.Combine(basePath, extraPath);
if (Utils.pathExists(path))
Instance.addSearchDirectory(path);
}
catch (Exception) {
}
}
public void addSearchDirectory(string dir) {

View File

@ -95,7 +95,7 @@ namespace de4dot {
miscOptions.Add(new OneArgOption("r", null, "Scan for .NET files in all subdirs", "dir", (val) => {
addSearchDir();
searchDir = new FilesDeobfuscator.SearchDir();
if (!new DirectoryInfo(val).Exists)
if (!Utils.pathExists(val))
exitError(string.Format("Directory {0} does not exist", val));
searchDir.InputDirectory = val;
}));
@ -112,7 +112,7 @@ namespace de4dot {
miscOptions.Add(new NoArgOption("d", null, "Detect obfuscators and exit", () => {
filesOptions.DetectObfuscators = true;
}));
miscOptions.Add(new OneArgOption(null, "asmpath", "Add an assembly search path", "path", (val) => {
miscOptions.Add(new OneArgOption(null, "asm-path", "Add an assembly search path", "path", (val) => {
AssemblyResolver.Instance.addSearchDirectory(val);
}));
miscOptions.Add(new NoArgOption(null, "dont-rename", "Don't rename classes, methods, etc.", () => {
@ -152,7 +152,7 @@ namespace de4dot {
defaultOption = new OneArgOption("f", null, "Name of .NET file", "file", (val) => {
addFile();
if (!new FileInfo(val).Exists)
if (!Utils.fileExists(val))
exitError(string.Format("File \"{0}\" does not exist.", val));
newFileOptions = new ObfuscatedFile.Options {
Filename = val,
@ -168,7 +168,7 @@ namespace de4dot {
fileOptions.Add(new OneArgOption("m", null, "Name of .methods file", "file", (val) => {
if (newFileOptions == null)
exitError("Missing input file");
if (!new FileInfo(val).Exists)
if (!Utils.fileExists(val))
exitError(string.Format("File \"{0}\" does not exist.", val));
newFileOptions.MethodsFilename = val;
}));

View File

@ -198,6 +198,12 @@ namespace de4dot {
return false;
}
if ((file.ModuleDefinition.Attributes & ModuleAttributes.ILOnly) == 0) {
Log.w("Ignoring assembly with native code {0}", file.Filename);
return false;
}
var deob = file.Deobfuscator;
if (skipUnknownObfuscator && deob is deobfuscators.Unknown.Deobfuscator) {
Log.v("Skipping unknown obfuscator: {0}", file.Filename);
@ -303,9 +309,15 @@ namespace de4dot {
void createDirectories(string path) {
if (string.IsNullOrEmpty(path))
return;
var di = new DirectoryInfo(path);
if (!di.Exists)
di.Create();
try {
var di = new DirectoryInfo(path);
if (!di.Exists)
di.Create();
}
catch (System.Security.SecurityException) {
}
catch (ArgumentException) {
}
}
}

View File

@ -258,7 +258,7 @@ namespace de4dot {
public void save() {
Log.n("Saving {0}", options.NewFilename);
assemblyModule.save(options.NewFilename);
assemblyModule.save(options.NewFilename, options.ControlFlowDeobfuscation);
}
IList<MethodDefinition> getAllMethods() {

View File

@ -198,5 +198,23 @@ namespace de4dot {
return name;
return name.Substring(0, i);
}
public static bool pathExists(string path) {
try {
return new DirectoryInfo(path).Exists;
}
catch (Exception) {
return false;
}
}
public static bool fileExists(string path) {
try {
return new FileInfo(path).Exists;
}
catch (Exception) {
return false;
}
}
}
}

View File

@ -126,6 +126,7 @@
<Compile Include="PE\DotNetStream.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

@ -290,8 +290,10 @@ namespace de4dot.deobfuscators.SmartAssembly {
public override void deobfuscateBegin() {
base.deobfuscateBegin();
if (options.RemoveMemoryManager)
if (options.RemoveMemoryManager) {
addModuleCctorInitCallToBeRemoved(memoryManagerInfo.CctorInitMethod);
addCallToBeRemoved(module.EntryPoint, memoryManagerInfo.CctorInitMethod);
}
initDecrypters();
proxyDelegateFinder.find();
}

View File

@ -44,11 +44,17 @@ namespace de4dot.deobfuscators.SmartAssembly {
}
bool find() {
var cctor = DotNetUtils.getMethod(DotNetUtils.getModuleType(module), ".cctor");
if (cctor == null)
return false;
if (checkCalledMethods(DotNetUtils.getMethod(DotNetUtils.getModuleType(module), ".cctor")))
return true;
if (checkCalledMethods(module.EntryPoint))
return true;
return false;
}
foreach (var tuple in DotNetUtils.getCalledMethods(module, cctor)) {
bool checkCalledMethods(MethodDefinition checkMethod) {
if (checkMethod == null)
return false;
foreach (var tuple in DotNetUtils.getCalledMethods(module, checkMethod)) {
var method = tuple.Item2;
if (method.Name == ".cctor" || method.Name == ".ctor")
continue;

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

@ -211,6 +211,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;
@ -504,7 +506,8 @@ namespace de4dot.renamer {
}
if (isAutoCreatedType(typeReference))
return null;
throw new ApplicationException(string.Format("Could not resolve TypeReference {0} ({1:X8})", typeReference, typeReference.MetadataToken.ToInt32()));
Log.e("Could not resolve TypeReference {0} ({1:X8})", typeReference, typeReference.MetadataToken.ToInt32());
return null;
}
public MethodDef resolve(MethodReference methodReference) {
@ -520,7 +523,8 @@ namespace de4dot.renamer {
}
if (isAutoCreatedType(methodReference.DeclaringType))
return null;
throw new ApplicationException(string.Format("Could not resolve MethodReference {0} ({1:X8})", methodReference, methodReference.MetadataToken.ToInt32()));
Log.e("Could not resolve MethodReference {0} ({1:X8})", methodReference, methodReference.MetadataToken.ToInt32());
return null;
}
public FieldDef resolve(FieldReference fieldReference) {
@ -536,7 +540,8 @@ namespace de4dot.renamer {
}
if (isAutoCreatedType(fieldReference.DeclaringType))
return null;
throw new ApplicationException(string.Format("Could not resolve FieldReference {0} ({1:X8})", fieldReference, fieldReference.MetadataToken.ToInt32()));
Log.e("Could not resolve FieldReference {0} ({1:X8})", fieldReference, fieldReference.MetadataToken.ToInt32());
return null;
}
public MethodDef findMethod(MethodReference methodReference) {

View File

@ -69,9 +69,20 @@ namespace de4dot.renamer {
Log.w("Could not load assembly {0}", asmFullName);
return null;
}
Log.v("Loaded assembly {0}", asmFullName);
if (assemblies.ContainsKey(asmDef.Name.FullName)) {
assemblies[asmFullName] = assemblies[asmDef.Name.FullName];
return assemblies[asmDef.Name.FullName];
}
return assemblies[asmFullName] = new ExternalAssembly(asmDef);
if (asmFullName == asmDef.Name.FullName)
Log.v("Loaded assembly {0}", asmFullName);
else
Log.v("Loaded assembly {0} (but wanted {1})", asmDef.Name.FullName, asmFullName);
asm = new ExternalAssembly(asmDef);
assemblies[asmFullName] = asm;
assemblies[asmDef.Name.FullName] = asm;
return asm;
}
public TypeDefinition resolve(TypeReference type) {

View File

@ -91,13 +91,20 @@ namespace de4dot {
Dictionary<string, bool> exceptionMessages = new Dictionary<string, bool>(StringComparer.Ordinal);
void access(Action action) {
string exMessage = null;
try {
action();
}
catch (ResolutionException ex) {
exMessage = ex.Message;
}
catch (AssemblyResolutionException ex) {
if (!exceptionMessages.ContainsKey(ex.Message)) {
exceptionMessages[ex.Message] = true;
Log.w("Could not resolve a reference. ERROR: {0}", ex.Message);
exMessage = ex.Message;
}
if (exMessage != null) {
if (!exceptionMessages.ContainsKey(exMessage)) {
exceptionMessages[exMessage] = true;
Log.w("Could not resolve a reference. ERROR: {0}", exMessage);
}
}
}
@ -421,7 +428,7 @@ namespace de4dot {
void addSecurityDeclaration(SecurityDeclaration decl) {
if (decl == null)
return;
addSecurityAttributes(decl.SecurityAttributes);
access(() => addSecurityAttributes(decl.SecurityAttributes));
}
void addSecurityAttribute(SecurityAttribute attr) {
if (attr == null)

View File

@ -21,6 +21,7 @@ using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Mono.Cecil;
using Mono.Cecil.Cil;
using de4dot.blocks;
using de4dot.deobfuscators;
@ -286,6 +287,103 @@ namespace de4dot.renamer {
}
class TypeDef : Ref {
static Dictionary<string, bool> windowsFormsControlClasses = new Dictionary<string, bool>(StringComparer.Ordinal);
static TypeDef() {
windowsFormsControlClasses["System.Windows.Forms.Control"] = true;
windowsFormsControlClasses["System.Windows.Forms.AxHost"] = true;
windowsFormsControlClasses["System.Windows.Forms.ButtonBase"] = true;
windowsFormsControlClasses["System.Windows.Forms.Button"] = true;
windowsFormsControlClasses["System.Windows.Forms.CheckBox"] = true;
windowsFormsControlClasses["System.Windows.Forms.RadioButton"] = true;
windowsFormsControlClasses["System.Windows.Forms.DataGrid"] = true;
windowsFormsControlClasses["System.Windows.Forms.DataGridView"] = true;
windowsFormsControlClasses["System.Windows.Forms.DataVisualization.Charting.Chart"] = true;
windowsFormsControlClasses["System.Windows.Forms.DateTimePicker"] = true;
windowsFormsControlClasses["System.Windows.Forms.GroupBox"] = true;
windowsFormsControlClasses["System.Windows.Forms.Integration.ElementHost"] = true;
windowsFormsControlClasses["System.Windows.Forms.Label"] = true;
windowsFormsControlClasses["System.Windows.Forms.LinkLabel"] = true;
windowsFormsControlClasses["System.Windows.Forms.ListControl"] = true;
windowsFormsControlClasses["System.Windows.Forms.ComboBox"] = true;
windowsFormsControlClasses["Microsoft.VisualBasic.Compatibility.VB6.DriveListBox"] = true;
windowsFormsControlClasses["System.Windows.Forms.DataGridViewComboBoxEditingControl"] = true;
windowsFormsControlClasses["System.Windows.Forms.ListBox"] = true;
windowsFormsControlClasses["Microsoft.VisualBasic.Compatibility.VB6.DirListBox"] = true;
windowsFormsControlClasses["Microsoft.VisualBasic.Compatibility.VB6.FileListBox"] = true;
windowsFormsControlClasses["System.Windows.Forms.CheckedListBox"] = true;
windowsFormsControlClasses["System.Windows.Forms.ListView"] = true;
windowsFormsControlClasses["System.Windows.Forms.MdiClient"] = true;
windowsFormsControlClasses["System.Windows.Forms.MonthCalendar"] = true;
windowsFormsControlClasses["System.Windows.Forms.PictureBox"] = true;
windowsFormsControlClasses["System.Windows.Forms.PrintPreviewControl"] = true;
windowsFormsControlClasses["System.Windows.Forms.ProgressBar"] = true;
windowsFormsControlClasses["System.Windows.Forms.ScrollableControl"] = true;
windowsFormsControlClasses["System.Windows.Forms.ContainerControl"] = true;
windowsFormsControlClasses["System.Windows.Forms.Form"] = true;
windowsFormsControlClasses["System.ComponentModel.Design.CollectionEditor.CollectionForm"] = true;
windowsFormsControlClasses["System.Messaging.Design.QueuePathDialog"] = true;
windowsFormsControlClasses["System.ServiceProcess.Design.ServiceInstallerDialog"] = true;
windowsFormsControlClasses["System.Web.UI.Design.WebControls.CalendarAutoFormatDialog"] = true;
windowsFormsControlClasses["System.Web.UI.Design.WebControls.RegexEditorDialog"] = true;
windowsFormsControlClasses["System.Windows.Forms.Design.ComponentEditorForm"] = true;
windowsFormsControlClasses["System.Windows.Forms.PrintPreviewDialog"] = true;
windowsFormsControlClasses["System.Windows.Forms.ThreadExceptionDialog"] = true;
windowsFormsControlClasses["System.Workflow.Activities.Rules.Design.RuleConditionDialog"] = true;
windowsFormsControlClasses["System.Workflow.Activities.Rules.Design.RuleSetDialog"] = true;
windowsFormsControlClasses["System.Workflow.ComponentModel.Design.ThemeConfigurationDialog"] = true;
windowsFormsControlClasses["System.Workflow.ComponentModel.Design.TypeBrowserDialog"] = true;
windowsFormsControlClasses["System.Workflow.ComponentModel.Design.WorkflowPageSetupDialog"] = true;
windowsFormsControlClasses["System.Windows.Forms.PropertyGrid"] = true;
windowsFormsControlClasses["System.Windows.Forms.SplitContainer"] = true;
windowsFormsControlClasses["System.Windows.Forms.ToolStripContainer"] = true;
windowsFormsControlClasses["System.Windows.Forms.ToolStripPanel"] = true;
windowsFormsControlClasses["System.Windows.Forms.UpDownBase"] = true;
windowsFormsControlClasses["System.Windows.Forms.DomainUpDown"] = true;
windowsFormsControlClasses["System.Windows.Forms.NumericUpDown"] = true;
windowsFormsControlClasses["System.Windows.Forms.UserControl"] = true;
windowsFormsControlClasses["Microsoft.VisualBasic.Compatibility.VB6.ADODC"] = true;
windowsFormsControlClasses["System.Web.UI.Design.WebControls.ParameterEditorUserControl"] = true;
windowsFormsControlClasses["System.Workflow.ComponentModel.Design.WorkflowOutline"] = true;
windowsFormsControlClasses["System.Workflow.ComponentModel.Design.WorkflowView"] = true;
windowsFormsControlClasses["System.Windows.Forms.Design.ComponentTray"] = true;
windowsFormsControlClasses["System.Windows.Forms.Panel"] = true;
windowsFormsControlClasses["System.Windows.Forms.Design.ComponentEditorPage"] = true;
windowsFormsControlClasses["System.Windows.Forms.FlowLayoutPanel"] = true;
windowsFormsControlClasses["System.Windows.Forms.SplitterPanel"] = true;
windowsFormsControlClasses["System.Windows.Forms.TableLayoutPanel"] = true;
windowsFormsControlClasses["System.ComponentModel.Design.ByteViewer"] = true;
windowsFormsControlClasses["System.Windows.Forms.TabPage"] = true;
windowsFormsControlClasses["System.Windows.Forms.ToolStripContentPanel"] = true;
windowsFormsControlClasses["System.Windows.Forms.ToolStrip"] = true;
windowsFormsControlClasses["System.Windows.Forms.BindingNavigator"] = true;
windowsFormsControlClasses["System.Windows.Forms.MenuStrip"] = true;
windowsFormsControlClasses["System.Windows.Forms.StatusStrip"] = true;
windowsFormsControlClasses["System.Windows.Forms.ToolStripDropDown"] = true;
windowsFormsControlClasses["System.Windows.Forms.ToolStripDropDownMenu"] = true;
windowsFormsControlClasses["System.Windows.Forms.ContextMenuStrip"] = true;
windowsFormsControlClasses["System.Windows.Forms.ToolStripOverflow"] = true;
windowsFormsControlClasses["System.Windows.Forms.ScrollBar"] = true;
windowsFormsControlClasses["System.Windows.Forms.HScrollBar"] = true;
windowsFormsControlClasses["System.Windows.Forms.VScrollBar"] = true;
windowsFormsControlClasses["System.Windows.Forms.Splitter"] = true;
windowsFormsControlClasses["System.Windows.Forms.StatusBar"] = true;
windowsFormsControlClasses["System.Windows.Forms.TabControl"] = true;
windowsFormsControlClasses["System.Windows.Forms.TextBoxBase"] = true;
windowsFormsControlClasses["System.Windows.Forms.MaskedTextBox"] = true;
windowsFormsControlClasses["System.Windows.Forms.RichTextBox"] = true;
windowsFormsControlClasses["System.Windows.Forms.TextBox"] = true;
windowsFormsControlClasses["System.Windows.Forms.DataGridTextBox"] = true;
windowsFormsControlClasses["System.Windows.Forms.DataGridViewTextBoxEditingControl"] = true;
windowsFormsControlClasses["System.Windows.Forms.ToolBar"] = true;
windowsFormsControlClasses["System.Windows.Forms.TrackBar"] = true;
windowsFormsControlClasses["System.Windows.Forms.TreeView"] = true;
windowsFormsControlClasses["System.ComponentModel.Design.ObjectSelectorEditor.Selector"] = true;
windowsFormsControlClasses["System.Windows.Forms.WebBrowserBase"] = true;
windowsFormsControlClasses["System.Windows.Forms.WebBrowser"] = true;
}
Dictionary<MethodDef, string> newMethodsNames = new Dictionary<MethodDef, string>();
public IDefFinder defFinder;
public TypeInfo baseType = null;
public IList<TypeInfo> interfaces = new List<TypeInfo>(); // directly implemented interfaces
@ -344,6 +442,23 @@ namespace de4dot.renamer {
get { return methods.getAll(); }
}
bool? isWindowsFormsControlDerivedClass_cached;
bool isWindowsFormsControlDerivedClass() {
if (!isWindowsFormsControlDerivedClass_cached.HasValue)
isWindowsFormsControlDerivedClass_cached = isWindowsFormsControlDerivedClassInternal();
return isWindowsFormsControlDerivedClass_cached.Value;
}
bool isWindowsFormsControlDerivedClassInternal() {
if (windowsFormsControlClasses.ContainsKey(OldFullName))
return true;
if (baseType != null)
return baseType.typeDef.isWindowsFormsControlDerivedClass();
if (TypeDefinition.BaseType != null)
return windowsFormsControlClasses.ContainsKey(TypeDefinition.BaseType.FullName);
return false;
}
public void addMembers() {
var type = TypeDefinition;
@ -482,7 +597,13 @@ namespace de4dot.renamer {
if (OldFullName != "<Module>" && !typeNameState.IsValidName(OldName)) {
var newBaseType = baseType != null && baseType.typeDef.Renamed ? baseType.typeDef.NewName : null;
rename(nameCreator.newName(typeDefinition, newBaseType));
string origClassName = null;
if (isWindowsFormsControlDerivedClass())
origClassName = findWindowsFormsClassName();
if (origClassName != null && typeNameState.IsValidName(origClassName))
rename(typeNameState.currentNames.newName(OldName, new NameCreator2(origClassName)));
else
rename(nameCreator.newName(typeDefinition, newBaseType));
}
if (typeDefinition.Namespace != "" && !typeNameState.isValidNamespace(typeDefinition.Namespace))
@ -491,6 +612,71 @@ namespace de4dot.renamer {
prepareRenameGenericParams(genericParams, typeNameState.IsValidName);
}
string findWindowsFormsClassName() {
foreach (var methodDef in methods.getAll()) {
if (methodDef.MethodDefinition.Body == null)
continue;
if (methodDef.MethodDefinition.IsStatic || methodDef.MethodDefinition.IsVirtual)
continue;
var instructions = methodDef.MethodDefinition.Body.Instructions;
for (int i = 2; i < instructions.Count; i++) {
var call = instructions[i];
if (call.OpCode.Code != Code.Call && call.OpCode.Code != Code.Callvirt)
continue;
if (!isWindowsFormsSetNameMethod(call.Operand as MethodReference))
continue;
var ldstr = instructions[i - 1];
if (ldstr.OpCode.Code != Code.Ldstr)
continue;
var className = ldstr.Operand as string;
if (className == null)
continue;
if (DotNetUtils.getArgIndex(methodDef.MethodDefinition, instructions[i - 2]) != 0)
continue;
findInitializeComponentMethod(methodDef);
return className;
}
}
return null;
}
void findInitializeComponentMethod(MethodDef possibleInitMethod) {
foreach (var methodDef in methods.getAll()) {
if (methodDef.OldName != ".ctor")
continue;
if (methodDef.MethodDefinition.Body == null)
continue;
foreach (var instr in methodDef.MethodDefinition.Body.Instructions) {
if (instr.OpCode.Code != Code.Call)
continue;
if (!MemberReferenceHelper.compareMethodReferenceAndDeclaringType(possibleInitMethod.MethodDefinition, instr.Operand as MethodReference))
continue;
newMethodsNames[possibleInitMethod] = "InitializeComponent";
return;
}
}
}
static bool isWindowsFormsSetNameMethod(MethodReference method) {
if (method == null)
return false;
if (method.Name != "set_Name")
return false;
if (method.MethodReturnType.ReturnType.FullName != "System.Void")
return false;
if (method.Parameters.Count != 1)
return false;
if (method.Parameters[0].ParameterType.FullName != "System.String")
return false;
if (!method.DeclaringType.FullName.StartsWith("System.Windows.Forms.", StringComparison.Ordinal))
return false;
return true;
}
public void rename() {
var typeDefinition = TypeDefinition;
@ -635,6 +821,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).
@ -657,6 +850,9 @@ namespace de4dot.renamer {
prepareRenameFields(); // must be first
prepareRenameProperties();
prepareRenameEvents();
initializeEventHandlerNames();
prepareRenameMethods(); // must be last
}
}
@ -726,6 +922,9 @@ namespace de4dot.renamer {
void prepareRenameFields() {
var variableNameState = MemberRenameState.variableNameState;
if (isWindowsFormsControlDerivedClass())
initializeWindowsFormsFields();
if (TypeDefinition.IsEnum) {
var instanceFields = new List<FieldDef>(getInstanceFields());
if (instanceFields.Count == 1) {
@ -739,6 +938,8 @@ namespace de4dot.renamer {
int i = 0;
string nameFormat = hasFlagsAttribute() ? "flag_{0}" : "const_{0}";
foreach (var fieldDef in fields.getSorted()) {
if (fieldDef.Renamed)
continue;
if (!fieldDef.FieldDefinition.IsStatic || !fieldDef.FieldDefinition.IsLiteral)
continue;
if (!variableNameState.IsValidName(fieldDef.OldName))
@ -754,6 +955,134 @@ namespace de4dot.renamer {
}
}
void initializeWindowsFormsFields() {
var ourFields = new Dictionary<FieldReferenceAndDeclaringTypeKey, FieldDef>();
foreach (var fieldDef in fields.getAll())
ourFields[new FieldReferenceAndDeclaringTypeKey(fieldDef.FieldDefinition)] = fieldDef;
var variableNameState = MemberRenameState.variableNameState;
foreach (var methodDef in methods.getAll()) {
if (methodDef.MethodDefinition.Body == null)
continue;
if (methodDef.MethodDefinition.IsStatic || methodDef.MethodDefinition.IsVirtual)
continue;
var instructions = methodDef.MethodDefinition.Body.Instructions;
for (int i = 2; i < instructions.Count; i++) {
var call = instructions[i];
if (call.OpCode.Code != Code.Call && call.OpCode.Code != Code.Callvirt)
continue;
if (!isWindowsFormsSetNameMethod(call.Operand as MethodReference))
continue;
var ldstr = instructions[i - 1];
if (ldstr.OpCode.Code != Code.Ldstr)
continue;
var fieldName = ldstr.Operand as string;
if (fieldName == null || !variableNameState.IsValidName(fieldName))
continue;
var ldfld = instructions[i - 2];
var fieldRef = ldfld.Operand as FieldReference;
if (fieldRef == null)
continue;
FieldDef fieldDef;
if (!ourFields.TryGetValue(new FieldReferenceAndDeclaringTypeKey(fieldRef), out fieldDef))
continue;
if (fieldDef.Renamed)
continue;
fieldDef.rename(variableNameState.getNewFieldName(fieldDef.OldName, new NameCreator2(fieldName)));
}
}
}
void initializeEventHandlerNames() {
var ourFields = new Dictionary<FieldReferenceAndDeclaringTypeKey, FieldDef>();
foreach (var fieldDef in fields.getAll())
ourFields[new FieldReferenceAndDeclaringTypeKey(fieldDef.FieldDefinition)] = fieldDef;
var ourMethods = new Dictionary<MethodReferenceAndDeclaringTypeKey, MethodDef>();
foreach (var methodDef in methods.getAll())
ourMethods[new MethodReferenceAndDeclaringTypeKey(methodDef.MethodDefinition)] = methodDef;
var variableNameState = MemberRenameState.variableNameState;
foreach (var methodDef in methods.getAll()) {
if (methodDef.MethodDefinition.Body == null)
continue;
if (methodDef.MethodDefinition.IsStatic)
continue;
var instructions = methodDef.MethodDefinition.Body.Instructions;
for (int i = 0; i < instructions.Count - 5; i++) {
// We're looking for this code pattern:
// ldarg.0
// ldfld field
// ldarg.0
// ldftn method
// newobj event_handler_ctor
// callvirt add_SomeEvent
if (DotNetUtils.getArgIndex(methodDef.MethodDefinition, instructions[i]) != 0)
continue;
var ldfld = instructions[i + 1];
if (ldfld.OpCode.Code != Code.Ldfld)
continue;
var fieldRef = ldfld.Operand as FieldReference;
if (fieldRef == null)
continue;
FieldDef fieldDef;
if (!ourFields.TryGetValue(new FieldReferenceAndDeclaringTypeKey(fieldRef), out fieldDef))
continue;
if (DotNetUtils.getArgIndex(methodDef.MethodDefinition, instructions[i + 2]) != 0)
continue;
var ldftn = instructions[i + 3];
if (ldftn.OpCode.Code != Code.Ldftn)
continue;
var methodRef = ldftn.Operand as MethodReference;
if (methodRef == null)
continue;
MethodDef handlerMethod;
if (!ourMethods.TryGetValue(new MethodReferenceAndDeclaringTypeKey(methodRef), out handlerMethod))
continue;
var newobj = instructions[i + 4];
if (newobj.OpCode.Code != Code.Newobj)
continue;
if (!isEventHandlerCtor(newobj.Operand as MethodReference))
continue;
var call = instructions[i + 5];
if (call.OpCode.Code != Code.Call && call.OpCode.Code != Code.Callvirt)
continue;
var addHandler = call.Operand as MethodReference;
if (addHandler == null)
continue;
if (!addHandler.Name.StartsWith("add_", StringComparison.Ordinal))
continue;
var eventName = addHandler.Name.Substring(4);
if (!MemberRenameState.variableNameState.IsValidName(eventName))
continue;
newMethodsNames[handlerMethod] = string.Format("{0}_{1}", fieldDef.NewName, eventName);
}
}
}
static bool isEventHandlerCtor(MethodReference method) {
if (method == null)
return false;
if (method.Name != ".ctor")
return false;
if (!DotNetUtils.isMethod(method, "System.Void", "(System.Object,System.IntPtr)"))
return false;
if (!method.DeclaringType.FullName.EndsWith("EventHandler", StringComparison.Ordinal))
return false;
return true;
}
static MethodReference getOverrideMethod(MethodDefinition meth) {
if (meth == null || !meth.HasOverrides)
return null;
@ -927,6 +1256,9 @@ namespace de4dot.renamer {
methodDef.Renamed = true;
bool canRenameMethodName = true;
if (suggestedName == null)
newMethodsNames.TryGetValue(methodDef, out suggestedName);
if (IsDelegate && methodDef.isVirtual()) {
switch (methodDef.MethodDefinition.Name) {
case "BeginInvoke":
@ -941,16 +1273,29 @@ namespace de4dot.renamer {
if (canRenameMethodName) {
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.Renamed = true;
if (isEventHandler(methodDef)) {
methodDef.ParamDefs[0].NewName = "sender";
methodDef.ParamDefs[0].Renamed = true;
methodDef.ParamDefs[1].NewName = "e";
methodDef.ParamDefs[1].Renamed = true;
}
else {
var newVariableNameState = variableNameState.clone();
foreach (var paramDef in methodDef.ParamDefs) {
if (!newVariableNameState.IsValidName(paramDef.OldName)) {
paramDef.NewName = newVariableNameState.getNewParamName(paramDef.OldName, paramDef.ParameterDefinition);
paramDef.Renamed = true;
}
}
}
}
@ -961,21 +1306,23 @@ namespace de4dot.renamer {
MemberRenameState.add(methodDef);
}
string getPinvokeName(MethodDef methodDef) {
var methodNames = new Dictionary<string, bool>(StringComparer.Ordinal);
foreach (var method in methods.getAll())
methodNames[method.NewName] = true;
static bool isEventHandler(MethodDef methodDef) {
if (methodDef.MethodDefinition.Parameters.Count != 2)
return false;
if (methodDef.MethodDefinition.MethodReturnType.ReturnType.FullName != "System.Void")
return false;
if (methodDef.MethodDefinition.Parameters[0].ParameterType.FullName != "System.Object")
return false;
if (!methodDef.MethodDefinition.Parameters[1].ParameterType.FullName.Contains("EventArgs"))
return false;
return true;
}
if (methodDef.MethodDefinition.PInvokeInfo == null)
throw new ApplicationException(string.Format("PInvokeInfo is null: A type was probably removed but still referenced by the code."));
string getPinvokeName(MethodDef methodDef) {
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) {
@ -983,7 +1330,7 @@ namespace de4dot.renamer {
INameCreator nameCreator = null;
string newName = null;
if (methodDef.MethodDefinition.HasPInvokeInfo)
if (methodDef.MethodDefinition.PInvokeInfo != null)
newName = getPinvokeName(methodDef);
else if (methodDef.MethodDefinition.IsStatic)
nameCreator = variableNameState.staticMethodNameCreator;
@ -1007,8 +1354,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,19 @@ 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 getNewFieldName(string oldName, INameCreator nameCreator) {
return currentVariableNames.newName(oldName, () => nameCreator.newName());
}
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);
}
}