void addAllOptions() { 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) exitError(string.Format("Directory {0} does not exist", val)); searchDir.InputDirectory = val; })); miscOptions.Add(new OneArgOption("ro", null, "Output base dir for recursively found files", "dir", (val) => { if (searchDir == null) exitError("Missing -r option"); searchDir.OutputDirectory = val; })); miscOptions.Add(new NoArgOption("ru", null, "Skip recursively found files with unsupported obfuscator", () => { if (searchDir == null) exitError("Missing -r option"); searchDir.SkipUnknownObfuscators = true; })); 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) => { AssemblyResolver.Instance.addSearchDirectory(val); })); miscOptions.Add(new NoArgOption(null, "dont-rename", "Don't rename classes, methods, etc.", () => { filesOptions.RenameSymbols = false; })); miscOptions.Add(new OneArgOption(null, "default-strtyp", "Default string decrypter type", "type", (val) => { object decrypterType; if (!stringDecrypterTypes.getValue(val, out decrypterType)) exitError(string.Format("Invalid string decrypter type '{0}'", val)); defaultStringDecrypterType = (DecrypterType)decrypterType; })); miscOptions.Add(new OneArgOption(null, "default-strtok", "Default string decrypter method token or [type::][name][(args,...)]", "method", (val) => { defaultStringDecrypterMethods.Add(val); })); miscOptions.Add(new NoArgOption(null, "no-control-flow-deob", "No control flow deobfuscation (NOT recommended)", () => { filesOptions.ControlFlowDeobfuscation = false; })); miscOptions.Add(new NoArgOption(null, "load-new-process", "Load executed assemblies into a new process", () => { filesOptions.AssemblyClientFactory = new NewProcessAssemblyClientFactory(); })); miscOptions.Add(new NoArgOption(null, "keep-types", "Keep obfuscator types, fields, methods", () => { filesOptions.KeepObfuscatorTypes = true; })); miscOptions.Add(new NoArgOption(null, "one-file", "Deobfuscate one file at a time", () => { filesOptions.OneFileAtATime = true; })); miscOptions.Add(new NoArgOption("v", null, "Verbose", () => { Log.logLevel = Log.LogLevel.verbose; })); miscOptions.Add(new NoArgOption("vv", null, "Very verbose", () => { Log.logLevel = Log.LogLevel.veryverbose; })); miscOptions.Add(new NoArgOption("h", "help", "Show this help message", () => { usage(); exit(0); })); defaultOption = new OneArgOption("f", null, "Name of .NET file", "file", (val) => { addFile(); if (!new FileInfo(val).Exists) exitError(string.Format("File \"{0}\" does not exist.", val)); newFileOptions = new ObfuscatedFile.Options { Filename = val, RenameSymbols = filesOptions.RenameSymbols, ControlFlowDeobfuscation = filesOptions.ControlFlowDeobfuscation, KeepObfuscatorTypes = filesOptions.KeepObfuscatorTypes, }; if (defaultStringDecrypterType != null) newFileOptions.StringDecrypterType = defaultStringDecrypterType.Value; newFileOptions.StringDecrypterMethods.AddRange(defaultStringDecrypterMethods); }); fileOptions.Add(defaultOption); fileOptions.Add(new OneArgOption("m", null, "Name of .methods file", "file", (val) => { if (newFileOptions == null) exitError("Missing input file"); if (!new FileInfo(val).Exists) exitError(string.Format("File \"{0}\" does not exist.", val)); newFileOptions.MethodsFilename = val; })); fileOptions.Add(new OneArgOption("o", null, "Name of output file", "file", (val) => { if (newFileOptions == null) exitError("Missing input file"); if (string.Equals(Utils.getFullPath(newFileOptions.Filename), Utils.getFullPath(val), StringComparison.OrdinalIgnoreCase)) exitError(string.Format("Output file can't be same as input file ({0})", val)); newFileOptions.NewFilename = val; })); fileOptions.Add(new OneArgOption("p", null, "Obfuscator type (see below)", "type", (val) => { if (newFileOptions == null) exitError("Missing input file"); if (!isValidObfuscatorType(val)) exitError(string.Format("Invalid obfuscator type '{0}'", val)); newFileOptions.ForcedObfuscatorType = val; })); fileOptions.Add(new OneArgOption(null, "strtyp", "String decrypter type", "type", (val) => { if (newFileOptions == null) exitError("Missing input file"); object decrypterType; if (!stringDecrypterTypes.getValue(val, out decrypterType)) exitError(string.Format("Invalid string decrypter type '{0}'", val)); newFileOptions.StringDecrypterType = (DecrypterType)decrypterType; })); fileOptions.Add(new OneArgOption(null, "strtok", "String decrypter method token or [type::][name][(args,...)]", "method", (val) => { if (newFileOptions == null) exitError("Missing input file"); newFileOptions.StringDecrypterMethods.Add(val); })); addOptions(miscOptions); addOptions(fileOptions); foreach (var info in deobfuscatorInfos) addOptions(info.getOptions()); }
void addFile() { if (newFileOptions == null) return; files.Add(new ObfuscatedFile(newFileOptions, filesOptions.AssemblyClientFactory)); newFileOptions = null; }
IObfuscatedFile createObfuscatedFile(SearchDir searchDir, string filename) { var fileOptions = new ObfuscatedFile.Options { Filename = Utils.getFullPath(filename), RenameSymbols = options.RenameSymbols, ControlFlowDeobfuscation = options.ControlFlowDeobfuscation, KeepObfuscatorTypes = options.KeepObfuscatorTypes, }; if (options.DefaultStringDecrypterType != null) fileOptions.StringDecrypterType = options.DefaultStringDecrypterType.Value; fileOptions.StringDecrypterMethods.AddRange(options.DefaultStringDecrypterMethods); if (!string.IsNullOrEmpty(searchDir.OutputDirectory)) { var inDir = Utils.getFullPath(searchDir.InputDirectory); var outDir = Utils.getFullPath(searchDir.OutputDirectory); if (!Utils.StartsWith(fileOptions.Filename, inDir, StringComparison.OrdinalIgnoreCase)) throw new UserException(string.Format("Filename {0} does not start with inDir {1}", fileOptions.Filename, inDir)); var subDirs = fileOptions.Filename.Substring(inDir.Length); if (subDirs.Length > 0 && subDirs[0] == Path.DirectorySeparatorChar) subDirs = subDirs.Substring(1); fileOptions.NewFilename = Utils.getFullPath(Path.Combine(outDir, subDirs)); if (fileOptions.Filename.Equals(fileOptions.NewFilename, StringComparison.OrdinalIgnoreCase)) throw new UserException(string.Format("Input and output filename is the same: {0}", fileOptions.Filename)); } var obfuscatedFile = new ObfuscatedFile(fileOptions, options.AssemblyClientFactory); if (add(obfuscatedFile, searchDir.SkipUnknownObfuscators)) return obfuscatedFile; return null; }