/// <summary>
		/// Print out information about whether or not a devirtualization attempt was
		/// successful, and if not why not.
		/// </summary>
		/// <param name="options">MonoOptions set from passed command-line arguments</param>
		/// <param name="module">EazModule</param>
		/// <param name="attempt">Data about the devirtualization attempt</param>
		static void PrintAttemptSuccess(MonoOptions options, EazModule module,
			DevirtualizeAttempt attempt)
		{
			var reader = attempt.Reader;

			if (attempt.Successful)
				Console.WriteLine("--> Devirtualizable");
			else if (attempt.WasInstructionUnknown)
			{
				var matches = module.VirtualInstructions
							.Where((instr) => { return instr.VirtualCode == reader.LastVirtualOpCode; })
							.ToArray();

				if (matches.Length > 0)
				{
					VirtualOpCode v = matches[0];
					Console.WriteLine("--> Not yet devirtualizable (contains unknown virtual instruction)");
					Console.WriteLine("-----> Virtual OpCode = {0} @ [{1}] (0x{2:X8})",
						reader.LastVirtualOpCode, reader.CurrentInstructionOffset, reader.CurrentVirtualOffset);
					Console.WriteLine("-----> Delegate method: {0} (MDToken = 0x{1:X8})",
						v.DelegateMethod.FullName, v.DelegateMethod.MDToken.Raw);
				}
				else
				{
					Console.WriteLine("--> Not yet devirtualizable (contains unexpected virtual instruction @ [{0}] (0x{1:X8}))",
						reader.CurrentInstructionOffset, reader.CurrentVirtualOffset);
				}
			}
			else
				Console.WriteLine("--> Not yet devirtualizable (threw exception)");
		}
        /// <summary>
        /// Print out information about whether or not a devirtualization attempt was
        /// successful, and if not why not.
        /// </summary>
        /// <param name="options">MonoOptions set from passed command-line arguments</param>
        /// <param name="module">EazModule</param>
        /// <param name="attempt">Data about the devirtualization attempt</param>
        static void PrintAttemptSuccess(MonoOptions options, EazModule module,
                                        DevirtualizeAttempt attempt)
        {
            var reader = attempt.Reader;

            if (attempt.Successful)
            {
                Console.WriteLine("--> Devirtualizable");
            }
            else if (attempt.WasInstructionUnknown)
            {
                var matches = module.VirtualInstructions
                              .Where((instr) => { return(instr.VirtualCode == reader.LastVirtualOpCode); })
                              .ToArray();

                if (matches.Length > 0)
                {
                    VirtualOpCode v = matches[0];
                    Console.WriteLine("--> Not yet devirtualizable (contains unknown virtual instruction)");
                    Console.WriteLine("-----> Virtual OpCode = {0} @ [{1}] (0x{2:X8})",
                                      reader.LastVirtualOpCode, reader.CurrentInstructionOffset, reader.CurrentVirtualOffset);
                    Console.WriteLine("-----> Delegate method: {0} (MDToken = 0x{1:X8})",
                                      v.DelegateMethod.FullName, v.DelegateMethod.MDToken.Raw);
                }
                else
                {
                    Console.WriteLine("--> Not yet devirtualizable (contains unexpected virtual instruction @ [{0}] (0x{1:X8}))",
                                      reader.CurrentInstructionOffset, reader.CurrentVirtualOffset);
                }
            }
            else
            {
                Console.WriteLine("--> Not yet devirtualizable (threw exception)");
            }
        }
Example #3
0
        /// <summary>
        /// Perform "methods" verb.
        /// </summary>
        /// <param name="options">Options</param>
        static void DoMethods(MonoOptions options)
        {
            ILogger logger = GetLogger(options);

            EazModule module;

            if (!TryLoadModule(options.AssemblyPath, logger, out module))
            {
                return;
            }

            Devirtualizer devirtualizer = new Devirtualizer(module, options.MethodFixers, logger);

            var results = devirtualizer.Devirtualize((attempt) => {
                PrintAttempt(options, module, attempt);
            });

            if (results.Empty)
            {
                Console.WriteLine("No virtualized methods found");
                return;
            }

            Console.WriteLine("{0}/{1} method stubs devirtualizable",
                              results.DevirtualizedCount, results.MethodCount);
        }
        /// <summary>
        /// Perform "generate" verb.
        /// </summary>
        /// <param name="options">Options</param>
        static void DoGenerate(MonoOptions options)
        {
            var generator = new VirtualizableAssemblyGenerator();

            String instructionSet = "all";

            if (options.InstructionSet != null && options.InstructionSet.Length > 0)
            {
                instructionSet = options.InstructionSet.ToLower();
            }

            String[] sets;
            if (instructionSet.Contains(','))
            {
                sets = instructionSet.Split(',');
            }
            else
            {
                sets = new String[] { instructionSet }
            };

            Boolean all = sets.Contains("all");

            if (sets.Contains("calli") || all)
            {
                generator.AddCalliMethod();
            }
            if (sets.Contains("conv") || all)
            {
                generator.AddConvMethod();
            }
            if (sets.Contains("ind") || all)
            {
                generator.AddIndMethod();
            }
            if (sets.Contains("static-field") || all)
            {
                generator.AddStaticFieldMethod();
            }

            if (!generator.HasMethod)
            {
                Console.WriteLine("Unknown set(s): {0}", instructionSet);
                return;
            }

            var assembly = generator.Generate();

            String filepath = options.OutputPath;

            if (filepath == null)
            {
                filepath = "eazdevirt-test.exe";
            }

            Console.WriteLine("Saving test assembly {0}", filepath);

            assembly.Write(filepath);
        }
    }
