コード例 #1
0
ファイル: ReadyToRunLanguage.cs プロジェクト: xueye123/ILSpy
        private void Disassemble(ITextOutput output, ReadyToRunReader reader, ReadyToRunMethod readyToRunMethod, RuntimeFunction runtimeFunction, int bitness, ulong address)
        {
            WriteCommentLine(output, readyToRunMethod.SignatureString);
            byte[] codeBytes = new byte[runtimeFunction.Size];
            for (int i = 0; i < runtimeFunction.Size; i++)
            {
                codeBytes[i] = reader.Image[reader.GetOffset(runtimeFunction.StartAddress) + i];
            }

            // TODO: Decorate the disassembly with Unwind, GC and debug info
            var codeReader = new ByteArrayCodeReader(codeBytes);
            var decoder    = Decoder.Create(bitness, codeReader);

            decoder.IP = address;
            ulong endRip = decoder.IP + (uint)codeBytes.Length;

            var instructions = new InstructionList();

            while (decoder.IP < endRip)
            {
                decoder.Decode(out instructions.AllocUninitializedElement());
            }

            string    disassemblyFormat = ReadyToRunOptions.GetDisassemblyFormat(null);
            Formatter formatter         = null;

            if (disassemblyFormat.Equals(ReadyToRunOptions.intel))
            {
                formatter = new NasmFormatter();
            }
            else
            {
                Debug.Assert(disassemblyFormat.Equals(ReadyToRunOptions.gas));
                formatter = new GasFormatter();
            }
            formatter.Options.DigitSeparator        = "`";
            formatter.Options.FirstOperandCharIndex = 10;
            var tempOutput = new StringBuilderFormatterOutput();

            foreach (var instr in instructions)
            {
                int byteBaseIndex = (int)(instr.IP - address);
                formatter.Format(instr, tempOutput);
                output.Write(instr.IP.ToString("X16"));
                output.Write(" ");
                int instrLen = instr.ByteLength;
                for (int i = 0; i < instrLen; i++)
                {
                    output.Write(codeBytes[byteBaseIndex + i].ToString("X2"));
                }
                int missingBytes = 10 - instrLen;
                for (int i = 0; i < missingBytes; i++)
                {
                    output.Write("  ");
                }
                output.Write(" ");
                output.WriteLine(tempOutput.ToStringAndReset());
            }
            output.WriteLine();
        }
コード例 #2
0
        private static IEnumerable <Asm> Decode(ulong startAddress, uint size, State state, int depth, ClrMethod currentMethod)
        {
            byte[] code = new byte[size];
            if (!state.Runtime.DataTarget.ReadProcessMemory(startAddress, code, code.Length, out int bytesRead) || bytesRead == 0)
            {
                yield break;
            }

            var reader  = new ByteArrayCodeReader(code, 0, bytesRead);
            var decoder = Decoder.Create(state.Runtime.PointerSize * 8, reader);

            decoder.IP = startAddress;

            while (reader.CanReadByte)
            {
                decoder.Decode(out var instruction);

                TryTranslateAddressToName(instruction, state, depth, currentMethod);

                yield return(new Asm
                {
                    InstructionPointer = instruction.IP,
                    Instruction = instruction
                });
            }
        }
コード例 #3
0
ファイル: DecoderTest.cs プロジェクト: xoofx/iced
        Decoder CreateDecoder(int codeSize, string hexBytes)
        {
            Decoder decoder;
            var     codeReader = new ByteArrayCodeReader(hexBytes);

            switch (codeSize)
            {
            case 16:
                decoder = Decoder.Create16(codeReader);
                decoder.InstructionPointer = DecoderConstants.DEFAULT_IP16;
                break;

            case 32:
                decoder = Decoder.Create32(codeReader);
                decoder.InstructionPointer = DecoderConstants.DEFAULT_IP32;
                break;

            case 64:
                decoder = Decoder.Create64(codeReader);
                decoder.InstructionPointer = DecoderConstants.DEFAULT_IP64;
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(codeSize));
            }

            Assert.Equal(codeSize, decoder.Bitness);
            return(decoder);
        }
コード例 #4
0
ファイル: MemoryCore.cs プロジェクト: Tamerz/MBBSEmu
        /// <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;
        }
コード例 #5
0
ファイル: DetourGenerator.cs プロジェクト: zmey13/BepInEx
        public static void Disassemble(ManualLogSource logSource, IntPtr memoryPtr, int size)
        {
            var data = new byte[size];

            Marshal.Copy(memoryPtr, data, 0, size);

            var formatter  = new NasmFormatter();
            var output     = new StringOutput();
            var codeReader = new ByteArrayCodeReader(data);
            var decoder    = Decoder.Create(64, codeReader);

            decoder.IP = (ulong)memoryPtr.ToInt64();
            while (codeReader.CanReadByte)
            {
                decoder.Decode(out var instr);
                formatter.Format(instr, output);
                logSource.LogDebug($"{instr.IP:X16} {output.ToStringAndReset()}");

                if (instr.Code == Code.Jmp_rm64 && instr.Immediate32 == 0
                    ) // && instr.IsIPRelativeMemoryOperand && instr.IPRelativeMemoryAddress = 6
                {
                    var address = new byte[8];

                    for (var i = 0; i < 8; i++)
                    {
                        address[i] = (byte)codeReader.ReadByte();
                    }

                    logSource.LogDebug($"{instr.IP + (ulong) instr.Length:X16} db 0x{BitConverter.ToUInt64(address, 0):X16}");
                    decoder.IP += 8;
                }
            }
        }
コード例 #6
0
        Decoder CreateDecoder(int codeSize, byte[] hexBytes, DecoderOptions options)
        {
            var codeReader = new ByteArrayCodeReader(hexBytes);
            var decoder    = Decoder.Create(codeSize, codeReader, options);

            switch (codeSize)
            {
            case 16:
                decoder.IP = DecoderConstants.DEFAULT_IP16;
                break;

            case 32:
                decoder.IP = DecoderConstants.DEFAULT_IP32;
                break;

            case 64:
                decoder.IP = DecoderConstants.DEFAULT_IP64;
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(codeSize));
            }

            Assert.Equal(codeSize, decoder.Bitness);
            return(decoder);
        }
コード例 #7
0
        static void Main(string[] args)
        {
            int exampleCodeBitness = 32;

            if (args.Length == 2)
            {
                switch (args[0])
                {
                case "32": { exampleCodeBitness = 32; break; }

                case "64": { exampleCodeBitness = 64; break; }

                default:
                    break;
                }
            }
            else
            {
                Console.Write("Must use arguments: <bit-length[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();

            var codeReader = new ByteArrayCodeReader(codeBytes);
            var decoder    = Decoder.Create(exampleCodeBitness, codeReader);

            decoder.IP = exampleCodeRIP;
            ulong endRip = decoder.IP + (uint)codeBytes.Length;

            var instructions = new InstructionList();

            while (decoder.IP < endRip)
            {
                decoder.Decode(out instructions.AllocUninitializedElement());
            }

            var formatter = new MasmFormatter();

            formatter.Options.DigitSeparator        = "`";
            formatter.Options.FirstOperandCharIndex = 10;
            var output = new StringOutput();

            foreach (ref var instr in instructions)
            {
                formatter.Format(instr, output);
                Console.WriteLine(instr.IP.ToString("X8") + " " + output.ToStringAndReset());
            }

            sw.Stop();
            Console.Error.WriteLine("Total dump time: {0:F} sec.", sw.Elapsed.TotalSeconds);
        }
コード例 #8
0
ファイル: EncoderTest.cs プロジェクト: yamiM0NSTER/iced
        Decoder CreateDecoder(int bitness, byte[] hexBytes, ulong ip, DecoderOptions options)
        {
            var codeReader = new ByteArrayCodeReader(hexBytes);
            var decoder    = Decoder.Create(bitness, codeReader, options);

            decoder.IP = ip;
            Assert.Equal(bitness, decoder.Bitness);
            return(decoder);
        }
コード例 #9
0
        public ModuleDisassembly(byte[] moduleData)
        {
            _moduleData = moduleData;
            _codeReader = new ByteArrayCodeReader(_moduleData);
            _decoder    = Decoder.Create(16, _codeReader);
            _decoder.IP = 0x0;

            Instructions = new InstructionList();
        }
コード例 #10
0
        static void ShellcodeDecoder(string shellcode, string RIP, bool x64)
        {
            string[] hexValues = shellcode.Split("\\x").Skip(1).ToArray();
            int      bitness;

            if (x64)
            {
                bitness = 64;
            }
            else
            {
                bitness = 32;
            }
            byte[] code = hexValues
                          .Select(value => Convert.ToByte(value, 16))
                          .ToArray();
            var   codeBytes  = code;
            var   codeReader = new ByteArrayCodeReader(codeBytes);
            var   decoder    = Iced.Intel.Decoder.Create(bitness, codeReader);
            ulong CodeRIP    = Convert.ToUInt64(RIP, 16);

            decoder.IP = CodeRIP;

            ulong endRip = decoder.IP + (uint)codeBytes.Length;

            var instructions = new InstructionList();

            while (decoder.IP < endRip)
            {
                decoder.Decode(out instructions.AllocUninitializedElement());
            }
            var formatter = new NasmFormatter();

            formatter.Options.DigitSeparator        = "";
            formatter.Options.FirstOperandCharIndex = 10;
            var output = new StringBuilderFormatterOutput();

            foreach (ref var instr in instructions)
            {
                formatter.Format(instr, output);
                int instrLen      = instr.ByteLength;
                int byteBaseIndex = (int)(instr.IP - CodeRIP);
                for (int i = 0; i < instrLen; i++)
                {
                    Console.Write(codeBytes[byteBaseIndex + i].ToString("X2"));
                }
                int missingBytes = 10 - instrLen;
                for (int i = 0; i < missingBytes; i++)
                {
                    Console.Write("  ");
                }
                Console.Write(" ");
                Console.WriteLine(output.ToStringAndReset().ToUpper());
            }
        }
コード例 #11
0
ファイル: Deconstructor.cs プロジェクト: 0xCM/arrows
		static InstructionList DecodeAsm(CodeBlock src)
		{
            var dst = new InstructionList();
            var reader = new ByteArrayCodeReader(src.Data);
			var decoder = Decoder.Create(IntPtr.Size * 8, reader);
			decoder.IP = src.Address;			
			while (reader.CanReadByte) 
			{
				ref var instruction = ref dst.AllocUninitializedElement();
				decoder.Decode(out instruction);                
			}
コード例 #12
0
ファイル: MiscTests.cs プロジェクト: wtf3505/iced
        void Test_ByteArrayCodeReader_ctor(ByteArrayCodeReader reader, byte[] expectedData)
        {
            int i = 0;

            Assert.Equal(0, reader.Position);
            while (reader.CanReadByte)
            {
                Assert.Equal(i, reader.Position);
                Assert.True(i < expectedData.Length);
                Assert.Equal(expectedData[i], reader.ReadByte());
                i++;
            }
            Assert.Equal(i, reader.Position);
            Assert.Equal(expectedData.Length, i);
            Assert.Equal(-1, reader.ReadByte());
            Assert.Equal(i, reader.Position);

            reader.Position = 0;
            Assert.Equal(0, reader.Position);
            i = 0;
            while (reader.CanReadByte)
            {
                Assert.Equal(i, reader.Position);
                Assert.True(i < expectedData.Length);
                Assert.Equal(expectedData[i], reader.ReadByte());
                i++;
            }
            Assert.Equal(i, reader.Position);
            Assert.Equal(expectedData.Length, i);
            Assert.Equal(-1, reader.ReadByte());
            Assert.Equal(i, reader.Position);

            reader.Position = reader.Count;
            Assert.Equal(reader.Count, reader.Position);
            Assert.False(reader.CanReadByte);
            Assert.Equal(-1, reader.ReadByte());

            for (i = expectedData.Length - 1; i >= 0; i--)
            {
                reader.Position = i;
                Assert.Equal(i, reader.Position);
                Assert.True(reader.CanReadByte);
                Assert.Equal(expectedData[i], reader.ReadByte());
                Assert.Equal(i + 1, reader.Position);
            }

            Assert.Throws <ArgumentOutOfRangeException>(() => reader.Position = int.MinValue);
            Assert.Throws <ArgumentOutOfRangeException>(() => reader.Position = -1);
            Assert.Throws <ArgumentOutOfRangeException>(() => reader.Position = expectedData.Length + 1);
            Assert.Throws <ArgumentOutOfRangeException>(() => reader.Position = int.MaxValue);
        }
コード例 #13
0
ファイル: EncoderTest.cs プロジェクト: ming-hai/iced
        Decoder CreateDecoder(int bitness, byte[] hexBytes, DecoderOptions options)
        {
            var codeReader = new ByteArrayCodeReader(hexBytes);
            var decoder    = Decoder.Create(bitness, codeReader, options);

            decoder.IP = bitness switch {
                16 => DecoderConstants.DEFAULT_IP16,
                32 => DecoderConstants.DEFAULT_IP32,
                64 => DecoderConstants.DEFAULT_IP64,
                _ => throw new ArgumentOutOfRangeException(nameof(bitness)),
            };
            Assert.Equal(bitness, decoder.Bitness);
            return(decoder);
        }
コード例 #14
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);
        }
コード例 #15
0
ファイル: Program.cs プロジェクト: donfanning/MBBSEmu
        private static void CreateCodeSegment(ReadOnlySpan <byte> byteCode, ushort segmentOrdinal = 1)
        {
            //Decode the Segment
            var instructionList = new InstructionList();
            var codeReader      = new ByteArrayCodeReader(byteCode.ToArray());
            var decoder         = Decoder.Create(16, codeReader);

            decoder.IP = 0x0;

            while (decoder.IP < (ulong)byteCode.Length)
            {
                decoder.Decode(out instructionList.AllocUninitializedElement());
            }

            CreateCodeSegment(instructionList, segmentOrdinal);
        }
コード例 #16
0
        protected void CreateCodeSegment(ReadOnlySpan <byte> byteCode, ushort segmentOrdinal = 1)
        {
            //Decode the Segment
            var instructionList = new InstructionList();
            var codeReader      = new ByteArrayCodeReader(byteCode.ToArray());
            var decoder         = Decoder.Create(16, codeReader);

            decoder.IP = 0x0;

            while (decoder.IP < (ulong)byteCode.Length)
            {
                decoder.Decode(out instructionList.AllocUninitializedElement());
            }

            mbbsEmuMemoryCore.AddSegment(segmentOrdinal, instructionList);
        }
コード例 #17
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);
        }
