コード例 #1
0
        void EncodeDeclareByte(string hexBytes)
        {
            const int   bitness = 64;
            const ulong newRip  = 0x8000000000000000;

            var data         = HexUtils.ToByteArray(hexBytes);
            var instructions = new Instruction[] {
                Instruction.Create(Code.Nopd),
                Instruction.CreateDeclareByte(data),
                Instruction.Create(Code.Nopd),
            };

            var expectedData = new byte[data.Length + 2];

            expectedData[0] = 0x90;
            Array.Copy(data, 0, expectedData, 1, data.Length);
            expectedData[expectedData.Length - 1] = 0x90;

            var  codeWriter = new CodeWriterImpl();
            bool b          = BlockEncoder.TryEncode(bitness, new InstructionBlock(codeWriter, instructions, newRip), out var errorMessage, out var result);

            Assert.True(b);
            Assert.Null(errorMessage);
            Assert.Equal(expectedData, codeWriter.ToArray());
            Assert.Equal(newRip, result.RIP);
            Assert.Null(result.RelocInfos);
            Assert.NotNull(result.NewInstructionOffsets);
            Assert.True(result.NewInstructionOffsets.Length == 0);
            Assert.NotNull(result.ConstantOffsets);
            Assert.True(result.ConstantOffsets.Length == 0);
        }
コード例 #2
0
        void DefaultArgs()
        {
            const int   bitness = 64;
            const ulong origRip = 0x123456789ABCDE00;
            const ulong newRip  = 0x8000000000000000;

            var originalData = new byte[] {
                /*0000*/ 0xB0, 0x00,                   // mov al,0
                /*0002*/ 0xEB, 0x09,                   // jmp short 123456789ABCDE0Dh
                /*0004*/ 0xB0, 0x01,                   // mov al,1
                /*0006*/ 0xE9, 0x03, 0x00, 0x00, 0x00, // jmp near ptr 123456789ABCDE0Eh
                /*000B*/ 0xB0, 0x02,                   // mov al,2
            };
            var  instructions = BlockEncoderTest.Decode(bitness, origRip, originalData, DecoderOptions.None);
            var  codeWriter   = new CodeWriterImpl();
            bool b            = BlockEncoder.TryEncode(bitness, new InstructionBlock(codeWriter, instructions, newRip), out var errorMessage, out var result);

            Assert.True(b);
            Assert.Null(errorMessage);
            Assert.Equal(newRip, result.RIP);
            Assert.Equal(0x28, codeWriter.ToArray().Length);
            Assert.Null(result.RelocInfos);
            Assert.NotNull(result.NewInstructionOffsets);
            Assert.True(result.NewInstructionOffsets.Length == 0);
            Assert.NotNull(result.ConstantOffsets);
            Assert.True(result.ConstantOffsets.Length == 0);
        }
コード例 #3
0
        void Encode_zero_blocks()
        {
            bool   b;
            string errorMessage;

            BlockEncoderResult[] result;

            b = BlockEncoder.TryEncode(16, new InstructionBlock[0], out errorMessage, out result, BlockEncoderOptions.None);
            Assert.True(b);
            Assert.Null(errorMessage);
            Assert.NotNull(result);
            Assert.True(result.Length == 0);

            b = BlockEncoder.TryEncode(32, new InstructionBlock[0], out errorMessage, out result, BlockEncoderOptions.None);
            Assert.True(b);
            Assert.Null(errorMessage);
            Assert.NotNull(result);
            Assert.True(result.Length == 0);

            b = BlockEncoder.TryEncode(64, new InstructionBlock[0], out errorMessage, out result, BlockEncoderOptions.None);
            Assert.True(b);
            Assert.Null(errorMessage);
            Assert.NotNull(result);
            Assert.True(result.Length == 0);
        }
