private byte[] GetOldCode(IntPtr codeAddress, int maxBytes) { SharpDisasm.ArchitectureMode mode = (IntPtr.Size == 8) ? SharpDisasm.ArchitectureMode.x86_64 : SharpDisasm.ArchitectureMode.x86_32; List <byte> entranceCodes = new List <byte>(); int totalLen = 0; using (var disasm = new SharpDisasm.Disassembler(codeAddress, maxBytes + NativeMethods.MaxLengthOpCode, mode)) { foreach (var insn in disasm.Disassemble()) { if (SharpDisasm.Udis86.ud_mnemonic_code.UD_Ija <= insn.Mnemonic && insn.Mnemonic <= SharpDisasm.Udis86.ud_mnemonic_code.UD_Ijz) { return(null); } for (int i = 0; i < insn.Length; i++) { entranceCodes.Add(codeAddress.ReadByte(totalLen + i)); } totalLen += insn.Length; if (totalLen >= maxBytes) { return(entranceCodes.ToArray()); } } } return(null); }
private void LoadNewCode(UInt64 Addr, UInt64 len) { // Refresh Disasm view this.dtSet.Tables[1].Rows.Clear(); this.Code = Commands.ps4ninja_read_proc_mem(this.PID, Addr, len, this.Client); // Configure the translator to output instruction addresses and instruction binary as hex SharpDisasm.Disassembler.Translator.IncludeAddress = false; SharpDisasm.Disassembler.Translator.IncludeBinary = false; // Create the disassembler var disasm = new SharpDisasm.Disassembler(this.Code, SharpDisasm.ArchitectureMode.x86_64, Addr, true); for (int i = 0; ; i++) { try { System.Data.DataRow dr = this.dtSet.Tables[1].NewRow(); SharpDisasm.Instruction insn = disasm.NextInstruction(); dr["Address"] = string.Format("{0:X16}", insn.Offset); dr["ASM"] = insn.ToString(); this.dtSet.Tables[1].Rows.Add(dr); } catch (Exception) { break; } } dataGridView2.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells); }
private static void Disassemble(string input, int architecture, bool includeAddress, bool includeBinary, ListView listView) { SharpDisasm.ArchitectureMode mode = SharpDisasm.ArchitectureMode.x86_32; switch(architecture) { case 0: mode = SharpDisasm.ArchitectureMode.x86_16; break; case 1: mode = SharpDisasm.ArchitectureMode.x86_32; break; case 2: mode = SharpDisasm.ArchitectureMode.x86_64; break; } SharpDisasm.Disassembler.Translator.IncludeAddress = includeAddress; SharpDisasm.Disassembler.Translator.IncludeBinary = includeBinary; try { var disasm = new SharpDisasm.Disassembler(HexStringToByteArray(input.ToString().Replace(" ", "").Replace("\n", "")), mode, 0, true); foreach (var insn in disasm.Disassemble()) { listView.Items.Add(insn.ToString()); } } catch(Exception ex) { ErrorMessage(ex.Message, false); } }
static void Main(string[] args) { // Determine the architecture mode or us 32-bit by default SharpDisasm.ArchitectureMode mode = SharpDisasm.ArchitectureMode.x86_32; if (args.Length > 0) { switch (args[0]) { case "16": { mode = SharpDisasm.ArchitectureMode.x86_16; break; } case "32": { mode = SharpDisasm.ArchitectureMode.x86_32; break; } case "64": { mode = SharpDisasm.ArchitectureMode.x86_64; break; } default: break; } } // Allow input >256 chars Console.SetIn(new StreamReader(Console.OpenStandardInput(8192))); StringBuilder input = new StringBuilder(); while (Console.In.Peek() != -1) { input.Append(Console.In.ReadLine()); } // Configure the translator to output instruction addresses and instruction binary as hex SharpDisasm.Disassembler.Translator.IncludeAddress = true; SharpDisasm.Disassembler.Translator.IncludeBinary = true; // Create the disassembler var disasm = new SharpDisasm.Disassembler( HexStringToByteArray(input.ToString().Replace(" ", "")), mode, 0, true); // Disassemble each instruction and output to console foreach (var insn in disasm.Disassemble()) Console.Out.WriteLine(insn.ToString()); }
public void DisassembleTests() { var disasm = new SharpDisasm.Disassembler(new byte[] { 0xA1, 0xC9, 0xFD, 0xFF, 0xFF, // mov eax,[0xfffffdc9] (or ds:0xfffffdc9) 0xA1, 0x37, 0x02, 0x00, 0x00, // mov eax,[0x237] (or ds:0x237) 0xB8, 0x37, 0x02, 0x00, 0x00, // mov eax,0x237 0xB4, 0x09, // mov ah,0x9 0x8B, 0x04, 0x6D, 0x85, 0xFF, 0xFF, 0xFF, // mov eax, [ebp*2-0x7b] }, ArchitectureMode.x86_32, 0, false); Assert.AreEqual((long)-0x7b, disasm.Disassemble().Last().Operands.Last().Value); foreach (var ins in disasm.Disassemble()) { Debug.WriteLine(ins.ToString()); } disasm = new SharpDisasm.Disassembler(new byte[] { 0x67, 0x66, 0x03, 0x07, // add ax, [bx] 0x66, 0xB8, 0xF7, 0xFF, // mov ax, 0xfff7 (or -0x9) }, ArchitectureMode.x86_64, 0, false); Assert.AreEqual((long)-9, disasm.Disassemble().Last().Operands.Last().Value); foreach (var ins in disasm.Disassemble()) { Debug.WriteLine(ins.ToString()); } }
public void DisassemblerPrintATTSyntaxBound() { var disasm = new SharpDisasm.Disassembler(new byte[] { 0x62, 0x05, 0x01, 0x00, 0x00, 0x00 }, ArchitectureMode.x86_32, 0, true); var boundInstr = disasm.Disassemble().First(); Assert.IsTrue(boundInstr.ToString().Contains("bound")); }
/// <summary> /// Disassembles opcodes into the associated instructions. Takes a byte array containing opcodes, a MachineType of I386 or x64, /// an instance of the ERC_Core object and returns an ERC_Result containing associated instructions. /// </summary> /// <param name="opcodes">A byte array containing opcodes to be disassembled</param> /// <param name="machineType">a ERC.MachineType of either I386 or x64</param> /// <returns>Returns an ERC_Result containing associated instructions.</returns> public static ErcResult <string> Disassemble(byte[] opcodes, MachineType machineType) { ErcResult <string> result = new ErcResult <string>(new ErcCore()); SharpDisasm.Disassembler.Translator.IncludeAddress = true; SharpDisasm.Disassembler.Translator.IncludeBinary = true; SharpDisasm.Disassembler disasm; SharpDisasm.ArchitectureMode mode; try { if (machineType == MachineType.I386) { mode = SharpDisasm.ArchitectureMode.x86_32; } else if (machineType == MachineType.x64) { mode = SharpDisasm.ArchitectureMode.x86_64; } else { throw new ERCException("User input error: Machine Type is invalid, must be ERC.MachineType.x86_64 or ERC.MachineType.x86_32"); } } catch (ERCException e) { result.Error = e; result.LogEvent(); return(result); } try { disasm = new SharpDisasm.Disassembler( HexStringToByteArray(BitConverter.ToString(opcodes).Replace("-", "")), mode, 0, true); } catch (Exception e) { result.Error = e; result.LogEvent(e); return(result); } foreach (var insn in disasm.Disassemble()) { var mne = insn.ToString().Split(new string[] { " " }, StringSplitOptions.None); result.ReturnValue += mne[mne.Length - 1].Trim() + Environment.NewLine; } return(result); }
public void DisassemblerPrintIntelUnexpectedPrefix() { var disasm = new SharpDisasm.Disassembler(new byte[] { 0x2e, // cs prefix has no meaning in 'outsd' context 0x6f // outsd }, ArchitectureMode.x86_64, 0, true); var results = disasm.Disassemble().ToArray(); foreach (var ins in results) { Debug.WriteLine(ins.ToString()); } }
public void DisassembleInvalidInstruction() { var disasm = new SharpDisasm.Disassembler(new byte[] { 0xA1, 0x37 }, ArchitectureMode.x86_32, 0, false); Assert.AreEqual(disasm.Disassemble().Last().Mnemonic, Udis86.ud_mnemonic_code.UD_Iinvalid); foreach (var ins in disasm.Disassemble()) { Assert.IsTrue(ins.Error); Debug.WriteLine(ins.ToString()); } }
static void Main(string[] args) { // Determine the architecture mode or us 32-bit by default SharpDisasm.ArchitectureMode mode = SharpDisasm.ArchitectureMode.x86_32; if (args.Length > 0) { switch (args[0]) { case "16": { mode = SharpDisasm.ArchitectureMode.x86_16; break; } case "32": { mode = SharpDisasm.ArchitectureMode.x86_32; break; } case "64": { mode = SharpDisasm.ArchitectureMode.x86_64; break; } default: break; } if (args.Length > 1) { if (args[1].ToLower() == "resolverip") { SharpDisasm.Disassembler.Translator.ResolveRip = true; } } } // Allow input >256 chars Console.SetIn(new StreamReader(Console.OpenStandardInput(8192))); StringBuilder input = new StringBuilder(); while (Console.In.Peek() != -1) { input.Append(Console.In.ReadLine()); } // Configure the translator to output instruction addresses and instruction binary as hex SharpDisasm.Disassembler.Translator.IncludeAddress = true; SharpDisasm.Disassembler.Translator.IncludeBinary = true; // Create the disassembler var disasm = new SharpDisasm.Disassembler( HexStringToByteArray(input.ToString().Replace(" ", "")), mode, 0, true); // Disassemble each instruction and output to console foreach (var insn in disasm.Disassemble()) { Console.Out.WriteLine(insn.ToString()); } }
static IntPtr GetExportFunctionPtrInfo(IntPtr funcAddr, out IntPtr ptrContainingFuncAddress) { ptrContainingFuncAddress = IntPtr.Zero; SharpDisasm.ArchitectureMode mode = (IntPtr.Size == 8) ? SharpDisasm.ArchitectureMode.x86_64 : SharpDisasm.ArchitectureMode.x86_32; SharpDisasm.Disassembler.Translator.IncludeAddress = true; SharpDisasm.Disassembler.Translator.IncludeBinary = true; const int maxOpCode = 5; byte[] code = funcAddr.ReadBytes(NativeMethods.MaxLengthOpCode * maxOpCode); var disasm = new SharpDisasm.Disassembler(code, mode, (ulong)funcAddr.ToInt64(), true); foreach (var insn in disasm.Disassemble().Take(maxOpCode)) { switch (insn.Mnemonic) { case SharpDisasm.Udis86.ud_mnemonic_code.UD_Imov: if (insn.Operands.Length == 2) { long value = insn.Operands[1].Value; IntPtr jumpPtr = new IntPtr(value); ptrContainingFuncAddress = jumpPtr; return(new IntPtr(IntPtr.Size == 8 ? jumpPtr.ReadInt64() : jumpPtr.ReadInt32())); } break; case SharpDisasm.Udis86.ud_mnemonic_code.UD_Ijmp: // 48 FF 25 C1 D2 05 00 jmp qword ptr [7FFD2E8B7398h] if (insn.Operands.Length == 1) { long value = insn.Operands[0].Value; IntPtr jumpPtr = new IntPtr(value); if (IntPtr.Size == 8) { jumpPtr = new IntPtr((long)insn.PC + value); } ptrContainingFuncAddress = jumpPtr; return(new IntPtr(IntPtr.Size == 8 ? jumpPtr.ReadInt64() : jumpPtr.ReadInt32())); } break; } } return(IntPtr.Zero); }
public void DisassembleBytesDecoded() { var disasm = new SharpDisasm.Disassembler(new byte[] { 0x00, 0x00, // add [eax], al 0x00, 0x67, // invalid }, ArchitectureMode.x86_32, 0, false); foreach (SharpDisasm.Instruction instruction in disasm.Disassemble()) { Assert.IsTrue(instruction.Length > 0); } // Only 1 valid instruction is read that is 2 bytes long // The final 2 bytes are discarded as an invalid instruction Assert.AreEqual(2, disasm.BytesDecoded); }
public void Disassemble64BitRIPRelative() { var disasm = new SharpDisasm.Disassembler(new byte[] { 0x48, 0x8B, 0x05, 0xF7, 0xFF, 0xFF, 0xFF, // mov rax, [rip-0x9] }, ArchitectureMode.x86_64, 0, true); Assert.AreEqual((long)-9, disasm.Disassemble().Last().Operands.Last().Value); Assert.AreEqual("mov rax, [rip-0x9]", disasm.Disassemble().First().ToString()); Disassembler.Translator.IncludeAddress = true; Disassembler.Translator.IncludeBinary = true; foreach (var ins in disasm.Disassemble()) { Debug.WriteLine(ins.ToString()); } }
public void DisassembleScaleIndexBaseTests() { var disasm = new SharpDisasm.Disassembler(new byte[] { 0x8B, 0x04, 0xAA, // mov eax, [edx+ebp*4] 0x8B, 0x44, 0x15, 0x00, // mov eax, [ebp+edx] 0x8B, 0x04, 0x2A, // mov eax, [edx+ebp] 0x8B, 0x45, 0x00, // mov eax, [ebp] 0x8B, 0x04, 0x6D, 0x00, 0x00, 0x00, 0x00, // mov eax, [ebp*2] 0x8B, 0x44, 0x2A, 0x85, // mov eax, [edx+ebp-0x7b] }, ArchitectureMode.x86_32, 0, false); var results = disasm.Disassemble().ToArray(); // mov eax, [edx+ebp*4] Assert.AreEqual(4, results[0].Operands.Last().Scale); Assert.AreEqual(Udis86.ud_type.UD_R_EAX, results[0].Operands.First().Base); Assert.AreEqual(Udis86.ud_type.UD_R_EDX, results[0].Operands.Last().Base); Assert.AreEqual(Udis86.ud_type.UD_R_EBP, results[0].Operands.Last().Index); // mov eax, [ebp+edx] Assert.AreEqual(Udis86.ud_type.UD_R_EBP, results[1].Operands.Last().Base); Assert.AreEqual(Udis86.ud_type.UD_R_EDX, results[1].Operands.Last().Index); // mov eax, [edx+ebp] Assert.AreEqual(Udis86.ud_type.UD_R_EDX, results[2].Operands.Last().Base); Assert.AreEqual(Udis86.ud_type.UD_R_EBP, results[2].Operands.Last().Index); // mov eax, [ebp] Assert.AreEqual(Udis86.ud_type.UD_R_EBP, results[3].Operands.Last().Base); // mov eax, [ebp*2] Assert.AreEqual(Udis86.ud_type.UD_NONE, results[4].Operands.Last().Base); Assert.AreEqual(Udis86.ud_type.UD_R_EBP, results[4].Operands.Last().Index); Assert.AreEqual(2, results[4].Operands.Last().Scale); // mov eax, [edx+ebp-0x7b] Assert.AreEqual(Udis86.ud_type.UD_R_EDX, results[5].Operands.Last().Base); Assert.AreEqual(Udis86.ud_type.UD_R_EBP, results[5].Operands.Last().Index); Assert.AreEqual((long)-0x7b, results[5].Operands.Last().Value); foreach (var ins in disasm.Disassemble()) { Debug.WriteLine(ins.ToString()); } }
static void Main(string[] args) { SharpDisasm.ArchitectureMode mode = SharpDisasm.ArchitectureMode.x86_32; if (args.Length == 2) { switch (args[0]) { case "16": { mode = SharpDisasm.ArchitectureMode.x86_16; break; } case "32": { mode = SharpDisasm.ArchitectureMode.x86_32; break; } case "64": { mode = SharpDisasm.ArchitectureMode.x86_64; break; } default: break; } } else { Console.Write("Must use arguments: <bit-length[16|32|64]> <target file path>"); return; } string filePath = args[1]; BinaryReader reader = new BinaryReader(File.Open(filePath, FileMode.Open)); var fileSize = Convert.ToInt32(new FileInfo(filePath).Length); var codeBytes = reader.ReadBytes(fileSize); var sw = Stopwatch.StartNew(); SharpDisasm.Disassembler.Translator.IncludeAddress = true; var disasm = new SharpDisasm.Disassembler(codeBytes, mode, 0, true); foreach (var insn in disasm.Disassemble()) { Console.Out.WriteLine(insn.ToString()); } sw.Stop(); Console.Error.WriteLine("Total dump time: {0:F} sec.", sw.Elapsed.TotalSeconds); }
private static IntPtr GetOperandOffset(IntPtr address, MatchType matchType) { var buffer = new byte[100]; IntPtr bytesRead = IntPtr.Zero, result = IntPtr.Zero; if (!ReadProcessMemory(GetCurrentProcess(), address, buffer, buffer.Length, out bytesRead)) { throw GetWin32Exception("ReadProcessMemory()"); } var offset = address.ToInt64(); var disasm = new SharpDisasm.Disassembler(buffer, SharpDisasm.ArchitectureMode.x86_64, 0, true); foreach (var insn in disasm.Disassemble()) { offset += insn.Length; if (matchType == MatchType.MATCH_CALL_OR_JMP && insn.Mnemonic == ud_mnemonic_code.UD_Ijmp) { result = new IntPtr(offset + insn.Operands[0].Value); break; } else if (matchType == MatchType.MATCH_MOV_ECX && insn.Mnemonic == ud_mnemonic_code.UD_Imov) { if (insn.Operands[1].Base == ud_type.UD_R_ECX) { result = new IntPtr(offset + insn.Operands[0].Value); break; } } if (insn.Mnemonic == ud_mnemonic_code.UD_Iint3) { break; } } return(result); }
public void DisassembleBufferOffset() { byte[] b = new byte[] { }; var disasm = new SharpDisasm.Disassembler(new byte[] { 0x67, 0x66, 0x8b, 0x40, 0xf0 // mov ax, [eax-0x10] , 0x67, 0x66, 0x03, 0x5e, 0x10 // add bx, [esi+0x10] , 0x48, 0x03, 0x04, 0x25, 0xff, 0xff, 0x00, 0x00 // add rax, [0xffff] , 0x67, 0x66, 0x03, 0x44, 0xbe, 0xf0 // add ax, [esi+edi*4-0x10] , 0x4c, 0x03, 0x84, 0x98, 0x00, 0x00, 0x00, 0x80 // add r8, [rax+rbx*4-0x80000000] , 0x48, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00 // mov rax, [0x800000000000] }, ArchitectureMode.x86_64, 0x10000, false); var result = disasm.Disassemble().ToArray(); Assert.AreEqual((ulong)0x10000, (ulong)disasm.Disassemble().First().Offset); foreach (var ins in disasm.Disassemble()) { Assert.IsFalse(ins.Error); Debug.WriteLine(ins.ToString()); } }
public void DisassembleBufferTest() { var code = new byte[] { 0x67, 0x66, 0x8b, 0x40, 0xf0 // mov ax, [eax-0x10] , 0x67, 0x66, 0x03, 0x5e, 0x10 // add bx, [esi+0x10] , 0x48, 0x03, 0x04, 0x25, 0xff, 0xff, 0x00, 0x00 // add rax, [0xffff] , 0x67, 0x66, 0x03, 0x44, 0xbe, 0xf0 // add ax, [esi+edi*4-0x10] , 0x4c, 0x03, 0x84, 0x98, 0x00, 0x00, 0x00, 0x80 // add r8, [rax+rbx*4-0x80000000] , 0x48, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00 // mov rax, [0x800000000000] }; var disasm = new SharpDisasm.Disassembler(code, ArchitectureMode.x86_64, 0, false); var results = disasm.Disassemble().ToArray(); Assert.AreEqual(6, results.Length, "There should be 6 instructions"); Assert.AreEqual(4, (from insn in results where insn.Length > 5 select insn).Count(), "There should be 4 instructions that are larger than 5 bytes"); Assert.AreEqual("mov rax, [0x800000000000]", (from insn in results where insn.Length == 10 select insn).First().ToString()); foreach (SharpDisasm.Instruction instruction in results) { Assert.IsFalse(instruction.Error); Assert.IsTrue(instruction.Length > 0); } Assert.AreEqual(code.Length, disasm.BytesDecoded); foreach (var ins in results) { Debug.WriteLine(ins.ToString()); } }
private static void OutputAssembly(byte[] codeBuffer, string fileName) { SharpDisasm.ArchitectureMode mode = SharpDisasm.ArchitectureMode.x86_32; // Configure the translator to output instruction addresses and instruction binary as hex SharpDisasm.Disassembler.Translator.IncludeAddress = true; SharpDisasm.Disassembler.Translator.IncludeBinary = true; // Create the disassembler var disasm = new SharpDisasm.Disassembler( codeBuffer, mode, 0, true); int instructions = 0; using (System.IO.StreamWriter file = new System.IO.StreamWriter(fileName)) { List <string> jumpInstructions = new List <string>(); // Disassemble each instruction and output to console foreach (var insn in disasm.Disassemble()) { file.WriteLine(insn.ToString()); instructions++; } } }
public void DisassemblerPrintIntelSyntax() { var disasm = new SharpDisasm.Disassembler(new byte[] { 0x48, 0x8B, 0x05, 0xF7, 0xFF, 0xFF, 0xFF, // mov rax, [rip-0x9] 0x67, 0x66, 0x8b, 0x40, 0xf0 // mov ax, [eax-0x10] , 0x67, 0x66, 0x03, 0x5e, 0x10 // add bx, [esi+0x10] , 0x48, 0x03, 0x04, 0x25, 0xff, 0xff, 0x00, 0x00 // add rax, [0xffff] , 0x67, 0x66, 0x03, 0x44, 0xbe, 0xf0 // add ax, [esi+edi*4-0x10] , 0x4c, 0x03, 0x84, 0x98, 0x00, 0x00, 0x00, 0x80 // add r8, [rax+rbx*4-0x80000000] , 0x48, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00 // mov rax, [0x800000000000] }, ArchitectureMode.x86_64, 0, true); var results = disasm.Disassemble().ToArray(); foreach (var ins in results) { Debug.WriteLine(ins.ToString()); } Debug.WriteLine("-------------------"); disasm = new SharpDisasm.Disassembler(new byte[] { 0xA1, 0xC9, 0xFD, 0xFF, 0xFF, // mov eax,[0xfffffdc9] (or ds:0xfffffdc9) 0xA1, 0x37, 0x02, 0x00, 0x00, // mov eax,[0x237] (or ds:0x237) 0xB8, 0x37, 0x02, 0x00, 0x00, // mov eax,0x237 0xB4, 0x09, // mov ah,0x9 0x8A, 0x25, 0x09, 0x00, 0x00, 0x00, // mov ah,[0x9] 0x8B, 0x04, 0x6D, 0x85, 0xFF, 0xFF, 0xFF, // mov eax, [ebp*2-0x7b] 0x89, 0x45, 0xEC, // mov DWORD [ebp-0x14],eax }, ArchitectureMode.x86_32, 0x1000, true); Disassembler.Translator.IncludeAddress = true; Disassembler.Translator.IncludeBinary = true; results = disasm.Disassemble().ToArray(); Assert.IsTrue(results.First().ToString().StartsWith("00001000 "), "Incorrect instruction address/IP/PC, expected 00001000"); foreach (var ins in results) { Debug.WriteLine(ins.ToString()); } Debug.WriteLine("-------------------"); disasm = new SharpDisasm.Disassembler(new byte[] { 0xC8, 0x04, 0x00, 0x00, // enter 0x4, 0 0xA1, 0xC9, 0xFD, 0xFF, 0xFF, // mov eax,[0xfffffdc9] (or ds:0xfffffdc9) 0xA1, 0x37, 0x02, 0x00, 0x00, // mov eax,[0x237] (or ds:0x237) 0xB8, 0x37, 0x02, 0x00, 0x00, // mov eax,0x237 0xB4, 0x09, // mov ah,0x9 0x8A, 0x25, 0x09, 0x00, 0x00, 0x00, // mov ah,[0x9] 0x8B, 0x04, 0x6D, 0x85, 0xFF, 0xFF, 0xFF, // mov eax, [ebp*2-0x7b] 0x89, 0x45, 0xEC, // mov DWORD [ebp-0x14],eax }, ArchitectureMode.x86_32, 0, false); Disassembler.Translator.IncludeAddress = true; Disassembler.Translator.IncludeBinary = true; results = disasm.Disassemble().ToArray(); foreach (var ins in results) { Debug.WriteLine(ins.ToString()); } }
private static void DisassembleMethod( MethodInfo methodInfo, StringBuilder result, bool tryToEnsureJIT) { #if true // TODO: this is a total HACK! To do it right requires creating a separate process that activates the CLR debugger // interfaces, attaches to this process, enumerates the active state to find the native code segments corresponding // to cachedMethodInfo, and then return those to us so we can invoke the disassembler. That's way too much work // for the time being. // this code could well crash, so make sure autosave has happened. MainWindow.DoAutosaveGlobally(); #if true // additional HACK to try to ensure JIT has happened by invoking method with bogus arguments. if (tryToEnsureJIT) { object[] args = new object[methodInfo.GetParameters().Length]; try { object o = methodInfo.Invoke(null, args); } catch { } } #endif IntPtr codeBaseAddress = methodInfo.MethodHandle.GetFunctionPointer(); TryAgain: int length = 0; SharpDisasm.Disassembler.Translator.IncludeAddress = false; SharpDisasm.Disassembler.Translator.IncludeBinary = false; // HACK to guess the code length: // seek to first RET instruction, unless there are branches to the instruction immedately // after that RET, in which case, ignore it and keep going. List <ulong> addresses = new List <ulong>(); bool firstReturnSeen = false; while (true) { IntPtr currentAddress = new IntPtr(codeBaseAddress.ToInt64() + length); // detect RET or INT3 bool stop = (Marshal.ReadByte(currentAddress) == 0xC3) || (Marshal.ReadByte(currentAddress) == 0xCC); firstReturnSeen = firstReturnSeen || stop; SharpDisasm.Disassembler disassembler2 = new SharpDisasm.Disassembler( currentAddress, 17, Environment.Is64BitProcess ? SharpDisasm.ArchitectureMode.x86_64 : SharpDisasm.ArchitectureMode.x86_32, (ulong)currentAddress.ToInt64(), true, SharpDisasm.Vendor.Any); foreach (SharpDisasm.Instruction instruction in disassembler2.Disassemble()) { length += instruction.Bytes.Length; string mnemonic = instruction.ToString().Trim(); string name = mnemonic; int space = mnemonic.IndexOf(' '); if (space >= 0) { name = name.Substring(0, space); } switch (name) { case "call": case "ja": case "jae": case "jb": case "jbe": case "jc": case "jcxz": case "je": case "jg": case "jge": case "jl": case "jle": case "jmp": case "jna": case "jnae": case "jnb": case "jnbe": case "jnc": case "jne": case "jng": case "jnge": case "jnl": case "jnle": case "jno": case "jnp": case "jns": case "jnz": case "jo": case "jp": case "jpe": case "jpo": case "js": case "jz": string address = mnemonic.Substring(mnemonic.IndexOf(' ')).Trim(); if (address.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) { // Disassembler doesn't expose absolute target address as property, but it knows it, since it // generates text output. Reverse the text to get the address. address = address.Substring(2); ulong target = UInt64.Parse(address, System.Globalization.NumberStyles.HexNumber); if (Environment.Is64BitProcess && (address.Length <= 8)) { target += instruction.Offset & 0xffffffff00000000; } addresses.Add(target); if (String.Equals(name, "jmp") && unchecked (instruction.Offset == (ulong)codeBaseAddress.ToInt64())) { // if JMP is the first instruction, assume we've hit a trampoline and restart at target codeBaseAddress = new IntPtr(unchecked ((long)target)); goto TryAgain; } } // else could be register indirect addressing mode, etc. if (String.Equals("invalid", name)) { length -= instruction.Bytes.Length; stop = true; goto ReallyStop; } // Aux code often terminates with JMP back to main body if (String.Equals("jmp", name)) { if (firstReturnSeen) // do not test stop after jmp in main body of code { stop = true; } } // Aux code also may terminate with CALL to thunk (which pops context and returns to it's caller) // No way to distinguish between that case and normal function calls that may resume execution // at next instruction - so we'll include garbage after in that case. Main risk is of access // violation if at end of mapped region. break; } break; } IntPtr nextAddress = new IntPtr(codeBaseAddress.ToInt64() + length); if (stop) { addresses.Sort(); int i = 0; while ((i < addresses.Count) && (addresses[i] < (ulong)nextAddress.ToInt64())) { i++; } addresses.RemoveRange(0, i); if ((addresses.Count != 0) && (addresses[0] == (ulong)nextAddress.ToInt64())) { stop = false; } } ReallyStop: if (stop) { break; } } SharpDisasm.Disassembler.Translator.IncludeAddress = true; SharpDisasm.Disassembler.Translator.IncludeBinary = true; SharpDisasm.Disassembler disassembler = new SharpDisasm.Disassembler( codeBaseAddress, length, Environment.Is64BitProcess ? SharpDisasm.ArchitectureMode.x86_64 : SharpDisasm.ArchitectureMode.x86_32, (ulong)codeBaseAddress.ToInt64(), SharpDisasm.Disassembler.Translator.IncludeBinary, SharpDisasm.Vendor.Any); foreach (SharpDisasm.Instruction instruction in disassembler.Disassemble()) { result.AppendLine(instruction.ToString()); } result.AppendLine(); #endif }
public void DisassemblerPrintATTSyntax() { var defaultTranslator = SharpDisasm.Disassembler.Translator; // Set translator to AT&T Syntax SharpDisasm.Disassembler.Translator = new SharpDisasm.Translators.ATTTranslator() { IncludeAddress = true, IncludeBinary = false, SymbolResolver = null }; try { var disasm = new SharpDisasm.Disassembler(new byte[] { 0x48, 0x8B, 0x05, 0xF7, 0xFF, 0xFF, 0xFF, // movq -0x9(%rip), %rax 0x67, 0x66, 0x8b, 0x40, 0xf0, // movw -0x10(%eax), %ax 0x67, 0x66, 0x03, 0x5e, 0x10, // addw 0x10(%esi), %bx 0x48, 0x03, 0x04, 0x25, 0xff, 0xff, 0x00, 0x00, // addq 0xffff, %rax 0x67, 0x66, 0x03, 0x44, 0xbe, 0xf0, // addw -0x10(%esi,%edi,4), %ax 0x4c, 0x03, 0x84, 0x98, 0x00, 0x00, 0x00, 0x80, // addq -0x80000000(%rax,%rbx,4), %r8 0x48, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, // movq 0x800000000000, %rax 0x67, 0x8D, 0x04, 0x85, 0x08, 0x00, 0x00, 0x00, // leal 0x8(%eax,4), %eax }, ArchitectureMode.x86_64, 0, true); var results = disasm.Disassemble().ToArray(); foreach (var ins in results) { Debug.WriteLine(ins.ToString()); } Debug.WriteLine("-------------------"); disasm = new SharpDisasm.Disassembler(new byte[] { 0xA1, 0xC9, 0xFD, 0xFF, 0xFF, // movl 0xfffffdc9, %eax 0xA1, 0x37, 0x02, 0x00, 0x00, // movl 0x237, %eax 0xB8, 0x37, 0x02, 0x00, 0x00, // mov $0x237, %eax 0xB4, 0x09, // mov $0x9, %ah 0x8A, 0x25, 0x09, 0x00, 0x00, 0x00, // movb 0x9, %ah 0x8B, 0x04, 0x6D, 0x85, 0xFF, 0xFF, 0xFF, // movl -0x7b(%ebp,2), %eax 0x89, 0x45, 0xEC, // movl %eax, -0x14(%ebp) 0xB8, 0x05, 0x00, 0x00, 0x00, // mov $0x5, %eax 0x8B, 0x45, 0x04, // movl 0x4(%ebp), %eax 0x66, 0x8B, 0x8C, 0x83, 0x00, 0x00, 0x00, 0x00, // movw (%ebx,%eax,4), %cx 0x8D, 0x04, 0x85, 0x08, 0x00, 0x00, 0x00, // leal 0x8(%eax,4), %eax 0x67, 0x89, 0x07, // movl %eax, (%bx) 0xA3, 0xFF, 0x00, 0x00, 0x00, // movl %eax, 0xff 0x83, 0xEC, 0x12, // sub $0x12, %esp }, ArchitectureMode.x86_32, 0x1000, true); Disassembler.Translator.IncludeAddress = true; Disassembler.Translator.IncludeBinary = true; results = disasm.Disassemble().ToArray(); Assert.IsTrue(results.First().ToString().StartsWith("00001000 "), "Incorrect instruction address/IP/PC, expected 00001000"); foreach (var ins in results) { Debug.WriteLine(ins.ToString()); } Debug.WriteLine("-------------------"); disasm = new SharpDisasm.Disassembler(new byte[] { 0xA1, 0xC9, 0xFD, 0xFF, 0xFF, // movl 0xfffffdc9, %eax 0xA1, 0x37, 0x02, 0x00, 0x00, // movl 0x237, %eax 0xB8, 0x37, 0x02, 0x00, 0x00, // mov $0x237, %eax 0xB4, 0x09, // mov $0x9, %ah 0x8A, 0x25, 0x09, 0x00, 0x00, 0x00, // movb 0x9, %ah 0x8B, 0x04, 0x6D, 0x85, 0xFF, 0xFF, 0xFF, // movl -0x7b(%ebp,2), %eax 0x89, 0x45, 0xEC, // movl %eax, -0x14(%ebp) }, ArchitectureMode.x86_32, 0, false); Disassembler.Translator.IncludeAddress = true; Disassembler.Translator.IncludeBinary = true; results = disasm.Disassemble().ToArray(); foreach (var ins in results) { Debug.WriteLine(ins.ToString()); } } finally { SharpDisasm.Disassembler.Translator = defaultTranslator; } }