コード例 #18
0
ファイル: Form1.cs プロジェクト: killvxk/DiffAsm
        private CodeByte Disamexe(string fileexe)
        {
            progressBar1.Maximum = 100;
            CodeByte codeByte = new CodeByte();

            int exampleCodeBitness;
            var peHeader = new PeNet.PeFile(fileexe);

            if (peHeader.Is64Bit)
            {
                exampleCodeBitness = 64;
            }
            else
            {
                exampleCodeBitness = 32;
            }

            FileStream   input  = new FileStream(fileexe, FileMode.Open, FileAccess.Read);
            BinaryReader reader = new BinaryReader(input);

            reader.ReadBytes((int)peHeader.ImageSectionHeaders[0].PointerToRawData);
            byte[] buffer = reader.ReadBytes((int)peHeader.ImageSectionHeaders[0].SizeOfRawData);
            input.Close();

            ulong exampleCodeRIP = peHeader.ImageNtHeaders.OptionalHeader.ImageBase + peHeader.ImageSectionHeaders[0].VirtualAddress;
            var   codeBytes      = buffer;
            var   codeReader     = new ByteArrayCodeReader(codeBytes);
            var   decoder        = Iced.Intel.Decoder.Create(exampleCodeBitness, codeReader);

            decoder.IP = exampleCodeRIP;
            ulong endRip       = decoder.IP + (uint)codeBytes.Length;
            var   instructions = new InstructionList();

            while (decoder.IP < endRip)
            {
                decoder.Decode(out instructions.AllocUninitializedElement());
                if (decoder.IP % PROGRESS_MODULO == 0)
                {
                    progressBar1.Value = (int)(decoder.IP * 100 / endRip);
                }
            }
            codeByte.instructions = instructions;
            codeByte.hexcode      = buffer;
            codeByte.CodeRIP      = exampleCodeRIP;

            return(codeByte);
        }
