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; }
bool RenameResourcesInCode { get; }
bool RenameSymbols { get; }
bool RemoveNamespaceWithOneType { get; }
void deobfuscateBegin();
void deobfuscate();

View File

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

View File

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

View File

@ -44,6 +44,11 @@ namespace de4dot.deobfuscators {
AllowAll = AllowNoDecryption | AllowStaticDecryption | AllowDynamicDecryption,
}
[Flags]
enum RenamingOptions {
RemoveNamespaceIfOneType = 1,
}
interface IDeobfuscator {
string Type { get; }
string Name { get; }
@ -51,6 +56,7 @@ namespace de4dot.deobfuscators {
IDeobfuscatorOptions TheOptions { get; }
IOperations Operations { get; set; }
StringFeatures StringFeatures { get; }
RenamingOptions RenamingOptions { get; }
DecrypterType DefaultDecrypterType { get; }
// 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/>.
*/
using System;
using System.Collections.Generic;
using Mono.Cecil;
using Mono.Cecil.Cil;
@ -34,6 +35,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
BoolOption removeInlinedMethods;
BoolOption dumpEmbeddedAssemblies;
BoolOption decryptResources;
BoolOption removeNamespaces;
public DeobfuscatorInfo()
: base(DEFAULT_REGEX) {
@ -44,6 +46,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
removeInlinedMethods = new BoolOption(null, makeArgName("remove-inlined"), "Remove inlined methods", true);
dumpEmbeddedAssemblies = new BoolOption(null, makeArgName("embedded"), "Dump embedded assemblies", 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 {
@ -64,6 +67,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
RemoveInlinedMethods = removeInlinedMethods.get(),
DumpEmbeddedAssemblies = dumpEmbeddedAssemblies.get(),
DecryptResources = decryptResources.get(),
RemoveNamespaces = removeNamespaces.get(),
});
}
@ -76,6 +80,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
removeInlinedMethods,
dumpEmbeddedAssemblies,
decryptResources,
removeNamespaces,
};
}
}
@ -105,6 +110,7 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
public bool RemoveInlinedMethods { get; set; }
public bool DumpEmbeddedAssemblies { get; set; }
public bool DecryptResources { get; set; }
public bool RemoveNamespaces { get; set; }
}
public override string Type {
@ -122,6 +128,11 @@ namespace de4dot.deobfuscators.dotNET_Reactor {
public Deobfuscator(Options options)
: base(options) {
this.options = options;
if (options.RemoveNamespaces)
this.RenamingOptions |= RenamingOptions.RemoveNamespaceIfOneType;
else
this.RenamingOptions &= ~RenamingOptions.RemoveNamespaceIfOneType;
}
public override void init(ModuleDefinition module) {

View File

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

View File

@ -421,6 +421,11 @@ namespace de4dot.renamer {
bool IsDelegate { get; set; }
public string NewNamespace {
get { return newNamespace; }
set { newNamespace = value; }
}
public TypeDef(TypeDefinition typeDefinition)
: this(typeDefinition, null) {
}
@ -607,7 +612,7 @@ namespace de4dot.renamer {
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);
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) {
if (!Utils.StartsWith(s, oldTypeName, StringComparison.Ordinal))
return s;