Example #5
0
		/// <summary>
		/// Perform "get-key" verb.
		/// </summary>
		/// <param name="options">Options</param>
		static void DoGetKey(MonoOptions options)
		{
			EazModule module;
			if (!TryLoadModule(options.AssemblyPath, out module))
				return;

			MethodStub method = module.FindFirstVirtualizedMethod();
			Console.WriteLine("Key: {0}", method.ResourceCryptoKey);
		}
Example #6
0
        /// <summary>
        /// Perform "get-key" verb.
        /// </summary>
        /// <param name="options">Options</param>
        static void DoGetKey(MonoOptions options)
        {
            EazModule module;

            if (!TryLoadModule(options.AssemblyPath, out module))
            {
                return;
            }

            MethodStub method = module.FindFirstVirtualizedMethod();

            Console.WriteLine("Key: {0}", method.ResourceCryptoKey);
        }
Example #7
0
        /// <summary>
        /// Perform "resource" verb.
        /// </summary>
        /// <param name="options">Options</param>
        static void DoResource(MonoOptions options)
        {
            EazModule module;

            if (!TryLoadModule(options.AssemblyPath, out module))
            {
                return;
            }

            // If no action set, set the default action (extract)
            //if (!options.Extract)
            //	options.Extract = true;

            MethodStub method = module.FindFirstVirtualizedMethod();

            if (method != null)
            {
                if (true /* options.Extract */)
                {
                    String outputPath = options.OutputPath;
                    if (outputPath == null || outputPath.Equals(""))
                    {
                        outputPath = method.ResourceStringId;
                    }

                    FileMode fileMode = FileMode.CreateNew;
                    if (options.OverwriteExisting)
                    {
                        fileMode = FileMode.Create;
                    }

                    using (Stream resourceStream = module.GetResourceStream(options.KeepEncrypted))
                    {
                        try
                        {
                            using (FileStream fileStream = new FileStream(outputPath, fileMode, FileAccess.Write))
                            {
                                resourceStream.CopyTo(fileStream);
                            }
                        }
                        catch (IOException e)
                        {
                            Console.Write(e);
                        }
                    }

                    Console.WriteLine("Extracted {0} resource to {1}",
                                      options.KeepEncrypted ? "encrypted" : "decrypted", outputPath);
                }
            }
        }
        /// <summary>
        /// Perform "devirtualize" verb.
        /// </summary>
        /// <param name="options">Options</param>
        static void DoDevirtualize(MonoOptions options)
        {
            ILogger logger = GetLogger(options);

            EazModule module;

            if (!TryLoadModule(options.AssemblyPath, logger, out module))
            {
                return;
            }

            // Setup devirtualize options
            var opts = DevirtualizeOptions.Nothing;

            if (options.InjectAttributes)
            {
                opts |= DevirtualizeOptions.InjectAttributes;
            }

            Devirtualizer devirtualizer = new Devirtualizer(module, opts, options.MethodFixers, logger);

            var results = devirtualizer.Devirtualize((attempt) => {
                if (attempt.Successful)
                {
                    PrintAttempt(options, module, attempt);
                }
            });

            if (results.Empty)
            {
                Console.WriteLine("No virtualized methods found");
                return;
            }
            else if (!options.Verbose)
            {
                Console.WriteLine();
            }

            Console.WriteLine("Devirtualized {0}/{1} methods",
                              results.DevirtualizedCount, results.MethodCount);

            // Only save if at least one method devirtualized
            if (results.DevirtualizedCount > 0)
            {
                String outputPath = options.OutputPath ?? GetDevirtualizedModulePath(options.AssemblyPath);
                Console.WriteLine("Saving {0}", outputPath);
                module.Write(outputPath, options.NoThrow);
            }
        }
Example #9
0
        static ILogger GetLogger(MonoOptions options)
        {
            LoggerEvent e = LoggerEvent.Info;

            if (options.VerboseLevel == 1)
            {
                e = LoggerEvent.Verbose;
            }
            else if (options.VerboseLevel > 1)
            {
                e = LoggerEvent.VeryVerbose;
            }

            return(new ConsoleLogger(e));
        }
Example #10
0
		static void PrintHelp(MonoOptions parsed)
		{
			Console.WriteLine(GetDescriptorString());
			Console.WriteLine();

			Console.WriteLine("usage: eazdevirt [-dgikmpr] [options] <assembly>");
			Console.WriteLine();

			String generatedHelp = parsed.OptionDescriptors;
			Console.Write(generatedHelp);
			Console.WriteLine();

			Console.WriteLine("examples:");
			Console.WriteLine("  eazdevirt -d MyAssembly.exe");
			Console.WriteLine("  eazdevirt -r --keep-encrypted MyAssembly.exe");
		}