コード例 #19
0
        private InstructionList DisassembleMethodInstructions(long methodOffset)
        {
            const int NativeBitness   = 64;
            const int MaxMethodLength = 0xFFFF;

            var codeReader = new ByteArrayCodeReader(NativeDllCode, (int)methodOffset, (int)Math.Min(MaxMethodLength, NativeDllCode.Length - methodOffset));
            var decoder    = Decoder.Create(NativeBitness, codeReader);

            decoder.InstructionPointer = 0;
            ulong endRip = decoder.InstructionPointer + MaxMethodLength;

            var instructions = new InstructionList();
            int int3count    = 0;

            while (decoder.InstructionPointer < endRip)
            {
                if (decoder.InstructionPointer > 0)
                {
                    long currentOffset = methodOffset + (long)decoder.InstructionPointer;
                    if (Offsets.MethodsFromOffsets.ContainsKey(currentOffset))
                    {
                        break;
                    }
                }
                decoder.Decode(out Instruction instruction);
                if (instruction.Code == Code.INVALID)
                {
                    break;
                }
                else if (instruction.Code == Code.Int3)
                {
                    int3count++;
                    if (int3count >= 2)
                    {
                        break;
                    }
                }
                else
                {
                    int3count = 0;
                }
                instructions.Add(instruction);
            }

            return(instructions);
        }
コード例 #20
0
        /// <summary>
        /// Returns a set of instructions represented by the prologue this type was instantiated with.
        /// </summary>
        private IList <Instruction> DecodePrologue()
        {
            var codeReader = new ByteArrayCodeReader(_bytes);
            var decoder    = Decoder.Create(_bitness, codeReader);

            decoder.IP = _originalFunctionAddress;
            ulong endRip = decoder.IP + (uint)_bytes.Length;

            var instructions = new InstructionList();

            while (decoder.IP < endRip)
            {
                decoder.Decode(out instructions.AllocUninitializedElement());
            }

            return(instructions);
        }
コード例 #21
0
        public static void Main(string[] args)
        {
            var code   = File.ReadAllBytes(args[0]);
            var reader = new ByteArrayCodeReader(code);

            var decoder = Decoder.Create(64, reader);

            decoder.InstructionPointer = 0x00007FFAC46ACDA4;

            var end          = decoder.InstructionPointer + (uint)code.Length;
            var instructions = new InstructionList();

            while (decoder.InstructionPointer < end)
            {
                decoder.Decode(out instructions.AllocUninitializedElement());
            }
        }
コード例 #22
0
        public void TestNops()
        {
            foreach (var bitness in new[] { 16, 32, 64 })
            {
                for (int i = 0; i <= 128; i++)
                {
                    var a = new Assembler(bitness);
                    a.nop(i);
                    var writer = new CodeWriterImpl();
                    a.Assemble(writer, 0);
                    var data = writer.ToArray();
                    Assert.Equal(i, data.Length);
                    var reader  = new ByteArrayCodeReader(data);
                    var decoder = Decoder.Create(bitness, reader);
                    while (reader.CanReadByte)
                    {
                        var instr = decoder.Decode();
                        switch (instr.Code)
                        {
                        case Code.Nopw:
                        case Code.Nopd:
                        case Code.Nopq:
                        case Code.Nop_rm16:
                        case Code.Nop_rm32:
                        case Code.Nop_rm64:
                            break;

                        default:
                            Assert.True(false, $"Expected a NOP but got {instr.Code}");
                            break;
                        }
                    }
                }

                {
                    var a = new Assembler(bitness);
                    Assert.Throws <ArgumentOutOfRangeException>(() => a.nop(-1));
                }
            }
        }
