Exemple #1
0
        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);
        }
Exemple #4
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);
        }
Exemple #6
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;
        }
Exemple #7
0
 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);
        }
Exemple #9
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;
        }
Exemple #10
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());
        }
Exemple #11
0
 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;
     }
 }
Exemple #12
0
 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>();
 }
Exemple #13
0
        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);
        }
Exemple #14
0
 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);
        }
Exemple #20
0
        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);
        }
Exemple #22
0
        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;
                }
            }
        }
Exemple #23
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());
        }
Exemple #24
0
        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;
                }
            }
        }
Exemple #25
0
        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);
            });
        }
Exemple #26
0
 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());
        }
Exemple #30
0
        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);
        }