private static void CleanControlFlow() { Logger.Instance.MaxLoggerEvent = 0; var options = new ObfuscatedFile.Options { Filename = _obfOsuPath, ControlFlowDeobfuscation = true, KeepObfuscatorTypes = true, RenamerFlags = 0, StringDecrypterType = DecrypterType.None, MetadataFlags = DEFAULT_METADATA_FLAGS }; var obfFile = new ObfuscatedFile(options, new ModuleContext(TheAssemblyResolver.Instance), new NewAppDomainAssemblyClientFactory()) { DeobfuscatorContext = new DeobfuscatorContext() }; obfFile.Load(new List <IDeobfuscator> { new de4dot.code.deobfuscators.Unknown.DeobfuscatorInfo().CreateDeobfuscator() }); obfFile.DeobfuscateBegin(); obfFile.Deobfuscate(); obfFile.DeobfuscateEnd(); _obfOsuModule = obfFile.ModuleDefMD; }
public static IObfuscatedFile SearchDeobfuscator(string filename) { TheAssemblyResolver.Instance.ClearAll(); var fileOptions = new ObfuscatedFile.Options { Filename = filename }; var moduleContext = new ModuleContext(TheAssemblyResolver.Instance); var ofile = new ObfuscatedFile(fileOptions, moduleContext, new NewAppDomainAssemblyClientFactory()) { DeobfuscatorContext = new DeobfuscatorContext(), }; try { ofile.Load(CreateDeobfuscatorInfos().Select(di => di.CreateDeobfuscator()).ToList()); } catch (Exception) { return(null); } return(ofile); }
void AddFile() { if (newFileOptions == null) { return; } files.Add(new ObfuscatedFile(newFileOptions, filesOptions.ModuleContext, filesOptions.AssemblyClientFactory)); newFileOptions = null; }
public IObfuscatedFile SearchDeobfuscator(string filename) { ModuleContext context = new ModuleContext(); ObfuscatedFile.Options fileOptions = new ObfuscatedFile.Options { Filename = filename }; ObfuscatedFile ofile = CreateObfuscationFile(fileOptions, context); return(ofile); }
private IObfuscatedFile UpdateObfuscationFileWithOptions(De4dotWrapper de4Dot, string location, string newFile) { ObfuscatedFile.Options options = new ObfuscatedFile.Options(); options.ControlFlowDeobfuscation = this.EnableControlFlowDeobfuscation; options.NewFilename = newFile; options.KeepObfuscatorTypes = this.KeepObfuscatorClasses; options.Filename = location; var context = new ModuleContext(); ObfuscatedFile result = de4Dot.CreateObfuscationFile(options, context); return(result); }
public FileSystemPath Execute(IAssemblyFile existingAssemblyFile, string newFileName, IProgressIndicator progressIndicator) { var context = new ModuleContext(); var fileOptions = new ObfuscatedFile.Options { Filename = existingAssemblyFile.Location.FullPath, NewFilename = newFileName, }; IObfuscatedFile obfuscationFile = CreateObfuscationFile(fileOptions, context); return(Deobfuscate(obfuscationFile, progressIndicator)); }
public override void Process() { IList <IObfuscatedFile> files = new List <IObfuscatedFile>(); var filesOptions = new FilesDeobfuscator.Options(); filesOptions.DeobfuscatorInfos = deobfuscatorInfos; filesOptions.AssemblyClientFactory = new NewAppDomainAssemblyClientFactory(); filesOptions.RenameSymbols = true; filesOptions.ControlFlowDeobfuscation = true; filesOptions.KeepObfuscatorTypes = false; filesOptions.MetaDataFlags = MetaDataFlags.PreserveAll; filesOptions.Files = files; var newFileOptions = new ObfuscatedFile.Options { Filename = DeobfuscatorContext.Filename, NewFilename = "XPADDING", ControlFlowDeobfuscation = filesOptions.ControlFlowDeobfuscation, RenamerFlags = filesOptions.RenamerFlags, KeepObfuscatorTypes = filesOptions.KeepObfuscatorTypes, MetaDataFlags = filesOptions.MetaDataFlags, PreserveTokens = true }; using (var asm = new MemoryStream()) { DeobfuscatorContext.Assembly.Write(asm, new ModuleWriterOptions() { Logger = DummyLogger.NoThrowInstance }); files.Add(new ObfuscatedFile(newFileOptions, filesOptions.ModuleContext, filesOptions.AssemblyClientFactory, asm)); using (var ms = new MemoryStream()) { new FilesDeobfuscator(filesOptions).doIt(ms, Rename); // Better way to preserve these options? var cor20Ver = DeobfuscatorContext.Assembly.ManifestModule.Cor20HeaderRuntimeVersion; var clrVer = DeobfuscatorContext.Assembly.ManifestModule.RuntimeVersion; var clrFlags = DeobfuscatorContext.Assembly.ManifestModule.Cor20HeaderFlags; DeobfuscatorContext.Assembly = AssemblyDef.Load(ms); DeobfuscatorContext.Assembly.ManifestModule.Cor20HeaderRuntimeVersion = cor20Ver; DeobfuscatorContext.Assembly.ManifestModule.RuntimeVersion = clrVer; DeobfuscatorContext.Assembly.ManifestModule.Cor20HeaderFlags = clrFlags; } } }
IObfuscatedFile CreateObfuscatedFile(SearchDir searchDir, string filename) { var fileOptions = new ObfuscatedFile.Options { Filename = Utils.GetFullPath(filename), ControlFlowDeobfuscation = options.ControlFlowDeobfuscation, KeepObfuscatorTypes = options.KeepObfuscatorTypes, MetaDataFlags = options.MetaDataFlags, RenamerFlags = options.RenamerFlags, }; 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.ModuleContext, options.AssemblyClientFactory); if (Add(obfuscatedFile, searchDir.SkipUnknownObfuscators, false)) { return(obfuscatedFile); } obfuscatedFile.Dispose(); return(null); }
public ObfuscatedFile CreateObfuscationFile(ObfuscatedFile.Options fileOptions, ModuleContext moduleContext) { ObfuscatedFile ofile = new ObfuscatedFile(fileOptions, moduleContext, new NewAppDomainAssemblyClientFactory()); ofile.DeobfuscatorContext = new DeobfuscatorContext(); try { ofile.Load(CreateDeobfuscatorInfos().Select(di => di.CreateDeobfuscator()).ToList()); } catch (Exception ex) { MessageBox.Show(ex.Message); return(null); } return(ofile); }
private IObfuscatedFile CreateObfuscationFile(ObfuscatedFile.Options fileOptions, ModuleContext moduleContext) { var obfuscatedFile = new ObfuscatedFile(fileOptions, moduleContext, new NewAppDomainAssemblyClientFactory()) { DeobfuscatorContext = new DeobfuscatorContext() }; try { obfuscatedFile.load(knownDeobfuscators.Select(info => info.createDeobfuscator()).ToList()); } catch (Exception ex) { MessageBox.ShowError(ex.Message); return(null); } return(obfuscatedFile); }
void AddAllOptions() { miscOptions.Add(new OneArgOption("r", null, "Scan for .NET files in all subdirs", "dir", (val) => { AddSearchDir(); searchDir = new FilesDeobfuscator.SearchDir(); if (!Utils.PathExists(val)) { ExitError($"Directory {val} does not exist"); } 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, "asm-path", "Add an assembly search path", "path", (val) => { TheAssemblyResolver.Instance.AddSearchDirectory(val); })); miscOptions.Add(new NoArgOption(null, "dont-rename", "Don't rename classes, methods, etc.", () => { filesOptions.RenameSymbols = false; filesOptions.RenamerFlags = 0; })); miscOptions.Add(new OneArgOption(null, "keep-names", "Don't rename n(amespaces), t(ypes), p(rops), e(vents), f(ields), m(ethods), a(rgs), g(enericparams), d(elegate fields). Can be combined, eg. efm", "flags", (val) => { foreach (var c in val) { switch (c) { case 'n': filesOptions.RenamerFlags &= ~RenamerFlags.RenameNamespaces; break; case 't': filesOptions.RenamerFlags &= ~RenamerFlags.RenameTypes; break; case 'p': filesOptions.RenamerFlags &= ~RenamerFlags.RenameProperties; break; case 'e': filesOptions.RenamerFlags &= ~RenamerFlags.RenameEvents; break; case 'f': filesOptions.RenamerFlags &= ~RenamerFlags.RenameFields; break; case 'm': filesOptions.RenamerFlags &= ~RenamerFlags.RenameMethods; break; case 'a': filesOptions.RenamerFlags &= ~RenamerFlags.RenameMethodArgs; break; case 'g': filesOptions.RenamerFlags &= ~RenamerFlags.RenameGenericParams; break; case 'd': filesOptions.RenamerFlags |= RenamerFlags.DontRenameDelegateFields; break; default: throw new UserException($"Unrecognized --keep-names char: '{c}'"); } } })); miscOptions.Add(new NoArgOption(null, "dont-create-params", "Don't create method params when renaming", () => { filesOptions.RenamerFlags |= RenamerFlags.DontCreateNewParamDefs; })); miscOptions.Add(new NoArgOption(null, "dont-restore-props", "Don't restore properties/events", () => { filesOptions.RenamerFlags &= ~(RenamerFlags.RestorePropertiesFromNames | RenamerFlags.RestoreEventsFromNames); })); miscOptions.Add(new OneArgOption(null, "default-strtyp", "Default string decrypter type", "type", (val) => { if (!stringDecrypterTypes.GetValue(val, out object decrypterType)) { ExitError($"Invalid string decrypter type '{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-cflow-deob", "No control flow deobfuscation (NOT recommended)", () => { filesOptions.ControlFlowDeobfuscation = false; })); miscOptions.Add(new NoArgOption(null, "only-cflow-deob", "Only control flow deobfuscation", () => { filesOptions.ControlFlowDeobfuscation = true; // --strtyp none defaultStringDecrypterType = DecrypterType.None; // --keep-types filesOptions.KeepObfuscatorTypes = true; // --preserve-tokens filesOptions.MetadataFlags |= MetadataFlags.PreserveRids | MetadataFlags.PreserveUSOffsets | MetadataFlags.PreserveBlobOffsets | MetadataFlags.PreserveExtraSignatureData; // --dont-rename filesOptions.RenameSymbols = false; filesOptions.RenamerFlags = 0; })); 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", () => { newFileOptions.KeepObfuscatorTypes = true; })); miscOptions.Add(new NoArgOption(null, "preserve-tokens", "Preserve important tokens, #US, #Blob, extra sig data", () => { newFileOptions.MetadataFlags |= MetadataFlags.PreserveRids | MetadataFlags.PreserveUSOffsets | MetadataFlags.PreserveBlobOffsets | MetadataFlags.PreserveExtraSignatureData; })); miscOptions.Add(new OneArgOption(null, "preserve-table", "Preserve rids in table: tr (TypeRef), td (TypeDef), fd (Field), md (Method), pd (Param), mr (MemberRef), s (StandAloneSig), ed (Event), pr (Property), ts (TypeSpec), ms (MethodSpec), all (all previous tables). Use - to disable (eg. all,-pd). Can be combined: ed,fd,md", "flags", (val) => { foreach (var t in val.Split(',')) { var s = t.Trim(); if (s.Length == 0) { continue; } bool clear = s[0] == '-'; if (clear) { s = s.Substring(1); } MetadataFlags flag; switch (s.Trim()) { case "": flag = 0; break; case "all": flag = MetadataFlags.PreserveRids; break; case "tr": flag = MetadataFlags.PreserveTypeRefRids; break; case "td": flag = MetadataFlags.PreserveTypeDefRids; break; case "fd": flag = MetadataFlags.PreserveFieldRids; break; case "md": flag = MetadataFlags.PreserveMethodRids; break; case "pd": flag = MetadataFlags.PreserveParamRids; break; case "mr": flag = MetadataFlags.PreserveMemberRefRids; break; case "s": flag = MetadataFlags.PreserveStandAloneSigRids; break; case "ed": flag = MetadataFlags.PreserveEventRids; break; case "pr": flag = MetadataFlags.PreservePropertyRids; break; case "ts": flag = MetadataFlags.PreserveTypeSpecRids; break; case "ms": flag = MetadataFlags.PreserveMethodSpecRids; break; default: throw new UserException($"Invalid --preserve-table option: {s}"); } if (clear) { filesOptions.MetadataFlags &= ~flag; } else { filesOptions.MetadataFlags |= flag; } } })); miscOptions.Add(new NoArgOption(null, "preserve-all", "Preserve all tokens", () => { newFileOptions.MetadataFlags |= MetadataFlags.PreserveAll; })); miscOptions.Add(new NoArgOption(null, "preserve-strings", "Preserve #Strings heap offsets", () => { newFileOptions.MetadataFlags |= MetadataFlags.PreserveStringsOffsets; })); miscOptions.Add(new NoArgOption(null, "preserve-us", "Preserve #US heap offsets", () => { newFileOptions.MetadataFlags |= MetadataFlags.PreserveUSOffsets; })); miscOptions.Add(new NoArgOption(null, "preserve-blob", "Preserve #Blob heap offsets", () => { newFileOptions.MetadataFlags |= MetadataFlags.PreserveBlobOffsets; })); miscOptions.Add(new NoArgOption(null, "preserve-sig-data", "Preserve extra data at the end of signatures", () => { newFileOptions.MetadataFlags |= MetadataFlags.PreserveExtraSignatureData; })); miscOptions.Add(new NoArgOption(null, "one-file", "Deobfuscate one file at a time", () => { filesOptions.OneFileAtATime = true; })); miscOptions.Add(new NoArgOption("v", null, "Verbose", () => { Logger.Instance.MaxLoggerEvent = LoggerEvent.Verbose; Logger.Instance.CanIgnoreMessages = false; })); miscOptions.Add(new NoArgOption("vv", null, "Very verbose", () => { Logger.Instance.MaxLoggerEvent = LoggerEvent.VeryVerbose; Logger.Instance.CanIgnoreMessages = false; })); 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 (!Utils.FileExists(val)) { ExitError($"File \"{val}\" does not exist."); } newFileOptions = new ObfuscatedFile.Options { Filename = val, ControlFlowDeobfuscation = filesOptions.ControlFlowDeobfuscation, KeepObfuscatorTypes = filesOptions.KeepObfuscatorTypes, MetadataFlags = filesOptions.MetadataFlags, RenamerFlags = filesOptions.RenamerFlags, }; if (defaultStringDecrypterType != null) { newFileOptions.StringDecrypterType = defaultStringDecrypterType.Value; } newFileOptions.StringDecrypterMethods.AddRange(defaultStringDecrypterMethods); }); fileOptions.Add(defaultOption); fileOptions.Add(new OneArgOption("o", null, "Name of output file", "file", (val) => { if (newFileOptions == null) { ExitError("Missing input file"); } var newFilename = Utils.GetFullPath(val); if (string.Equals(Utils.GetFullPath(newFileOptions.Filename), newFilename, StringComparison.OrdinalIgnoreCase)) { ExitError($"Output file can't be same as input file ({newFilename})"); } newFileOptions.NewFilename = newFilename; })); fileOptions.Add(new OneArgOption("p", null, "Obfuscator type (see below)", "type", (val) => { if (newFileOptions == null) { ExitError("Missing input file"); } if (!IsValidObfuscatorType(val)) { ExitError($"Invalid obfuscator type '{val}'"); } newFileOptions.ForcedObfuscatorType = val; })); fileOptions.Add(new OneArgOption(null, "strtyp", "String decrypter type", "type", (val) => { if (newFileOptions == null) { ExitError("Missing input file"); } if (!stringDecrypterTypes.GetValue(val, out object decrypterType)) { ExitError($"Invalid string decrypter type '{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 addAllOptions() { miscOptions.Add(new OneArgOption("r", null, "Scan for .NET files in all subdirs", "dir", (val) => { addSearchDir(); searchDir = new FilesDeobfuscator.SearchDir(); if (!Utils.pathExists(val)) { 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, "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.", () => { filesOptions.RenameSymbols = false; })); miscOptions.Add(new NoArgOption(null, "dont-restore-props", "Don't restore properties/events", () => { filesOptions.RestorePropsEvents = 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-cflow-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 (!Utils.fileExists(val)) { exitError(string.Format("File \"{0}\" does not exist.", val)); } newFileOptions = new ObfuscatedFile.Options { Filename = val, ControlFlowDeobfuscation = filesOptions.ControlFlowDeobfuscation, KeepObfuscatorTypes = filesOptions.KeepObfuscatorTypes, }; if (defaultStringDecrypterType != null) { newFileOptions.StringDecrypterType = defaultStringDecrypterType.Value; } newFileOptions.StringDecrypterMethods.AddRange(defaultStringDecrypterMethods); }); fileOptions.Add(defaultOption); 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()); } }