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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }