private bool InstructionIsPush_EBP(IAssemblyInstructionForTransformation instruction)
 {
     return(instruction.Mnemonic == SharpDisasm.Udis86.ud_mnemonic_code.UD_Ipush &&
            instruction.Operands != null &&
            instruction.Operands.Count() == 1 &&
            instruction.Operands[0].Base == SharpDisasm.Udis86.ud_type.UD_R_EBP);
 }
        public IReadOnlyList <IFunction> Parse(IAssemblyInstructionForTransformation firstAssemblyInstruction,
                                               AddressesRange addressesRangePermittedForParsing, Dictionary <ulong, ulong> jumpTargetAddresses)
        {
            if (firstAssemblyInstruction == null)
            {
                throw new ArgumentNullException("firstAssemblyInstruction");
            }

            List <IFunction> functionsList = new List <IFunction>();
            var instruction = firstAssemblyInstruction;

            while (instruction != null && instruction.Offset <= addressesRangePermittedForParsing.EndAddress)
            {
                var prologInstruction = PrologParser.Parse(instruction, addressesRangePermittedForParsing.EndAddress);
                if (prologInstruction == null)
                {
                    break;
                }

                var epilogInstruction = EpilogParser.Parse(prologInstruction, addressesRangePermittedForParsing.EndAddress);
                if (epilogInstruction == null)
                {
                    break;
                }

                IReadOnlyList <IBasicBlock> basicBlocks = BasicBlockParser.Parse(prologInstruction,
                                                                                 epilogInstruction, jumpTargetAddresses);
                functionsList.Add(FunctionFactory.Create(prologInstruction, epilogInstruction, basicBlocks));

                //set instruction to the instruction after the epilog instruction
                instruction = epilogInstruction.NextInstruction;
            }

            return(functionsList);
        }
        /// <summary>
        /// Parse a function prolog given an assembly instruction to start from.
        /// Searches for the pattern of :
        /// push ebp
        /// mov  ebp, esp
        /// </summary>
        /// <param name="assemblyToStartFrom">Assembly instruction to start from </param>
        /// <param name="lastAddress">last address to try parsing</param>
        /// <returns>the address where the function starts,null otherwise</returns>
        public IAssemblyInstructionForTransformation Parse(IAssemblyInstructionForTransformation assemblyToStartFrom, ulong lastAddress)
        {
            if (assemblyToStartFrom == null)
            {
                throw new ArgumentNullException("assemblyToStartFrom");
            }
            if (assemblyToStartFrom.Offset >= lastAddress)
            {
                throw new ArgumentOutOfRangeException("lastAddress", "assembly start address can not be greater nor equal to the last address param");
            }
            IAssemblyInstructionForTransformation currentInstruction = assemblyToStartFrom;

            while (currentInstruction != null && currentInstruction.Offset <= lastAddress)
            {
                //if current examined instruction is PUSH EBP
                if (InstructionIsPush_EBP(currentInstruction) &&
                    currentInstruction.NextInstruction != null &&
                    //and next instruction is MOV EBP ESP
                    InstructionIsMov_EBP_ESP(currentInstruction.NextInstruction))
                {
                    return(currentInstruction);
                }
                currentInstruction = currentInstruction.NextInstruction;
            }

            return(null);
        }
        public bool IsInstructionWithAbsoluteAddressOperand(
            IAssemblyInstructionForTransformation instruction,
            ICodeInMemoryLayout codeInMemoryLayout, out ulong addressOperand)
        {
            var codeBeginAddress = codeInMemoryLayout.CodeVirtualAddress +
                                   codeInMemoryLayout.ImageBaseAddress;
            var codeEndAddress = codeInMemoryLayout.CodeVirtualAddress +
                                 codeInMemoryLayout.CodePhysicalSizeInBytes +
                                 codeInMemoryLayout.ImageBaseAddress;

            addressOperand = ulong.MaxValue;

            if (instruction.Operands == null || instruction.Operands.Length == 0)
            {
                return(false);
            }
            for (int i = 0; i < instruction.Operands.Length; i++)
            {
                if (instruction.Operands[i].SignedValue >= (long)codeBeginAddress &&
                    instruction.Operands[i].SignedValue < (long)codeEndAddress)
                {
                    if (instruction.Mnemonic == ud_mnemonic_code.UD_Ijmp)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                    addressOperand = (ulong)instruction.Operands[i].SignedValue;
                    return(true);
                }
            }

            return(false);
        }
 private bool InstructionIsMov_EBP_ESP(IAssemblyInstructionForTransformation instruction)
 {
     return(instruction.Mnemonic == SharpDisasm.Udis86.ud_mnemonic_code.UD_Imov &&
            instruction.Operands != null &&
            instruction.Operands.Count() == 2 &&
            instruction.Operands[0].Base == SharpDisasm.Udis86.ud_type.UD_R_EBP &&
            instruction.Operands[1].Base == SharpDisasm.Udis86.ud_type.UD_R_ESP);
 }
Exemplo n.º 6
0
 public IFunction Create(IAssemblyInstructionForTransformation startInstruction,
                         IAssemblyInstructionForTransformation endInstruction,
                         IReadOnlyList <IBasicBlock> basicBlocks)
 {
     return(Container.Container.Resolve <IFunction>(new Parameter(nameof(startInstruction), startInstruction),
                                                    new Parameter(nameof(endInstruction), endInstruction),
                                                    new Parameter(nameof(basicBlocks), basicBlocks)));
 }
 public bool IsReturnInstruction(IAssemblyInstructionForTransformation instruction)
 {
     return(instruction.Mnemonic == SharpDisasm.Udis86.ud_mnemonic_code.UD_Iiretw ||
            instruction.Mnemonic == SharpDisasm.Udis86.ud_mnemonic_code.UD_Iiretd ||
            instruction.Mnemonic == SharpDisasm.Udis86.ud_mnemonic_code.UD_Iiretq ||
            instruction.Mnemonic == SharpDisasm.Udis86.ud_mnemonic_code.UD_Iret ||
            instruction.Mnemonic == SharpDisasm.Udis86.ud_mnemonic_code.UD_Iretf);
 }
Exemplo n.º 8
0
 public Function(IAssemblyInstructionForTransformation startInstruction,
                 IAssemblyInstructionForTransformation endInstruction,
                 IReadOnlyList <IBasicBlock> basicBlocks)
 {
     StartInstruction = startInstruction ?? throw new ArgumentNullException("startInstrucion");
     EndInstruction   = endInstruction ?? throw new ArgumentNullException("endInstruction");
     AddressesRange   = new AddressesRange(startInstruction.Offset, endInstruction.Offset);
     BasicBlocks      = basicBlocks ?? throw new ArgumentNullException("basicBlocks");
 }
 public bool IsCallInstruction(IAssemblyInstructionForTransformation instruction)
 {
     if (instruction == null)
     {
         throw new ArgumentNullException(nameof(instruction));
     }
     if (instruction.Mnemonic != ud_mnemonic_code.UD_Icall)
     {
         return(false);
     }
     return(instruction.Operands != null && instruction.Operands.Length == 1);
 }
 public bool IsJumpInstructionWithRelativeAddressOperand(IAssemblyInstructionForTransformation instruction)
 {
     if (instruction == null)
     {
         throw new ArgumentNullException(nameof(instruction));
     }
     if (instruction.Operands == null || instruction.Operands.Length == 0)
     {
         return(false);
     }
     return(IsJumpInstruction(instruction.Mnemonic) &&
            instruction.Operands[0].Type == ud_type.UD_OP_JIMM);
 }
Exemplo n.º 11
0
        public ICode Create(IAssemblyInstructionForTransformation firstInstruction,
                            IReadOnlyList <IFunction> functions,
                            ICodeInMemoryLayout codeInMemoryLayout)
        {
            if (firstInstruction == null)
            {
                throw new ArgumentNullException(nameof(firstInstruction));
            }
            var instruction      = firstInstruction;
            var instructionsList = new List <IAssemblyInstructionForTransformation>();

            return(Create(instructionsList, functions, codeInMemoryLayout));
        }
        private byte[] GetEmptyExapndedJumpInstructionWith4Bytes(IAssemblyInstructionForTransformation instruction)
        {
            byte[] newInstructionBytes;
            //get the instruction's bytes from dictionary
            newInstructionBytes = m_dictionaryJumpInstructionBytes[instruction.Mnemonic];
            ////we can not replace this instruction, (jcxz,jecxz instructions) because of different parameters size
            if (newInstructionBytes.Length <= 3)
            {
                throw new NotSupportedException("transformation doesn not support jcxz,jecxz instruction for now :(");
            }

            //copy the original target address to the new bytes of the instruction
            //get a copy of the same instruction with 4 bytes operand size.
            return((byte[])m_dictionaryJumpInstructionBytes[instruction.Mnemonic].Clone());
        }
        public bool TryCreateNegativeJumpIntruction(IAssemblyInstructionForTransformation instruction,
                                                    int instructionOffset, out IAssemblyInstructionForTransformation newInstruction)
        {
            newInstruction = null;

            if (instruction == null ||
                !m_InstructionWithAddressOperandDecider.IsConditionalJumpInstruction(instruction.Mnemonic))
            {
                return(false);
            }

            newInstruction = CreateNegativeJumpInstruction(instruction, instructionOffset);

            return(newInstruction != null);
        }
        public bool TryTransformJumpInstructionTo4BytesOperandSize(IAssemblyInstructionForTransformation instruction,
                                                                   out IAssemblyInstructionForTransformation transformedInstruction)
        {
            transformedInstruction = instruction;

            if (instruction == null)
            {
                throw new ArgumentNullException(nameof(instruction));
            }
            if (!m_InstructionWithAddressOperandDecider.IsJumpInstruction(instruction.Mnemonic))
            {
                throw new ArgumentException("instruction is not a jump instruction");
            }
            if (!m_InstructionWithAddressOperandDecider.IsJumpInstructionWithRelativeAddressOperand(instruction))
            {
                return(false);
            }
            if (!m_dictionaryJumpInstructionBytes.ContainsKey(instruction.Mnemonic))
            {
                return(false);
            }
            if (instruction.Operands[0].Size == 32)
            {
                return(false);                                   //because the size of operand is already 4 bytes
            }
            var operand = instruction.Operands[0];

            if (operand == null)
            {
                throw new ApplicationException("Jump instruction transformation didn't find an operand with JIMM type. program doesnt support other types.");
            }

            //get an expanded jump instruction with 4 bytes, which have empty (or incorrect operand bytes).
            var newInstructionBytes = GetEmptyExapndedJumpInstructionWith4Bytes(instruction);

            //fill the target address with the new operand bytes
            var newInstructionBytesWithTargetAddress = FillInstructionWithOperandBytes(instruction, newInstructionBytes);

            //create new insruction from the bytes of new instruction
            transformedInstruction = m_disasmFactory.Create(newInstructionBytes, false).Disassemble().First();
            transformedInstruction.SetOffset(instruction.Offset);
            transformedInstruction.SetPC(instruction.PC);

            return(true);
        }