コード例 #23
0
ファイル: Program.cs プロジェクト: tuday2/MBBSEmu
        private void CreateCodeSegment(ReadOnlySpan <byte> byteCode, ushort segmentOrdinal = 0x1000)
        {
            if (realModeMemoryCore != null)
            {
                realModeMemoryCore.SetArray(segmentOrdinal, 0, byteCode);
                return;
            }

            //Decode the Segment
            var instructionList = new InstructionList();
            var codeReader      = new ByteArrayCodeReader(byteCode.ToArray());
            var decoder         = Decoder.Create(16, codeReader);

            decoder.IP = 0x0;

            while (decoder.IP < (ulong)byteCode.Length)
            {
                decoder.Decode(out instructionList.AllocUninitializedElement());
            }

            CreateCodeSegment(instructionList, segmentOrdinal);
        }
コード例 #24
0
ファイル: MemoryCore.cs プロジェクト: Tamerz/MBBSEmu
        /// <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);
        }
コード例 #25
0
        private static IEnumerable <Asm> Decode(ILToNativeMap map, State state, int depth, ClrMethod currentMethod)
        {
            ulong startAddress = map.StartAddress;
            uint  size         = (uint)(map.EndAddress - map.StartAddress);

            byte[] code = new byte[size];

            int totalBytesRead = 0;

            do
            {
                int bytesRead = state.Runtime.DataTarget.DataReader.Read(startAddress + (ulong)totalBytesRead, new Span <byte>(code, totalBytesRead, (int)size - totalBytesRead));
                if (bytesRead <= 0)
                {
                    throw new EndOfStreamException($"Tried to read {size} bytes for {currentMethod.Signature}, got only {totalBytesRead}");
                }
                totalBytesRead += bytesRead;
            } while (totalBytesRead != size);

            var reader  = new ByteArrayCodeReader(code, 0, (int)size);
            var decoder = Decoder.Create(state.Runtime.DataTarget.DataReader.PointerSize * 8, reader);

            decoder.IP = startAddress;

            while (reader.CanReadByte)
            {
                decoder.Decode(out var instruction);

                TryTranslateAddressToName(instruction, state, depth, currentMethod);

                yield return(new Asm
                {
                    InstructionPointer = instruction.IP,
                    Instruction = instruction
                });
            }
        }
コード例 #26
0
        private void Disassemble(PEFile currentFile, ITextOutput output, ReadyToRunReader reader, ReadyToRunMethod readyToRunMethod, RuntimeFunction runtimeFunction, int bitness, ulong address, bool showMetadataTokens, bool showMetadataTokensInBase10)
        {
            // TODO: Decorate the disassembly with GCInfo
            WriteCommentLine(output, readyToRunMethod.SignatureString);

            Dictionary <ulong, UnwindCode> unwindInfo = null;

            if (ReadyToRunOptions.GetIsShowUnwindInfo(null) && bitness == 64)
            {
                unwindInfo = WriteUnwindInfo(runtimeFunction, output);
            }

            bool isShowDebugInfo = ReadyToRunOptions.GetIsShowDebugInfo(null);
            Dictionary <VarLocType, HashSet <ValueTuple <DebugInfo, NativeVarInfo> > > debugInfo = null;

            if (isShowDebugInfo)
            {
                debugInfo = WriteDebugInfo(readyToRunMethod, output);
            }

            byte[] codeBytes = new byte[runtimeFunction.Size];
            for (int i = 0; i < runtimeFunction.Size; i++)
            {
                codeBytes[i] = reader.Image[reader.GetOffset(runtimeFunction.StartAddress) + i];
            }

            var codeReader = new ByteArrayCodeReader(codeBytes);
            var decoder    = Decoder.Create(bitness, codeReader);

            decoder.IP = address;
            ulong endRip = decoder.IP + (uint)codeBytes.Length;

            var instructions = new InstructionList();

            while (decoder.IP < endRip)
            {
                decoder.Decode(out instructions.AllocUninitializedElement());
            }

            string    disassemblyFormat = ReadyToRunOptions.GetDisassemblyFormat(null);
            Formatter formatter         = null;

            if (disassemblyFormat.Equals(ReadyToRunOptions.intel))
            {
                formatter = new NasmFormatter();
            }
            else
            {
                Debug.Assert(disassemblyFormat.Equals(ReadyToRunOptions.gas));
                formatter = new GasFormatter();
            }
            formatter.Options.DigitSeparator        = "`";
            formatter.Options.FirstOperandCharIndex = 10;
            var   tempOutput  = new StringOutput();
            ulong baseInstrIP = instructions[0].IP;

            foreach (var instr in instructions)
            {
                int byteBaseIndex = (int)(instr.IP - address);
                if (isShowDebugInfo && runtimeFunction.DebugInfo != null)
                {
                    foreach (var bound in runtimeFunction.DebugInfo.BoundsList)
                    {
                        if (bound.NativeOffset == byteBaseIndex)
                        {
                            if (bound.ILOffset == (uint)DebugInfoBoundsType.Prolog)
                            {
                                WriteCommentLine(output, "Prolog");
                            }
                            else if (bound.ILOffset == (uint)DebugInfoBoundsType.Epilog)
                            {
                                WriteCommentLine(output, "Epilog");
                            }
                            else
                            {
                                WriteCommentLine(output, $"IL_{bound.ILOffset:x4}");
                            }
                        }
                    }
                }
                formatter.Format(instr, tempOutput);
                output.Write(instr.IP.ToString("X16"));
                output.Write(" ");
                int instrLen = instr.Length;
                for (int i = 0; i < instrLen; i++)
                {
                    output.Write(codeBytes[byteBaseIndex + i].ToString("X2"));
                }
                int missingBytes = 10 - instrLen;
                for (int i = 0; i < missingBytes; i++)
                {
                    output.Write("  ");
                }
                output.Write(" ");
                output.Write(tempOutput.ToStringAndReset());
                DecorateUnwindInfo(output, unwindInfo, baseInstrIP, instr);
                DecorateDebugInfo(output, instr, debugInfo, baseInstrIP);
                DecorateCallSite(currentFile, output, reader, showMetadataTokens, showMetadataTokensInBase10, instr);
            }
            output.WriteLine();
        }
