public XbeginInstr(BlockEncoder blockEncoder, ref Instruction instruction) : base(blockEncoder, instruction.IP64) { this.instruction = instruction; switch (blockEncoder.Bitness) { case 16: targetAddr = instruction.NearBranch16Target; break; case 32: targetAddr = instruction.NearBranch32Target; break; case 64: targetAddr = instruction.NearBranch64Target; break; default: throw new InvalidOperationException(); } if (blockEncoder.FixBranches) { if (blockEncoder.Bitness == 16) { this.instruction.Code = Code.Xbegin_Jw16; } else { Debug.Assert(blockEncoder.Bitness == 32 || blockEncoder.Bitness == 64); this.instruction.Code = Code.Xbegin_Jd32; } } Size = (uint)blockEncoder.NullEncoder.Encode(ref this.instruction, instruction.IP64, out var errorMessage); if (errorMessage != null) { Size = DecoderConstants.MaxInstructionLength; } }
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); }
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); }
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); }
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); }
public IpRelMemOpInstr(BlockEncoder blockEncoder, ref Instruction instruction) : base(blockEncoder, instruction.IP64) { Debug.Assert(instruction.IsIPRelativeMemoryOp); this.instruction = instruction; instrKind = InstrKind.Uninitialized; string errorMessage; instruction.MemoryBase = Register.RIP; ripInstructionSize = (uint)blockEncoder.NullEncoder.Encode(ref instruction, instruction.IP64, out errorMessage); if (errorMessage != null) { ripInstructionSize = DecoderConstants.MaxInstructionLength; } instruction.MemoryBase = Register.EIP; eipInstructionSize = (uint)blockEncoder.NullEncoder.Encode(ref instruction, instruction.IP64, out errorMessage); if (errorMessage != null) { eipInstructionSize = DecoderConstants.MaxInstructionLength; } Debug.Assert(eipInstructionSize >= ripInstructionSize); Size = eipInstructionSize; }
public CallInstr(BlockEncoder blockEncoder, ref Instruction instruction) : base(blockEncoder, instruction.IP64) { bitness = blockEncoder.Bitness; this.instruction = instruction; origInstructionSize = (uint)blockEncoder.NullEncoder.Encode(ref instruction, instruction.IP64, out var errorMessage); if (errorMessage != null) { origInstructionSize = DecoderConstants.MaxInstructionLength; } if (!blockEncoder.FixBranches) { Size = origInstructionSize; useOrigInstruction = true; done = true; } else if (blockEncoder.Bitness == 64) { // Make sure it's not shorter than the real instruction. It can happen if there are extra prefixes. Size = Math.Max(origInstructionSize, CallOrJmpPointerDataInstructionSize64); } else { Size = origInstructionSize; } }
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); }
public IpRelMemOpInstr(BlockEncoder blockEncoder, ref Instruction instruction) : base(blockEncoder, instruction.IP) { Debug.Assert(instruction.IsIPRelativeMemoryOperand); this.instruction = instruction; instrKind = InstrKind.Uninitialized; string errorMessage; var instrCopy = instruction; instrCopy.MemoryBase = Register.RIP; if (!blockEncoder.NullEncoder.TryEncode(ref instrCopy, instrCopy.IP, out ripInstructionSize, out errorMessage)) { ripInstructionSize = DecoderConstants.MaxInstructionLength; } instrCopy.MemoryBase = Register.EIP; if (!blockEncoder.NullEncoder.TryEncode(ref instrCopy, instrCopy.IP, out eipInstructionSize, out errorMessage)) { eipInstructionSize = DecoderConstants.MaxInstructionLength; } Debug.Assert(eipInstructionSize >= ripInstructionSize); Size = eipInstructionSize; }
/// <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()); }
public SimpleInstr(BlockEncoder blockEncoder, ref Instruction instruction) : base(blockEncoder, instruction.IP64) { this.instruction = instruction; if (!blockEncoder.NullEncoder.TryEncode(ref instruction, instruction.IP64, out Size, out var errorMessage)) { Size = DecoderConstants.MaxInstructionLength; } }
public Block(BlockEncoder blockEncoder, CodeWriter codeWriter, ulong rip, List <RelocInfo>?relocInfos) { CodeWriter = new CodeWriterImpl(codeWriter); RIP = rip; this.relocInfos = relocInfos; instructions = Array2.Empty <Instr>(); dataList = new List <BlockData>(); alignment = (uint)blockEncoder.Bitness / 8; validData = new List <BlockData>(); }
public void EncodeBlock() { BlockEncoder instance = new BlockEncoder(new KeyScheduler { Key = Key, IV = IV }); byte[] block = hasher.ComputeHash(Key); byte[] encoded = instance.Encode(block, iterations: 1); CollectionAssert.AreNotEqual(encoded, block); }
public SimpleInstr(BlockEncoder blockEncoder, ref Instruction instruction) : base(blockEncoder, instruction.IP64) { this.instruction = instruction; Size = (uint)blockEncoder.NullEncoder.Encode(ref instruction, instruction.IP64, out var errorMessage); if (errorMessage != null) { Size = DecoderConstants.MaxInstructionLength; } }
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); }
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 _)); } }
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>(); }
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); }
public void EncodeDecodeBlock() { BlockEncoder encoder = new BlockEncoder(); Hash hash = new Hash(); Block block = new Block(1, hash); var result = encoder.Decode(encoder.Encode(block)); Assert.IsNotNull(result); Assert.AreEqual(1, result.Number); Assert.AreEqual(hash, result.ParentHash); }
public void DecodeBlock() { BlockEncoder encoder = new BlockEncoder(new KeyScheduler { Key = Key, IV = IV }); BlockEncoder decoder = new BlockEncoder(new KeyScheduler { Key = Key, IV = IV }); byte[] block = hasher.ComputeHash(Key); byte[] encoded = encoder.Encode(block, iterations: 1); byte[] decoded = decoder.Decode(block, iterations: 1); }
void Encode_zero_blocks() { string errorMessage; errorMessage = BlockEncoder.Encode(16, new InstructionBlock[0], BlockEncoderOptions.None); Assert.Null(errorMessage); errorMessage = BlockEncoder.Encode(32, new InstructionBlock[0], BlockEncoderOptions.None); Assert.Null(errorMessage); errorMessage = BlockEncoder.Encode(64, new InstructionBlock[0], BlockEncoderOptions.None); Assert.Null(errorMessage); }
public JccInstr(BlockEncoder blockEncoder, ref Instruction instruction) : base(blockEncoder, instruction.IP64) { bitness = blockEncoder.Bitness; this.instruction = instruction; instrKind = InstrKind.Uninitialized; string errorMessage; if (!blockEncoder.FixBranches) { instrKind = InstrKind.Unchanged; Size = (uint)blockEncoder.NullEncoder.Encode(ref instruction, instruction.IP64, out errorMessage); if (errorMessage != null) { Size = DecoderConstants.MaxInstructionLength; } } else { Instruction instrCopy; instrCopy = instruction; instrCopy.Code = instruction.Code.ToShortBranchCode(); instrCopy.NearBranch64Target = 0; shortInstructionSize = (uint)blockEncoder.NullEncoder.Encode(ref instrCopy, 0, out errorMessage); if (errorMessage != null) { shortInstructionSize = DecoderConstants.MaxInstructionLength; } instrCopy = instruction; instrCopy.Code = instruction.Code.ToNearBranchCode(); instrCopy.NearBranch64Target = 0; nearInstructionSize = (uint)blockEncoder.NullEncoder.Encode(ref instrCopy, 0, out errorMessage); if (errorMessage != null) { nearInstructionSize = DecoderConstants.MaxInstructionLength; } if (blockEncoder.Bitness == 64) { // Make sure it's not shorter than the real instruction. It can happen if there are extra prefixes. Size = Math.Max(nearInstructionSize, longInstructionSize64); } else { Size = nearInstructionSize; } } }
/// <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()); }
public JmpInstr(BlockEncoder blockEncoder, ref Instruction instruction) : base(blockEncoder, instruction.IP64) { bitness = blockEncoder.Bitness; this.instruction = instruction; instrKind = InstrKind.Uninitialized; string errorMessage; Instruction instrCopy; if (!blockEncoder.FixBranches) { instrKind = InstrKind.Unchanged; instrCopy = instruction; instrCopy.NearBranch64 = 0; if (!blockEncoder.NullEncoder.TryEncode(ref instrCopy, 0, out Size, out errorMessage)) { Size = DecoderConstants.MaxInstructionLength; } } else { instrCopy = instruction; instrCopy.Code = instruction.Code.ToShortBranchCode(); instrCopy.NearBranch64 = 0; if (!blockEncoder.NullEncoder.TryEncode(ref instrCopy, 0, out shortInstructionSize, out errorMessage)) { shortInstructionSize = DecoderConstants.MaxInstructionLength; } instrCopy = instruction; instrCopy.Code = instruction.Code.ToNearBranchCode(); instrCopy.NearBranch64 = 0; if (!blockEncoder.NullEncoder.TryEncode(ref instrCopy, 0, out nearInstructionSize, out errorMessage)) { nearInstructionSize = DecoderConstants.MaxInstructionLength; } if (blockEncoder.Bitness == 64) { // Make sure it's not shorter than the real instruction. It can happen if there are extra prefixes. Size = Math.Max(nearInstructionSize, CallOrJmpPointerDataInstructionSize64); } else { Size = nearInstructionSize; } } }
public void EncodeAndDecode() { byte[] block = hasher.ComputeHash(Key); byte[] copy = (byte[])block.Clone(); BlockEncoder encoder = new BlockEncoder(new KeyScheduler { Key = Key, IV = IV }); List <EncodingPlan> plans = encoder.GetEncodingPlans(block.Length, CryptoTransform.MinRounds + CryptoTransform.MaxAdditionalRounds); plans.ForEach((EncodingPlan plan) => { block = encoder.EncodeBlock(plan, block); block = encoder.DecodeBlock(plan, block); CollectionAssert.AreEqual(block, copy); }); }
public Block(BlockEncoder blockEncoder, CodeWriter codeWriter, ulong rip, IList <RelocInfo> relocInfos, uint[] newInstructionOffsets, ConstantOffsets[] constantOffsets, Instr[] instructions) { CodeWriter = new CodeWriterImpl(codeWriter); RIP = rip; this.relocInfos = relocInfos; NewInstructionOffsets = newInstructionOffsets; ConstantOffsets = constantOffsets; Instructions = instructions ?? throw new ArgumentNullException(nameof(instructions)); dataList = new List <BlockData>(); alignment = (uint)blockEncoder.Bitness / 8; validData = new List <BlockData>(); foreach (var instr in instructions) { instr.Block = this; } }
public void EncodeDecodeBlockWithTransaction() { BlockEncoder encoder = new BlockEncoder(); Address from = new Address(); Address to = new Address(); Transaction transaction = new Transaction(from, to, new BigInteger(2)); Block original = new Block(0, null, new Transaction[] { transaction }); Block block = encoder.Decode(encoder.Encode(original)); Assert.IsNotNull(block.Transactions); Assert.AreEqual(1, block.Transactions.Count); Transaction result = block.Transactions.First(); Assert.AreEqual(new BigInteger(2), result.Value); }
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); }
void Encode_zero_instructions() { string errorMessage; var codeWriter = new CodeWriterImpl(); errorMessage = BlockEncoder.Encode(16, new InstructionBlock(codeWriter, Array.Empty <Instruction>(), 0, Array.Empty <RelocInfo>(), Array.Empty <uint>(), Array.Empty <ConstantOffsets>()), BlockEncoderOptions.None); Assert.Null(errorMessage); Assert.Empty(codeWriter.ToArray()); errorMessage = BlockEncoder.Encode(32, new InstructionBlock(codeWriter, Array.Empty <Instruction>(), 0, Array.Empty <RelocInfo>(), Array.Empty <uint>(), Array.Empty <ConstantOffsets>()), BlockEncoderOptions.None); Assert.Null(errorMessage); Assert.Empty(codeWriter.ToArray()); errorMessage = BlockEncoder.Encode(64, new InstructionBlock(codeWriter, Array.Empty <Instruction>(), 0, Array.Empty <RelocInfo>(), Array.Empty <uint>(), Array.Empty <ConstantOffsets>()), BlockEncoderOptions.None); Assert.Null(errorMessage); Assert.Empty(codeWriter.ToArray()); }
public void Encode() { List <string> results = new List <string>() { }; for (int i = CryptoTransform.MinRounds; i < CryptoTransform.MinRounds + CryptoTransform.MaxAdditionalRounds; i++) { BlockEncoder instance = new BlockEncoder(new KeyScheduler { Key = Key, IV = IV }); byte[] block = hasher.ComputeHash(Key); byte[] encoded = instance.Encode(block, iterations: i); Assert.IsTrue(block.Length == encoded.Length); results.Add(Encoding.ASCII.GetString(encoded)); } CollectionAssert.AllItemsAreUnique(results); }