Exemplo n.º 15
0
        private void ValidateNewCode(ICode code)
        {
            IAssemblyInstructionForTransformation lastInstruction = null;
            var instructionEnumerator = code.AssemblyInstructions.GetEnumerator();

            while (instructionEnumerator.MoveNext())
            {
                if (lastInstruction != null && !instructionEnumerator.Current.IsNew &&
                    lastInstruction.Offset >= instructionEnumerator.Current.Offset)
                {
                    var instructionIndex = ((List <IAssemblyInstructionForTransformation>)code.AssemblyInstructions).IndexOf(instructionEnumerator.Current);
                    throw new ApplicationException($"Code structure is incorrect. instruction:{instructionEnumerator.Current.ToString()}" +
                                                   $"at index {instructionIndex} has higher or equal address than last instruction {lastInstruction.ToString()}");
                }
                if (!instructionEnumerator.Current.IsNew)
                {
                    lastInstruction = instructionEnumerator.Current;
                }
            }
        }
        public void IncrementInstructionAddressTest()
        {
            //arrange
            byte[] code        = new byte[] { 0xeb, 0xe9 }; //jmp 0xe9
            var    instruction = new DisassemblerFactory().Create(code).Disassemble().First();
            IAssemblyInstructionForTransformation newInstruction = null;

            //act
            try
            {
                newInstruction = m_jumpTransform.IncrementJumpInstructionTargetAddress(instruction, 5);
            }
            catch (Exception ex)
            {
                Assert.Fail("IncrementInstructionAddressTest. Details:" + ex.ToString());
            }


            //assert
            Assert.IsTrue(ArrayEquals(newInstruction.Bytes, new byte[] { 0xeb, 0xee }));
        }
        public IAssemblyInstructionForTransformation CreateNegativeJumpInstruction(
            IAssemblyInstructionForTransformation instruction, int instructionOffset)
        {
            if (instruction == null)
            {
                throw new ArgumentNullException(nameof(instruction));
            }
            if (!m_InstructionWithAddressOperandDecider.IsJumpInstruction(instruction.Mnemonic))
            {
                throw new ArgumentException("instruction must be jump instruction", nameof(instruction));
            }

            if (!m_dictionaryOfJumpToNegativeJump.ContainsKey(instruction.Mnemonic))
            {
                return(null);
            }
            var negativeJump = m_dictionaryOfJumpToNegativeJump[instruction.Mnemonic];

            //get instrution with 4 bytes operand
            var jumpInstructionBytes = (byte[])m_dictionaryJumpInstructionBytes[negativeJump].Clone();

            if (jumpInstructionBytes.Length != 6)
            {
                throw new ApplicationException("creating new conditional jump instruction consists of instruction 6 bytes long");
            }

            //set the required offset
            var bytesWithAddressShift = BitConverter.GetBytes(instructionOffset);

            //change the address from index 2 to 5. The size of the instruction is 6.
            var addressIdx = 2;

            replaceBytes(jumpInstructionBytes, addressIdx, bytesWithAddressShift);

            //create new instruction based on the new bytes
            var disasm         = m_disasmFactory.Create(jumpInstructionBytes);
            var newInstruction = disasm.Disassemble().First();

            return(newInstruction);
        }
