/* Copyright (C) 2011-2015 de4dot@gmail.com This file is part of de4dot. de4dot is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. de4dot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with de4dot. If not, see . */ using System; using System.Collections.Generic; using System.Text; using dnlib.DotNet; using de4dot.code; using de4dot.code.deobfuscators; using System.IO; using System.Reflection; namespace de4dot.cui { class ExitException : Exception { public readonly int code; public ExitException(int code) { this.code = code; } } class Program { static IList deobfuscatorInfos = CreateDeobfuscatorInfos(); static IList LoadPlugin(string assembly) { var plugins = new List(); try { foreach (Type item in Assembly.LoadFile(assembly).GetTypes()) { var interfaces = new List(item.GetInterfaces()); if (item.IsClass && interfaces.Contains(typeof(IDeobfuscatorInfo))) plugins.Add((IDeobfuscatorInfo)Activator.CreateInstance(item)); } } catch { } return plugins; } public static void GetPlugins(string directory, ref Dictionary result) { var plugins = new List(); try { var files = Directory.GetFiles(directory, "deobfuscator.*.dll", SearchOption.TopDirectoryOnly); foreach (var file in files) plugins.AddRange(LoadPlugin(Path.GetFullPath(file))); } catch { } foreach(var p in plugins) result[p.Type] = p; } static IList CreateDeobfuscatorInfos() { var local = new List { new de4dot.code.deobfuscators.Unknown.DeobfuscatorInfo(), new de4dot.code.deobfuscators.Agile_NET.DeobfuscatorInfo(), new de4dot.code.deobfuscators.Babel_NET.DeobfuscatorInfo(), new de4dot.code.deobfuscators.CodeFort.DeobfuscatorInfo(), new de4dot.code.deobfuscators.CodeVeil.DeobfuscatorInfo(), new de4dot.code.deobfuscators.CodeWall.DeobfuscatorInfo(), new de4dot.code.deobfuscators.Confuser.DeobfuscatorInfo(), new de4dot.code.deobfuscators.ConfuserEx.DeobfuscatorInfo(), new de4dot.code.deobfuscators.CryptoObfuscator.DeobfuscatorInfo(), new de4dot.code.deobfuscators.DeepSea.DeobfuscatorInfo(), new de4dot.code.deobfuscators.Dotfuscator.DeobfuscatorInfo(), new de4dot.code.deobfuscators.dotNET_Reactor.v3.DeobfuscatorInfo(), new de4dot.code.deobfuscators.dotNET_Reactor.v4.DeobfuscatorInfo(), new de4dot.code.deobfuscators.Eazfuscator_NET.DeobfuscatorInfo(), new de4dot.code.deobfuscators.Goliath_NET.DeobfuscatorInfo(), new de4dot.code.deobfuscators.ILProtector.DeobfuscatorInfo(), new de4dot.code.deobfuscators.MaxtoCode.DeobfuscatorInfo(), new de4dot.code.deobfuscators.MPRESS.DeobfuscatorInfo(), new de4dot.code.deobfuscators.Rummage.DeobfuscatorInfo(), new de4dot.code.deobfuscators.Skater_NET.DeobfuscatorInfo(), new de4dot.code.deobfuscators.SmartAssembly.DeobfuscatorInfo(), new de4dot.code.deobfuscators.Spices_Net.DeobfuscatorInfo(), new de4dot.code.deobfuscators.Xenocode.DeobfuscatorInfo(), }; var dict = new Dictionary(); foreach (var d in local) dict[d.Type] = d; string pluginDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin"); GetPlugins(pluginDir, ref dict); return new List(dict.Values); } public static int Main(string[] args) { int exitCode = 0; const string showAllMessagesEnvName = "SHOWALLMESSAGES"; try { if (Console.OutputEncoding.IsSingleByte) Console.OutputEncoding = new UTF8Encoding(false); Logger.Instance.CanIgnoreMessages = !HasEnv(showAllMessagesEnvName); Logger.n(""); Logger.n("de4dot v{0} Copyright (C) 2011-2015 de4dot@gmail.com", System.Reflection.Assembly.GetExecutingAssembly().GetName().Version); Logger.n("Latest version and source code: https://github.com/0xd4d/de4dot"); Logger.n(""); var options = new FilesDeobfuscator.Options(); ParseCommandLine(args, options); new FilesDeobfuscator(options).DoIt(); } catch (ExitException ex) { exitCode = ex.code; } catch (UserException ex) { Logger.Instance.LogErrorDontIgnore("{0}", ex.Message); exitCode = 1; } //TODO: Re-enable exception handler /*catch (Exception ex) { throw; if (PrintFullStackTrace()) { PrintStackTrace(ex); Logger.Instance.LogErrorDontIgnore("\nTry the latest version!"); } else { Logger.Instance.LogErrorDontIgnore("\n\n"); Logger.Instance.LogErrorDontIgnore("Hmmmm... something didn't work. Try the latest version."); } exitCode = 1; }*/ if (Logger.Instance.NumIgnoredMessages > 0) { if (Logger.Instance.NumIgnoredMessages == 1) Logger.n("Ignored {0} warning/error", Logger.Instance.NumIgnoredMessages); else Logger.n("Ignored {0} warnings/errors", Logger.Instance.NumIgnoredMessages); Logger.n("Use -v/-vv option or set environment variable {0}=1 to see all messages", showAllMessagesEnvName); } if (IsN00bUser()) { Console.Error.WriteLine("\n\nPress any key to exit...\n"); try { Console.ReadKey(true); } catch (InvalidOperationException) { } } return exitCode; } static bool PrintFullStackTrace() { if (!Logger.Instance.IgnoresEvent(LoggerEvent.Verbose)) return true; if (HasEnv("STACKTRACE")) return true; return false; } static bool HasEnv(string name) { foreach (var tmp in Environment.GetEnvironmentVariables().Keys) { var env = tmp as string; if (env == null) continue; if (string.Equals(env, name, StringComparison.OrdinalIgnoreCase)) return true; } return false; } static bool IsN00bUser() { if (HasEnv("VisualStudioDir")) return false; if (HasEnv("SHELL")) return false; return HasEnv("windir") && !HasEnv("PROMPT"); } public static void PrintStackTrace(Exception ex) { PrintStackTrace(ex, LoggerEvent.Error); } public static void PrintStackTrace(Exception ex, LoggerEvent loggerEvent) { var line = new string('-', 78); Logger.Instance.Log(false, null, loggerEvent, "\n\n"); Logger.Instance.Log(false, null, loggerEvent, line); Logger.Instance.Log(false, null, loggerEvent, "Stack trace:\n{0}", ex.StackTrace); Logger.Instance.Log(false, null, loggerEvent, "\n\nCaught an exception:\n"); Logger.Instance.Log(false, null, loggerEvent, line); Logger.Instance.Log(false, null, loggerEvent, "Message:"); Logger.Instance.Log(false, null, loggerEvent, " {0}", ex.Message); Logger.Instance.Log(false, null, loggerEvent, "Type:"); Logger.Instance.Log(false, null, loggerEvent, " {0}", ex.GetType()); Logger.Instance.Log(false, null, loggerEvent, line); } static void ParseCommandLine(string[] args, FilesDeobfuscator.Options options) { new CommandLineParser(deobfuscatorInfos, options).Parse(args); Logger.vv("Args:"); Logger.Instance.Indent(); foreach (var arg in args) Logger.vv("{0}", Utils.ToCsharpString(arg)); Logger.Instance.DeIndent(); } } }