コード例 #4
0
        public static IntPtr RunRemoteCode(IntPtr hProc, IReadOnlyList <Instruction> instructions, bool x86)
        {
            var cw = new CodeWriterImpl();
            var ib = new InstructionBlock(cw, new List <Instruction>(instructions), 0);

            if (!BlockEncoder.TryEncode(x86 ? 32 : 64, ib, out string?errMsg, out _))
            {
                throw new Exception("Error during Iced encode: " + errMsg);
            }
            byte[] bytes = cw.ToArray();

            var ptrStub = Native.VirtualAllocEx(hProc, IntPtr.Zero, (uint)bytes.Length, 0x1000, 0x40);

            Native.WriteProcessMemory(hProc, ptrStub, bytes, (uint)bytes.Length, out _);
            Console.WriteLine("Written to 0x" + ptrStub.ToInt64().ToString("X8"));

#if DEBUG
            Console.WriteLine("Press ENTER to start remote thread (you have the chance to place a breakpoint now)");
            Console.ReadLine();
#endif

            var thread = Native.CreateRemoteThread(hProc, IntPtr.Zero, 0u, ptrStub, IntPtr.Zero, 0u, IntPtr.Zero);

            // NOTE: could wait for thread to finish with WaitForSingleObject
            Debug.Assert(thread != IntPtr.Zero);

            return(thread);
        }
コード例 #5
0
        public bool TryPatchX64(out string errorMessage)
        {
            var function = functionProvider.GetFunction(IsDebuggerPresentConstants.DllName, IsDebuggerPresentConstants.FuncName);

            /*
             *      Generate the following code:
             *
             *      xor eax,eax
             *      ret
             */

            var instructions = new InstructionList();

            instructions.Add(Instruction.Create(II.Code.Xor_r32_rm32, Register.EAX, Register.EAX));
            instructions.Add(Instruction.Create(II.Code.Retnq));

            var block = new InstructionBlock(new CodeWriterImpl(function), instructions, function.NewCodeAddress);

            if (!BlockEncoder.TryEncode(process.Bitness, block, out var encErrMsg))
            {
                errorMessage = $"Failed to encode: {encErrMsg}";
                return(false);
            }

            errorMessage = null;
            return(true);
        }
コード例 #6
0
        /// <summary>
        /// Encodes the original bytes for a new address fixing e.g. branches, calls, jumps for execution at a given address.
        /// </summary>
        /// <param name="newAddress">The new address to encode the original instructions for.</param>
        public byte[] EncodeForNewAddress(IntPtr newAddress)
        {
            var writer = new CodeWriterImpl(_bytes.Length * 2);
            var block  = new InstructionBlock(writer, DecodePrologue(), (ulong)newAddress);

            BlockEncoder.TryEncode(_bitness, block, out _);
            return(writer.ToArray());
        }
コード例 #7
0
		public Type CompileDelegateType<T>(IEnumerable<Instruction> instructions, string methodName, Attribute[] typeAttributes = null, Attribute[] methodAttributes = null) where T : IAsmDelegate
		{
			var block = new InstructionBlock(_writer, new InstructionList(instructions) { Instruction.Create(Code.Retnq) }, _writer.NextFunctionPointer);
			if (!BlockEncoder.TryEncode(IntPtr.Size * 8, block, out var errorMessage))
			{
				throw new InvalidOperationException(errorMessage);
			}

			return _writer.CommitToAssembly<T>(methodName);
		}
コード例 #8
0
 void TryEncode_with_invalid_bitness_throws()
 {
     foreach (var bitness in BitnessUtils.GetInvalidBitnessValues())
     {
         Assert.Throws <ArgumentOutOfRangeException>(() => BlockEncoder.TryEncode(bitness, new InstructionBlock(new CodeWriterImpl(), new Instruction[1], 0), out _, out _));
     }
     foreach (var bitness in BitnessUtils.GetInvalidBitnessValues())
     {
         Assert.Throws <ArgumentOutOfRangeException>(() => BlockEncoder.TryEncode(bitness, new[] { new InstructionBlock(new CodeWriterImpl(), new Instruction[1], 0) }, out _, out _));
     }
 }