Exemplo n.º 18
0
        private List <IAssemblyInstructionForTransformation> ParseInstructions(byte[] code)
        {
            var disasm = m_disassemblerFactory.Create(code);

            if (disasm == null)
            {
                throw new NullReferenceException(nameof(disasm));
            }

            // Disassemble each instruction and output to console
            IAssemblyInstructionForTransformation lastInstruction = null;
            var listOfInstruction = new List <IAssemblyInstructionForTransformation>();

            foreach (IAssemblyInstructionForTransformation instruction in disasm.Disassemble())
            {
                if (instruction == null)
                {
                    StringBuilder errorMessage = new StringBuilder("can not disassemble instruction after ");
                    if (lastInstruction != null)
                    {
                        errorMessage.Append(lastInstruction.Offset.ToString());
                    }
                    else
                    {
                        errorMessage.Append("Begining of program");
                    }
                    throw new ApplicationException(errorMessage.ToString());
                }
                if (lastInstruction != null)
                {
                    lastInstruction.NextInstruction = instruction;
                    instruction.PreviousInstruction = lastInstruction;
                }
                listOfInstruction.Add(instruction);
                lastInstruction = instruction;
            }

            return(listOfInstruction);
        }
        private byte[] FillInstructionWithOperandBytes(IAssemblyInstructionForTransformation instruction,
                                                       byte[] instructionBytes)
        {
            long targetAddressShiftAsLong;

            bool succeededGettingAddress = instruction.TryParseInstructionTargetAddress(InstructionToStringTargetAddressMode.AddressShift,
                                                                                        out targetAddressShiftAsLong);

            if (!succeededGettingAddress)
            {
                throw new ApplicationException("jump instruction should have target address");
            }

            byte[] targetAddressBytes = BitConverter.GetBytes((int)targetAddressShiftAsLong);
            int    operandBytesOffset = instructionBytes.Length - 4;

            for (int j = 0; j < 4; j++)
            {
                instructionBytes[j + operandBytesOffset] = targetAddressBytes[j];
            }
            return(instructionBytes);
        }
        public IAssemblyInstructionForTransformation Parse(
            IAssemblyInstructionForTransformation assemblyToStartFrom, ulong lastAddress,
            Dictionary <ulong, ulong> jumpTargetAddresses)
        {
            if (assemblyToStartFrom == null)
            {
                throw new ArgumentNullException(nameof(assemblyToStartFrom));
            }
            if (jumpTargetAddresses == null)
            {
                throw new ArgumentNullException(nameof(jumpTargetAddresses));
            }
            var currentInstruction = assemblyToStartFrom;
            var epilogFound        = false;

            do
            {
                if (m_jumpInstructionDecider.IsJumpInstruction(currentInstruction.Mnemonic) ||
                    m_jumpInstructionDecider.IsReturnInstruction(currentInstruction) ||
                    m_jumpInstructionDecider.IsCallInstruction(currentInstruction) ||
                    (currentInstruction.NextInstruction != null &&
                     InstructionIsJumpTarget(currentInstruction.NextInstruction, jumpTargetAddresses)))
                {
                    //epilog instruction is found
                    epilogFound = true;
                    break;
                }
                currentInstruction = currentInstruction.NextInstruction;
            } while (currentInstruction.Offset <= lastAddress);

            var returnedInstruction = currentInstruction;

            if (!epilogFound)
            {
                returnedInstruction = null;
            }
            return(returnedInstruction);
        }
        public IAssemblyInstructionForTransformation Parse(IAssemblyInstructionForTransformation assemblyToStartFrom, ulong lastAddress)
        {
            if (assemblyToStartFrom == null)
            {
                throw new ArgumentNullException("assemblyToStartFrom");
            }
            if (assemblyToStartFrom.Offset >= lastAddress)
            {
                throw new ArgumentOutOfRangeException("lastAddress", "assembly start address can not be greater nor equal to the last address param");
            }
            IAssemblyInstructionForTransformation currentInstruction = assemblyToStartFrom;

            while (currentInstruction != null && currentInstruction.Offset <= lastAddress)
            {
                if (InstructionIsRet(currentInstruction))
                {
                    return(currentInstruction);
                }
                currentInstruction = currentInstruction.NextInstruction;
            }

            return(null);
        }
