Ejemplo n.º 1
0
 public Disassembler(int bitness, string commentPrefix, SourceCodeProvider sourceCodeProvider, KnownSymbols knownSymbols, DisassemblerOptions disassemblerOptions)
 {
     this.bitness            = bitness;
     this.commentPrefix      = commentPrefix;
     this.sourceCodeProvider = sourceCodeProvider;
     if (bitness == 64)
     {
         diffableSymAddrLo = DIFFABLE_SYM_ADDR64_LO;
         diffableSymAddrHi = DIFFABLE_SYM_ADDR64_HI;
     }
     else
     {
         diffableSymAddrLo = DIFFABLE_SYM_ADDR32_LO;
         diffableSymAddrHi = DIFFABLE_SYM_ADDR32_HI;
     }
     targets                  = new Dictionary <ulong, AddressInfo>();
     sortedTargets            = new List <KeyValuePair <ulong, AddressInfo> >();
     formatterOutput          = new FormatterOutputImpl();
     charBuf                  = new char[100];
     this.knownSymbols        = knownSymbols;
     this.disassemblerOptions = disassemblerOptions;
     if ((disassemblerOptions & DisassemblerOptions.Diffable) != 0)
     {
         this.disassemblerOptions = (disassemblerOptions & ~(DisassemblerOptions.ShowAddresses | DisassemblerOptions.ShowHexBytes));
     }
 }
Ejemplo n.º 2
0
        /// <summary>
        /// Task for disassembling one individual file.
        /// </summary>
        /// <param name="logger">The logging implementation to log errors/info to.</param>
        /// <param name="options">The options to use while disassembling.</param>
        /// <returns>True if the disassembler could successfully disassemble the file; otherwise returns false.</returns>
        public bool DisassembleFile(ILogger logger, DisassemblerOptions options)
        {
            bool success = true;

            logger.Log(LogLevel.Info, "Invoking disassembler for file " + options.InputFileName);
            try
            {
                ICompiledFileReader  fileParser = m_FileParserFac.GetFileParser(options.InputFileName);
                DisassembledFileBase fileBase   = fileParser.ParseFile(options.InputFileName, logger);
                IAssemblyFileWriter  fileWriter = fileBase.AssemblyTextFileWriter;
                fileWriter.GenerateOutputFile(options.OutputFileName);
            }
            catch (IOException ex)
            {
                logger.Log(LogLevel.Critical, ex.Message);
                success = false;
            }
            catch (Exception ex)
            {
                logger.Log(LogLevel.Critical, "In file " + options.InputFileName + ":");
                logger.Log(LogLevel.Critical, ex.Message);
                success = false;
            }

            return(success);
        }
Ejemplo n.º 3
0
 public MethodBodyDisassembler(ITextOutput output, bool detectControlStructure, DisassemblerOptions options)
 {
     if (output == null)
         throw new ArgumentNullException("output");
     this.output = output;
     this.detectControlStructure = detectControlStructure;
     this.options = options;
 }
 /// <summary>
 /// Creates a new managed disassembler
 /// </summary>
 /// <param name="compilationData">The compilation data</param>
 /// <param name="createDisassembler">Function to create the disassembler</param>
 /// <param name="options">The options</param>
 public Disassembler(
     AbstractCompilationData compilationData,
     Func<AbstractCompilationData, INativeDisassembler> createDisassembler,
     DisassemblerOptions options = DisassemblerOptions.None)
 {
     this.compilationData = compilationData;
     this.nativeDisassembler = createDisassembler(compilationData);
     this.options = options;
 }
Ejemplo n.º 5
0
 /// <summary>
 /// Creates a new managed disassembler
 /// </summary>
 /// <param name="compilationData">The compilation data</param>
 /// <param name="createDisassembler">Function to create the disassembler</param>
 /// <param name="options">The options</param>
 public Disassembler(
     AbstractCompilationData compilationData,
     Func <AbstractCompilationData, INativeDisassembler> createDisassembler,
     DisassemblerOptions options = DisassemblerOptions.None)
 {
     this.compilationData    = compilationData;
     this.nativeDisassembler = createDisassembler(compilationData);
     this.options            = options;
 }