Example #11
0
        /// <summary>
        /// Perform "position" verb.
        /// </summary>
        /// <param name="options">Options</param>
        static void DoPosition(MonoOptions options)
        {
            IPositionTranslator translator = PositionTranslator.DefaultInstance;

            Int64 position = 0;

            if (options.Key.HasValue)
            {
                // This doesn't work yet: Command line parser can't parse Nullable?
                position = translator.ToPosition(options.PositionString, options.Key.Value);
            }
            else if (options.AssemblyPath != null)
            {
                EazModule module;
                if (!TryLoadModule(options.AssemblyPath, out module))
                {
                    return;
                }

                MethodStub method = module.FindFirstVirtualizedMethod();
                if (method != null)
                {
                    try
                    {
                        position = translator.ToPosition(options.PositionString, method.ResourceCryptoKey);
                    }
                    catch (FormatException e)
                    {
                        Console.WriteLine(e.Message);
                        return;
                    }
                }
                else
                {
                    Console.WriteLine("No virtualized methods found in specified assembly");
                    return;
                }
            }
            else
            {
                Console.WriteLine("Provide either the crypto key or assembly from which to extract the crypto key");
                return;
            }

            Console.WriteLine("{0} => {1:X8}", options.PositionString, position);
        }
Example #12
0
        static void PrintHelp(MonoOptions parsed)
        {
            Console.WriteLine(GetDescriptorString());
            Console.WriteLine();

            Console.WriteLine("usage: eazdevirt [-dgikmpr] [options] <assembly>");
            Console.WriteLine();

            String generatedHelp = parsed.OptionDescriptors;

            Console.Write(generatedHelp);
            Console.WriteLine();

            Console.WriteLine("examples:");
            Console.WriteLine("  eazdevirt -d MyAssembly.exe");
            Console.WriteLine("  eazdevirt -r --keep-encrypted MyAssembly.exe");
        }
Example #13
0
        /// <summary>
        /// Perform "generate" verb.
        /// </summary>
        /// <param name="options">Options</param>
        static void DoGenerate(MonoOptions options)
        {
            var generator = new VirtualizableAssemblyGenerator();

            String instructionSet = string.IsNullOrEmpty(options.InstructionSet)
                ? "all"
                : options.InstructionSet.ToLower();

            String[] sets = instructionSet.Contains(',')
                ? instructionSet.Split(',')
                : new String[] { instructionSet };

            Boolean all = sets.Contains("all");

            if (sets.Contains("calli") || all)
            {
                generator.AddCalliMethod();
            }
            if (sets.Contains("conv") || all)
            {
                generator.AddConvMethod();
            }
            if (sets.Contains("ind") || all)
            {
                generator.AddIndMethod();
            }
            if (sets.Contains("static-field") || all)
            {
                generator.AddStaticFieldMethod();
            }

            if (!generator.HasMethod)
            {
                Console.WriteLine("Unknown set(s): {0}", instructionSet);
                return;
            }

            var assembly = generator.Generate();

            String filepath = options.OutputPath ?? "eazdevirt-test.exe";

            Console.WriteLine("Saving test assembly {0}", filepath);

            assembly.Write(filepath);
        }
Example #14
0
        /// <summary>
        /// Perform "position" verb.
        /// </summary>
        /// <param name="options">Options</param>
        static void DoPosition(MonoOptions options)
        {
            IPositionTranslator translator = PositionTranslator.DefaultInstance;

            Int64 position = 0;

            if (options.Key.HasValue)
            {
                // This doesn't work yet: Command line parser can't parse Nullable?
                position = translator.ToPosition(options.PositionString, options.Key.Value);
            }
            else if (options.AssemblyPath != null)
            {
                EazModule module;
                if (!TryLoadModule(options.AssemblyPath, out module))
                    return;

                MethodStub method = module.FindFirstVirtualizedMethod();
                if (method != null)
                {
                    try
                    {
                        position = translator.ToPosition(options.PositionString, method.ResourceCryptoKey);
                    }
                    catch (FormatException e)
                    {
                        Console.WriteLine(e.Message);
                        return;
                    }
                }
                else
                {
                    Console.WriteLine("No virtualized methods found in specified assembly");
                    return;
                }
            }
            else
            {
                Console.WriteLine("Provide either the crypto key or assembly from which to extract the crypto key");
                return;
            }

            Console.WriteLine("{0} => {1:X8}", options.PositionString, position);
        }
Example #15
0
		/// <summary>
		/// Perform "resource" verb.
		/// </summary>
		/// <param name="options">Options</param>
		static void DoResource(MonoOptions options)
		{
			EazModule module;
			if (!TryLoadModule(options.AssemblyPath, out module))
				return;

			// If no action set, set the default action (extract)
			//if (!options.Extract)
			//	options.Extract = true;

			MethodStub method = module.FindFirstVirtualizedMethod();
			if (method != null)
			{
				if (true /* options.Extract */)
				{
					String outputPath = options.OutputPath;
					if (outputPath == null || outputPath.Equals(""))
						outputPath = method.ResourceStringId;

					FileMode fileMode = FileMode.CreateNew;
					if (options.OverwriteExisting)
						fileMode = FileMode.Create;

					using (Stream resourceStream = module.GetResourceStream(options.KeepEncrypted))
					{
						try
						{
							using (FileStream fileStream = new FileStream(outputPath, fileMode, FileAccess.Write))
							{
								resourceStream.CopyTo(fileStream);
							}
						}
						catch (IOException e)
						{
							Console.Write(e);
						}
					}

					Console.WriteLine("Extracted {0} resource to {1}",
						options.KeepEncrypted ? "encrypted" : "decrypted", outputPath);
				}
			}
		}
        /// <summary>
        /// Perform "position" verb.
        /// </summary>
        /// <param name="options">Options</param>
        static void DoPosition(MonoOptions options)
        {
            Int64 position = 0;

            if (options.AssemblyPath != null)
            {
                EazModule module;
                if (!TryLoadModule(options.AssemblyPath, out module))
                {
                    return;
                }

                IPositionTranslator translator = module.PositionTranslator;

                MethodStub method = module.FindFirstVirtualizedMethod();
                if (method != null)
                {
                    try
                    {
                        position = translator.ToPosition(options.PositionString, method.ResourceCryptoKey);
                    }
                    catch (FormatException e)
                    {
                        Console.WriteLine(e.Message);
                        return;
                    }
                }
                else
                {
                    Console.WriteLine("No virtualized methods found in specified assembly");
                    return;
                }
            }
            else
            {
                Console.WriteLine("Provide either the crypto key or assembly from which to extract the crypto key");
                return;
            }

            Console.WriteLine("{0} => {1:X8}", options.PositionString, position);
        }