コード例 #9
0
		public T Compile<T>(IEnumerable<Instruction> instructions) where T : Delegate
		{
			var instructionList = new InstructionList(instructions) { Instruction.Create(Code.Retnq) };
			var block = new InstructionBlock(_writer, instructionList, _writer.NextFunctionPointer);
			if (!BlockEncoder.TryEncode(IntPtr.Size * 8, block, out var errorMessage))
			{
				throw new InvalidOperationException(errorMessage);
			}

			return _writer.CommitToPInvokeDelegate<T>();
		}
コード例 #10
0
        void EncodeRipRelMemOp()
        {
            var  instr      = Instruction.Create(Code.Add_r32_rm32, Register.ECX, new MemoryOperand(Register.RIP, Register.None, 1, 0x1234_5678_9ABC_DEF1, 8, false, Register.None));
            var  codeWriter = new CodeWriterImpl();
            bool b          = BlockEncoder.TryEncode(64, new InstructionBlock(codeWriter, new[] { instr }, 0x1234_5678_ABCD_EF02), out var errorMessage, out _);

            Assert.True(b, $"Couldn't encode it: {errorMessage}");
            var encoded  = codeWriter.ToArray();
            var expected = new byte[] { 0x03, 0x0D, 0xE9, 0xEF, 0xEE, 0xEE };

            Assert.Equal(expected, encoded);
        }
コード例 #11
0
        /// <summary>
        /// Encodes the original bytes for a new address fixing e.g. branches, calls, jumps for execution at a given address.
        /// </summary>
        /// <param name="newAddress">The new address to encode the original instructions for.</param>
        public byte[] EncodeForNewAddress(nuint newAddress)
        {
            var writer = new CodeWriterImpl(_bytes.Length * 2);
            var block  = new InstructionBlock(writer, DecodePrologue(), newAddress);

            if (!BlockEncoder.TryEncode(_bitness, block, out var error, out _))
            {
                throw new Exception($"Reloaded Hooks: Internal Error in {nameof(Reloaded.Hooks.Internal)}/{nameof(IcedPatcher)}. " +
                                    $"Failed to re-encode code for new address. Process will probably die." +
                                    $"Error: {error}");
            }

            return(writer.ToArray());
        }
コード例 #12
0
        void Encode_zero_blocks()
        {
            bool   b;
            string errorMessage;

            b = BlockEncoder.TryEncode(16, new InstructionBlock[0], out errorMessage, BlockEncoderOptions.None);
            Assert.True(b);
            Assert.Null(errorMessage);

            b = BlockEncoder.TryEncode(32, new InstructionBlock[0], out errorMessage, BlockEncoderOptions.None);
            Assert.True(b);
            Assert.Null(errorMessage);

            b = BlockEncoder.TryEncode(64, new InstructionBlock[0], out errorMessage, BlockEncoderOptions.None);
            Assert.True(b);
            Assert.Null(errorMessage);
        }
コード例 #13
0
        void Encode_zero_instructions()
        {
            bool   b;
            string errorMessage;
            var    codeWriter = new CodeWriterImpl();

            b = BlockEncoder.TryEncode(16, new InstructionBlock(codeWriter, Array.Empty <Instruction>(), 0, Array.Empty <RelocInfo>(), Array.Empty <uint>(), Array.Empty <ConstantOffsets>()), out errorMessage, BlockEncoderOptions.None);
            Assert.True(b);
            Assert.Null(errorMessage);
            Assert.Empty(codeWriter.ToArray());

            b = BlockEncoder.TryEncode(32, new InstructionBlock(codeWriter, Array.Empty <Instruction>(), 0, Array.Empty <RelocInfo>(), Array.Empty <uint>(), Array.Empty <ConstantOffsets>()), out errorMessage, BlockEncoderOptions.None);
            Assert.True(b);
            Assert.Null(errorMessage);
            Assert.Empty(codeWriter.ToArray());

            b = BlockEncoder.TryEncode(64, new InstructionBlock(codeWriter, Array.Empty <Instruction>(), 0, Array.Empty <RelocInfo>(), Array.Empty <uint>(), Array.Empty <ConstantOffsets>()), out errorMessage, BlockEncoderOptions.None);
            Assert.True(b);
            Assert.Null(errorMessage);
            Assert.Empty(codeWriter.ToArray());
        }