Ejemplo n.º 6
0
        private static ValueTask <EInputBlockResult> DisassembleRomAsync(IRomData romData)
        {
            Console.WriteLine("Disassembling ROM.");
            Console.WriteLine();
            Console.WriteLine("HEADER");
            var romBuild = romData.GetRomBuild();

            Console.WriteLine($"{romData.Header.Title}");
            Console.WriteLine($"Build: {romBuild.Version} ({romBuild.BuildNumber})");
            Console.WriteLine($"Size: {romData.Size.Size.Mebibits}Mib (0x{romData.Length:X})");
            Console.WriteLine($"Destination Code: {romData.Header.DestinationCode}");
            Console.WriteLine($"Game Code: {romData.Header.GameCode}");
            Console.WriteLine($"Format: {romData.Header.Format}");
            Console.WriteLine($"Mask Rom Version: {romData.Header.Version}");
            Console.WriteLine($"Entry Address: 0x{romData.Header.EntryAddress:X}");
            Console.WriteLine($"Return Address: 0x{romData.Header.ReturnAddress:X}");
            Console.WriteLine();

            using var decompressedRomData = romData.Decompress();

            var disassembler = new Disassembler();
            var options      = new DisassemblerOptions
            {
                OutputDir  = new DirectoryInfo(@"C:\Users\shira\Desktop\OoTDecomp"),
                SplitFiles = false,
                KnownFiles =
                {
                    new FileEntry("INTERNAL_HEADER",                  0xA4000000, romData.GetHeaderData()),
                    new FileEntry("IPL3",                             0xA4000040, romData.GetIPL3Data()),
                    // We don't know what this is, but we can figure this out
                    // when we start disassembling correctly and getting a bunch of opcode errors.
                    // For reference, we know that Mario ends at 0x0B6A40. We'll go a bit higher then
                    // work our way down.
                    new FileEntry("CODE",            romData.Header.EntryAddress, decompressedRomData.GetCodeData(0x0C3500))
                },
                Regions =
                {
                    new DataRegion("INTERNAL_HEADER", 0xA4000000, 0xA400003F)
                },
                KnownFunctions =
                {
                    { 0x80000400, "Main" }
                }
            };

            //disassembler.AddRegion(new DataRegion("INTERNAL_HEADER", 0xA4000000, 0xA400003F));

            Console.WriteLine();

            if (!PerformChecklistOperation("Disassembling ROM to MIPS.", () => disassembler.Disassemble(options), r => r.Exception))
            {
                return(new ValueTask <EInputBlockResult>(EInputBlockResult.Failed));
            }

            return(new ValueTask <EInputBlockResult>(EInputBlockResult.Success));
        }
Ejemplo n.º 7
0
 public MethodBodyDisassembler(ITextOutput output, bool detectControlStructure, DisassemblerOptions options)
 {
     if (output == null)
     {
         throw new ArgumentNullException("output");
     }
     this.output = output;
     this.detectControlStructure = detectControlStructure;
     this.options = options;
 }
Ejemplo n.º 8
0
		ReflectionDisassembler CreateReflectionDisassembler(ITextOutput output, DecompilationOptions options, ModuleDef ownerModule) {
			var disOpts = new DisassemblerOptions(options.CancellationToken, ownerModule);
			if (options.DecompilerSettings.ShowILComments)
				disOpts.GetOpCodeDocumentation = GetOpCodeDocumentation;
			if (options.DecompilerSettings.ShowXmlDocumentation)
				disOpts.GetXmlDocComments = GetXmlDocComments;
			disOpts.CreateInstructionBytesReader = InstructionBytesReader.Create;
			disOpts.ShowTokenAndRvaComments = options.DecompilerSettings.ShowTokenAndRvaComments;
			disOpts.ShowILBytes = options.DecompilerSettings.ShowILBytes;
			disOpts.SortMembers = options.DecompilerSettings.SortMembers;
			return new ReflectionDisassembler(output, detectControlStructure, disOpts);
		}
Ejemplo n.º 9
0
		ReflectionDisassembler CreateReflectionDisassembler(ITextOutput output, DecompilationOptions options, ModuleDef ownerModule)
		{
			var disOpts = new DisassemblerOptions(options.CancellationToken, ownerModule);
			if (options.DecompilerSettings.ShowILComments)
				disOpts.GetOpCodeDocumentation = GetOpCodeDocumentation;
			if (options.DecompilerSettings.ShowXmlDocumentation)
				disOpts.GetXmlDocComments = GetXmlDocComments;
			disOpts.CreateInstructionBytesReader = InstructionBytesReader.Create;
			disOpts.ShowTokenAndRvaComments = options.DecompilerSettings.ShowTokenAndRvaComments;
			disOpts.ShowILBytes = options.DecompilerSettings.ShowILBytes;
			disOpts.SortMembers = options.DecompilerSettings.SortMembers;
			return new ReflectionDisassembler(output, detectControlStructure, disOpts);
		}