Example #17
0
		/// <summary>
		/// Perform "position" verb.
		/// </summary>
		/// <param name="options">Options</param>
		static void DoPosition(MonoOptions options)
		{
			Int64 position = 0;

			if (options.AssemblyPath != null)
			{
				EazModule module;
				if (!TryLoadModule(options.AssemblyPath, out module))
					return;

				IPositionTranslator translator = module.PositionTranslator;

				MethodStub method = module.FindFirstVirtualizedMethod();
				if (method != null)
				{
					try
					{
						position = translator.ToPosition(options.PositionString, method.ResourceCryptoKey);
					}
					catch (FormatException e)
					{
						Console.WriteLine(e.Message);
						return;
					}
				}
				else
				{
					Console.WriteLine("No virtualized methods found in specified assembly");
					return;
				}
			}
			else
			{
				Console.WriteLine("Provide either the crypto key or assembly from which to extract the crypto key");
				return;
			}

			Console.WriteLine("{0} => {1:X8}", options.PositionString, position);
		}
Example #18
0
		/// <summary>
		/// Perform "generate" verb.
		/// </summary>
		/// <param name="options">Options</param>
		static void DoGenerate(MonoOptions options)
		{
			var generator = new VirtualizableAssemblyGenerator();

			String instructionSet = "all";
			if (options.InstructionSet != null && options.InstructionSet.Length > 0)
				instructionSet = options.InstructionSet.ToLower();

			String[] sets;
			if (instructionSet.Contains(','))
				sets = instructionSet.Split(',');
			else sets = new String[] { instructionSet };

			Boolean all = sets.Contains("all");
			if (sets.Contains("calli") || all)
				generator.AddCalliMethod();
			if (sets.Contains("conv") || all)
				generator.AddConvMethod();
			if (sets.Contains("ind") || all)
				generator.AddIndMethod();
			if (sets.Contains("static-field") || all)
				generator.AddStaticFieldMethod();

			if (!generator.HasMethod)
			{
				Console.WriteLine("Unknown set(s): {0}", instructionSet);
				return;
			}

			var assembly = generator.Generate();

			String filepath = options.OutputPath;
			if (filepath == null)
				filepath = "eazdevirt-test.exe";

			Console.WriteLine("Saving test assembly {0}", filepath);

			assembly.Write(filepath);
		}