コード例 #14
0
        void Encode_zero_instructions()
        {
            bool               b;
            string             errorMessage;
            BlockEncoderResult result;
            var codeWriter = new CodeWriterImpl();

            b = BlockEncoder.TryEncode(16, new InstructionBlock(codeWriter, Array.Empty <Instruction>(), 0), out errorMessage, out result, BlockEncoderOptions.None);
            Assert.True(b);
            Assert.Null(errorMessage);
            Assert.Empty(codeWriter.ToArray());
            Assert.Equal(0UL, result.RIP);
            Assert.Null(result.RelocInfos);
            Assert.NotNull(result.NewInstructionOffsets);
            Assert.True(result.NewInstructionOffsets.Length == 0);
            Assert.NotNull(result.ConstantOffsets);
            Assert.True(result.ConstantOffsets.Length == 0);

            b = BlockEncoder.TryEncode(32, new InstructionBlock(codeWriter, Array.Empty <Instruction>(), 0), out errorMessage, out result, BlockEncoderOptions.None);
            Assert.True(b);
            Assert.Null(errorMessage);
            Assert.Empty(codeWriter.ToArray());
            Assert.Equal(0UL, result.RIP);
            Assert.Null(result.RelocInfos);
            Assert.NotNull(result.NewInstructionOffsets);
            Assert.True(result.NewInstructionOffsets.Length == 0);
            Assert.NotNull(result.ConstantOffsets);
            Assert.True(result.ConstantOffsets.Length == 0);

            b = BlockEncoder.TryEncode(64, new InstructionBlock(codeWriter, Array.Empty <Instruction>(), 0), out errorMessage, out result, BlockEncoderOptions.None);
            Assert.True(b);
            Assert.Null(errorMessage);
            Assert.Empty(codeWriter.ToArray());
            Assert.Equal(0UL, result.RIP);
            Assert.Null(result.RelocInfos);
            Assert.NotNull(result.NewInstructionOffsets);
            Assert.True(result.NewInstructionOffsets.Length == 0);
            Assert.NotNull(result.ConstantOffsets);
            Assert.True(result.ConstantOffsets.Length == 0);
        }
コード例 #15
0
        /// <summary>
        /// Patches the prologue of a function with iced and returns the new address of the prologue.
        /// </summary>
        /// <returns></returns>
        public IntPtr GetFunctionAddress()
        {
            if (_newPrologueAddress != IntPtr.Zero)
            {
                return(_newPrologueAddress);
            }

            var estimateLength = _bytes.Length * 2;  // Super generous! Exact length not known till relocated, just ensuring the size is enough under any circumstance.
            var buffer         = Utilities.FindOrCreateBufferInRange(estimateLength);

            return(buffer.ExecuteWithLock(() =>
            {
                // Patch prologue
                var newBaseAddress = buffer.Properties.WritePointer;
                var writer = new CodeWriterImpl(estimateLength);
                var block = new InstructionBlock((CodeWriter)writer, DecodePrologue(), (ulong)newBaseAddress);
                BlockEncoder.TryEncode(_bitness, block, out _);

                var data = writer.ToArray();
                _newPrologueAddress = buffer.Add(data, 1);

                return _newPrologueAddress;
            }));
        }