Exemplo n.º 22
0
        public IReadOnlyList <IBasicBlock> Parse(IAssemblyInstructionForTransformation firstInstruction,
                                                 IAssemblyInstructionForTransformation lastInstruction, Dictionary <ulong, ulong> jumpTargetAddresses)
        {
            if (firstInstruction == null)
            {
                throw new ArgumentNullException(nameof(firstInstruction));
            }
            if (lastInstruction == null)
            {
                throw new ArgumentNullException(nameof(lastInstruction));
            }
            if (jumpTargetAddresses == null)
            {
                throw new ArgumentNullException(nameof(jumpTargetAddresses));
            }
            if (firstInstruction.Offset >= lastInstruction.Offset)
            {
                throw new ArgumentException("first argument address should be less then last argument address", "firstInstruction");
            }

            List <IBasicBlock> basicBlocks = new List <IBasicBlock>();
            var currrentInstruction        = firstInstruction;

            while (currrentInstruction.Offset <= lastInstruction.Offset)
            {
                //find the basic block epilog
                var basicBlockEpilog = BasicBlockEpilogParser.Parse(currrentInstruction,
                                                                    lastInstruction.Offset, jumpTargetAddresses);

                //no epilog was found, for example because the code examined is not a function or ends when the whole code section ends...
                if (basicBlockEpilog == null)
                {
                    break;
                }

                //initialize the assembly instructions of the current basic block being parsed.
                var assemblyInstructions = new List <IAssemblyInstructionForTransformation>()
                {
                    currrentInstruction
                };

                //Add all instruction in between the current and epilog instruction of the basic block
                if (currrentInstruction != basicBlockEpilog)
                {
                    currrentInstruction = currrentInstruction.NextInstruction;
                    while (currrentInstruction != null &&  //may not be possible to happen
                           currrentInstruction != basicBlockEpilog)
                    {
                        assemblyInstructions.Add(currrentInstruction);
                        currrentInstruction = currrentInstruction.NextInstruction;
                    }

                    //add epilog instruction
                    assemblyInstructions.Add(basicBlockEpilog);
                }

                IBasicBlock basicBlock = BasicBlockFactory.Create(assemblyInstructions);
                basicBlocks.Add(basicBlock);
                currrentInstruction = currrentInstruction.NextInstruction;
            }
            return(basicBlocks);
        }
 private bool IsJumpInstructionToCodeSection(ICode code, IAssemblyInstructionForTransformation instruction)
 {
     return(instruction.GetAbsoluteAddressFromRelativeAddress() < (code.CodeInMemoryLayout.CodeVirtualAddress + code.CodeInMemoryLayout.CodeActualSizeInBytes));
 }
 public bool IsCallInstructionWithAddressOperand(IAssemblyInstructionForTransformation instruction)
 {
     return(IsCallInstruction(instruction) &&
            instruction.Operands[0].Type == ud_type.UD_OP_JIMM);
 }
        private bool TryGenerateJunkInstruction(IBasicBlock basicBlock,
                                                IJunkBytesProvider junkBytesProvider,
                                                IStatistics statistics,
                                                out IAssemblyInstructionForTransformation junkInstruction)
        {
            junkInstruction = null;
            bool retVal = false;

            //get junk bytes
            byte[] junkBytes = junkBytesProvider.GetJunkBytes();
            if (junkBytes == null)
            {
                throw new NullReferenceException(nameof(junkBytes));
            }

            //get basic block bytes
            byte[] basicBlockBytes = basicBlock.GetAllBytes();

            //the size of the junk we try to insert
            uint junkBytesSize = (uint)junkBytes.Count();

            //the inde of the most far insruction that has been syncronized
            uint mostFarSyncInstructionIdx = 0;
            //the partial instruction that causes the synchronization to be far as possible
            uint bestPartialInstructionSize = 0;

            //check what sub array of the inserted junk causes the most of confusion
            //so instruction are disassembled not correctly as far as possible
            while (junkBytesSize > 0)
            {
                uint   sizeOfNewBytesArray = basicBlock.NumberOfBytes + junkBytesSize;
                byte[] newBasicBlockBytes  = new byte[sizeOfNewBytesArray];

                //copy junk bytes and then basic block bytes
                Array.Copy(junkBytes, newBasicBlockBytes, junkBytesSize);
                basicBlockBytes.CopyTo(newBasicBlockBytes, junkBytesSize);

                //the index of first identical disassembled instruction to original
                uint?indexOfFirstIdenticalInstruction = CompareDisassembleToOriginal(newBasicBlockBytes, basicBlock,
                                                                                     m_disassemblerFactory);

                //in case that there is no even one instruction that synchronizes, so try another sequence
                //because the parsing error can not proceed to the next block
                if (!indexOfFirstIdenticalInstruction.HasValue)
                {
                    junkBytesSize--;
                    continue;
                }

                if (indexOfFirstIdenticalInstruction.Value > mostFarSyncInstructionIdx)
                {
                    mostFarSyncInstructionIdx  = indexOfFirstIdenticalInstruction.Value;
                    bestPartialInstructionSize = junkBytesSize;
                }

                junkBytesSize--;
            }

            //update basic block with the instruction that causes the synchronization to be as far as
            //possible
            if (mostFarSyncInstructionIdx > 0)
            {
                byte[] junkBytesSelected = new byte[bestPartialInstructionSize];
                for (int i = 0; i < bestPartialInstructionSize; i++)
                {
                    junkBytesSelected[i] = junkBytes[i];
                }

                var disasm = m_disassemblerFactory.Create(junkBytesSelected);
                junkInstruction       = disasm.Disassemble().First();
                junkInstruction.IsNew = true;

                statistics.IncrementMissinterpretedInstructions(mostFarSyncInstructionIdx);
                statistics.IncrementJunkInstructions(1, (uint)junkInstruction.Length);
                retVal = true;
            }

            return(retVal);
        }
 private bool InstructionIsJumpTarget(IAssemblyInstructionForTransformation instruction,
                                      Dictionary <ulong, ulong> jumpTargetAddresses)
 {
     return(jumpTargetAddresses.ContainsKey(instruction.Offset));
 }
        public IAssemblyInstructionForTransformation CreateInstructionWithNewAddress(ICode code,
                                                                                     IAssemblyInstructionForTransformation instruction, ulong newProgramCounter,
                                                                                     ulong newOffset, ulong oldAddressInOperand, ulong newAddressInOperand)
        {
            if (instruction == null)
            {
                throw new ArgumentNullException(nameof(instruction));
            }
            if (code == null)
            {
                throw new ArgumentNullException(nameof(code));
            }
            if (instruction.Operands == null)
            {
                throw new ArgumentException("parameters operands can be 0", "instruction.Operands");
            }
            if (instruction.Operands.Count() == 0)
            {
                throw new ArgumentException("parameters operands can not be 0");
            }

            var opr = instruction.Operands[0];

            //same instruction target, no change is needed
            if (oldAddressInOperand == newAddressInOperand)
            {
                instruction.SetOffset(newOffset);
                instruction.SetPC(newProgramCounter);
                return(instruction);
            }


            byte[] oldAddressBytes = BitConverter.GetBytes((uint)oldAddressInOperand);
            byte[] newAddressBytes = BitConverter.GetBytes((uint)newAddressInOperand);
            int    idx             = FindOriginalBytesIndex(instruction.Bytes, oldAddressBytes);

            if (idx < 0)
            {
                throw new ApplicationException("Could not replace target address in instruction");
            }

            byte[] newInstructionBytes = instruction.Bytes.Clone() as byte[];
            replaceBytes(newInstructionBytes, idx, newAddressBytes);

            //create new instruction based on the new bytes
            var disasm         = m_disasmFactory.Create(newInstructionBytes);
            var newInstruction = disasm.Disassemble().First();

            newInstruction.SetOffset(newOffset);
            newInstruction.SetPC(newProgramCounter);

            //validate new instructions
            ulong parsedAddress;

            if (!newInstruction.TryGetAbsoluteAddressFromAnyOperand(code.CodeInMemoryLayout, out parsedAddress) ||
                newAddressInOperand != parsedAddress)
            {
                throw new ApplicationException("updating jump instruction target address failed");
            }
            return(newInstruction);
        }