Example #19
0
		/// <summary>
		/// Perform "methods" verb.
		/// </summary>
		/// <param name="options">Options</param>
		static void DoMethods(MonoOptions options)
		{
			ILogger logger = GetLogger(options);

			EazModule module;
			if (!TryLoadModule(options.AssemblyPath, logger, out module))
				return;

			Devirtualizer devirtualizer = new Devirtualizer(module, options.MethodFixers, logger);

			var results = devirtualizer.Devirtualize((attempt) => {
				PrintAttempt(options, module, attempt);
			});

			if (results.Empty)
			{
				Console.WriteLine("No virtualized methods found");
				return;
			}

			Console.WriteLine("{0}/{1} method stubs devirtualizable",
				results.DevirtualizedCount, results.MethodCount);
		}
        /// <summary>
        /// Perform "instructions" verb.
        /// </summary>
        /// <param name="options">Options</param>
        static void DoInstructions(MonoOptions options)
        {
            EazModule module;

            if (!TryLoadModule(options.AssemblyPath, out module))
            {
                return;
            }

            MethodStub method = module.FindFirstVirtualizedMethod();

            if (method == null)
            {
                Console.WriteLine("No methods in assembly seem to be virtualized");
                return;
            }

            // The virtual-call-method should belong to the main virtualization type
            TypeDef virtualizationType = method.VirtualCallMethod.DeclaringType;
            var     vInstructions      = module.VirtualInstructions;

            if (vInstructions.Count > 0)
            {
                // Get # of identified instructions
                Int32 identified = 0;
                foreach (var v in vInstructions)
                {
                    if (v.IsIdentified)
                    {
                        identified++;
                    }
                }

                // Get % of identified instructions as a string
                String percentIdentified;
                if (identified == 0)
                {
                    percentIdentified = "0%";
                }
                else if (identified == vInstructions.Count)
                {
                    percentIdentified = "100%";
                }
                else
                {
                    percentIdentified = Math.Floor(
                        (((double)identified) / ((double)vInstructions.Count)) * 100d
                        ) + "%";
                }

                Console.WriteLine("Virtual instruction types found: {0}", vInstructions.Count);
                Console.WriteLine("{0}/{1} instruction types identified ({2})",
                                  identified, vInstructions.Count, percentIdentified);

                if (!options.Verbose)
                {
                    Console.WriteLine();
                }

                // If only showing identified instructions, remove all non-identified and sort by name
                if (options.OnlyIdentified)
                {
                    vInstructions = new List <VirtualOpCode>(vInstructions
                                                             .Where((instruction) => { return(instruction.IsIdentified); })
                                                             .OrderBy((instruction) => { return(instruction.Name); }));
                }

                // If only showing instructions with specific virtual operand types, filter
                if (options.OperandTypeWhitelist != Int32.MinValue)
                {
                    vInstructions = new List <VirtualOpCode>(vInstructions
                                                             .Where((instruction) =>
                    {
                        return(options.OperandTypeWhitelist == instruction.VirtualOperandType);
                    }));
                }

                foreach (var v in vInstructions)
                {
                    if (!options.Verbose)                     // Simple output
                    {
                        if (v.IsIdentified)
                        {
                            Console.WriteLine("Instruction: {0}, Method: {1}", v.Name, v.DelegateMethod.FullName);
                        }
                        else
                        {
                            Console.WriteLine("Instruction: Unknown, Method: {0}", v.DelegateMethod.FullName);
                        }
                    }
                    else                     // Not-Simple output?
                    {
                        Console.WriteLine();

                        if (v.IsIdentified)
                        {
                            Console.WriteLine("Instruction: {0}", v.Name);
                        }
                        else
                        {
                            Console.WriteLine("Instruction: Unknown");
                        }

                        if (v.IsIdentified || !options.OnlyIdentified)
                        {
                            if (v.HasVirtualCode)
                            {
                                Console.WriteLine("--> Virtual OpCode:  {0} ({0:X8})", v.VirtualCode);
                                Console.WriteLine("--> Operand type:    {0}", v.VirtualOperandType);
                            }

                            {
                                Console.WriteLine("--> Delegate method: {0}", v.DelegateMethod.FullName);
                            }
                        }
                    }
                }

                // Print operand information
                if (options.Operands)
                {
                    var operandTypeDict = new Dictionary <Int32, Int32>();
                    foreach (var vInstr in vInstructions)
                    {
                        var type = vInstr.VirtualOperandType;
                        if (operandTypeDict.ContainsKey(type))
                        {
                            operandTypeDict[type] = (operandTypeDict[type] + 1);
                        }
                        else
                        {
                            operandTypeDict.Add(type, 1);
                        }
                    }

                    Console.WriteLine();
                    Console.WriteLine("Virtual operand type counts:");
                    foreach (var kvp in operandTypeDict)
                    {
                        Console.WriteLine("  Operand {0}: {1} occurrence(s)", kvp.Key, kvp.Value);
                    }
                }
            }
            else
            {
                Console.WriteLine("No virtual instructions found?");
            }
        }
		/// <summary>
		/// Print out information about a devirtualization attempt.
		/// </summary>
		/// <param name="options">MonoOptions set from passed command-line arguments</param>
		/// <param name="module">EazModule</param>
		/// <param name="attempt">Data about the devirtualization attempt</param>
		static void PrintAttempt(MonoOptions options, EazModule module,
			DevirtualizeAttempt attempt)
		{
			var reader = attempt.Reader;
			var method = attempt.Method;
			var stub = attempt.VirtualizedMethod;
			var body = attempt.MethodBody;

			IList<Local> locals = attempt.Successful ?
				body.Variables : reader.Locals;
			IList<ExceptionHandler> handlers = attempt.Successful ?
				body.ExceptionHandlers : reader.ExceptionHandlers;
			IList<Instruction> instructions = attempt.Successful ?
				body.Instructions : reader.Instructions;

			// Message prefix
			String prefix;
			switch(options.Action)
			{
				case ProgramAction.Devirtualize:
					prefix = "Devirtualized";
					break;
				case ProgramAction.Methods:
				default:
					prefix = "Found";
					break;
			}

			Console.WriteLine("{0} {1} (MDToken = 0x{2:X8})", prefix, method.FullName, method.MDToken.Raw);

			if (options.Action == ProgramAction.Methods || options.Verbose)
			{
				Console.WriteLine("--> Position string: {0}", stub.PositionString);
				Console.WriteLine("--> Position: {0} (0x{0:X8})", stub.Position);
				Console.WriteLine("--> Resource: {0}", stub.ResourceStringId);
				Console.WriteLine("--> Crypto key: {0}", stub.ResourceCryptoKey);
				Console.WriteLine("--> Actual method size: {0} (0x{0:X8})", reader.CodeSize);

				if (options.Action == ProgramAction.Methods)
					PrintAttemptSuccess(options, module, attempt);
			}

			if (options.Action == ProgramAction.Methods || options.Verbose)
			{
				Console.WriteLine();

				// Print locals
				if (locals.Count > 0)
				{
					Int32 index = 0;
					Console.WriteLine("Locals:");
					Console.WriteLine("-------");
					foreach (var local in locals)
						Console.WriteLine("local[{0}]: {1}", index++, local.Type.FullName);
					Console.WriteLine();
				}

				// Print exception handlers
				if (handlers.Count > 0)
				{
					Int32 index = 0;
					Console.WriteLine("Exception Handlers:");
					Console.WriteLine("-------------------");
					foreach (var handler in handlers)
					{
						if (handler.CatchType != null)
							Console.WriteLine("handler[{0}]: HandlerType = {1}, CatchType = {2}",
								index++, handler.HandlerType, handler.CatchType);
						else
							Console.WriteLine("handler[{0}]: HandlerType = {1}",
								index++, handler.HandlerType);
						Console.WriteLine("--> Try:     [{0}, {1}]", handler.TryStart, handler.TryEnd);
						Console.WriteLine("--> Handler: [{0}, {1}]", handler.HandlerStart, handler.HandlerEnd);
						Console.WriteLine("--> Filter:  {0}", handler.FilterStart);
					}
					Console.WriteLine();
				}

				// Print instructions
				if (instructions != null && instructions.Count > 0)
				{
					Console.WriteLine("Instructions:");
					Console.WriteLine("-------------");
					foreach (var instr in instructions)
						Console.WriteLine(instr);
					Console.WriteLine();
				}

				// Print out exception, if any
				if (!attempt.Successful && !attempt.WasInstructionUnknown)
				{
					Console.Write(attempt.Exception);
					Console.WriteLine();
					Console.WriteLine();
				}
			}

			if (!(options.Action == ProgramAction.Devirtualize && !options.Verbose))
				Console.WriteLine();
		}
        /// <summary>
        /// Print out information about a devirtualization attempt.
        /// </summary>
        /// <param name="options">MonoOptions set from passed command-line arguments</param>
        /// <param name="module">EazModule</param>
        /// <param name="attempt">Data about the devirtualization attempt</param>
        static void PrintAttempt(MonoOptions options, EazModule module,
                                 DevirtualizeAttempt attempt)
        {
            var reader = attempt.Reader;
            var method = attempt.Method;
            var stub   = attempt.VirtualizedMethod;
            var body   = attempt.MethodBody;

            IList <Local> locals = attempt.Successful ?
                                   body.Variables : reader.Locals;
            IList <ExceptionHandler> handlers = attempt.Successful ?
                                                body.ExceptionHandlers : reader.ExceptionHandlers;
            IList <Instruction> instructions = attempt.Successful ?
                                               body.Instructions : reader.Instructions;

            // Message prefix
            String prefix;

            switch (options.Action)
            {
            case ProgramAction.Devirtualize:
                prefix = "Devirtualized";
                break;

            case ProgramAction.Methods:
            default:
                prefix = "Found";
                break;
            }

            Console.WriteLine("{0} {1} (MDToken = 0x{2:X8})", prefix, method.FullName, method.MDToken.Raw);

            if (options.Action == ProgramAction.Methods || options.Verbose)
            {
                Console.WriteLine("--> Position string: {0}", stub.PositionString);
                Console.WriteLine("--> Position: {0} (0x{0:X8})", stub.Position);
                Console.WriteLine("--> Resource: {0}", stub.ResourceStringId);
                Console.WriteLine("--> Crypto key: {0}", stub.ResourceCryptoKey);
                Console.WriteLine("--> Actual method size: {0} (0x{0:X8})", reader.CodeSize);

                if (options.Action == ProgramAction.Methods)
                {
                    PrintAttemptSuccess(options, module, attempt);
                }
            }

            if (options.Action == ProgramAction.Methods || options.Verbose)
            {
                Console.WriteLine();

                // Print locals
                if (locals.Count > 0)
                {
                    Int32 index = 0;
                    Console.WriteLine("Locals:");
                    Console.WriteLine("-------");
                    foreach (var local in locals)
                    {
                        Console.WriteLine("local[{0}]: {1}", index++, local.Type.FullName);
                    }
                    Console.WriteLine();
                }

                // Print exception handlers
                if (handlers.Count > 0)
                {
                    Int32 index = 0;
                    Console.WriteLine("Exception Handlers:");
                    Console.WriteLine("-------------------");
                    foreach (var handler in handlers)
                    {
                        if (handler.CatchType != null)
                        {
                            Console.WriteLine("handler[{0}]: HandlerType = {1}, CatchType = {2}",
                                              index++, handler.HandlerType, handler.CatchType);
                        }
                        else
                        {
                            Console.WriteLine("handler[{0}]: HandlerType = {1}",
                                              index++, handler.HandlerType);
                        }
                        Console.WriteLine("--> Try:     [{0}, {1}]", handler.TryStart, handler.TryEnd);
                        Console.WriteLine("--> Handler: [{0}, {1}]", handler.HandlerStart, handler.HandlerEnd);
                        Console.WriteLine("--> Filter:  {0}", handler.FilterStart);
                    }
                    Console.WriteLine();
                }

                // Print instructions
                if (instructions != null && instructions.Count > 0)
                {
                    Console.WriteLine("Instructions:");
                    Console.WriteLine("-------------");
                    foreach (var instr in instructions)
                    {
                        Console.WriteLine(instr);
                    }
                    Console.WriteLine();
                }

                // Print out exception, if any
                if (!attempt.Successful && !attempt.WasInstructionUnknown)
                {
                    Console.Write(attempt.Exception);
                    Console.WriteLine();
                    Console.WriteLine();
                }
            }

            if (!(options.Action == ProgramAction.Devirtualize && !options.Verbose))
            {
                Console.WriteLine();
            }
        }
		/// <summary>
		/// Perform "devirtualize" verb.
		/// </summary>
		/// <param name="options">Options</param>
		static void DoDevirtualize(MonoOptions options)
		{
			ILogger logger = GetLogger(options);

			EazModule module;
			if (!TryLoadModule(options.AssemblyPath, logger, out module))
				return;

			// Setup devirtualize options
			var opts = DevirtualizeOptions.Nothing;
			if (options.InjectAttributes)
				opts |= DevirtualizeOptions.InjectAttributes;

			Devirtualizer devirtualizer = new Devirtualizer(module, opts, options.MethodFixers, logger);

			var results = devirtualizer.Devirtualize((attempt) => {
				if (attempt.Successful)
					PrintAttempt(options, module, attempt);
			});

			if (results.Empty)
			{
				Console.WriteLine("No virtualized methods found");
				return;
			}
			else if (!options.Verbose)
				Console.WriteLine();

			Console.WriteLine("Devirtualized {0}/{1} methods",
				results.DevirtualizedCount, results.MethodCount);

			// Only save if at least one method devirtualized
			if (results.DevirtualizedCount > 0)
			{
				String outputPath = options.OutputPath ?? GetDevirtualizedModulePath(options.AssemblyPath);
				Console.WriteLine("Saving {0}", outputPath);
				module.Write(outputPath, options.NoThrow);
			}
		}
		/// <summary>
		/// Perform "instructions" verb.
		/// </summary>
		/// <param name="options">Options</param>
		static void DoInstructions(MonoOptions options)
		{
			EazModule module;
			if (!TryLoadModule(options.AssemblyPath, out module))
				return;

			MethodStub method = module.FindFirstVirtualizedMethod();
			if (method == null)
			{
				Console.WriteLine("No methods in assembly seem to be virtualized");
				return;
			}

			// The virtual-call-method should belong to the main virtualization type
			TypeDef virtualizationType = method.VirtualCallMethod.DeclaringType;
			var vInstructions = module.VirtualInstructions;

			if (vInstructions.Count > 0)
			{
				// Get # of identified instructions
				Int32 identified = 0;
				foreach (var v in vInstructions)
					if (v.IsIdentified) identified++;

				// Get % of identified instructions as a string
				String percentIdentified;
				if (identified == 0)
					percentIdentified = "0%";
				else if (identified == vInstructions.Count)
					percentIdentified = "100%";
				else
					percentIdentified = Math.Floor(
						(((double)identified) / ((double)vInstructions.Count)) * 100d
					) + "%";

				Console.WriteLine("Virtual instruction types found: {0}", vInstructions.Count);
				Console.WriteLine("{0}/{1} instruction types identified ({2})",
					identified, vInstructions.Count, percentIdentified);

				if (!options.Verbose)
					Console.WriteLine();

				// If only showing identified instructions, remove all non-identified and sort by name
				if (options.OnlyIdentified)
				{
					vInstructions = new List<VirtualOpCode>(vInstructions
						.Where((instruction) => { return instruction.IsIdentified; })
						.OrderBy((instruction) => { return instruction.Name; }));
				}

				// If only showing instructions with specific virtual operand types, filter
				if (options.OperandTypeWhitelist != Int32.MinValue)
				{
					vInstructions = new List<VirtualOpCode>(vInstructions
						.Where((instruction) =>
						{
							return options.OperandTypeWhitelist == instruction.VirtualOperandType;
						}));
				}

				foreach (var v in vInstructions)
				{
					if (!options.Verbose) // Simple output
					{
						if (v.IsIdentified)
							Console.WriteLine("Instruction: {0}, Method: {1}", v.Name, v.DelegateMethod.FullName);
						else
							Console.WriteLine("Instruction: Unknown, Method: {0}", v.DelegateMethod.FullName);
					}
					else // Not-Simple output?
					{
						Console.WriteLine();

						if (v.IsIdentified)
							Console.WriteLine("Instruction: {0}", v.Name);
						else
							Console.WriteLine("Instruction: Unknown");

						if (v.IsIdentified || !options.OnlyIdentified)
						{
							if (v.HasVirtualCode)
							{
								Console.WriteLine("--> Virtual OpCode:  {0} ({0:X8})", v.VirtualCode);
								Console.WriteLine("--> Operand type:    {0}", v.VirtualOperandType);
							}

							{
								Console.WriteLine("--> Delegate method: {0}", v.DelegateMethod.FullName);
							}
						}
					}
				}

				// Print operand information
				if (options.Operands)
				{
					var operandTypeDict = new Dictionary<Int32, Int32>();
					foreach (var vInstr in vInstructions)
					{
						var type = vInstr.VirtualOperandType;
						if (operandTypeDict.ContainsKey(type))
							operandTypeDict[type] = (operandTypeDict[type] + 1);
						else operandTypeDict.Add(type, 1);
					}

					Console.WriteLine();
					Console.WriteLine("Virtual operand type counts:");
					foreach (var kvp in operandTypeDict)
						Console.WriteLine("  Operand {0}: {1} occurrence(s)", kvp.Key, kvp.Value);
				}
			}
			else Console.WriteLine("No virtual instructions found?");
		}