コード例 #16
0
        private static IntPtr AllocateStub(IntPtr hProc, string asmPath, string typeName, string methodName, string?args, IntPtr fnAddr, bool x86, bool isV4)
        {
            const string clrVersion2 = "v2.0.50727";
            const string clrVersion4 = "v4.0.30319";
            string       clrVersion  = isV4 ? clrVersion4 : clrVersion2;

            const string buildFlavor = "wks";    // WorkStation

            var clsidCLRRuntimeHost = new Guid(0x90F1A06E, 0x7712, 0x4762, 0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02);
            var iidICLRRuntimeHost  = new Guid(0x90F1A06C, 0x7712, 0x4762, 0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02);

            IntPtr ppv             = alloc(IntPtr.Size);
            IntPtr riid            = allocBytes(iidICLRRuntimeHost.ToByteArray());
            IntPtr rcslid          = allocBytes(clsidCLRRuntimeHost.ToByteArray());
            IntPtr pwszBuildFlavor = allocString(buildFlavor);
            IntPtr pwszVersion     = allocString(clrVersion);

            IntPtr pReturnValue    = alloc(4);
            IntPtr pwzArgument     = allocString(args);
            IntPtr pwzMethodName   = allocString(methodName);
            IntPtr pwzTypeName     = allocString(typeName);
            IntPtr pwzAssemblyPath = allocString(asmPath);

            var instructions = new InstructionList();

            if (x86)
            {
                // call CorBindtoRuntimeEx
                instructions.Add(Instruction.Create(Code.Pushd_imm32, ppv.ToInt32()));
                instructions.Add(Instruction.Create(Code.Pushd_imm32, riid.ToInt32()));
                instructions.Add(Instruction.Create(Code.Pushd_imm32, rcslid.ToInt32()));
                instructions.Add(Instruction.Create(Code.Pushd_imm8, 0));     // startupFlags
                instructions.Add(Instruction.Create(Code.Pushd_imm32, pwszBuildFlavor.ToInt32()));
                instructions.Add(Instruction.Create(Code.Pushd_imm32, pwszVersion.ToInt32()));
                instructions.Add(Instruction.Create(Code.Mov_r32_imm32, Register.EAX, fnAddr.ToInt32()));
                instructions.Add(Instruction.Create(Code.Call_rm32, Register.EAX));

                // call ICLRRuntimeHost::Start
                instructions.Add(Instruction.Create(Code.Mov_r32_rm32, Register.EAX, new MemoryOperand(Register.None, ppv.ToInt32())));
                instructions.Add(Instruction.Create(Code.Mov_r32_rm32, Register.ECX, new MemoryOperand(Register.EAX)));
                instructions.Add(Instruction.Create(Code.Mov_r32_rm32, Register.EDX, new MemoryOperand(Register.ECX, 0x0C)));
                instructions.Add(Instruction.Create(Code.Push_r32, Register.EAX));
                instructions.Add(Instruction.Create(Code.Call_rm32, Register.EDX));

                // call ICLRRuntimeHost::ExecuteInDefaultAppDomain
                instructions.Add(Instruction.Create(Code.Pushd_imm32, pReturnValue.ToInt32()));
                instructions.Add(Instruction.Create(Code.Pushd_imm32, pwzArgument.ToInt32()));
                instructions.Add(Instruction.Create(Code.Pushd_imm32, pwzMethodName.ToInt32()));
                instructions.Add(Instruction.Create(Code.Pushd_imm32, pwzTypeName.ToInt32()));
                instructions.Add(Instruction.Create(Code.Pushd_imm32, pwzAssemblyPath.ToInt32()));
                instructions.Add(Instruction.Create(Code.Mov_r32_rm32, Register.EAX, new MemoryOperand(Register.None, ppv.ToInt32())));
                instructions.Add(Instruction.Create(Code.Mov_r32_rm32, Register.ECX, new MemoryOperand(Register.EAX)));
                instructions.Add(Instruction.Create(Code.Push_r32, Register.EAX));
                instructions.Add(Instruction.Create(Code.Mov_r32_rm32, Register.EAX, new MemoryOperand(Register.ECX, 0x2C)));
                instructions.Add(Instruction.Create(Code.Call_rm32, Register.EAX));

                instructions.Add(Instruction.Create(Code.Retnd));
            }
            else
            {
                const int maxStackIndex = 3;
                const int stackSize     = 0x20 + maxStackIndex * 8; // 0x20 bytes shadow space, because x64
                MemoryOperand stackAccess(int i) => new MemoryOperand(Register.RSP, stackSize - (maxStackIndex - i) * 8);

                instructions.Add(Instruction.Create(Code.Sub_rm64_imm8, Register.RSP, stackSize));

                // call CorBindtoRuntimeEx
                // calling convention: https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=vs-2019
                instructions.Add(Instruction.Create(Code.Mov_r64_imm64, Register.RAX, ppv.ToInt64()));
                instructions.Add(Instruction.Create(Code.Mov_rm64_r64, stackAccess(1), Register.RAX));
                instructions.Add(Instruction.Create(Code.Mov_r64_imm64, Register.RAX, riid.ToInt64()));
                instructions.Add(Instruction.Create(Code.Mov_rm64_r64, stackAccess(0), Register.RAX));

                instructions.Add(Instruction.Create(Code.Mov_r64_imm64, Register.R9, rcslid.ToInt64()));
                instructions.Add(Instruction.Create(Code.Mov_r32_imm32, Register.R8D, 0));    // startupFlags
                instructions.Add(Instruction.Create(Code.Mov_r64_imm64, Register.RDX, pwszBuildFlavor.ToInt64()));
                instructions.Add(Instruction.Create(Code.Mov_r64_imm64, Register.RCX, pwszVersion.ToInt64()));
                instructions.Add(Instruction.Create(Code.Mov_r64_imm64, Register.RAX, fnAddr.ToInt64()));
                instructions.Add(Instruction.Create(Code.Call_rm64, Register.RAX));

                // call pClrHost->Start();
                instructions.Add(Instruction.Create(Code.Mov_r64_imm64, Register.RCX, ppv.ToInt64()));
                instructions.Add(Instruction.Create(Code.Mov_r64_rm64, Register.RCX, new MemoryOperand(Register.RCX)));
                instructions.Add(Instruction.Create(Code.Mov_r64_rm64, Register.RAX, new MemoryOperand(Register.RCX)));
                instructions.Add(Instruction.Create(Code.Mov_r64_rm64, Register.RDX, new MemoryOperand(Register.RAX, 0x18)));
                instructions.Add(Instruction.Create(Code.Call_rm64, Register.RDX));

                // call pClrHost->ExecuteInDefaultAppDomain()
                instructions.Add(Instruction.Create(Code.Mov_r64_imm64, Register.RDX, pReturnValue.ToInt64()));
                instructions.Add(Instruction.Create(Code.Mov_rm64_r64, stackAccess(1), Register.RDX));
                instructions.Add(Instruction.Create(Code.Mov_r64_imm64, Register.RDX, pwzArgument.ToInt64()));
                instructions.Add(Instruction.Create(Code.Mov_rm64_r64, stackAccess(0), Register.RDX));

                instructions.Add(Instruction.Create(Code.Mov_r64_imm64, Register.R9, pwzMethodName.ToInt64()));
                instructions.Add(Instruction.Create(Code.Mov_r64_imm64, Register.R8, pwzTypeName.ToInt64()));
                instructions.Add(Instruction.Create(Code.Mov_r64_imm64, Register.RDX, pwzAssemblyPath.ToInt64()));

                instructions.Add(Instruction.Create(Code.Mov_r64_imm64, Register.RCX, ppv.ToInt64()));
                instructions.Add(Instruction.Create(Code.Mov_r64_rm64, Register.RCX, new MemoryOperand(Register.RCX)));
                instructions.Add(Instruction.Create(Code.Mov_r64_rm64, Register.RAX, new MemoryOperand(Register.RCX)));
                instructions.Add(Instruction.Create(Code.Mov_r64_rm64, Register.RAX, new MemoryOperand(Register.RAX, 0x58)));
                instructions.Add(Instruction.Create(Code.Call_rm64, Register.RAX));

                instructions.Add(Instruction.Create(Code.Add_rm64_imm8, Register.RSP, stackSize));

                instructions.Add(Instruction.Create(Code.Retnq));
            }

            var  cw      = new CodeWriterImpl();
            var  ib      = new InstructionBlock(cw, instructions, 0);
            bool success = BlockEncoder.TryEncode(x86 ? 32 : 64, ib, out string errMsg);

            if (!success)
            {
                throw new Exception("Error during Iced encode: " + errMsg);
            }
            byte[] bytes = cw.ToArray();

            var ptrStub = alloc(bytes.Length, 0x40);    // RWX

            writeBytes(ptrStub, bytes);

            return(ptrStub);

            IntPtr alloc(int size, int protection = 0x04) => Native.VirtualAllocEx(hProc, IntPtr.Zero, (uint)size, 0x1000, protection);
            void writeBytes(IntPtr address, byte[] b) => Native.WriteProcessMemory(hProc, address, b, (uint)b.Length, out _);
            void writeString(IntPtr address, string str) => writeBytes(address, new UnicodeEncoding().GetBytes(str));

            IntPtr allocString(string?str)
            {
                if (str is null)
                {
                    return(IntPtr.Zero);
                }

                IntPtr pString = alloc(str.Length * 2 + 2);

                writeString(pString, str);
                return(pString);
            }

            IntPtr allocBytes(byte[] buffer)
            {
                IntPtr pBuffer = alloc(buffer.Length);

                writeBytes(pBuffer, buffer);
                return(pBuffer);
            }
        }