Exemplo n.º 28
0
        public ICode Transform(ICode code, TryTransformInstructionDelegate transformInstructionDelegate,
                               Func <ICodeInMemoryLayout> codeInLayoutFactoryDelegate = null)
        {
            var newInstructionsList        = new List <IAssemblyInstructionForTransformation>();
            var newFunctionsList           = new List <IFunction>();
            var instructionListIterator    = code.AssemblyInstructions.GetEnumerator();
            var lastInstructionInLastBlock = code.Functions.Last().BasicBlocks.Last().AssemblyInstructions.Last();
            IAssemblyInstructionForTransformation previousInstruction = null;
            bool afterInstructionOfLastBlock = false;

            //move to the first instruction
            instructionListIterator.MoveNext();

            //iterate through all functions
            foreach (var function in code.Functions)
            {
                var basicBlockList = new List <IBasicBlock>();
                //iterate through all basic block
                foreach (var basicBlock in function.BasicBlocks)
                {
                    var instructionsListOfBlock = new List <IAssemblyInstructionForTransformation>();
                    foreach (var instructionInBasicBlock in basicBlock.AssemblyInstructions)
                    {
                        bool isInstructionInBasicBlock;
                        bool done = false;

                        //transform instructions from instruction list.
                        //this loop transform:
                        //1. instructions before the basic block which are left to process
                        //2. instructions inside a basic block
                        //3. instructions after the last basic block
                        while (!done)
                        {
                            isInstructionInBasicBlock = instructionListIterator.Current == instructionInBasicBlock;
                            IAssemblyInstructionForTransformation instructionToTransform =
                                instructionListIterator.Current;

                            //perfom the transformation of the instruction
                            List <IAssemblyInstructionForTransformation> transformedInstructionList;
                            var wasTransformed = transformInstructionDelegate(instructionToTransform,
                                                                              isInstructionInBasicBlock ? basicBlock : null,
                                                                              isInstructionInBasicBlock ? function : null,
                                                                              out transformedInstructionList);

                            if (wasTransformed)
                            {
                                if (transformedInstructionList.Count == 0)
                                {
                                    throw new ApplicationException("transformation should return at least one instruction");
                                }

                                if (isInstructionInBasicBlock)
                                {
                                    instructionsListOfBlock.AddRange(transformedInstructionList);
                                }
                                newInstructionsList.AddRange(transformedInstructionList);

                                if (previousInstruction != null)
                                {
                                    transformedInstructionList[0].PreviousInstruction = previousInstruction;
                                    previousInstruction.NextInstruction = transformedInstructionList[0];
                                }

                                if (transformedInstructionList.Count > 1)
                                {
                                    for (int i = 1; i < transformedInstructionList.Count; i++)
                                    {
                                        transformedInstructionList[i].PreviousInstruction = transformedInstructionList[i - 1];
                                        transformedInstructionList[i - 1].NextInstruction = transformedInstructionList[i];
                                    }
                                }

                                previousInstruction = transformedInstructionList.Last();
                            }
                            else
                            {
                                if (isInstructionInBasicBlock)
                                {
                                    instructionsListOfBlock.Add(instructionToTransform);
                                }
                                newInstructionsList.Add(instructionToTransform);
                                if (previousInstruction != null)
                                {
                                    instructionToTransform.PreviousInstruction = previousInstruction;
                                    previousInstruction.NextInstruction        = instructionToTransform;
                                }
                                previousInstruction = instructionToTransform;
                            }

                            //check weather this is the last instruction in the last basic block
                            if (isInstructionInBasicBlock && !afterInstructionOfLastBlock)
                            {
                                //The transformed instruction is now in the end of program
                                //after the last basic block instruction
                                afterInstructionOfLastBlock = (instructionToTransform == lastInstructionInLastBlock);
                            }

                            instructionListIterator.MoveNext();

                            //stop transforming intructions in loop when all instruction in scope are processed
                            done = (isInstructionInBasicBlock ||
                                    instructionListIterator.Current == null);

                            //keep transforming after the last basic block instruction to the end of the program
                            if (afterInstructionOfLastBlock && instructionListIterator.Current != null)
                            {
                                done = false;
                            }
                        }
                    }

                    IBasicBlock newBasicBlock = m_basicBlockFactory.Create(instructionsListOfBlock);
                    basicBlockList.Add(newBasicBlock);
                }

                var newFunction = m_functionFactory.Create(basicBlockList.First().AssemblyInstructions.First(),
                                                           basicBlockList.Last().AssemblyInstructions.Last(),
                                                           basicBlockList);
                newFunctionsList.Add(newFunction);
            }


            //if there is a factory to create a new code in memory layout structure than use it, otherwise use
            //the original code layout in memrory instance
            ICodeInMemoryLayout codeInMemoryLayout = codeInLayoutFactoryDelegate == null ? code.CodeInMemoryLayout:codeInLayoutFactoryDelegate();

            //return m_codeFactory.Create(newInstructionsList, newFunctionsList,codeInMemoryLayout);
            var newcode = m_codeFactory.Create(newInstructionsList, newFunctionsList, codeInMemoryLayout);

            ValidateNewCode(newcode);
            return(newcode);
        }
        public IAssemblyInstructionForTransformation CreateJumpInstructionWithNewTargetAddress(
            IAssemblyInstructionForTransformation instruction,
            ulong newProgramCounter, ulong newOffset, ulong newTargetAddress)
        {
            if (instruction == null)
            {
                throw new ArgumentNullException(nameof(instruction));
            }
            if (instruction.Operands == null)
            {
                throw new ArgumentException("parameters operands can be 0", "instruction.Operands");
            }
            if (instruction.Operands.Count() == 0)
            {
                throw new ArgumentException("parameters operands can not be 0");
            }
            if (instruction.Operands[0].Type != ud_type.UD_OP_JIMM)
            {
                throw new ArgumentException("parameters operand must be of type 'JIMM'");
            }

            var opr = instruction.Operands[0];

            //same instruction target, no change is needed
            if (instruction.GetAbsoluteAddressFromRelativeAddress(newProgramCounter) == newTargetAddress)
            {
                instruction.SetOffset(newOffset);
                instruction.SetPC(newProgramCounter);
                return(instruction);
            }

            byte[] bytesWithAddressShift = null;
            byte[] bytesOriginal         = null;
            byte[] newInstructionBytes   = instruction.Bytes.Clone() as byte[];

            int offsetValue = newTargetAddress > newProgramCounter ? (int)(newTargetAddress - newProgramCounter) : (int)(newProgramCounter - newTargetAddress) * -1;

            switch (opr.Size)
            {
            case 8:
                if (offsetValue > (long)sbyte.MaxValue)
                {
                    throw new ApplicationException("operand value is more than 128 which is the max value. operand size have to be extended!");
                }
                if (offsetValue < (long)sbyte.MinValue)
                {
                    throw new ApplicationException("operand value is less than -127 which is the min value. operand size have to be extended!");
                }
                bytesWithAddressShift = new byte[] { (byte)(offsetValue) };
                bytesOriginal         = new byte[] { (byte)(opr.LvalSByte) };
                break;

            case 16:
                if (offsetValue > short.MaxValue)
                {
                    throw new ApplicationException("operand value is more than 32,768 which is the max value. operand size have to be extended!");
                }
                if (offsetValue < short.MinValue)
                {
                    throw new ApplicationException("operand value is more than -32,767 which is the max value. operand size have to be extended!");
                }

                bytesWithAddressShift = BitConverter.GetBytes((short)(offsetValue));
                bytesOriginal         = BitConverter.GetBytes(opr.LvalSWord);
                break;

            case 32:
                if (offsetValue > int.MaxValue)
                {
                    throw new ApplicationException("operand value is more than 2,147,483,648 which is the max value.operand size have to be extended!");
                }
                if (offsetValue < int.MinValue)
                {
                    throw new ApplicationException("operand value is less than -2,147,483,647 which is the max value.operand size have to be extended!");
                }

                bytesWithAddressShift = BitConverter.GetBytes(offsetValue);
                break;
            }

            int idx = instruction.Bytes.Length - (opr.Size / 8);

            if (idx > -1)
            {
                replaceBytes(newInstructionBytes, idx, bytesWithAddressShift);
            }
            else
            {
                throw new ApplicationException("Could not replace target address in instruction");
            }

            //create new instruction based on the new bytes
            var disasm         = m_disasmFactory.Create(newInstructionBytes);
            var newInstruction = disasm.Disassemble().First();

            newInstruction.SetOffset(newOffset);
            newInstruction.SetPC(newProgramCounter);

            if (newTargetAddress != newInstruction.GetAbsoluteAddressFromRelativeAddress())
            {
                throw new ApplicationException("updating jump instruction target address failed");
            }
            return(newInstruction);
        }
        /// <summary>
        /// Increment the jump instruction target
        /// </summary>
        /// <param name="instruction">the jump instruction</param>
        /// <param name="addressShift">the address shift</param>
        /// <returns>new instruction that its target address is shifted by the parameter</returns>
        public IAssemblyInstructionForTransformation IncrementJumpInstructionTargetAddress(IAssemblyInstructionForTransformation instruction,
                                                                                           int addressShift)
        {
            if (instruction == null)
            {
                throw new ArgumentNullException(nameof(instruction));
            }
            if (instruction.Operands == null)
            {
                throw new ArgumentException("parameters operands can be 0", "instruction.Operands");
            }
            if (instruction.Operands.Count() == 0)
            {
                throw new ArgumentException("parameters operands can not be 0");
            }
            if (instruction.Operands[0].Type != ud_type.UD_OP_JIMM)
            {
                throw new ArgumentException("parameters operand must be of type 'JIMM'");
            }

            byte[] bytesWithAddressShift = null;
            byte[] bytesOriginal         = null;
            byte[] newInstructionBytes   = instruction.Bytes.Clone() as byte[];

            var opr = instruction.Operands[0];

            switch (opr.Size)
            {
            case 8:
                if (opr.LvalSByte + addressShift > sbyte.MaxValue)
                {
                    throw new ApplicationException("operand value is more than 128 which is the max value. operand size have to be extended!");
                }
                if (opr.LvalSByte + addressShift < sbyte.MinValue)
                {
                    throw new ApplicationException("operand value is less than -127 which is the min value. operand size have to be extended!");
                }

                bytesWithAddressShift = new byte[] { (byte)(opr.LvalSByte + addressShift) };
                bytesOriginal         = new byte[] { (byte)(opr.LvalSByte) };
                break;

            case 16:
                if (opr.LvalSWord + addressShift > short.MaxValue)
                {
                    throw new ApplicationException("operand value is more than 32,768 which is the max value. operand size have to be extended!");
                }
                if (opr.LvalSWord + addressShift < short.MinValue)
                {
                    throw new ApplicationException("operand value is more than -32,767 which is the max value. operand size have to be extended!");
                }

                bytesWithAddressShift = BitConverter.GetBytes((short)(opr.LvalSWord + addressShift));
                bytesOriginal         = BitConverter.GetBytes(opr.LvalSWord);
                break;

            case 32:
                if (opr.LvalSDWord + addressShift > int.MaxValue)
                {
                    throw new ApplicationException("operand value is more than 2,147,483,648 which is the max value.operand size have to be extended!");
                }
                if (opr.LvalSDWord + addressShift < int.MinValue)
                {
                    throw new ApplicationException("operand value is less than -2,147,483,647 which is the max value.operand size have to be extended!");
                }

                bytesWithAddressShift = BitConverter.GetBytes(opr.LvalSDWord + addressShift);
                break;
            }

            int idx = instruction.Bytes.Length - (opr.Size / 8);

            if (idx > -1)
            {
                replaceBytes(newInstructionBytes, idx, bytesWithAddressShift);
            }
            else
            {
                throw new ApplicationException("Could not replace target address in instruction");
            }

            //validate the byte array modification
            var disasm         = m_disasmFactory.Create(newInstructionBytes);
            var newInstruction = disasm.Disassemble().First();

            if ((opr.SignedValue + addressShift) != newInstruction.Operands[0].SignedValue)
            {
                throw new ApplicationException("updating jump instruction target address failed");
            }

            return(newInstruction);
        }