/// <summary> /// Directly adds a raw segment from an NE file segment /// </summary> /// <param name="segment"></param> public void AddSegment(Segment segment) { //Get Address for this Segment var segmentMemory = new byte[0x10000]; //Add the data to memory and record the segment offset in memory Array.Copy(segment.Data, 0, segmentMemory, 0, segment.Data.Length); _memorySegments.Add(segment.Ordinal, segmentMemory); if (segment.Flags.Contains(EnumSegmentFlags.Code)) { //Decode the Segment var instructionList = new InstructionList(); var codeReader = new ByteArrayCodeReader(segment.Data); var decoder = Decoder.Create(16, codeReader); decoder.IP = 0x0; while (decoder.IP < (ulong)segment.Data.Length) { decoder.Decode(out instructionList.AllocUninitializedElement()); } _decompiledSegments.Add(segment.Ordinal, new Dictionary <ushort, Instruction>()); foreach (var i in instructionList) { _decompiledSegments[segment.Ordinal].Add(i.IP16, i); } } _segments[segment.Ordinal] = segment; }
private static void DecodeMethod(IntPtr ptr, uint size, StringBuilder builder, Formatter formatter) { // You can also pass in a hex string, eg. "90 91 929394", or you can use your own CodeReader // reading data from a file or memory etc. var codeReader = new UnmanagedCodeReader(ptr, size); var decoder = Decoder.Create(IntPtr.Size * 8, codeReader); decoder.IP = (ulong)ptr.ToInt64(); ulong endRip = decoder.IP + (uint)size; // This list is faster than List<Instruction> since it uses refs to the Instructions // instead of copying them (each Instruction is 32 bytes in size). It has a ref indexer, // and a ref iterator. Add() uses 'in' (ref readonly). var instructions = new InstructionList(); while (decoder.IP < endRip) { // The method allocates an uninitialized element at the end of the list and // returns a reference to it which is initialized by Decode(). decoder.Decode(out instructions.AllocUninitializedElement()); } var output = new StringOutput(); // Use InstructionList's ref iterator (C# 7.3) to prevent copying 32 bytes every iteration foreach (ref var instr in instructions) { // Don't use instr.ToString(), it allocates more, uses masm syntax and default options formatter.Format(in instr, output); builder.AppendLine($"{instr.IP:X16} {output.ToStringAndReset()}"); } }
public ModuleDisassembly(byte[] moduleData) { _moduleData = moduleData; _codeReader = new ByteArrayCodeReader(_moduleData); _decoder = Decoder.Create(16, _codeReader); _decoder.IP = 0x0; Instructions = new InstructionList(); }
private static void Disasm(Stream stream, uint size, TextWriter writer, Formatter formatter = null) { var buffer = ArrayPool <byte> .Shared.Rent((int)size); var startPosition = stream.Position; stream.Read(buffer, 0, (int)size); stream.Position = startPosition; // You can also pass in a hex string, eg. "90 91 929394", or you can use your own CodeReader // reading data from a file or memory etc var codeReader = new StreamCodeReader(stream, size); var decoder = Decoder.Create(IntPtr.Size * 8, codeReader); decoder.IP = (ulong)0; ulong endRip = decoder.IP + (uint)size; // This list is faster than List<Instruction> since it uses refs to the Instructions // instead of copying them (each Instruction is 32 bytes in size). It has a ref indexer, // and a ref iterator. Add() uses 'in' (ref readonly). var instructions = new InstructionList(); while (decoder.IP < endRip) { // The method allocates an uninitialized element at the end of the list and // returns a reference to it which is initialized by Decode(). decoder.Decode(out instructions.AllocUninitializedElement()); } // Formatters: Masm*, Nasm* and Gas* (AT&T) if (formatter == null) { formatter = new NasmFormatter(); formatter.Options.DigitSeparator = ""; formatter.Options.FirstOperandCharIndex = 10; } var output = new StringBuilderFormatterOutput(); // Use InstructionList's ref iterator (C# 7.3) to prevent copying 32 bytes every iteration foreach (ref var instr in instructions) { // Don't use instr.ToString(), it allocates more, uses masm syntax and default options formatter.Format(instr, output); writer.Write($"{instr.IP:X16} "); for (int i = 0; i < instr.ByteLength; i++) { writer.Write(buffer[(int)instr.IP + i].ToString("X2")); } writer.Write(new string(' ', 16 * 2 - instr.ByteLength * 2)); writer.WriteLine($"{output.ToStringAndReset()}"); } }
public unsafe XrefScanner(IntPtr codeStart, int lengthLimit = 1000) { if (codeStart == IntPtr.Zero) { throw new NullReferenceException(nameof(codeStart)); } myUnmanagedMemoryStream = new UnmanagedMemoryStream((byte *)codeStart, lengthLimit, lengthLimit, FileAccess.Read); var codeReader = new StreamCodeReader(myUnmanagedMemoryStream); myDecoder = Decoder.Create(IntPtr.Size * 8, codeReader); myDecoder.IP = (ulong)codeStart; }
public Instruction Recompile(ushort segment, ushort instructionPointer) { //If it wasn't able to decompile linear through the data, there might have been //data in the path of the code that messed up decoding, in this case, we grab up to //6 bytes at the IP and decode the instruction manually. This works 9 times out of 10 Span <byte> segmentData = _segments[segment].Data; var reader = new ByteArrayCodeReader(segmentData.Slice(instructionPointer, 6).ToArray()); var decoder = Decoder.Create(16, reader); decoder.IP = instructionPointer; decoder.Decode(out var outputInstruction); _decompiledSegments[segment][instructionPointer] = outputInstruction; return(outputInstruction); }
public static InstructionList DisassembleBytesNew(bool is32Bit, byte[] bytes, ulong methodBase) { var codeReader = new ByteArrayCodeReader(bytes); var decoder = Decoder.Create(is32Bit ? 32 : 64, codeReader); decoder.IP = methodBase; var instructions = new InstructionList(); var endRip = decoder.IP + (uint)bytes.Length; while (decoder.IP < endRip) { decoder.Decode(out instructions.AllocUninitializedElement()); } return(instructions); }
/// <summary> /// Returns the decompiled instruction from the specified segment:pointer /// </summary> /// <param name="segment"></param> /// <param name="instructionPointer"></param> /// <returns></returns> public Instruction GetInstruction(ushort segment, ushort instructionPointer) { //Prevents constant hash lookups for instructions from the same segment if (_currentCodeSegment != segment) { _currentCodeSegment = segment; _currentCodeSegmentInstructions = _decompiledSegments[segment]; } //If it wasn't able to decompile linear through the data, there might have been //data in the path of the code that messed up decoding, in this case, we grab up to //6 bytes at the IP and decode the instruction manually. This works 9 times out of 10 if (!_currentCodeSegmentInstructions.TryGetValue(instructionPointer, out var outputInstruction)) { Span <byte> segmentData = _segments[segment].Data; var reader = new ByteArrayCodeReader(segmentData.Slice(instructionPointer, 6).ToArray()); var decoder = Decoder.Create(16, reader); decoder.IP = instructionPointer; decoder.Decode(out outputInstruction); } return(outputInstruction); }