コード例 #27
0
        /// <summary>
        /// Follow a JMP or Jcc instruction to the next logical location.
        /// </summary>
        /// <param name="address">Address of the instruction.</param>
        /// <returns>The address referenced by the jmp.</returns>
        private static IntPtr FollowJmp(IntPtr address)
        {
            while (true)
            {
                var hasOtherHooks = HookManager.Originals.ContainsKey(address);
                if (hasOtherHooks)
                {
                    // This address has been hooked already. Do not follow a jmp into a trampoline of our own making.
                    Log.Verbose($"Detected hook trampoline at {address.ToInt64():X}, stopping jump resolution.");
                    return(address);
                }

                var bytes = MemoryHelper.ReadRaw(address, 8);

                var codeReader = new ByteArrayCodeReader(bytes);
                var decoder    = Decoder.Create(64, codeReader);
                decoder.IP = (ulong)address.ToInt64();
                decoder.Decode(out var inst);

                if (inst.Mnemonic == Mnemonic.Jmp)
                {
                    var kind = inst.Op0Kind;

                    IntPtr newAddress;
                    switch (inst.Op0Kind)
                    {
                    case OpKind.NearBranch64:
                    case OpKind.NearBranch32:
                    case OpKind.NearBranch16:
                        newAddress = (IntPtr)inst.NearBranchTarget;
                        break;

                    case OpKind.Immediate16:
                    case OpKind.Immediate8to16:
                    case OpKind.Immediate8to32:
                    case OpKind.Immediate8to64:
                    case OpKind.Immediate32to64:
                    case OpKind.Immediate32 when IntPtr.Size == 4:
                    case OpKind.Immediate64:
                        newAddress = (IntPtr)inst.GetImmediate(0);
                        break;

                    case OpKind.Memory when inst.IsIPRelativeMemoryOperand:
                        newAddress = (IntPtr)inst.IPRelativeMemoryAddress;
                        newAddress = Marshal.ReadIntPtr(newAddress);
                        break;

                    case OpKind.Memory:
                        newAddress = (IntPtr)inst.MemoryDisplacement64;
                        newAddress = Marshal.ReadIntPtr(newAddress);
                        break;

                    default:
                        var debugBytes = string.Join(" ", bytes.Take(inst.Length).Select(b => $"{b:X2}"));
                        throw new Exception($"Unknown OpKind {inst.Op0Kind} from {debugBytes}");
                    }

                    Log.Verbose($"Resolving assembly jump ({kind}) from {address.ToInt64():X} to {newAddress.ToInt64():X}");
                    address = newAddress;
                }
                else
                {
                    break;
                }
            }

            return(address);
        }