Example #25
0
        /// <summary>
        /// Parse a MonoOptions from passed arguments.
        /// </summary>
        /// <param name="args">Arguments passed to program</param>
        /// <returns>MonoOptions</returns>
        static MonoOptions Parse(String[] args)
        {
            MonoOptions options   = new MonoOptions();
            OptionSet   optionSet = new OptionSet()
            {
                // Program action options
                { "d|devirtualize", "attempt to devirtualize methods in a protected assembly",
                  v => options.Action = ProgramAction.Devirtualize },
                { "g|generate", "generate a test executable to be protected and analysed",
                  v => options.Action = ProgramAction.Generate },
                { "i|instructions", "print virtual opcode information extracted from a protected assembly",
                  v => options.Action = ProgramAction.Instructions },
                { "k|get-key", "extract the integer crypto key from a protected assembly",
                  v => options.Action = ProgramAction.GetKey },
                { "m|methods", "print virtualized method + method stub information extracted from a protected assembly",
                  v => options.Action = ProgramAction.Methods },
                { "p|position", "translate a position string into its Int64 representation given either an integer "
                  + "crypto key or a protected assembly",
                  v => options.Action = ProgramAction.Position },
                { "r|resource", "extract the embedded resource from a protected assembly",
                  v => options.Action = ProgramAction.Resource },

                { "N|no-throw", "don't throw when writing a module", v => options.NoThrow = true },

                // `devirtualize` options
                { "j|inject", "inject attributes", v => options.InjectAttributes = true },
                { "F=|fixers=", "fixers to use", v => options.FixersString = v },

                // `generate` options
                { "I=|instruction-set=", "name of \"instruction sets\" to generate",
                  v => options.InstructionSet = v },

                // `instructions` options
                { "only-identified", "only show identified opcodes",
                  v => options.OnlyIdentified = true },
                { "operands", "print info about operand types",
                  v => options.Operands = true },
                { "operand-type=", "operand type whitelist",
                  (Int32 v) => options.OperandTypeWhitelist = v },

                // `position` options
                { "K=|key=", "integer crypto key used to translate a position string",
                  (Int32 v) => options.Key = v },
                { "P=|position-string=", "position string to translate",
                  v => options.PositionString = v },

                // `resource` options
                { "o=|destination=", "destination file (type of file depends on program action)",
                  v => options.OutputPath = v },
                { "f|force", "overwrite destination file if it exists",
                  v => options.OverwriteExisting = true },
                { "x|extract", v => options.ExtractResource = true },
                { "D|keep-encrypted", "don't decrypt the resource file when extracting",
                  v => options.KeepEncrypted = true },

                // Other options
                { "L|no-logo", "don't show the ascii logo", v => options.NoLogo = true },
                { "h|?|help", "show help/usage info and exit", v => options.Help = true },
                { "v|verbose", "more output", v => options.VerboseLevel++ }
            };

            options.Extra     = optionSet.Parse(args);
            options.OptionSet = optionSet;

            if (options.Extra.Count > 0)
            {
                options.AssemblyPath = options.Extra[0];
            }

            return(options);
        }
