Ejemplo n.º 1
0
        private static IEnumerable <IntPtr> JumpTargetsImpl(Decoder myDecoder)
        {
            while (true)
            {
                myDecoder.Decode(out var instruction);
                if (myDecoder.InvalidNoMoreBytes)
                {
                    yield break;
                }
                if (instruction.FlowControl == FlowControl.Return)
                {
                    yield break;
                }

                if (instruction.FlowControl == FlowControl.UnconditionalBranch || instruction.FlowControl == FlowControl.Call)
                {
                    yield return((IntPtr)ExtractTargetAddress(in instruction));

                    if (instruction.FlowControl == FlowControl.UnconditionalBranch)
                    {
                        yield break;
                    }
                }
            }
        }
Ejemplo n.º 2
0
        /// <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;
        }
Ejemplo n.º 3
0
        private static IEnumerable <IntPtr> JumpTargetsImpl(Decoder myDecoder)
        {
            var formatter = new IntelFormatter();
            var builder   = new StringBuilder();

            while (true)
            {
                myDecoder.Decode(out var instruction);
                builder.Clear();
                formatter.Format(in instruction, new StringOutput(builder));
                LogSupport.Trace($"Decoded instruction: {builder}");
                if (myDecoder.InvalidNoMoreBytes)
                {
                    yield break;
                }
                if (instruction.FlowControl == FlowControl.Return)
                {
                    yield break;
                }

                if (instruction.FlowControl == FlowControl.UnconditionalBranch || instruction.FlowControl == FlowControl.Call)
                {
                    yield return((IntPtr)ExtractTargetAddress(in instruction));

                    if (instruction.FlowControl == FlowControl.UnconditionalBranch)
                    {
                        yield break;
                    }
                }
            }
        }
Ejemplo n.º 4
0
        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()}");
            }
        }
Ejemplo n.º 5
0
        public ModuleDisassembly(byte[] moduleData)
        {
            _moduleData = moduleData;
            _codeReader = new ByteArrayCodeReader(_moduleData);
            _decoder    = Decoder.Create(16, _codeReader);
            _decoder.IP = 0x0;

            Instructions = new InstructionList();
        }
Ejemplo n.º 6
0
        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;
        }
Ejemplo n.º 8
0
        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);
        }
Ejemplo n.º 9
0
        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);
        }
Ejemplo n.º 10
0
        private static IEnumerable <IntPtr> CallAndIndirectTargetsImpl(Decoder decoder)
        {
            while (true)
            {
                decoder.Decode(out var instruction);
                if (decoder.InvalidNoMoreBytes)
                {
                    yield break;
                }

                if (instruction.FlowControl == FlowControl.Return)
                {
                    yield break;
                }

                if (instruction.Mnemonic == Mnemonic.Int || instruction.Mnemonic == Mnemonic.Int1)
                {
                    yield break;
                }

                if (instruction.Mnemonic == Mnemonic.Call || instruction.Mnemonic == Mnemonic.Jmp)
                {
                    var targetAddress = XrefScanner.ExtractTargetAddress(instruction);
                    if (targetAddress != 0)
                    {
                        yield return((IntPtr)targetAddress);
                    }
                    continue;
                }

                if (instruction.Mnemonic == Mnemonic.Lea)
                {
                    if (instruction.MemoryBase == Register.RIP)
                    {
                        var targetAddress = instruction.IPRelativeMemoryAddress;
                        if (targetAddress != 0)
                        {
                            yield return((IntPtr)targetAddress);
                        }
                    }
                }
            }
        }
Ejemplo n.º 11
0
        /// <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);
        }