コード例 #28
0
        public static Block[] Create(int bitness, NativeCodeBlock[] blocks)
        {
            var targets   = new Dictionary <ulong, TargetKind>();
            var instrInfo = new List <(Instruction instruction, int block, ArraySegment <byte> code)>();

            for (int blockIndex = 0; blockIndex < blocks.Length; blockIndex++)
            {
                var block = blocks[blockIndex];

                var reader  = new ByteArrayCodeReader(block.Code);
                var decoder = Decoder.Create(bitness, reader);
                decoder.IP = block.Address;
                while (reader.CanReadByte)
                {
                    decoder.Decode(out var instr);
                    instrInfo.Add((instr, blockIndex, GetBytes(block.Code, block.Address, ref instr)));

                    switch (instr.FlowControl)
                    {
                    case FlowControl.Next:
                    case FlowControl.Interrupt:
                        break;

                    case FlowControl.UnconditionalBranch:
                        Add(targets, instr.NextIP, TargetKind.Unknown);
                        if (instr.Op0Kind == OpKind.NearBranch16 || instr.Op0Kind == OpKind.NearBranch32 || instr.Op0Kind == OpKind.NearBranch64)
                        {
                            Add(targets, instr.NearBranchTarget, TargetKind.Branch);
                        }
                        break;

                    case FlowControl.ConditionalBranch:
                    case FlowControl.XbeginXabortXend:
                        if (instr.Op0Kind == OpKind.NearBranch16 || instr.Op0Kind == OpKind.NearBranch32 || instr.Op0Kind == OpKind.NearBranch64)
                        {
                            Add(targets, instr.NearBranchTarget, TargetKind.Branch);
                        }
                        break;

                    case FlowControl.Call:
                        if (instr.Op0Kind == OpKind.NearBranch16 || instr.Op0Kind == OpKind.NearBranch32 || instr.Op0Kind == OpKind.NearBranch64)
                        {
                            Add(targets, instr.NearBranchTarget, TargetKind.Call);
                        }
                        break;

                    case FlowControl.IndirectBranch:
                        Add(targets, instr.NextIP, TargetKind.Unknown);
                        // Unknown target
                        break;

                    case FlowControl.IndirectCall:
                        // Unknown target
                        break;

                    case FlowControl.Return:
                    case FlowControl.Exception:
                        Add(targets, instr.NextIP, TargetKind.Unknown);
                        break;

                    default:
                        Debug.Fail($"Unknown flow control: {instr.FlowControl}");
                        break;
                    }

                    var baseReg = instr.MemoryBase;
                    if (baseReg == Register.RIP || baseReg == Register.EIP)
                    {
                        int opCount = instr.OpCount;
                        for (int i = 0; i < opCount; i++)
                        {
                            if (instr.GetOpKind(i) == OpKind.Memory)
                            {
                                if (IsCodeAddress(blocks, instr.IPRelativeMemoryAddress))
                                {
                                    Add(targets, instr.IPRelativeMemoryAddress, TargetKind.Branch);
                                }
                                break;
                            }
                        }
                    }
                    else if (instr.MemoryDisplSize >= 2)
                    {
                        ulong displ;
                        switch (instr.MemoryDisplSize)
                        {
                        case 2:
                        case 4: displ = instr.MemoryDisplacement; break;

                        case 8: displ = (ulong)(int)instr.MemoryDisplacement; break;

                        default:
                            Debug.Fail($"Unknown mem displ size: {instr.MemoryDisplSize}");
                            goto case 8;
                        }
                        if (IsCodeAddress(blocks, displ))
                        {
                            Add(targets, displ, TargetKind.Branch);
                        }
                    }
                }
            }
            foreach (var block in blocks)
            {
                if (targets.TryGetValue(block.Address, out var origKind))
                {
                    if (origKind < TargetKind.BlockStart && origKind != TargetKind.Unknown)
                    {
                        targets[block.Address] = TargetKind.BlockStart;
                    }
                }
                else
                {
                    targets.Add(block.Address, TargetKind.Unknown);
                }
            }

            var       newBlocks = new List <BlockInfo>();
            BlockInfo currentBlock = default;
            int       labelIndex = 0, methodIndex = 0;

            for (int i = 0; i < instrInfo.Count; i++)
            {
                var     info  = instrInfo[i];
                ref var instr = ref info.instruction;
                if (targets.TryGetValue(instr.IP, out var targetKind))
                {
                    var origBlock = blocks[info.block];
                    currentBlock = new BlockInfo(targetKind, origBlock.Kind, instr.IP, origBlock.Address == instr.IP ? origBlock.Comment : null);
                    newBlocks.Add(currentBlock);
                }
                // The addr of each block is always in the dictionary so currentBlock is initialized
                Debug.Assert(!(currentBlock.Instructions is null));
                currentBlock.Instructions.Add(new X86InstructionInfo(info.code, instr));
            }
コード例 #29
0
ファイル: DetourGenerator.cs プロジェクト: zmey13/BepInEx
        /// <summary>
        ///     Reads assembly from <see cref="functionPtr" /> (at least <see cref="minimumTrampolineLength" /> bytes), and writes
        ///     it to <see cref="trampolinePtr" /> plus a jmp to continue execution.
        /// </summary>
        /// <param name="instructionBuffer">The buffer to copy assembly from.</param>
        /// <param name="functionPtr">The pointer to the function to copy assembly from.</param>
        /// <param name="trampolinePtr">The pointer to write the trampoline assembly to.</param>
        /// <param name="arch">The architecture of the current platform.</param>
        /// <param name="minimumTrampolineLength">Copies at least this many bytes of assembly from <see cref="functionPtr" />.</param>
        /// <param name="trampolineLength">Returns the total length of the trampoline, in bytes.</param>
        /// <param name="jmpLength">Returns the length of the jmp at the end of the trampoline, in bytes.</param>
        public static void CreateTrampolineFromFunction(byte[] instructionBuffer,
                                                        IntPtr functionPtr,
                                                        IntPtr trampolinePtr,
                                                        int minimumTrampolineLength,
                                                        Architecture arch,
                                                        out int trampolineLength,
                                                        out int jmpLength)
        {
            // Decode original function up until we go past the needed bytes to write the jump to patchedFunctionPtr

            var codeReader = new ByteArrayCodeReader(instructionBuffer);
            var decoder    = Decoder.Create(arch == Architecture.X64 ? 64 : 32, codeReader);

            decoder.IP = (ulong)functionPtr.ToInt64();

            uint totalBytes       = 0;
            var  origInstructions = new InstructionList();
            var  readOverflowArea = false;

            while (codeReader.CanReadByte)
            {
                decoder.Decode(out var instr);

                origInstructions.Add(instr);

                totalBytes += (uint)instr.Length;
                if (instr.Code == Code.INVALID)
                {
                    throw new Exception("Found garbage");
                }
                if (totalBytes >= minimumTrampolineLength)
                {
                    break;
                }

                if (readOverflowArea)
                {
                    if (instr.Mnemonic != Mnemonic.Int3 && instr.Mnemonic != Mnemonic.Nop)
                    {
                        throw new Exception("Function is too short to hook");
                    }
                    continue;
                }

                switch (instr.FlowControl)
                {
                case FlowControl.Next:
                    break;

                // Interrupts are usually used for aligning
                case FlowControl.Interrupt:     // eg. int n
                    break;

                // Handled by BlockEncoder in most cases
                case FlowControl.UnconditionalBranch:
                case FlowControl.IndirectBranch:        // eg. jmp reg/mem
                case FlowControl.ConditionalBranch:     // eg. je, jno, etc
                    break;

                case FlowControl.Return:     // eg. ret
                    // There is a possibility of an overflow area, attempt to allocate trampoline onto it
                    readOverflowArea = true;
                    break;

                case FlowControl.Call:          // eg. call method
                case FlowControl.IndirectCall:  // eg. call reg/mem
                case FlowControl.XbeginXabortXend:
                case FlowControl.Exception:     // eg. ud0
                default:
                    throw new Exception("Not supported yet - " + instr.FlowControl);
                }
            }

            if (totalBytes < minimumTrampolineLength)
            {
                throw new Exception("Not enough bytes!");
            }

            if (origInstructions.Count == 0)
            {
                throw new Exception("Not enough instructions!");
            }


            ref readonly var lastInstr = ref origInstructions[origInstructions.Count - 1];
コード例 #30
0
        public void TrampolineTest(int bitness)
        {
            byte[] exampleCode =
            {
                0x48, 0x89, 0x5C, 0x24, 0x10, 0x48, 0x89, 0x74, 0x24, 0x18, 0x55, 0x57, 0x41, 0x56, 0x48, 0x8D,
                0xAC, 0x24, 0x00, 0xFF, 0xFF, 0xFF, 0x48, 0x81, 0xEC, 0x00, 0x02, 0x00, 0x00, 0x48, 0x8B, 0x05,
                0x18, 0x57, 0x0A, 0x00, 0x48, 0x33, 0xC4, 0x48, 0x89, 0x85, 0xF0, 0x00, 0x00, 0x00, 0x4C, 0x8B,
                0x05, 0x2F, 0x24, 0x0A, 0x00, 0x48, 0x8D, 0x05, 0x78, 0x7C, 0x04, 0x00, 0x33, 0xFF
            };

            var exampleCodePointer    = Marshal.AllocHGlobal(80);
            var trampolineCodePointer = Marshal.AllocHGlobal(80);

            Marshal.Copy(exampleCode, 0, exampleCodePointer, exampleCode.Length);


            void Disassemble(byte[] data, ulong ip)
            {
                var formatter  = new NasmFormatter();
                var output     = new StringOutput();
                var codeReader = new ByteArrayCodeReader(data);
                var decoder    = Decoder.Create(bitness, codeReader);

                decoder.IP = ip;
                while (codeReader.CanReadByte)
                {
                    decoder.Decode(out var instr);
                    formatter.Format(instr, output);
                    Console.WriteLine($"{instr.IP:X16} {output.ToStringAndReset()}");
                }

                Console.WriteLine();
            }

            Console.WriteLine("Original:");
            Console.WriteLine();


            Disassemble(exampleCode, (ulong)exampleCodePointer.ToInt64());

            DetourGenerator.CreateTrampolineFromFunction(exampleCodePointer, out var trampolineLength, out _);

            Console.WriteLine("Modified:");
            Console.WriteLine();


            Marshal.Copy(exampleCodePointer, exampleCode, 0, exampleCode.Length);
            Disassemble(exampleCode, (ulong)exampleCodePointer.ToInt64());


            Console.WriteLine();
            Console.WriteLine("Trampoline:");
            Console.WriteLine();

            var trampolineArray = new byte[trampolineLength];

            Marshal.Copy(trampolineCodePointer, trampolineArray, 0, trampolineLength);

            Disassemble(trampolineArray, (ulong)trampolineCodePointer.ToInt64());


            Marshal.FreeHGlobal(exampleCodePointer);
            Marshal.FreeHGlobal(trampolineCodePointer);

            Assert.IsFalse(false);
        }