Example #26
0
		/// <summary>
		/// Parse a MonoOptions from passed arguments.
		/// </summary>
		/// <param name="args">Arguments passed to program</param>
		/// <returns>MonoOptions</returns>
		static MonoOptions Parse(String[] args)
		{
			MonoOptions options = new MonoOptions();
			OptionSet optionSet = new OptionSet()
			{
				// Program action options
				{ "d|devirtualize", "attempt to devirtualize methods in a protected assembly",
					v => options.Action = ProgramAction.Devirtualize },
				{ "g|generate", "generate a test executable to be protected and analysed",
					v => options.Action = ProgramAction.Generate },
				{ "i|instructions", "print virtual opcode information extracted from a protected assembly",
					v => options.Action = ProgramAction.Instructions },
				{ "k|get-key", "extract the integer crypto key from a protected assembly",
					v => options.Action = ProgramAction.GetKey },
				{ "m|methods", "print virtualized method + method stub information extracted from a protected assembly",
					v => options.Action = ProgramAction.Methods },
				{ "p|position", "translate a position string into its Int64 representation given either an integer "
				              + "crypto key or a protected assembly",
					v => options.Action = ProgramAction.Position },
				{ "r|resource", "extract the embedded resource from a protected assembly",
					v => options.Action = ProgramAction.Resource },

				{ "N|no-throw", "don't throw when writing a module", v => options.NoThrow = true },

				// `devirtualize` options
				{ "j|inject", "inject attributes", v => options.InjectAttributes = true },
				{ "F=|fixers=", "fixers to use", v => options.FixersString = v },

				// `generate` options
				{ "I=|instruction-set=", "name of \"instruction sets\" to generate",
					v => options.InstructionSet = v },

				// `instructions` options
				{ "only-identified", "only show identified opcodes",
					v => options.OnlyIdentified = true },
				{ "operands", "print info about operand types",
					v => options.Operands = true },
				{ "operand-type=", "operand type whitelist",
					(Int32 v) => options.OperandTypeWhitelist = v },

				// `position` options
				{ "K=|key=", "integer crypto key used to translate a position string",
					(Int32 v) => options.Key = v },
				{ "P=|position-string=", "position string to translate",
					v => options.PositionString = v },

				// `resource` options
				{ "o=|destination=", "destination file (type of file depends on program action)",
					v => options.OutputPath = v },
				{ "f|force", "overwrite destination file if it exists",
					v => options.OverwriteExisting = true },
				{ "x|extract", v => options.ExtractResource = true },
				{ "D|keep-encrypted", "don't decrypt the resource file when extracting",
					v => options.KeepEncrypted = true },

				// Other options
				{ "L|no-logo", "don't show the ascii logo", v => options.NoLogo = true },
				{ "h|?|help", "show help/usage info and exit", v => options.Help = true },
				{ "v|verbose", "more output", v => options.VerboseLevel++ }
			};

			options.Extra = optionSet.Parse(args);
			options.OptionSet = optionSet;

			if (options.Extra.Count > 0)
				options.AssemblyPath = options.Extra[0];

			return options;
		}
Example #27
0
		static ILogger GetLogger(MonoOptions options)
		{
			LoggerEvent e = LoggerEvent.Info;

			if (options.VerboseLevel == 1)
				e = LoggerEvent.Verbose;
			else if (options.VerboseLevel > 1)
				e = LoggerEvent.VeryVerbose;

			return new ConsoleLogger(e);
		}