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 List <ITypeDeclaration> TransformToDeclaration(ITypeDeclaration typeDecl) { Stack <ITypeDeclaration> typesToTransform = new Stack <ITypeDeclaration>(); typesToTransform.Push(typeDecl); HashSet <ITypeDeclaration> typesTransformed = new HashSet <ITypeDeclaration>(); List <ITypeDeclaration> typeDeclarations = new List <ITypeDeclaration>(); while (typesToTransform.Count > 0) { ITypeDeclaration itd = typesToTransform.Pop(); ITypeDeclaration td = transform.Transform(itd); transformMap[itd] = td; typeDeclarations.Add(td); typesTransformed.Add(itd); foreach (ITypeDeclaration t2 in transform.Context.TypesToTransform) { if (!typesTransformed.Contains(t2)) { typesToTransform.Push(t2); } } } return(typeDeclarations); }
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); }