Less memory are used when loading files one at a time

This commit is contained in:
de4dot 2011-10-08 13:33:48 +02:00
parent 3719e9a375
commit ae9f59c918

View File

@ -63,17 +63,21 @@ namespace de4dot {
public void doIt() { public void doIt() {
if (options.DetectObfuscators) if (options.DetectObfuscators)
loadAllFiles(); detectObfuscators();
else if (options.OneFileAtATime) else if (options.OneFileAtATime)
deobfuscateOneAtATime(); deobfuscateOneAtATime();
else else
deobfuscateAll(); deobfuscateAll();
} }
void deobfuscateOneAtATime() { void detectObfuscators() {
loadAllFiles(); foreach (var file in loadAllFiles()) {
AssemblyResolver.Instance.removeModule(file.ModuleDefinition);
}
}
foreach (var file in options.Files) { void deobfuscateOneAtATime() {
foreach (var file in loadAllFiles()) {
try { try {
file.deobfuscateBegin(); file.deobfuscateBegin();
file.deobfuscate(); file.deobfuscate();
@ -95,13 +99,13 @@ namespace de4dot {
} }
void deobfuscateAll() { void deobfuscateAll() {
loadAllFiles(); var allFiles = new List<IObfuscatedFile>(loadAllFiles());
deobfuscateAllFiles(); deobfuscateAllFiles(allFiles);
renameAllFiles(); renameAllFiles(allFiles);
saveAllFiles(); saveAllFiles(allFiles);
} }
void loadAllFiles() { IEnumerable<IObfuscatedFile> loadAllFiles() {
var loader = new DotNetFileLoader(new DotNetFileLoader.Options { var loader = new DotNetFileLoader(new DotNetFileLoader.Options {
PossibleFiles = options.Files, PossibleFiles = options.Files,
SearchDirs = options.SearchDirs, SearchDirs = options.SearchDirs,
@ -113,14 +117,13 @@ namespace de4dot {
ControlFlowDeobfuscation = options.ControlFlowDeobfuscation, ControlFlowDeobfuscation = options.ControlFlowDeobfuscation,
KeepObfuscatorTypes = options.KeepObfuscatorTypes, KeepObfuscatorTypes = options.KeepObfuscatorTypes,
}); });
options.Files = loader.load(); return loader.load();
} }
class DotNetFileLoader { class DotNetFileLoader {
Options options; Options options;
Dictionary<string, bool> allFiles = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase); Dictionary<string, bool> allFiles = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
Dictionary<string, bool> visitedDirectory = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase); Dictionary<string, bool> visitedDirectory = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
IList<IObfuscatedFile> files;
public class Options { public class Options {
public IEnumerable<IObfuscatedFile> PossibleFiles { get; set; } public IEnumerable<IObfuscatedFile> PossibleFiles { get; set; }
@ -138,23 +141,23 @@ namespace de4dot {
this.options = options; this.options = options;
} }
public IList<IObfuscatedFile> load() { public IEnumerable<IObfuscatedFile> load() {
files = new List<IObfuscatedFile>(); foreach (var file in options.PossibleFiles) {
if (add(file))
yield return file;
}
foreach (var file in options.PossibleFiles) foreach (var searchDir in options.SearchDirs) {
add(file); foreach (var file in loadFiles(searchDir))
yield return file;
foreach (var searchDir in options.SearchDirs) }
recursiveAdd(searchDir);
return files;
} }
void add(IObfuscatedFile file, bool skipUnknownObfuscator = false) { bool add(IObfuscatedFile file, bool skipUnknownObfuscator = false) {
var key = Utils.getFullPath(file.Filename); var key = Utils.getFullPath(file.Filename);
if (allFiles.ContainsKey(key)) { if (allFiles.ContainsKey(key)) {
Log.w("Ingoring duplicate file: {0}", file.Filename); Log.w("Ingoring duplicate file: {0}", file.Filename);
return; return false;
} }
allFiles[key] = true; allFiles[key] = true;
@ -162,62 +165,77 @@ namespace de4dot {
file.load(options.CreateDeobfuscators()); file.load(options.CreateDeobfuscators());
} }
catch (NotSupportedException) { catch (NotSupportedException) {
return; // Eg. unsupported architecture return false; // Eg. unsupported architecture
} }
catch (BadImageFormatException) { catch (BadImageFormatException) {
return; // Not a .NET file return false; // Not a .NET file
}
catch (UnauthorizedAccessException) {
Log.w("Could not load file (not authorized): {0}", file.Filename);
return false;
} }
catch (NullReferenceException) { catch (NullReferenceException) {
Log.w("Could not load file (null ref): {0}", file.Filename); Log.w("Could not load file (null ref): {0}", file.Filename);
return; return false;
} }
catch (IOException) { catch (IOException) {
Log.w("Could not load file (io exception): {0}", file.Filename); Log.w("Could not load file (io exception): {0}", file.Filename);
return; return false;
} }
var deob = file.Deobfuscator; var deob = file.Deobfuscator;
if (skipUnknownObfuscator && deob is deobfuscators.Unknown.Deobfuscator) { if (skipUnknownObfuscator && deob is deobfuscators.Unknown.Deobfuscator) {
Log.v("Skipping unknown obfuscator: {0}", file.Filename); Log.v("Skipping unknown obfuscator: {0}", file.Filename);
return false;
} }
else { else {
Log.n("Detected {0} ({1})", deob.Name, file.Filename); Log.n("Detected {0} ({1})", deob.Name, file.Filename);
files.Add(file);
createDirectories(Path.GetDirectoryName(file.NewFilename)); createDirectories(Path.GetDirectoryName(file.NewFilename));
return true;
} }
} }
void recursiveAdd(SearchDir searchDir) { IEnumerable<IObfuscatedFile> loadFiles(SearchDir searchDir) {
DirectoryInfo di; DirectoryInfo di = null;
bool ok = false;
try { try {
di = new DirectoryInfo(searchDir.InputDirectory); di = new DirectoryInfo(searchDir.InputDirectory);
if (!di.Exists) if (di.Exists)
return; ok = true;
} }
catch (System.Security.SecurityException) { catch (System.Security.SecurityException) {
return;
} }
catch (ArgumentException) { catch (ArgumentException) {
return;
} }
doDirectoryInfo(searchDir, di); if (ok) {
foreach (var filename in doDirectoryInfo(searchDir, di)) {
var obfuscatedFile = createObfuscatedFile(searchDir, filename);
if (obfuscatedFile != null)
yield return obfuscatedFile;
}
}
} }
void recursiveAdd(SearchDir searchDir, IEnumerable<FileSystemInfo> fileSystemInfos) { IEnumerable<string> recursiveAdd(SearchDir searchDir, IEnumerable<FileSystemInfo> fileSystemInfos) {
foreach (var fsi in fileSystemInfos) { foreach (var fsi in fileSystemInfos) {
if ((int)(fsi.Attributes & FileAttributes.Directory) != 0) if ((int)(fsi.Attributes & FileAttributes.Directory) != 0) {
doDirectoryInfo(searchDir, (DirectoryInfo)fsi); foreach (var filename in doDirectoryInfo(searchDir, (DirectoryInfo)fsi))
else yield return filename;
doFileInfo(searchDir, (FileInfo)fsi); }
else {
var fi = (FileInfo)fsi;
if (fi.Exists)
yield return fi.FullName;
}
} }
} }
void doDirectoryInfo(SearchDir searchDir, DirectoryInfo di) { IEnumerable<string> doDirectoryInfo(SearchDir searchDir, DirectoryInfo di) {
if (!di.Exists) if (!di.Exists)
return; return null;
if (visitedDirectory.ContainsKey(di.FullName)) if (visitedDirectory.ContainsKey(di.FullName))
return; return null;
visitedDirectory[di.FullName] = true; visitedDirectory[di.FullName] = true;
FileSystemInfo[] fsinfos; FileSystemInfo[] fsinfos;
@ -225,20 +243,17 @@ namespace de4dot {
fsinfos = di.GetFileSystemInfos(); fsinfos = di.GetFileSystemInfos();
} }
catch (UnauthorizedAccessException) { catch (UnauthorizedAccessException) {
return; return null;
} }
catch (IOException) { catch (IOException) {
return; return null;
} }
recursiveAdd(searchDir, fsinfos); return recursiveAdd(searchDir, fsinfos);
} }
void doFileInfo(SearchDir searchDir, FileInfo fi) { IObfuscatedFile createObfuscatedFile(SearchDir searchDir, string filename) {
if (!fi.Exists)
return;
var fileOptions = new ObfuscatedFile.Options { var fileOptions = new ObfuscatedFile.Options {
Filename = Utils.getFullPath(fi.FullName), Filename = Utils.getFullPath(filename),
RenameSymbols = options.RenameSymbols, RenameSymbols = options.RenameSymbols,
ControlFlowDeobfuscation = options.ControlFlowDeobfuscation, ControlFlowDeobfuscation = options.ControlFlowDeobfuscation,
KeepObfuscatorTypes = options.KeepObfuscatorTypes, KeepObfuscatorTypes = options.KeepObfuscatorTypes,
@ -263,7 +278,10 @@ namespace de4dot {
throw new UserException(string.Format("Input and output filename is the same: {0}", fileOptions.Filename)); throw new UserException(string.Format("Input and output filename is the same: {0}", fileOptions.Filename));
} }
add(new ObfuscatedFile(fileOptions, options.AssemblyClientFactory), searchDir.SkipUnknownObfuscators); var obfuscatedFile = new ObfuscatedFile(fileOptions, options.AssemblyClientFactory);
if (add(obfuscatedFile, searchDir.SkipUnknownObfuscators))
return obfuscatedFile;
return null;
} }
void createDirectories(string path) { void createDirectories(string path) {
@ -275,29 +293,29 @@ namespace de4dot {
} }
} }
void deobfuscateAllFiles() { void deobfuscateAllFiles(IEnumerable<IObfuscatedFile> allFiles) {
try { try {
foreach (var file in options.Files) foreach (var file in allFiles)
file.deobfuscateBegin(); file.deobfuscateBegin();
foreach (var file in options.Files) { foreach (var file in allFiles) {
file.deobfuscate(); file.deobfuscate();
file.deobfuscateEnd(); file.deobfuscateEnd();
} }
} }
finally { finally {
foreach (var file in options.Files) foreach (var file in allFiles)
file.deobfuscateCleanUp(); file.deobfuscateCleanUp();
} }
} }
void renameAllFiles() { void renameAllFiles(IEnumerable<IObfuscatedFile> allFiles) {
if (!options.RenameSymbols) if (!options.RenameSymbols)
return; return;
new DefinitionsRenamer(options.Files).renameAll(); new DefinitionsRenamer(allFiles).renameAll();
} }
void saveAllFiles() { void saveAllFiles(IEnumerable<IObfuscatedFile> allFiles) {
foreach (var file in options.Files) foreach (var file in allFiles)
file.save(); file.save();
} }