コード例 #17
0
 void TryEncode_with_null_array_throws() =>
 Assert.Throws <ArgumentNullException>(() => BlockEncoder.TryEncode(64, null, out _, out _));
コード例 #18
0
 void TryEncode_with_default_InstructionBlock_throws()
 {
     Assert.Throws <ArgumentException>(() => BlockEncoder.TryEncode(64, default(InstructionBlock), out _, out _));
     Assert.Throws <ArgumentException>(() => BlockEncoder.TryEncode(64, new InstructionBlock[3], out _, out _));
 }
コード例 #19
0
        void VerifyResultArrays(BlockEncoderOptions options)
        {
            const int   bitness  = 64;
            const ulong origRip1 = 0x123456789ABCDE00;
            const ulong origRip2 = 0x223456789ABCDE00;
            const ulong newRip1  = 0x8000000000000000;
            const ulong newRip2  = 0x9000000000000000;

            {
                var  instructions1 = BlockEncoderTest.Decode(bitness, origRip1, new byte[] { 0xE9, 0x56, 0x78, 0xA5, 0x5A }, DecoderOptions.None);
                var  codeWriter1   = new CodeWriterImpl();
                bool b             = BlockEncoder.TryEncode(bitness, new InstructionBlock(codeWriter1, instructions1, newRip1), out var errorMessage, out var result, options);
                Assert.True(b);
                Assert.Null(errorMessage);
                Assert.Equal(newRip1, result.RIP);
                if ((options & BlockEncoderOptions.ReturnRelocInfos) != 0)
                {
                    Assert.NotNull(result.RelocInfos);
                    Assert.True(result.RelocInfos.Count == 1);
                }
                else
                {
                    Assert.Null(result.RelocInfos);
                }
                if ((options & BlockEncoderOptions.ReturnNewInstructionOffsets) != 0)
                {
                    Assert.NotNull(result.NewInstructionOffsets);
                    Assert.True(result.NewInstructionOffsets.Length == 1);
                }
                else
                {
                    Assert.NotNull(result.NewInstructionOffsets);
                    Assert.True(result.NewInstructionOffsets.Length == 0);
                }
                if ((options & BlockEncoderOptions.ReturnConstantOffsets) != 0)
                {
                    Assert.NotNull(result.ConstantOffsets);
                    Assert.True(result.ConstantOffsets.Length == 1);
                }
                else
                {
                    Assert.NotNull(result.ConstantOffsets);
                    Assert.True(result.ConstantOffsets.Length == 0);
                }
            }
            {
                var  instructions1 = BlockEncoderTest.Decode(bitness, origRip1, new byte[] { 0xE9, 0x56, 0x78, 0xA5, 0x5A }, DecoderOptions.None);
                var  instructions2 = BlockEncoderTest.Decode(bitness, origRip2, new byte[] { 0x90, 0xE9, 0x56, 0x78, 0xA5, 0x5A }, DecoderOptions.None);
                var  codeWriter1   = new CodeWriterImpl();
                var  codeWriter2   = new CodeWriterImpl();
                var  block1        = new InstructionBlock(codeWriter1, instructions1, newRip1);
                var  block2        = new InstructionBlock(codeWriter2, instructions2, newRip2);
                bool b             = BlockEncoder.TryEncode(bitness, new[] { block1, block2 }, out var errorMessage, out var resultArray, options);
                Assert.True(b);
                Assert.Null(errorMessage);
                Assert.NotNull(resultArray);
                Assert.Equal(2, resultArray.Length);
                Assert.Equal(newRip1, resultArray[0].RIP);
                Assert.Equal(newRip2, resultArray[1].RIP);
                if ((options & BlockEncoderOptions.ReturnRelocInfos) != 0)
                {
                    Assert.NotNull(resultArray[0].RelocInfos);
                    Assert.NotNull(resultArray[1].RelocInfos);
                    Assert.True(resultArray[0].RelocInfos.Count == 1);
                    Assert.True(resultArray[1].RelocInfos.Count == 1);
                }
                else
                {
                    Assert.Null(resultArray[0].RelocInfos);
                    Assert.Null(resultArray[1].RelocInfos);
                }
                if ((options & BlockEncoderOptions.ReturnNewInstructionOffsets) != 0)
                {
                    Assert.NotNull(resultArray[0].NewInstructionOffsets);
                    Assert.NotNull(resultArray[1].NewInstructionOffsets);
                    Assert.True(resultArray[0].NewInstructionOffsets.Length == 1);
                    Assert.True(resultArray[1].NewInstructionOffsets.Length == 2);
                }
                else
                {
                    Assert.NotNull(resultArray[0].NewInstructionOffsets);
                    Assert.True(resultArray[0].NewInstructionOffsets.Length == 0);
                    Assert.NotNull(resultArray[1].NewInstructionOffsets);
                    Assert.True(resultArray[1].NewInstructionOffsets.Length == 0);
                }
                if ((options & BlockEncoderOptions.ReturnConstantOffsets) != 0)
                {
                    Assert.NotNull(resultArray[0].ConstantOffsets);
                    Assert.NotNull(resultArray[1].ConstantOffsets);
                    Assert.True(resultArray[0].ConstantOffsets.Length == 1);
                    Assert.True(resultArray[1].ConstantOffsets.Length == 2);
                }
                else
                {
                    Assert.NotNull(resultArray[0].ConstantOffsets);
                    Assert.True(resultArray[0].ConstantOffsets.Length == 0);
                    Assert.NotNull(resultArray[1].ConstantOffsets);
                    Assert.True(resultArray[1].ConstantOffsets.Length == 0);
                }
            }
        }
コード例 #20
0
 void Invalid_ConstantOffsets_Throws()
 {
     Assert.Throws <ArgumentException>(() => BlockEncoder.TryEncode(64, new InstructionBlock(new CodeWriterImpl(), new Instruction[0], 0, Array.Empty <RelocInfo>(), null, new ConstantOffsets[1]), out _, BlockEncoderOptions.None));
     Assert.Throws <ArgumentException>(() => BlockEncoder.TryEncode(64, new InstructionBlock(new CodeWriterImpl(), new Instruction[1], 0, Array.Empty <RelocInfo>(), null, new ConstantOffsets[0]), out _, BlockEncoderOptions.None));
 }