Add option to remove namespace if there's only one class in it

This commit is contained in:
de4dot 2011-11-09 12:08:48 +01:00
parent ff0c0cddbd
commit c562c335e8
8 changed files with 64 additions and 1 deletions

View File

@ -30,6 +30,7 @@ namespace de4dot {
Func<string, bool> IsValidName { get; } Func<string, bool> IsValidName { get; }
bool RenameResourcesInCode { get; } bool RenameResourcesInCode { get; }
bool RenameSymbols { get; } bool RenameSymbols { get; }
bool RemoveNamespaceWithOneType { get; }
void deobfuscateBegin(); void deobfuscateBegin();
void deobfuscate(); void deobfuscate();

View File

@ -118,6 +118,10 @@ namespace de4dot {
get { return options.RenameSymbols; } get { return options.RenameSymbols; }
} }
public bool RemoveNamespaceWithOneType {
get { return (deob.RenamingOptions & RenamingOptions.RemoveNamespaceIfOneType) != 0; }
}
public IDeobfuscator Deobfuscator { public IDeobfuscator Deobfuscator {
get { return deob; } get { return deob; }
} }

View File

@ -66,6 +66,7 @@ namespace de4dot.deobfuscators {
public IOperations Operations { get; set; } public IOperations Operations { get; set; }
public IDeobfuscatedFile DeobfuscatedFile { get; set; } public IDeobfuscatedFile DeobfuscatedFile { get; set; }
public virtual StringFeatures StringFeatures { get; set; } public virtual StringFeatures StringFeatures { get; set; }
public virtual RenamingOptions RenamingOptions { get; set; }
public DecrypterType DefaultDecrypterType { get; set; } public DecrypterType DefaultDecrypterType { get; set; }
public abstract string Type { get; } public abstract string Type { get; }

View File

@ -44,6 +44,11 @@ namespace de4dot.deobfuscators {
AllowAll = AllowNoDecryption | AllowStaticDecryption | AllowDynamicDecryption, AllowAll = AllowNoDecryption | AllowStaticDecryption | AllowDynamicDecryption,
} }
[Flags]
enum RenamingOptions {
RemoveNamespaceIfOneType = 1,
}
interface IDeobfuscator { interface IDeobfuscator {
string Type { get; } string Type { get; }
string Name { get; } string Name { get; }
@ -51,6 +56,7 @@ namespace de4dot.deobfuscators {
IDeobfuscatorOptions TheOptions { get; } IDeobfuscatorOptions TheOptions { get; }
IOperations Operations { get; set; } IOperations Operations { get; set; }
StringFeatures StringFeatures { get; } StringFeatures StringFeatures { get; }
RenamingOptions RenamingOptions { get; }
DecrypterType DefaultDecrypterType { get; } DecrypterType DefaultDecrypterType { get; }
// This is non-null only in detect() and deobfuscateBegin(). // This is non-null only in detect() and deobfuscateBegin().

View File

@ -17,6 +17,7 @@
along with de4dot. If not, see <http://www.gnu.org/licenses/>. along with de4dot. If not, see <http://www.gnu.org/licenses/>.
*/ */
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Cil; using Mono.Cecil.Cil;
@ -34,6 +35,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
BoolOption removeInlinedMethods; BoolOption removeInlinedMethods;
BoolOption dumpEmbeddedAssemblies; BoolOption dumpEmbeddedAssemblies;
BoolOption decryptResources; BoolOption decryptResources;
BoolOption removeNamespaces;
public DeobfuscatorInfo() public DeobfuscatorInfo()
: base(DEFAULT_REGEX) { : base(DEFAULT_REGEX) {
@ -44,6 +46,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
removeInlinedMethods = new BoolOption(null, makeArgName("remove-inlined"), "Remove inlined methods", true); removeInlinedMethods = new BoolOption(null, makeArgName("remove-inlined"), "Remove inlined methods", true);
dumpEmbeddedAssemblies = new BoolOption(null, makeArgName("embedded"), "Dump embedded assemblies", true); dumpEmbeddedAssemblies = new BoolOption(null, makeArgName("embedded"), "Dump embedded assemblies", true);
decryptResources = new BoolOption(null, makeArgName("rsrc"), "Decrypt resources", true); decryptResources = new BoolOption(null, makeArgName("rsrc"), "Decrypt resources", true);
removeNamespaces = new BoolOption(null, makeArgName("ns1"), "Clear namespace if there's only one class in it", true);
} }
public override string Name { public override string Name {
@ -64,6 +67,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
RemoveInlinedMethods = removeInlinedMethods.get(), RemoveInlinedMethods = removeInlinedMethods.get(),
DumpEmbeddedAssemblies = dumpEmbeddedAssemblies.get(), DumpEmbeddedAssemblies = dumpEmbeddedAssemblies.get(),
DecryptResources = decryptResources.get(), DecryptResources = decryptResources.get(),
RemoveNamespaces = removeNamespaces.get(),
}); });
} }
@ -76,6 +80,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
removeInlinedMethods, removeInlinedMethods,
dumpEmbeddedAssemblies, dumpEmbeddedAssemblies,
decryptResources, decryptResources,
removeNamespaces,
}; };
} }
} }
@ -105,6 +110,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
public bool RemoveInlinedMethods { get; set; } public bool RemoveInlinedMethods { get; set; }
public bool DumpEmbeddedAssemblies { get; set; } public bool DumpEmbeddedAssemblies { get; set; }
public bool DecryptResources { get; set; } public bool DecryptResources { get; set; }
public bool RemoveNamespaces { get; set; }
} }
public override string Type { public override string Type {
@ -122,6 +128,11 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
public Deobfuscator(Options options) public Deobfuscator(Options options)
: base(options) { : base(options) {
this.options = options; this.options = options;
if (options.RemoveNamespaces)
this.RenamingOptions |= RenamingOptions.RemoveNamespaceIfOneType;
else
this.RenamingOptions &= ~RenamingOptions.RemoveNamespaceIfOneType;
} }
public override void init(ModuleDefinition module) { public override void init(ModuleDefinition module) {

View File

@ -210,6 +210,10 @@ namespace de4dot.renamer {
void renameTypeDefinitions() { void renameTypeDefinitions() {
Log.v("Renaming obfuscated type definitions"); Log.v("Renaming obfuscated type definitions");
foreach (var module in modules)
module.onBeforeRenamingTypeDefinitions();
typeNameState = new TypeNameState(); typeNameState = new TypeNameState();
foreach (var typeDef in allTypes) foreach (var typeDef in allTypes)
typeNameState.currentNames.add(typeDef.OldName); typeNameState.currentNames.add(typeDef.OldName);

View File

@ -421,6 +421,11 @@ namespace de4dot.renamer {
bool IsDelegate { get; set; } bool IsDelegate { get; set; }
public string NewNamespace {
get { return newNamespace; }
set { newNamespace = value; }
}
public TypeDef(TypeDefinition typeDefinition) public TypeDef(TypeDefinition typeDefinition)
: this(typeDefinition, null) { : this(typeDefinition, null) {
} }
@ -607,7 +612,7 @@ namespace de4dot.renamer {
rename(nameCreator.newName(typeDefinition, newBaseType)); rename(nameCreator.newName(typeDefinition, newBaseType));
} }
if (typeDefinition.Namespace != "" && !typeNameState.isValidNamespace(typeDefinition.Namespace)) if (newNamespace == null && typeDefinition.Namespace != "" && !typeNameState.isValidNamespace(typeDefinition.Namespace))
newNamespace = typeNameState.newNamespace(typeDefinition.Namespace); newNamespace = typeNameState.newNamespace(typeDefinition.Namespace);
prepareRenameGenericParams(genericParams, typeNameState.IsValidName); prepareRenameGenericParams(genericParams, typeNameState.IsValidName);

View File

@ -77,6 +77,37 @@ namespace de4dot.renamer {
} }
} }
public void onBeforeRenamingTypeDefinitions() {
if (obfuscatedFile.RemoveNamespaceWithOneType)
removeOneClassNamespaces();
}
void removeOneClassNamespaces() {
var nsToTypes = new Dictionary<string, List<TypeDef>>(StringComparer.Ordinal);
foreach (var typeDef in allTypes.getAll()) {
List<TypeDef> list;
var ns = typeDef.TypeDefinition.Namespace;
if (string.IsNullOrEmpty(ns))
continue;
if (IsValidName(ns))
continue;
if (!nsToTypes.TryGetValue(ns, out list))
nsToTypes[ns] = list = new List<TypeDef>();
list.Add(typeDef);
}
foreach (var list in nsToTypes.Values) {
const int maxClasses = 1;
if (list.Count != maxClasses)
continue;
var ns = list[0].TypeDefinition.Namespace;
Log.v("Removing namespace: {0}", ns);
foreach (var type in list)
type.NewNamespace = "";
}
}
static string renameResourceString(string s, string oldTypeName, string newTypeName) { static string renameResourceString(string s, string oldTypeName, string newTypeName) {
if (!Utils.StartsWith(s, oldTypeName, StringComparison.Ordinal)) if (!Utils.StartsWith(s, oldTypeName, StringComparison.Ordinal))
return s; return s;