private ICode ExpandTargetAddressOfJumpInstructionTo4Bytes(ICode code,
                                                                   IInstructionWithAddressOperandDecider InstructionWithAddressOperandDecider,
                                                                   IInstructionWithAddressOperandTransform InstructionWithAddressOperandTransform,
                                                                   ICodeTransform codeTransform,
                                                                   IStatistics statistics)
        {
            TryTransformInstructionDelegate transformInstructionDelegate =
                (IAssemblyInstructionForTransformation instruction, IBasicBlock basicBlock, IFunction function,
                 out List <IAssemblyInstructionForTransformation> listOfTransformedInstructions) =>
            {
                listOfTransformedInstructions = null;
                var wasTransformed = false;
                //replace jump instruction to jump instructions with 4 bytes operand=
                if (InstructionWithAddressOperandDecider.IsJumpInstructionWithRelativeAddressOperand(instruction) &&
                    IsJumpInstructionToCodeSection(code, instruction))
                {
                    if (InstructionWithAddressOperandTransform.TryTransformJumpInstructionTo4BytesOperandSize(instruction,
                                                                                                              out IAssemblyInstructionForTransformation transformedInstruction))
                    {
                        wasTransformed = true;
                        listOfTransformedInstructions = new List <IAssemblyInstructionForTransformation>()
                        {
                            transformedInstruction
                        };
                        statistics.IncrementInstructionExpanded((uint)(transformedInstruction.Bytes.Length - instruction.Bytes.Length));
                    }
                }

                return(wasTransformed);
            };

            return(codeTransform.Transform(code, transformInstructionDelegate));
        }
 public InstructionWithAddressOperandTransform(IInstructionWithAddressOperandDecider InstructionWithAddressOperandDecider,
                                               IDisassemblerFactory disasmFactory)
 {
     m_InstructionWithAddressOperandDecider = InstructionWithAddressOperandDecider ?? throw new ArgumentNullException(nameof(InstructionWithAddressOperandDecider));
     m_disasmFactory = disasmFactory ?? throw new ArgumentNullException(nameof(disasmFactory));
     m_dictionaryJumpInstructionBytes = FillDictionaryJumpInstructionBytes();
     m_dictionaryOfJumpToNegativeJump = FillDictionaryOfJumpToNegativeJump();
 }
 public CodeParser(IFunctionParser functionParser, ICodeFactory codeFactory,
                   IDisassemblerFactory disassemblerFactory,
                   IInstructionWithAddressOperandDecider jumpTargetAddressDecider)
 {
     m_functionParser           = functionParser ?? throw new ArgumentNullException(nameof(functionParser));
     m_codeFactory              = codeFactory ?? throw new ArgumentNullException(nameof(codeFactory));
     m_disassemblerFactory      = disassemblerFactory ?? throw new ArgumentNullException(nameof(disassemblerFactory));
     m_jumpTargetAddressDecider = jumpTargetAddressDecider ?? throw new ArgumentNullException(nameof(jumpTargetAddressDecider));
 }
        private IReadOnlyList <IFunction> parseFunctions(
            IInstructionWithAddressOperandDecider instructionWithAddressOperandDecider,
            IReadOnlyList <IAssemblyInstructionForTransformation> listOfInstructions)
        {
            AddressesRange addressesRange      = new AddressesRange(listOfInstructions[0].Offset, listOfInstructions.Last().Offset);
            var            jumpTargetAddresses = GetJumpTargetAddresses(instructionWithAddressOperandDecider,
                                                                        listOfInstructions);

            return(m_functionParser.Parse(listOfInstructions[0], addressesRange, jumpTargetAddresses));
        }
 public TransformationAddingUnconditionalJump(IInstructionWithAddressOperandDecider instructionWithAddressOperandDecider,
                                              IInstructionWithAddressOperandTransform instructionWithAddressOperandTransform,
                                              ICodeFactory codeFactory,
                                              ICodeInMemoryLayoutFactory codeInMemoryLayoutFactory,
                                              ICodeTransform codeTransform,
                                              IStatistics statistics,
                                              IRelocationDirectoryFromNewCode relocationDirectoryFromNewCode,
                                              ICodeParser codeParser) : base(instructionWithAddressOperandDecider,
                                                                             instructionWithAddressOperandTransform, codeFactory, codeInMemoryLayoutFactory, codeTransform,
                                                                             statistics, relocationDirectoryFromNewCode)
 {
     m_codeParser = codeParser ?? throw new ArgumentNullException(nameof(codeParser));
 }
 public TransformationBase(IInstructionWithAddressOperandDecider instructionWithAddressOperandDecider,
                           IInstructionWithAddressOperandTransform instructionWithAddressOperandTransform,
                           ICodeFactory codeFactory,
                           ICodeInMemoryLayoutFactory codeInMemoryLayoutFactory,
                           ICodeTransform codeTransform,
                           IStatistics statistics,
                           IRelocationDirectoryFromNewCode relocationDirectoryFromNewCode)
 {
     m_instructionWithAddressOperandDecider   = instructionWithAddressOperandDecider ?? throw new ArgumentNullException(nameof(instructionWithAddressOperandDecider));
     m_instructionWithAddressOperandTransform = instructionWithAddressOperandTransform ?? throw new ArgumentNullException(nameof(instructionWithAddressOperandTransform));
     m_codeInMemoryLayoutFactory = codeInMemoryLayoutFactory ?? throw new ArgumentNullException(nameof(codeInMemoryLayoutFactory));
     m_codeTransform             = codeTransform ?? throw new ArgumentNullException(nameof(codeTransform));
     m_statistics = statistics ?? throw new ArgumentNullException(nameof(statistics));
     m_relocationDirectoryFromNewCode = relocationDirectoryFromNewCode ?? throw new ArgumentNullException(nameof(relocationDirectoryFromNewCode));
 }
        /// <summary>
        /// Create a dictionary that holds the addresses that appears in dictionary
        /// </summary>
        /// <param name="code"></param>
        /// <param name="addressToInstructionMap"></param>
        /// <param name="InstructionWithAddressOperandDecider"></param>
        /// <returns></returns>
        private Dictionary <ulong, ulong> CreateAddresesInInstructionMap(ICode code,
                                                                         Dictionary <ulong, IAssemblyInstructionForTransformation> addressToInstructionMap,
                                                                         IInstructionWithAddressOperandDecider InstructionWithAddressOperandDecider)
        {
            var addressesInInstructionsDictionary = new Dictionary <ulong, ulong>();

            //this loop prepares the map, and create entry for each old target
            foreach (var instruction in code.AssemblyInstructions)
            {
                bool  result            = false;
                ulong instructionTarget = ulong.MaxValue;

                bool isJumpTargetOperand =
                    InstructionWithAddressOperandDecider.IsJumpInstructionWithRelativeAddressOperand(instruction) ||
                    InstructionWithAddressOperandDecider.IsCallInstructionWithAddressOperand(instruction);

                bool isAbsoluteAddressInOperand =
                    InstructionWithAddressOperandDecider.IsInstructionWithAbsoluteAddressOperand(
                        instruction, code.CodeInMemoryLayout, out instructionTarget);


                if (isJumpTargetOperand)
                {
                    result = instruction.TryGetAbsoluteAddressFromRelativeAddress(out instructionTarget);
                    if (result && !addressToInstructionMap.ContainsKey(instructionTarget))
                    {
                        throw new ApplicationException($"instruction: '{instruction}' with target address {instructionTarget} do not exist!");
                    }
                }
                else if (isAbsoluteAddressInOperand)
                {
                    instructionTarget -= (code.CodeInMemoryLayout.ImageBaseAddress + code.CodeInMemoryLayout.CodeVirtualAddress);
                    result             = true;
                }


                if (result)
                {
                    //Create entry for the instruction target address
                    addressesInInstructionsDictionary[instructionTarget] = 0;
                }
            }

            //add the entry point address to the map, becuase we need to update its new address
            addressesInInstructionsDictionary[code.CodeInMemoryLayout.EntryPointOffset] = 0;

            return(addressesInInstructionsDictionary);
        }
 public TransformationAddingJunkBytes(IInstructionWithAddressOperandDecider instructionWithAddressOperandDecider,
                                      IInstructionWithAddressOperandTransform instructionWithAddressOperandTransform,
                                      ICodeInMemoryLayoutFactory codeInMemoryLayoutFactory,
                                      ICodeFactory codeFactory,
                                      IInstructionWithAddressOperandTransform jumpInstrucionTransform,
                                      ICodeTransform codeTransform,
                                      IStatistics statistics,
                                      IRelocationDirectoryFromNewCode relocationDirectoryFromNewCode,
                                      IJunkBytesProvider junkBytesProvider,
                                      IDisassemblerFactory disassemblerFactory) :
     base(instructionWithAddressOperandDecider, instructionWithAddressOperandTransform,
          codeFactory, codeInMemoryLayoutFactory, codeTransform, statistics,
          relocationDirectoryFromNewCode)
 {
     m_junkBytesProvider   = junkBytesProvider ?? throw new ArgumentNullException(nameof(junkBytesProvider));
     m_disassemblerFactory = disassemblerFactory ?? throw new ArgumentNullException(nameof(disassemblerFactory));
 }
        private void ValidateCodeJumpInstructions(ICode code, IInstructionWithAddressOperandDecider InstructionWithAddressOperandDecider)
        {
            var map = new Dictionary <ulong, IAssemblyInstructionForTransformation>();

            foreach (var instruction in code.AssemblyInstructions)
            {
                map.Add(instruction.Offset, instruction);
            }

            foreach (var instruction in code.AssemblyInstructions)
            {
                if (InstructionWithAddressOperandDecider.IsJumpInstructionWithRelativeAddressOperand(instruction))
                {
                    ulong jumpTarget = instruction.GetAbsoluteAddressFromRelativeAddress();
                    if (!map.ContainsKey(jumpTarget))
                    {
                        throw new ApplicationException("code is incorrect, jump target is to no instruction");
                    }
                }
            }
        }
        private Dictionary <ulong, ulong> GetJumpTargetAddresses(
            IInstructionWithAddressOperandDecider instructionWithAddressOperandDecider,
            IReadOnlyList <IAssemblyInstructionForTransformation> listOfInstructions)
        {
            var addressesInInstructionsDictionary = new Dictionary <ulong, ulong>();

            //create the map, and create entry for each jump target
            foreach (var instruction in listOfInstructions)
            {
                ulong instructionTarget = ulong.MaxValue;

                bool isJumpTargetOperand =
                    instructionWithAddressOperandDecider.IsJumpInstructionWithRelativeAddressOperand(instruction) ||
                    instructionWithAddressOperandDecider.IsUnconditionalJumpInstruction(instruction.Mnemonic) ||
                    instructionWithAddressOperandDecider.IsCallInstructionWithAddressOperand(instruction);

                if (!isJumpTargetOperand)
                {
                    continue;
                }
                bool result = false;
                result = instruction.TryGetAbsoluteAddressFromRelativeAddress(out instructionTarget);
                if (!result)
                {
                    result = instruction.TryGetAbsoluteAddress(out instructionTarget);
                }
                if (!result)
                {
                    continue;
                }

                addressesInInstructionsDictionary[instructionTarget] = 0;
            }

            return(addressesInInstructionsDictionary);
        }
        private ICode UpdateJumpInstructionsTargetAddress(ICode code,
                                                          IInstructionWithAddressOperandDecider InstructionWithAddressOperandDecider,
                                                          IInstructionWithAddressOperandTransform InstructionWithAddressOperandTransform,
                                                          ICodeTransform codeTransform,
                                                          Dictionary <ulong, IAssemblyInstructionForTransformation> addressToInstructionMap,
                                                          ICodeInMemoryLayoutFactory codeInMemoryLayoutFactory,
                                                          IRelocationDirectoryFromNewCode relocationDirectoryFromNewCode,
                                                          Dictionary <ulong, ulong> jumpInstructionsMap)
        {
            if (code == null)
            {
                throw new ArgumentNullException(nameof(code));
            }
            if (code.AssemblyInstructions == null || code.AssemblyInstructions.Count == 0)
            {
                throw new ArgumentException("code.AssemblyInstructions");
            }
            if (InstructionWithAddressOperandDecider == null)
            {
                throw new ArgumentNullException(nameof(InstructionWithAddressOperandDecider));
            }
            if (InstructionWithAddressOperandTransform == null)
            {
                throw new ArgumentNullException(nameof(InstructionWithAddressOperandTransform));
            }
            if (codeInMemoryLayoutFactory == null)
            {
                throw new ArgumentNullException(nameof(codeInMemoryLayoutFactory));
            }
            if (relocationDirectoryFromNewCode == null)
            {
                throw new ArgumentNullException(nameof(relocationDirectoryFromNewCode));
            }

            //this is used map for the new and old addresses
            var oldToNewAddressDictionary = jumpInstructionsMap;

            //PASS 1:
            //map old instruction address to new address,
            //because new instructions are going to be added in between, and other instructions
            //are going to be expanded.
            ulong newOffset = 0;

            foreach (var instruction in code.AssemblyInstructions)
            {
                //look for each byte in instruction, because the addresses in operand
                //can be an instruction or somewhere INSIDE the instruction
                //for example: movzx eax, byte [edx+0x411d8c]
                //where edx = 0xbc, and 0x411d8c is no instruction
                for (ulong i = 0; i < (ulong)instruction.Bytes.Length; i++)
                {
                    if (oldToNewAddressDictionary.ContainsKey(instruction.Offset + i))
                    {
                        oldToNewAddressDictionary[instruction.Offset + i] = newOffset + i;
                    }
                }

                newOffset = newOffset + (ulong)instruction.Bytes.Length;
            }


            //PASS 2:Create the new relocation directory
            var newRelocationDirectoryInfo =
                relocationDirectoryFromNewCode.CreateNewRelocationDirectoryInfo(code);

            //PASS 3:
            //set the target jump address to the new address and then change the instruction offset
            newOffset = 0;
            ulong newProgramCounter = 0;

            TryTransformInstructionDelegate tryTransformDelegate = (IAssemblyInstructionForTransformation instruction, IBasicBlock basicBlock,
                                                                    IFunction function, out List <IAssemblyInstructionForTransformation> transformedInstructions) =>
            {
                transformedInstructions = null;
                var retVal = false;
                //old jump target address or old address in operand
                ulong oldAddress;

                newProgramCounter = newProgramCounter + (ulong)instruction.Bytes.Length;

                bool isJumpTargetOperand =
                    InstructionWithAddressOperandDecider.IsJumpInstructionWithRelativeAddressOperand(instruction) ||
                    InstructionWithAddressOperandDecider.IsCallInstructionWithAddressOperand(instruction);

                bool isAbsoluteAddressInOperand =
                    InstructionWithAddressOperandDecider.IsInstructionWithAbsoluteAddressOperand(instruction,
                                                                                                 code.CodeInMemoryLayout, out oldAddress);


                if (isJumpTargetOperand)
                {
                    transformedInstructions = new List <IAssemblyInstructionForTransformation>();

                    oldAddress = instruction.GetAbsoluteAddressFromRelativeAddress();
                    if (!oldToNewAddressDictionary.TryGetValue(oldAddress, out ulong newTargetAddress))
                    {
                        throw new ApplicationException("jump instruction target should exist on map");
                    }

                    var transformedInstruction = InstructionWithAddressOperandTransform.
                                                 CreateJumpInstructionWithNewTargetAddress(instruction, newProgramCounter, newOffset,
                                                                                           newTargetAddress);

                    transformedInstructions.Add(transformedInstruction);
                    retVal = true;
                }
                else if (isAbsoluteAddressInOperand)
                {
                    transformedInstructions = new List <IAssemblyInstructionForTransformation>();

                    ulong virtualOldAddress = (oldAddress - code.CodeInMemoryLayout.ImageBaseAddress) -
                                              code.CodeInMemoryLayout.CodeVirtualAddress;

                    if (!oldToNewAddressDictionary.TryGetValue(virtualOldAddress, out ulong newAddressInOperand))
                    {
                        throw new ApplicationException("jump instruction target should exist on map");
                    }

                    newAddressInOperand += (code.CodeInMemoryLayout.ImageBaseAddress +
                                            code.CodeInMemoryLayout.CodeVirtualAddress);

                    var transformedInstruction = InstructionWithAddressOperandTransform.
                                                 CreateInstructionWithNewAddress(code, instruction, newProgramCounter, newOffset,
                                                                                 oldAddress, newAddressInOperand);

                    transformedInstructions.Add(transformedInstruction);
                    retVal = true;
                }
                else
                {
                    instruction.SetPC(newProgramCounter);
                    instruction.SetOffset(newOffset);
                }

                newOffset = newProgramCounter;
                return(retVal);
            };

            //take care for updating the new entry point address, and new relocation diretory
            //define a factory to create the new code in memory layout instance
            Func <ICodeInMemoryLayout> codeInMemoryLayoutFactoryDelegate = () =>
                                                                           codeInMemoryLayoutFactory.Create(
                code.CodeInMemoryLayout.ImageBaseAddress,
                code.CodeInMemoryLayout.OffsetOfCodeInBytes,
                newProgramCounter,
                code.CodeInMemoryLayout.CodePhysicalSizeInBytes,
                oldToNewAddressDictionary[code.CodeInMemoryLayout.EntryPointOffset],
                code.CodeInMemoryLayout.CodeVirtualAddress,
                newRelocationDirectoryInfo);

            var newCode = codeTransform.Transform(code, tryTransformDelegate,
                                                  codeInMemoryLayoutFactoryDelegate);

            return(newCode);
        }
 public BasicBlockEpilogParser(IInstructionWithAddressOperandDecider jumpInstructionDecider)
 {
     m_jumpInstructionDecider = jumpInstructionDecider ?? throw new ArgumentNullException("jumpInstructionDecider");
 }