private void ProcessOverrideOperand(ref x86Instruction instruction) { x86OperandType operandType = instruction.OpCode.GetOverrideOperandType(); if (operandType.HasFlag(x86OperandType.ForceDwordPointer)) { if (instruction.operand2 != null) { if (instruction.operand2.Value is uint) { instruction.operand2 = CreatePtr((uint)instruction.operand2.Value, OperandType.DwordPointer); } else { instruction.operand2.ValueType = OperandType.DwordPointer; } } else if (instruction.operand1.Value is uint) { instruction.operand1 = CreatePtr((uint)instruction.operand1.Value, OperandType.DwordPointer); } else { instruction.operand1.ValueType = OperandType.DwordPointer; } } if (operandType.HasFlag(x86OperandType.OverrideOperandOrder)) { Operand temp = instruction.operand1; instruction.operand1 = instruction.operand2; instruction.operand2 = temp; } }
/// <summary> /// Replaces an instruction with a new instruction. /// </summary> /// <param name="targetInstruction">The instruction to replace.</param> /// <param name="newInstruction">The new instruction.</param> /// <param name="overwriteWhenLarger">A boolean indicating whenever the new instruction is larger, it should overwrite the following instructions.</param> public void Replace(x86Instruction targetInstruction, x86Instruction newInstruction, bool overwriteWhenLarger) { int targetOffset = (int)targetInstruction.Offset.FileOffset; if (!overwriteWhenLarger && targetInstruction.Size < newInstruction.Size) { throw new ArgumentException("The size of the new instruction is bigger than the target instruction.", "newInstruction"); } newInstruction.Offset = targetInstruction.Offset; int NopsToAdd = CalculateSpaceNeeded(targetInstruction, newInstruction) - newInstruction.Size; byte[] NOPS = new byte[NopsToAdd]; for (int i = 0; i < NopsToAdd; i++) { NOPS[i] = 0x90; } image.SetOffset(targetOffset); image.Writer.Write(newInstruction.OpCode.opcodebytes); if (newInstruction.operandbytes != null) { image.Writer.Write(newInstruction.operandbytes); } image.Writer.Write(NOPS); }
private void ProcessInvalidInstruction(ref x86Instruction instruction) { byte firstByte = instruction.OpCode.OpCodeBytes[0]; instruction.OpCode = x86OpCode.Create(x86OpCodes.Unknown); instruction.OpCode.opcodebytes = new byte[] { firstByte }; CurrentOffset = instruction.Offset.FileOffset + 1; }
/// <summary> /// Creates an instance of a x86 instruction with two operands. /// </summary> /// <param name="assembly">The parent assembly.</param> /// <param name="opcode">The opcode to use.</param> /// <param name="operand1">The first operand to use.</param> /// <param name="operand2">The second operand to use.</param> /// <returns></returns> public static x86Instruction Create(x86OpCode opcode, Operand operand1, Operand operand2) { x86Instruction newInstruction = new x86Instruction(); newInstruction.OpCode = opcode; newInstruction.operand1 = operand1; newInstruction.operand2 = operand2; newInstruction.GenerateBytes(); return(newInstruction); }
private void DecodeDoubleRegisters(ref x86Instruction instruction, byte registersToken) { x86Instruction result = instruction; x86OpCode resultopcode = instruction.OpCode; if (resultopcode.variableByteIndex == -1) { return; } resultopcode.opcodebytes[instruction.OpCode.variableByteIndex] = registersToken; result.OpCode = resultopcode; // lea instructions has got different notations. bool isLEA = instruction.OpCode.IsBasedOn(x86OpCodes.Lea); x86Register register1; x86Register register2; DecodeRegisterPair(instruction, registersToken, out register1, out register2); // one register is a dword pointer if (registersToken <= 0x3F) { instruction.operand1 = new Operand(register1, OperandType.DwordPointer); instruction.operand2 = new Operand(register2, OperandType.Normal); } // one register is a dword pointer with an sbyte addition else if (registersToken > 0x3F && registersToken < 0x7F) { instruction.operandbytes = reader.ReadBytes(1); instruction.code.operandlength++; instruction.operand1 = new Operand(register1, isLEA ? OperandType.LeaRegister : OperandType.DwordPointer, ASMGlobals.ByteToSByte(instruction.operandbytes[0])); instruction.operand2 = new Operand(register2, OperandType.Normal); } // one register is a dword pointer with an int32 addition else if (registersToken >= 0x80 && registersToken <= 0xBF) { instruction.operandbytes = reader.ReadBytes(4); instruction.code.operandlength += 4; int addition = BitConverter.ToInt32(instruction.operandbytes, 0); instruction.operand1 = new Operand(register1, isLEA ? OperandType.LeaRegister : OperandType.DwordPointer, addition); instruction.operand2 = new Operand(register2, OperandType.Normal); } // normal multiple registers. else if (registersToken >= 0xC0 && registersToken <= 0xFF) { instruction.operand1 = new Operand(register1, isLEA ? OperandType.LeaRegister : OperandType.Normal); instruction.operand2 = new Operand(register2, OperandType.Normal); } }
/// <summary> /// Gets the assembly instruction in the application by its virtual offset. /// </summary> /// <param name="TargetOffset">The Offset of the instruction go get.</param> /// <returns></returns> public x86Instruction GetInstructionByVirtualOffset(ulong TargetOffset) { x86Instruction TargetInstruction = null; foreach (x86Instruction instr in List) { if (instr.Offset.Va == TargetOffset) { TargetInstruction = instr; break; } } return(TargetInstruction); }
/// <summary> /// Gets the assembly instruction in the application by its offset. /// </summary> /// <param name="TargetOffset">The Offset of the instruction go get.</param> /// <returns></returns> public x86Instruction GetInstructionByOffset(long TargetOffset) { x86Instruction TargetInstruction = null; foreach (x86Instruction instr in List) { if (instr.Offset.FileOffset == TargetOffset) { TargetInstruction = instr; break; } } return(TargetInstruction); //int TargetInstructionIndex = assembly.instructions.IndexOf(TargetInstruction); }
/// <summary> /// Calculates and returns the size in bytes needed when replacing an instruction /// </summary> /// <param name="targetInstruction">The instruction to be replaced.</param> /// <param name="newSize">The new instruction's size.</param> /// <returns></returns> public int CalculateSpaceNeeded(x86Instruction targetInstruction, int newSize) { if (newSize <= targetInstruction.Size) return targetInstruction.Size; int sizeNeeded = 0; uint currentOffset = targetInstruction.Offset.FileOffset; while (sizeNeeded < newSize) { disassembler.CurrentOffset = currentOffset; x86Instruction currentInstruction = disassembler.DisassembleNextInstruction(); sizeNeeded += currentInstruction.Size; currentOffset += (uint)currentInstruction.Size; } return sizeNeeded; }
/// <summary> /// Disassembles the next instruction at the current offset. /// </summary> /// <returns></returns> public x86Instruction DisassembleNextInstruction() { x86Instruction newInstruction = new x86Instruction(); newInstruction.Offset = Offset.FromFileOffset((uint)reader.BaseStream.Position, assembly); newInstruction.OpCode = RetrieveNextOpCode(); ProcessVariableByteIndex(ref newInstruction.code); ProcessRegisterOperands(ref newInstruction); byte[] rawOperand = ReadRawOperand(newInstruction.OpCode); newInstruction.operandbytes = ASMGlobals.MergeBytes(newInstruction.operandbytes, rawOperand); ProcessOperandBytes(ref newInstruction); ProcessOverrideOperand(ref newInstruction); return(newInstruction); }
private void ProcessRegisterOperands(ref x86Instruction instruction) { switch (instruction.OpCode.GetRegisterOperandType()) { case x86OperandType.Multiple32Register: case x86OperandType.Multiple32Or8Register: case x86OperandType.Multiple16Register: case x86OperandType.RegisterLeaRegister: DecodeDoubleRegisters(ref instruction, instruction.code.opcodebytes[instruction.code.opcodebytes.Length - 1]); break; case x86OperandType.Register8: case x86OperandType.Register32: case x86OperandType.Register32Or8: DecodeSingleRegister(ref instruction, instruction.code.opcodebytes[instruction.code.opcodebytes.Length - 1]); break; } }
/// <summary> /// Gets the assembly instruction in the application by its virtual offset. /// </summary> /// <param name="TargetOffset">The Offset of the instruction go get.</param> /// <returns></returns> public int GetInstructionIndexByVirtualOffset(ulong TargetOffset) { x86Instruction TargetInstruction = null; foreach (x86Instruction instr in List) { if (instr.Offset.Va == TargetOffset) { TargetInstruction = instr; break; } } if (TargetInstruction == null) { return(-1); } return(List.IndexOf(TargetInstruction)); }
/// <summary> /// Disassembles bytes to a collection of assembly instructions. /// </summary> /// <param name="rawStartOffset">The starting offset</param> /// <param name="length">The length. This value is overwritten when the last instruction's bounds are outside of the bounds.</param> /// <returns></returns> public InstructionCollection Disassemble(long rawStartOffset, long length) { reader.BaseStream.Position = rawStartOffset; InstructionCollection instructions = new InstructionCollection(); long offset = rawStartOffset; long endOffset = rawStartOffset + length; while (reader.BaseStream.Position < endOffset) { x86Instruction instruction = DisassembleNextInstruction(); instructions.Add(instruction); offset += instruction.Size; reader.BaseStream.Position = offset; } // reader.Dispose(); return(instructions); }
/// <summary> /// Calculates and returns the size in bytes needed when replacing an instruction /// </summary> /// <param name="targetInstruction">The instruction to be replaced.</param> /// <param name="newSize">The new instruction's size.</param> /// <returns></returns> public int CalculateSpaceNeeded(x86Instruction targetInstruction, int newSize) { if (newSize <= targetInstruction.Size) { return(targetInstruction.Size); } int sizeNeeded = 0; uint currentOffset = targetInstruction.Offset.FileOffset; while (sizeNeeded < newSize) { disassembler.CurrentOffset = currentOffset; x86Instruction currentInstruction = disassembler.DisassembleNextInstruction(); sizeNeeded += currentInstruction.Size; currentOffset += (uint)currentInstruction.Size; } return(sizeNeeded); }
private void DecodeRegisterPair(x86Instruction instruction, byte registerToken, out x86Register register1, out x86Register register2) { byte registerToken1 = (byte)(registerToken >> 4 << 4); // high bits. byte registerToken2 = (byte)(registerToken - registerToken1); // lower bits. while (registerToken1 >= 0x40) { registerToken1 -= 0x40; } registerToken1 /= 8; if (registerToken2 > 0x7) { registerToken2 -= 8; registerToken1++; } switch (instruction.OpCode.OperandType) { case x86OperandType.Multiple16Register: // add bit16 mask registerToken1 |= (byte)x86Register.Bit16Mask; registerToken2 |= (byte)x86Register.Bit16Mask; break; case x86OperandType.Multiple32Or8Register: // Not sure if right or not byte mask1; byte mask2; GetRegisterMask(registerToken, out mask1, out mask2); registerToken1 |= mask1; registerToken2 |= mask2; break; case x86OperandType.Multiple32Register: // do nothing, normal registers are used. break; } // notice inverted registers. register2 = (x86Register)registerToken1; register1 = (x86Register)registerToken2; }
/// <summary> /// Replaces an instruction with a new instruction. /// </summary> /// <param name="targetInstruction">The instruction to replace.</param> /// <param name="newInstruction">The new instruction.</param> /// <param name="overwriteWhenLarger">A boolean indicating whenever the new instruction is larger, it should overwrite the following instructions.</param> public void Replace(x86Instruction targetInstruction, x86Instruction newInstruction, bool overwriteWhenLarger) { int targetOffset = (int)targetInstruction.Offset.FileOffset; if (!overwriteWhenLarger && targetInstruction.Size < newInstruction.Size) throw new ArgumentException("The size of the new instruction is bigger than the target instruction.", "newInstruction"); newInstruction.assembly = image.assembly; newInstruction.Offset = targetInstruction.Offset; int NopsToAdd = CalculateSpaceNeeded(targetInstruction, newInstruction) - newInstruction.Size; byte[] NOPS = new byte[NopsToAdd]; for (int i = 0; i < NopsToAdd; i++) NOPS[i] = 0x90; image.Write(targetOffset, newInstruction.OpCode.opcodebytes); if (newInstruction.operandbytes != null) image.Write(targetOffset + newInstruction.OpCode.opcodebytes.Length, newInstruction.operandbytes); image.Write(targetOffset + newInstruction.Size, NOPS); }
private ListViewItem CreateListViewItem(x86Instruction instr) { ListViewItem itm = new ListViewItem(); itm.UseItemStyleForSubItems = false; if (virtualInstructions) itm.Text = instr.Offset.Va.ToString("X8"); else itm.Text = instr.Offset.FileOffset.ToString("X8"); itm.SubItems.Add(ByteArrayToHexString(instr.OpCode.OpCodeBytes) + " " + ByteArrayToHexString(instr.OperandBytes)); itm.SubItems.Add(instr.ToAsmString(virtualInstructions)); itm.SubItems.Add(""); if (instr.OpCode.OperandType == x86OperandType.InstructionAddress || instr.OpCode.OperandType == x86OperandType.ShortInstructionAddress || instr.OpCode.OperandType == x86OperandType.DwordPtr) { if (instr.OpCode.Name.StartsWith("CALL")) itm.SubItems[2].BackColor = Color.Cyan; if (instr.OpCode.Name.StartsWith("J") || instr.OpCode.Name.StartsWith("LOOP")) itm.SubItems[2].BackColor = Color.Yellow; } itm.Tag = instr; return itm; }
/// <summary> /// Gets the index of a given instruction. /// </summary> /// <param name="instruction">The instruction to get the index from.</param> /// <returns></returns> public int IndexOf(x86Instruction instruction) { return(List.IndexOf(instruction)); }
internal void ProcessOperandBytes(x86Instruction instruction) { uint nextOffset = (uint)(instruction.Offset.FileOffset + instruction.Size); Operand operandValue = null; switch (instruction.OpCode.GetNormalOperandType()) { case x86OperandType.Byte: operandValue = new Operand(instruction.operandbytes[0]); break; case x86OperandType.Word: operandValue = new Operand(BitConverter.ToInt16(instruction.operandbytes, 0)); break; case x86OperandType.WordAndByte: break; // TODO case x86OperandType.Dword: operandValue = new Operand(BitConverter.ToUInt32(instruction.operandbytes, 0)); break; case x86OperandType.Fword: break; // TODO case x86OperandType.Qword: operandValue = new Operand(BitConverter.ToUInt64(instruction.operandbytes, 0)); break; case x86OperandType.InstructionAddress: operandValue = CreateTargetOffset((uint)(nextOffset + BitConverter.ToInt32(instruction.operandbytes, 0))); break; case x86OperandType.ShortInstructionAddress: operandValue = CreateTargetOffset((uint)(nextOffset + ASMGlobals.ByteToSByte(instruction.operandbytes[0]))); break; case x86OperandType.Register32: DecodeSingleRegister(ref instruction, instruction.code._opcodeBytes[instruction.code._opcodeBytes.Length - 1]); break; case x86OperandType.Instruction: // opcode is prefix. x86Instruction nextInstruction = DisassembleNextInstruction(); operandValue = new Operand(nextInstruction); instruction.operandbytes = ASMGlobals.MergeBytes(nextInstruction.code.OpCodeBytes, nextInstruction.operandbytes); instruction.code._operandLength = nextInstruction.Size; break; case x86OperandType.None: if (instruction.code.IsBasedOn(x86OpCodes.Unknown)) operandValue = new Operand(instruction.code._opcodeBytes[0]); break; } if (operandValue != null) { if (instruction.operand1 != null) instruction.operand2 = operandValue; else instruction.operand1 = operandValue; } }
/// <summary> /// Inserts at the specified index an instruction into the collection. /// </summary> /// <param name="index">The zero-based index at which value should be inserted.</param> /// <param name="instruction">The instruction to insert into the collection.</param> public void Insert(int index, x86Instruction instruction) { List.Insert(index, instruction); }
/// <summary> /// Gets the index of a given instruction. /// </summary> /// <param name="instruction">The instruction to get the index from.</param> /// <returns></returns> public int IndexOf(x86Instruction instruction) { return List.IndexOf(instruction); }
/// <summary> /// Disassembles the next instruction at the current offset. /// </summary> /// <returns></returns> public virtual x86Instruction DisassembleNextInstruction() { x86Instruction newInstruction = new x86Instruction(); newInstruction.Offset = Offset.FromFileOffset((uint)reader.BaseStream.Position, assembly) ; newInstruction.OpCode = RetrieveNextOpCode(); ProcessVariableByteIndex(ref newInstruction.code); ProcessRegisterOperands(newInstruction); byte[] rawOperand = ReadRawOperand(newInstruction.OpCode); newInstruction.operandbytes = ASMGlobals.MergeBytes(newInstruction.operandbytes, rawOperand); ProcessOperandBytes(newInstruction); ProcessOverrideOperand(newInstruction); return newInstruction; }
/// <summary> /// Creates a new instance of the ReadingProcessChangedEventArgs containing information about the new instruction and offset. /// </summary> /// <param name="totallength">The total lenght of the bytes.</param> /// <param name="currentoffset">The current offset of the bytes.</param> /// <param name="NewInstruction">The new instruction that is read from the bytes.</param> public ReadingProcessChangedEventArgs(long totallength, int currentoffset, x86Instruction NewInstruction) { filelength = totallength ; current = currentoffset; newinstruction = NewInstruction; }
internal void DecodeRegisterPair(x86Instruction instruction, byte registerToken, out x86Register register1, out x86Register register2) { byte registerToken1 = (byte)(registerToken >> 4 << 4); // high bits. byte registerToken2 = (byte)(registerToken - registerToken1); // lower bits. while (registerToken1 >= 0x40) registerToken1 -= 0x40; registerToken1 /= 8; if (registerToken2 > 0x7) { registerToken2 -= 8; registerToken1++; } switch (instruction.OpCode.OperandType) { case x86OperandType.Multiple16Register: // add bit16 mask registerToken1 |= (byte)x86Register.Bit16Mask; registerToken2 |= (byte)x86Register.Bit16Mask; break; case x86OperandType.Multiple32Or8Register: // Not sure if right or not byte mask1; byte mask2; GetDoubleRegisterMask(registerToken, out mask1, out mask2); registerToken1 |= mask1; registerToken2 |= mask2; break; case x86OperandType.Multiple32Register: // do nothing, normal registers are used. break; } // notice inverted registers. register2 = (x86Register)registerToken1; register1 = (x86Register)registerToken2; }
private void DecodeDoubleRegisters(ref x86Instruction instruction, byte registersToken) { x86Instruction result = instruction; x86OpCode resultopcode = instruction.OpCode; if (resultopcode._variableByteIndex == -1) return; resultopcode._opcodeBytes[instruction.OpCode._variableByteIndex] = registersToken; result.OpCode = resultopcode; // lea instructions has got different notations. bool isLEA = instruction.OpCode.IsBasedOn(x86OpCodes.Lea); x86Register register1; x86Register register2; DecodeRegisterPair(instruction, registersToken, out register1, out register2); // one register is a dword pointer if (registersToken <= 0x3F) { instruction.operand1 = new Operand(register1, OperandType.DwordPointer); instruction.operand2 = new Operand(register2, OperandType.Normal); } // one register is a dword pointer with an sbyte addition else if (registersToken > 0x3F && registersToken < 0x7F) { instruction.operandbytes = reader.ReadBytes(1); instruction.code._operandLength++; instruction.operand1 = new Operand(register1, isLEA ? OperandType.LeaRegister : OperandType.DwordPointer, ASMGlobals.ByteToSByte(instruction.operandbytes[0])); instruction.operand2 = new Operand(register2, OperandType.Normal); } // one register is a dword pointer with an int32 addition else if (registersToken >= 0x80 && registersToken <= 0xBF) { instruction.operandbytes = reader.ReadBytes(4); instruction.code._operandLength += 4; int addition = BitConverter.ToInt32(instruction.operandbytes, 0); instruction.operand1 = new Operand(register1, isLEA ? OperandType.LeaRegister : OperandType.DwordPointer, addition); instruction.operand2 = new Operand(register2, OperandType.Normal); } // normal multiple registers. else if (registersToken >= 0xC0 && registersToken <= 0xFF) { instruction.operand1 = new Operand(register1, isLEA ? OperandType.LeaRegister : OperandType.Normal); instruction.operand2 = new Operand(register2, OperandType.Normal); } }
internal void ProcessRegisterOperands(x86Instruction instruction) { switch (instruction.OpCode.GetRegisterOperandType()) { case x86OperandType.Multiple32Register: case x86OperandType.Multiple32Or8Register: case x86OperandType.Multiple16Register: case x86OperandType.RegisterLeaRegister: DecodeDoubleRegisters(ref instruction, instruction.code._opcodeBytes[instruction.code._opcodeBytes.Length - 1]); break; case x86OperandType.Register8: case x86OperandType.Register32: case x86OperandType.Register32Or8: DecodeSingleRegister(ref instruction, instruction.code._opcodeBytes[instruction.code._opcodeBytes.Length - 1]); break; } }
internal void ProcessOverrideOperand(x86Instruction instruction) { x86OperandType operandType = instruction.OpCode.GetOverrideOperandType(); if (operandType.HasFlag(x86OperandType.ForceDwordPointer)) { if (instruction.operand2 != null) if (instruction.operand2.Value is uint) instruction.operand2 = CreatePtr((uint)instruction.operand2.Value, OperandType.DwordPointer); else instruction.operand2.ValueType = OperandType.DwordPointer; else if (instruction.operand1.Value is uint) instruction.operand1 = CreatePtr((uint)instruction.operand1.Value, OperandType.DwordPointer); else instruction.operand1.ValueType = OperandType.DwordPointer; } if (operandType.HasFlag(x86OperandType.OverrideOperandOrder)) { Operand temp = instruction.operand1; instruction.operand1 = instruction.operand2; instruction.operand2 = temp; } }
private void DecodeSingleRegister(ref x86Instruction instruction, byte registerstoken) { x86Instruction result = instruction; x86OpCode resultopcode = instruction.OpCode; resultopcode.opcodebytes[instruction.OpCode.variableByteIndex] = registerstoken; result.OpCode = resultopcode; int multiplier = (int)Math.Floor(Convert.ToDouble(registerstoken / 0x8)); int start = multiplier * 0x8; int actualregister = registerstoken - start; OperandType registerValueType = OperandType.Normal; int addition = 0; if (registerstoken < 0x8) { //normal dword pointer registerValueType = OperandType.DwordPointer; } else if (registerstoken >= 0x40 && registerstoken < 0x48) { //dword pointer + sbyte addition registerValueType = OperandType.DwordPointer; instruction.operandbytes = new byte[] { image.ReadByte() }; instruction.OpCode.operandlength = 1; addition = ASMGlobals.ByteToSByte(instruction.operandbytes[0]); } else if (registerstoken >= 0x80 && registerstoken < 0x88) { //dword pointer + int addition registerValueType = OperandType.DwordPointer; instruction.operandbytes = image.ReadBytes(4); instruction.OpCode.operandlength = 4; addition = BitConverter.ToInt32(instruction.operandbytes, 0); } else if (registerstoken >= 0xC0 && registerstoken < 0xC8) { // normal register -> do nothing. } else { // TODO: Invalid single register token. } instruction.operand1 = new Operand((x86Register)actualregister, registerValueType, addition); }
/// <summary> /// Calculates and returns the size in bytes needed when replacing an instruction. /// </summary> /// <param name="targetInstruction">The instruction to be replaced.</param> /// <param name="newInstruction">The new instruction.</param> /// <returns></returns> public int CalculateSpaceNeeded(x86Instruction targetInstruction, x86Instruction newInstruction) { return(CalculateSpaceNeeded(targetInstruction, newInstruction.Size)); }
/// <summary> /// Creates an instance of a x86 instruction with two operands. /// </summary> /// <param name="assembly">The parent assembly.</param> /// <param name="opcode">The opcode to use.</param> /// <param name="operand1">The first operand to use.</param> /// <param name="operand2">The second operand to use.</param> /// <returns></returns> public static x86Instruction Create(Win32Assembly assembly, x86OpCode opcode, Operand operand1, Operand operand2) { x86Instruction newInstruction = new x86Instruction(assembly); newInstruction.OpCode = opcode; newInstruction.operand1 = operand1; newInstruction.operand2 = operand2; newInstruction.GenerateBytes(); return newInstruction; }
/// <summary> /// Disassembles the next instruction at the current offset. /// </summary> /// <returns></returns> public x86Instruction DisassembleNextInstruction() { x86Instruction newInstruction = new x86Instruction(image.assembly); newInstruction.Offset = Offset.FromFileOffset((uint)image.stream.Position, image.assembly); // if (newInstruction.offset == 0x6d1f) // System.Diagnostics.Debugger.Break(); newInstruction.OpCode = RetrieveNextOpCode(); ProcessVariableByteIndex(ref newInstruction.code); newInstruction.operandbytes = ReadRawOperand(newInstruction.OpCode); ProcessInstructionBytes(ref newInstruction); return newInstruction; }
/// <summary> /// Adds an instruction to the Assembly Instruction Collection. /// </summary> /// <param name="instruction">The instruction to add.</param> public void Add(x86Instruction instruction) { List.Add(instruction); }
/// <summary> /// Calculates and returns the size in bytes needed when replacing an instruction. /// </summary> /// <param name="targetInstruction">The instruction to be replaced.</param> /// <param name="newInstruction">The new instruction.</param> /// <returns></returns> public int CalculateSpaceNeeded(x86Instruction targetInstruction, x86Instruction newInstruction) { return CalculateSpaceNeeded(targetInstruction, newInstruction.Size); }
private void ProcessOperandBytes(ref x86Instruction instruction) { uint nextOffset = (uint)(instruction.Offset.FileOffset + instruction.Size); Operand operandValue = null; switch (instruction.OpCode.GetNormalOperandType()) { case x86OperandType.Byte: operandValue = new Operand(instruction.operandbytes[0]); break; case x86OperandType.Word: operandValue = new Operand(BitConverter.ToInt16(instruction.operandbytes, 0)); break; case x86OperandType.WordAndByte: break; // TODO case x86OperandType.Dword: operandValue = new Operand(BitConverter.ToUInt32(instruction.operandbytes, 0)); break; case x86OperandType.Fword: break; // TODO case x86OperandType.Qword: operandValue = new Operand(BitConverter.ToUInt64(instruction.operandbytes, 0)); break; case x86OperandType.InstructionAddress: operandValue = CreateTargetOffset((uint)(nextOffset + BitConverter.ToInt32(instruction.operandbytes, 0))); break; case x86OperandType.ShortInstructionAddress: operandValue = CreateTargetOffset((uint)(nextOffset + ASMGlobals.ByteToSByte(instruction.operandbytes[0]))); break; case x86OperandType.Register32: DecodeSingleRegister(ref instruction, instruction.code.opcodebytes[instruction.code.opcodebytes.Length - 1]); break; case x86OperandType.Instruction: // opcode is prefix. x86Instruction nextInstruction = DisassembleNextInstruction(); operandValue = new Operand(nextInstruction); instruction.operandbytes = ASMGlobals.MergeBytes(nextInstruction.code.OpCodeBytes, nextInstruction.operandbytes); instruction.code.operandlength = nextInstruction.Size; break; case x86OperandType.None: if (instruction.code.IsBasedOn(x86OpCodes.Unknown)) { operandValue = new Operand(instruction.code.opcodebytes[0]); } break; } if (operandValue != null) { if (instruction.operand1 != null) { instruction.operand2 = operandValue; } else { instruction.operand1 = operandValue; } } }
private void ProcessInstructionBytes(ref x86Instruction instruction) { uint nextOffset = (uint)(instruction.Offset.FileOffset + instruction.Size); switch (instruction.code.operandtype) { case x86OperandType.Byte: instruction.operand1 = new Operand(instruction.operandbytes[0]); break; case x86OperandType.DwordPtr: instruction.operand1 = CreatePtr(BitConverter.ToUInt32(instruction.operandbytes, 0), OperandType.DwordPointer); break; case x86OperandType.Dword: instruction.operand1 = new Operand(BitConverter.ToUInt32(instruction.operandbytes, 0)); break; case x86OperandType.InstructionAddress: instruction.operand1 = CreateTargetOffset((uint)(nextOffset + BitConverter.ToInt32(instruction.operandbytes, 0))); break; case x86OperandType.ShortInstructionAddress: instruction.operand1 = CreateTargetOffset(nextOffset + instruction.operandbytes[0]); break; case x86OperandType.Multiple32Register: case x86OperandType.Multiple32Or8Register: case x86OperandType.Multiple16Register: case x86OperandType.RegisterLeaRegister: DecodeDoubleRegisters(ref instruction, instruction.code.opcodebytes[instruction.code.opcodebytes.Length - 1]); break; case x86OperandType.Qword: instruction.operand1 = new Operand(BitConverter.ToUInt64(instruction.operandbytes, 0)); break; case x86OperandType.Register: DecodeSingleRegister(ref instruction, instruction.code.opcodebytes[instruction.code.opcodebytes.Length - 1]); break; case x86OperandType.RegisterAndDword: DecodeSingleRegister(ref instruction, instruction.code.opcodebytes[instruction.code.opcodebytes.Length - 1]); instruction.operand2 = new Operand(BitConverter.ToInt32(instruction.operandbytes, 0)); break; case x86OperandType.RegisterAndByte: case x86OperandType.RegisterOffset: case x86OperandType.RegisterPointer: case x86OperandType.Word: case x86OperandType.WordAndByte: case x86OperandType.Fword: case x86OperandType.FwordPtr: break; case x86OperandType.Instruction: // opcode is prefix. x86Instruction nextInstruction = DisassembleNextInstruction(); instruction.operand1 = new Operand(nextInstruction); instruction.operandbytes = ASMGlobals.MergeBytes(nextInstruction.code.OpCodeBytes, nextInstruction.operandbytes); instruction.code.operandlength = nextInstruction.Size; break; case x86OperandType.None: if (instruction.code.IsBasedOn(x86OpCodes.Unknown)) instruction.operand1 = new Operand(instruction.code.opcodebytes[0]); break; } }
private void DecodeSingleRegister(ref x86Instruction instruction, byte registerstoken) { x86Instruction result = instruction; x86OpCode resultopcode = instruction.OpCode; resultopcode.opcodebytes[instruction.OpCode.variableByteIndex] = registerstoken; result.OpCode = resultopcode; bool isGroupOpCode = MatchWithOpCodes(instruction.OpCode.opcodebytes[0]).Length > 1; int actualregister = registerstoken % 8; OperandType registerValueType = OperandType.Normal; int addition = 0; if (registerstoken < 0x40) { //normal dword pointer if (!isGroupOpCode && registerstoken >= 0x8) { ProcessInvalidInstruction(ref instruction); return; } registerValueType = OperandType.DwordPointer; } else if (registerstoken >= 0x40 && registerstoken < 0x80) { //dword pointer + sbyte addition if (!isGroupOpCode && registerstoken >= 0x48) { ProcessInvalidInstruction(ref instruction); return; } registerValueType = OperandType.DwordPointer; instruction.operandbytes = new byte[] { reader.ReadByte() }; instruction.OpCode.operandlength = 1; addition = ASMGlobals.ByteToSByte(instruction.operandbytes[0]); } else if (registerstoken >= 0x80 && registerstoken < 0xC0) { //dword pointer + int addition if (!isGroupOpCode && registerstoken >= 0x88) { ProcessInvalidInstruction(ref instruction); return; } registerValueType = OperandType.DwordPointer; instruction.operandbytes = reader.ReadBytes(4); instruction.OpCode.operandlength = 4; addition = BitConverter.ToInt32(instruction.operandbytes, 0); } else if (registerstoken >= 0xC0 && registerstoken <= 0xFF) { // normal register -> do nothing. if (!isGroupOpCode && registerstoken >= 0xC8) { ProcessInvalidInstruction(ref instruction); return; } } else { // TODO: Invalid single register token. } if (instruction.OpCode.operandtype.HasFlag(x86OperandType.Register8)) { actualregister |= (byte)x86Register.Bit8Mask; } instruction.operand1 = new Operand((x86Register)actualregister, registerValueType, addition); }
/// <summary> /// Replaces an instruction with a new instruction. /// </summary> /// <param name="targetInstruction">The instruction to replace.</param> /// <param name="newInstruction">The new instruction.</param> public void Replace(x86Instruction targetInstruction, x86Instruction newInstruction) { Replace(targetInstruction, newInstruction, false); }
private void DecodeSingleRegister(ref x86Instruction instruction, byte registersToken) { x86Instruction result = instruction; x86OpCode resultopcode = instruction.OpCode; resultopcode._opcodeBytes[instruction.OpCode._variableByteIndex] = registersToken; result.OpCode = resultopcode; bool isGroupOpCode = MatchWithOpCodes(instruction.OpCode._opcodeBytes[0]).Length > 1; int actualregister = registersToken % 8; OperandType registerValueType = OperandType.Normal; int addition = 0; if (registersToken < 0x40) { //normal dword pointer if (!isGroupOpCode && registersToken >= 0x8) { ProcessInvalidInstruction(instruction); return; } registerValueType = OperandType.DwordPointer; } else if (registersToken >= 0x40 && registersToken < 0x80) { //dword pointer + sbyte addition if (!isGroupOpCode && registersToken >= 0x48) { ProcessInvalidInstruction(instruction); return; } registerValueType = OperandType.DwordPointer; instruction.operandbytes = new byte[] { reader.ReadByte() }; instruction.OpCode._operandLength++; addition = ASMGlobals.ByteToSByte(instruction.operandbytes[0]); } else if (registersToken >= 0x80 && registersToken < 0xC0) { //dword pointer + int addition if (!isGroupOpCode && registersToken >= 0x88) { ProcessInvalidInstruction(instruction); return; } registerValueType = OperandType.DwordPointer; instruction.operandbytes = reader.ReadBytes(4); instruction.OpCode._operandLength += 4; addition = BitConverter.ToInt32(instruction.operandbytes, 0); } else if (registersToken >= 0xC0 && registersToken <= 0xFF) { // normal register -> do nothing. if (!isGroupOpCode && registersToken >= 0xC8) { ProcessInvalidInstruction(instruction); return; } } else { // TODO: Invalid single register token. } if (instruction.OpCode._operandType.HasFlag(x86OperandType.Register8)) { actualregister |= (byte)x86Register.Bit8Mask; } if (instruction.OpCode._operandType.HasFlag(x86OperandType.Register32Or8)) { actualregister |= GetSingleRegisterMask(registersToken); } instruction.operand1 = new Operand((x86Register)actualregister, registerValueType, addition); }
internal void ProcessInvalidInstruction(x86Instruction instruction) { byte firstByte = instruction.OpCode.OpCodeBytes[0]; instruction.OpCode = x86OpCode.Create(x86OpCodes.Unknown); instruction.OpCode._opcodeBytes = new byte[] { firstByte }; CurrentOffset = instruction.Offset.FileOffset + 1; }