Ejemplo n.º 10
0
        ReflectionDisassembler CreateReflectionDisassembler(ITextOutput output, DecompilationOptions options, ModuleDef ownerModule)
        {
            var disOpts = new DisassemblerOptions(options.CancellationToken, ownerModule);

            if (options.DecompilerSettings.AddILComments)
            {
                disOpts.GetOpCodeDocumentation = GetOpCodeDocumentation;
            }
            if (options.DecompilerSettings.ShowXmlDocumentation)
            {
                disOpts.GetXmlDocComments = GetXmlDocComments;
            }
            return(new ReflectionDisassembler(output, detectControlStructure, disOpts));
        }
Ejemplo n.º 11
0
        ReflectionDisassembler CreateReflectionDisassembler(ITextOutput output, DecompilationContext ctx, ModuleDef ownerModule)
        {
            var disOpts = new DisassemblerOptions(ctx.CancellationToken, ownerModule);

            if (langSettings.Settings.ShowILComments)
            {
                disOpts.GetOpCodeDocumentation = ILLanguageHelper.GetOpCodeDocumentation;
            }
            if (langSettings.Settings.ShowXmlDocumentation)
            {
                disOpts.GetXmlDocComments = GetXmlDocComments;
            }
            disOpts.CreateInstructionBytesReader = m => InstructionBytesReader.Create(m, ctx.IsBodyModified != null && ctx.IsBodyModified(m));
            disOpts.ShowTokenAndRvaComments      = langSettings.Settings.ShowTokenAndRvaComments;
            disOpts.ShowILBytes = langSettings.Settings.ShowILBytes;
            disOpts.SortMembers = langSettings.Settings.SortMembers;
            return(new ReflectionDisassembler(output, detectControlStructure, disOpts));
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Disassembles a .JEF file into instructions and data.
        /// </summary>
        /// <param name="options">The options used to disassemble the file</param>
        /// <param name="logger">A logging implementation to log errors to.</param>
        public void Disassemble(DisassemblerOptions options, ILogger logger)
        {
            var stopwatch = new Stopwatch();

            var tasks = new List <Task <bool> >();

            stopwatch.Start();
            DisassembleFile(logger, options);
            stopwatch.Stop();

            if (tasks.Any(t => !t.Result))
            {
                logger.Log(LogLevel.Info, "Disassembly completed (with errors) in " + stopwatch.Elapsed.ToString());
            }
            else
            {
                logger.Log(LogLevel.Info, "Disassembly completed in " + stopwatch.Elapsed.ToString());
            }
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Runs the disassembler with the provided set of arguments.
        /// </summary>
        /// <param name="options">The options provided by the user.</param>
        private static int RunDisassembler(DisassemblerOptions options)
        {
            ILogger logger      = null;
            string  logFileName = options.LogFile;

            if (!string.IsNullOrEmpty(logFileName) && !string.IsNullOrWhiteSpace(logFileName))
            {
                logger = new HybridLogger(logFileName.Trim());
            }
            else
            {
                logger = new ConsoleLogger();
            }

            var disassembler = new Disassembler();

            disassembler.Disassemble(options, logger);
            return(0);
        }
Ejemplo n.º 14
0
        ReflectionDisassembler CreateReflectionDisassembler(IDecompilerOutput output, DecompilationContext ctx, ModuleDef ownerModule)
        {
            var disOpts = new DisassemblerOptions(langSettings.Settings.SettingsVersion, ctx.CancellationToken, ownerModule);

            if (langSettings.Settings.ShowILComments)
            {
                disOpts.GetOpCodeDocumentation = ILLanguageHelper.GetOpCodeDocumentation;
            }
            var sb = new StringBuilder();

            if (langSettings.Settings.ShowXmlDocumentation)
            {
                disOpts.GetXmlDocComments = a => GetXmlDocComments(a, sb);
            }
            disOpts.CreateInstructionBytesReader = m => InstructionBytesReader.Create(m, !(ctx.IsBodyModified is null) && ctx.IsBodyModified(m));
            disOpts.ShowTokenAndRvaComments      = langSettings.Settings.ShowTokenAndRvaComments;
            disOpts.ShowILBytes     = langSettings.Settings.ShowILBytes;
            disOpts.SortMembers     = langSettings.Settings.SortMembers;
            disOpts.ShowPdbInfo     = langSettings.Settings.ShowPdbInfo;
            disOpts.MaxStringLength = langSettings.Settings.MaxStringLength;
            return(new ReflectionDisassembler(output, detectControlStructure, disOpts));
        }
Ejemplo n.º 15
0
        private void BlocksListView_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ILView.Document.Blocks.Clear();

            var  options  = new DisassemblerOptions(new System.Threading.CancellationToken(), null);
            uint rva      = (uint)method.RVA;
            uint baseRva  = rva == 0 ? 0 : rva + method.Body.HeaderSize;
            long baseOffs = baseRva == 0 ? 0 : method.Module.ToFileOffset(baseRva) ?? 0;
            int  startLocation;

            foreach (var instr in cflowDeobfuscator.UnsolvedBlocks[BlocksListView.SelectedIndex].Block.Instructions)
            {
                instr.Instruction.WriteTo(ilOutput, options, baseRva, baseOffs, null, method, out startLocation);
                ilOutput.Write("\r", BoxedTextColor.Text);
            }

            ExprView.Document.Blocks.Clear();

            var expr = cflowDeobfuscator.UnsolvedBlocks[BlocksListView.SelectedIndex].Expression;

            exprOutput.Write(TextColor.String, expr.ToString());

            Consts.Items.Clear();

            GetConsts(expr);

            Consts.IsEnabled = true;

            if (Consts.Items.Count > 0)
            {
                Consts.SelectedIndex = 0;
            }
            else
            {
                Consts.IsEnabled = false;
            }
        }
Ejemplo n.º 16
0
        public static void WriteTo(this Instruction instruction, ITextOutput writer, DisassemblerOptions options, uint baseRva, long baseOffs, IInstructionBytesReader byteReader, MethodDef method)
        {
            if (options != null && (options.ShowTokenAndRvaComments || options.ShowILBytes)) {
                writer.Write("/* ", TextTokenType.Comment);

                bool needSpace = false;

                if (options.ShowTokenAndRvaComments) {
                    ulong fileOffset = (ulong)baseOffs + instruction.Offset;
                    writer.WriteReference(string.Format("0x{0:X8}", fileOffset), new AddressReference(options.OwnerModule == null ? null : options.OwnerModule.Location, false, fileOffset, (ulong)instruction.GetSize()), TextTokenType.Comment, false);
                    needSpace = true;
                }

                if (options.ShowILBytes) {
                    if (needSpace)
                        writer.Write(' ', TextTokenType.Comment);
                    if (byteReader == null)
                        writer.Write("??", TextTokenType.Comment);
                    else {
                        int size = instruction.GetSize();
                        for (int i = 0; i < size; i++) {
                            var b = byteReader.ReadByte();
                            if (b < 0)
                                writer.Write("??", TextTokenType.Comment);
                            else
                                writer.Write(string.Format("{0:X2}", b), TextTokenType.Comment);
                        }
                        // Most instructions should be at most 5 bytes in length, but use 6 since
                        // ldftn/ldvirtftn are 6 bytes long. The longest instructions are those with
                        // 8 byte operands, ldc.i8 and ldc.r8: 9 bytes.
                        const int MIN_BYTES = 6;
                        for (int i = size; i < MIN_BYTES; i++)
                            writer.Write("  ", TextTokenType.Comment);
                    }
                }

                writer.Write(" */", TextTokenType.Comment);
                writer.WriteSpace();
            }
            writer.WriteDefinition(DnlibExtensions.OffsetToString(instruction.GetOffset()), new InstructionReference(method, instruction), TextTokenType.Label, false);
            writer.Write(':', TextTokenType.Operator);
            writer.WriteSpace();
            writer.WriteReference(instruction.OpCode.Name, instruction.OpCode, TextTokenType.OpCode);
            if (instruction.Operand != null) {
                int count = OPERAND_ALIGNMENT - instruction.OpCode.Name.Length;
                if (count <= 0)
                    count = 1;
                writer.Write(spaces[count], TextTokenType.Text);
                if (instruction.OpCode == OpCodes.Ldtoken) {
                    var member = instruction.Operand as IMemberRef;
                    if (member != null && member.IsMethod) {
                        writer.Write("method", TextTokenType.Keyword);
                        writer.WriteSpace();
                    }
                    else if (member != null && member.IsField) {
                        writer.Write("field", TextTokenType.Keyword);
                        writer.WriteSpace();
                    }
                }
                WriteOperand(writer, instruction.Operand, method);
            }
            if (options != null && options.GetOpCodeDocumentation != null) {
                var doc = options.GetOpCodeDocumentation(instruction.OpCode);
                if (doc != null) {
                    writer.Write("\t", TextTokenType.Text);
                    writer.Write("// " + doc, TextTokenType.Comment);
                }
            }
        }
Ejemplo n.º 17
0
 ReflectionDisassembler CreateReflectionDisassembler(ITextOutput output, DecompilationContext ctx, ModuleDef ownerModule)
 {
     var disOpts = new DisassemblerOptions(ctx.CancellationToken, ownerModule);
     if (langSettings.Settings.ShowILComments)
         disOpts.GetOpCodeDocumentation = ILLanguageHelper.GetOpCodeDocumentation;
     if (langSettings.Settings.ShowXmlDocumentation)
         disOpts.GetXmlDocComments = GetXmlDocComments;
     disOpts.CreateInstructionBytesReader = m => InstructionBytesReader.Create(m, ctx.IsBodyModified != null && ctx.IsBodyModified(m));
     disOpts.ShowTokenAndRvaComments = langSettings.Settings.ShowTokenAndRvaComments;
     disOpts.ShowILBytes = langSettings.Settings.ShowILBytes;
     disOpts.SortMembers = langSettings.Settings.SortMembers;
     return new ReflectionDisassembler(output, detectControlStructure, disOpts);
 }
Ejemplo n.º 18
0
        public static void WriteTo(this Instruction instruction, ITextOutput writer, DisassemblerOptions options, uint baseRva, long baseOffs, IInstructionBytesReader byteReader, MethodDef method)
        {
            if (options != null && (options.ShowTokenAndRvaComments || options.ShowILBytes))
            {
                writer.Write("/* ", TextTokenType.Comment);

                bool needSpace = false;

                if (options.ShowTokenAndRvaComments)
                {
                    ulong fileOffset = (ulong)baseOffs + instruction.Offset;
                    writer.WriteReference(string.Format("0x{0:X8}", fileOffset), new AddressReference(options.OwnerModule == null ? null : options.OwnerModule.Location, false, fileOffset, (ulong)instruction.GetSize()), TextTokenType.Comment, false);
                    needSpace = true;
                }

                if (options.ShowILBytes)
                {
                    if (needSpace)
                    {
                        writer.Write(' ', TextTokenType.Comment);
                    }
                    if (byteReader == null)
                    {
                        writer.Write("??", TextTokenType.Comment);
                    }
                    else
                    {
                        int size = instruction.GetSize();
                        for (int i = 0; i < size; i++)
                        {
                            var b = byteReader.ReadByte();
                            if (b < 0)
                            {
                                writer.Write("??", TextTokenType.Comment);
                            }
                            else
                            {
                                writer.Write(string.Format("{0:X2}", b), TextTokenType.Comment);
                            }
                        }
                        // Most instructions should be at most 5 bytes in length, but use 6 since
                        // ldftn/ldvirtftn are 6 bytes long. The longest instructions are those with
                        // 8 byte operands, ldc.i8 and ldc.r8: 9 bytes.
                        const int MIN_BYTES = 6;
                        for (int i = size; i < MIN_BYTES; i++)
                        {
                            writer.Write("  ", TextTokenType.Comment);
                        }
                    }
                }

                writer.Write(" */", TextTokenType.Comment);
                writer.WriteSpace();
            }
            writer.WriteDefinition(DnlibExtensions.OffsetToString(instruction.GetOffset()), new InstructionReference(method, instruction), TextTokenType.Label, false);
            writer.Write(':', TextTokenType.Operator);
            writer.WriteSpace();
            writer.WriteReference(instruction.OpCode.Name, instruction.OpCode, TextTokenType.OpCode);
            if (instruction.Operand != null)
            {
                int count = OPERAND_ALIGNMENT - instruction.OpCode.Name.Length;
                if (count <= 0)
                {
                    count = 1;
                }
                writer.Write(spaces[count], TextTokenType.Text);
                if (instruction.OpCode == OpCodes.Ldtoken)
                {
                    var member = instruction.Operand as IMemberRef;
                    if (member != null && member.IsMethod)
                    {
                        writer.Write("method", TextTokenType.Keyword);
                        writer.WriteSpace();
                    }
                    else if (member != null && member.IsField)
                    {
                        writer.Write("field", TextTokenType.Keyword);
                        writer.WriteSpace();
                    }
                }
                WriteOperand(writer, instruction.Operand, method);
            }
            if (options != null && options.GetOpCodeDocumentation != null)
            {
                var doc = options.GetOpCodeDocumentation(instruction.OpCode);
                if (doc != null)
                {
                    writer.Write("\t", TextTokenType.Text);
                    writer.Write("// " + doc, TextTokenType.Comment);
                }
            }
        }
Ejemplo n.º 19
0
 /// <summary>Set the options for the disassembly</summary>
 /// <param name="options">Options</param>
 /// <returns><see langword="true"/> if the options are all supported</returns>
 public bool SetOptions(DisassemblerOptions options)
 {
     return(LLVMSetDisasmOptions(DisasmHandle, ( ulong )options));
 }