public ThumbDisassembler(ImageReader rdr) { this.rdr = rdr; this.dasm = CapstoneDisassembler.CreateArmDisassembler(DisassembleMode.ArmThumb); dasm.EnableDetails = true; this.stream = dasm.DisassembleStream( rdr.Bytes, (int)rdr.Offset, (long)(rdr.Address.ToLinear())) .GetEnumerator(); }
public Arm32Disassembler(Arm32ProcessorArchitecture arch, EndianImageReader rdr) { var dasm = CapstoneDisassembler.CreateArmDisassembler( DisassembleMode.Arm32 | DisassembleMode.LittleEndian); dasm.EnableDetails = true; this.stream = dasm.DisassembleStream( rdr.Bytes, (int)rdr.Offset, (long)rdr.Address.ToLinear() - rdr.Offset) .GetEnumerator(); }
internal static void ShowArm(DisassembleMode mode) { // Create ARM Disassembler. // // Creating the disassembler in a "using" statement ensures that resources get cleaned up automatically // when it is no longer needed. using (var disassembler = CapstoneDisassembler.CreateArmDisassembler(mode)) { // Enable Disassemble Details. // // Enables disassemble details, which are disabled by default, to provide more detailed information on // disassembled binary code. disassembler.EnableDetails = true; // Set Disassembler's Syntax. // // Make the disassembler generate instructions in Intel syntax. disassembler.Syntax = DisassembleSyntaxOptionValue.Intel; var code = new byte[0]; switch (mode) { case DisassembleMode.Arm32: code = new byte[] { 0xED, 0xFF, 0xFF, 0xEB, 0x04, 0xe0, 0x2d, 0xe5, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x83, 0x22, 0xe5, 0xf1, 0x02, 0x03, 0x0e, 0x00, 0x00, 0xa0, 0xe3, 0x02, 0x30, 0xc1, 0xe7, 0x00, 0x00, 0x53, 0xe3, 0x00, 0x02, 0x01, 0xf1, 0x05, 0x40, 0xd0, 0xe8, 0xf4, 0x80, 0x00, 0x00 }; break; case (int)DisassembleMode.Arm32 + DisassembleMode.ArmV8: code = new byte[] { 0xe0, 0x3b, 0xb2, 0xee, 0x42, 0x00, 0x01, 0xe1, 0x51, 0xf0, 0x7f, 0xf5 }; break; case DisassembleMode.ArmThumb: code = new byte[] { 0x70, 0x47, 0xeb, 0x46, 0x83, 0xb0, 0xc9, 0x68, 0x1f, 0xb1, 0x30, 0xbf, 0xaf, 0xf3, 0x20, 0x84 }; break; case DisassembleMode.ArmThumbArmCortexM: code = new byte[] { 0xef, 0xf3, 0x02, 0x80 }; break; } // Disassemble All Binary Code. // // ... var instructions = disassembler.DisassembleAll(code); var hexCode = BitConverter.ToString(code).Replace("-", " "); Console.WriteLine(hexCode); Console.WriteLine(); // Loop Through Each Disassembled Instruction. // ... foreach (var instruction in instructions) { Console.WriteLine("{0:X}: \t {1} \t {2}", instruction.Address, instruction.Mnemonic, instruction.Operand); Console.WriteLine("\t Id = {0}", instruction.Id); if (instruction.ArchitectureDetail != null) { Console.WriteLine("\t CPS Flag = {0}", instruction.ArchitectureDetail.CpsFlag); Console.WriteLine("\t CPS Mode = {0}", instruction.ArchitectureDetail.CpsMode); Console.WriteLine("\t Code Condition = {0}", instruction.ArchitectureDetail.CodeCondition); Console.WriteLine("\t Load User Mode Registers? {0}", instruction.ArchitectureDetail.LoadUserModeRegisters); Console.WriteLine("\t Memory Barrier = {0}", instruction.ArchitectureDetail.MemoryBarrier); Console.WriteLine("\t Operand Count: {0}", instruction.ArchitectureDetail.Operands.Length); // Loop Through Each Instruction's Operands. // // ... foreach (var operand in instruction.ArchitectureDetail.Operands) { string operandValue = null; switch (operand.Type) { case ArmInstructionOperandType.CImmediate: operandValue = operand.ImmediateValue.Value.ToString("X"); break; case ArmInstructionOperandType.FloatingPoint: operandValue = operand.FloatingPointValue.Value.ToString(); break; case ArmInstructionOperandType.Immediate: operandValue = operand.ImmediateValue.Value.ToString("X"); break; case ArmInstructionOperandType.PImmediate: operandValue = operand.ImmediateValue.Value.ToString("X"); break; case ArmInstructionOperandType.Memory: operandValue = "-->"; break; case ArmInstructionOperandType.Register: operandValue = operand.RegisterValue.Value.ToString(); break; case ArmInstructionOperandType.SetEnd: operandValue = operand.SetEndValue.Value.ToString(); break; case ArmInstructionOperandType.SysRegister: operandValue = operand.SysRegisterValue.Value.ToString(); break; } Console.WriteLine("\t\t {0} = {1}", operand.Type, operandValue); // Handle Memory Operand. // // ... if (operand.Type == ArmInstructionOperandType.Memory) { Console.WriteLine("\t\t\t Base Register = {0} ", operand.MemoryValue.BaseRegister); Console.WriteLine("\t\t\t Displacement = {0:X} ", operand.MemoryValue.Displacement); Console.WriteLine("\t\t\t Index Register = {0} ", operand.MemoryValue.IndexRegister); Console.WriteLine("\t\t\t Index Register Scale = {0} ", operand.MemoryValue.IndexRegisterScale); Console.WriteLine(); } Console.WriteLine("\t\t\t Is Subtracted? = {0}", operand.IsSubtracted); Console.WriteLine("\t\t\t Shifter = -->"); Console.WriteLine("\t\t\t\t Type = {0}", operand.Shifter.Type); Console.WriteLine("\t\t\t\t Value = {0:X}", operand.Shifter.Value); Console.WriteLine("\t\t\t Vector Index = {0}", operand.VectorIndex); } Console.WriteLine("\t Update Flags? {0}", instruction.ArchitectureDetail.UpdateFlags); Console.WriteLine("\t Vector Data Type = {0}", instruction.ArchitectureDetail.VectorDataType); Console.WriteLine("\t Vector Size= {0}", instruction.ArchitectureDetail.VectorSize); Console.WriteLine("\t Write Back? {0}", instruction.ArchitectureDetail.WriteBack); } Console.WriteLine(); } } }
private void ReloadListButton_Click(object sender, EventArgs e) { ArmDisassembleMode disassembleMode = ArmDisassembleMode.Arm; if (thumb.Checked) { disassembleMode = ArmDisassembleMode.Thumb; } uint addr = (uint)ReadStartAddress.Value; if ((addr & 1) == 1) { disassembleMode = ArmDisassembleMode.Thumb; addr--; } if (addr >= GBAMemory.ROM_ADDR) { addr -= GBAMemory.ROM_ADDR; U.ForceUpdate(ReadStartAddress, addr); } if (addr >= (uint)Program.ROM.Data.Length) { return; } int count = (int)ReadCount.Value; if (count == 0) { count = 1; U.ForceUpdate(ReadCount, count); } assembly.Clear(); using (CapstoneArmDisassembler disassembler = CapstoneDisassembler.CreateArmDisassembler(disassembleMode)) { disassembler.DisassembleSyntax = DisassembleSyntax.Intel; if (syntax_att.Checked) { disassembler.DisassembleSyntax = DisassembleSyntax.Att; } if (syntax_msam.Checked) { disassembler.DisassembleSyntax = DisassembleSyntax.Masm; } // ... // // By enabling Skip Data Mode, we let Capstone will automatically skip over data and continue // disassembling at the next valid instruction it finds. if (skip_data.Checked) { disassembler.EnableSkipDataMode = true; } ArmInstruction[] instructions = disassembler.Disassemble(Program.ROM.Data.Skip((int)addr).ToArray(), GBAMemory.ROM_ADDR + addr, count); foreach (ArmInstruction instruction in instructions) { if (!instruction.IsSkippedData) { var address = instruction.Address; ArmInstructionId id = instruction.Id; if (!instruction.IsDietModeEnabled) { // ... // // An instruction's mnemonic and operand text are only available when Diet Mode is disabled. // An exception is thrown otherwise! var mnemonic = instruction.Mnemonic; var operand = instruction.Operand; assembly.AppendText(string.Format("/* {0:X} */ \t {1} \t {2}", address, mnemonic, operand)); } assembly.AppendText(System.Environment.NewLine); } } } return; }
public static AnalyzedFile Analyze(string FilePath, string AsmPath = null) { PeFile File = new PeFile(FilePath); SortedList <UInt32, ArmInstruction> AnalyzedCode = new SortedList <uint, ArmInstruction>(0x1000000); // Default capacity of 0x100000 was not enough for analyzing ntoskrnl.exe if ((AsmPath != null) && System.IO.File.Exists(AsmPath)) { using (StreamReader Reader = new StreamReader(AsmPath)) { while (Reader.Peek() >= 0) { ArmInstruction Instruction = new ArmInstruction(Reader.ReadLine()); AnalyzedCode.Add(Instruction.Address, Instruction); } } } else { CapstoneDisassembler <Gee.External.Capstone.Arm.ArmInstruction, ArmRegister, ArmInstructionGroup, ArmInstructionDetail> Disassembler = CapstoneDisassembler.CreateArmDisassembler(DisassembleMode.ArmThumb); // Initially use a Dictionary and sort it afterwards. For analyzing ntoskrnl.exe this is about 60 times faster than using a SortedList from the start. // Default capacity of 0x100000 was not enough for analyzing ntoskrnl.exe Dictionary <UInt32, ArmInstruction> TempCode = new Dictionary <uint, ArmInstruction>(0x1000000); // Analyze from entrypoint Analyze(Disassembler, File.Sections, TempCode, (UInt32)(File.ImageBase + File.EntryPoint)); // Analyze from exports foreach (FunctionDescriptor Function in File.Exports) { Analyze(Disassembler, File.Sections, TempCode, (UInt32)(Function.VirtualAddress)); } // Analyze from imports foreach (FunctionDescriptor Function in File.Imports) { Analyze(Disassembler, File.Sections, TempCode, (UInt32)(Function.VirtualAddress)); } // Analyze from runtime-functions foreach (FunctionDescriptor Function in File.RuntimeFunctions) { Analyze(Disassembler, File.Sections, TempCode, (UInt32)(Function.VirtualAddress)); } // Sort the instructions. // SortedList is used, because it can be indexed by value (not only by key). List <UInt32> Keys = TempCode.Keys.ToList(); Keys.Sort(); foreach (UInt32 Key in Keys) { AnalyzedCode.Add(Key, TempCode[Key]); } if (AsmPath != null) { System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(AsmPath)); using (StreamWriter Writer = new StreamWriter(AsmPath, false)) { for (int i = 0; i < AnalyzedCode.Count; i++) { Writer.WriteLine(AnalyzedCode.Values[i].ToString()); } } } } return(new AnalyzedFile() { File = File, Code = AnalyzedCode }); }