public void GetScalerWhenNoSIBPresent() { // mov ebp,esp code = new Byte[] { 0x89, 0xe5 }; Assert.IsFalse(ModRM.HasSIB(code)); SIB.GetScaler(code); }
private static String GetSourceOperandFor(Byte[] code) { if (opcode.HasImmediate(code)) { return(String.Format("0x{0:x}", opcode.GetImmediateFor(code))); } if (opcode.HasOffset(code) && opcode.HasModRM(code)) { var offset = String.Format("0x{0:x}", ModRM.GetOffsetFor(code)); return(Encase(offset)); } if (SourceIsEffectiveAddress(code) && ModRM.HasSIB(code)) { return(Encase(GetSIBFor(code))); } if (opcode.HasSourceRegister(code)) { return(GetSourceRegisterFor(code)); } throw new ArgumentException( "don't know how to format this code's source operand: " + GetBytesFor(code) ); }
public void EsiEbp8() { // mov esi,DWORD PTR [ebp-8] code = new Byte[] { 0x8b, 0x75, 0xf8 }; Assert.AreEqual(RegisterName.EBP, ModRM.GetEvFor(code)); Assert.AreEqual(RegisterName.ESI, ModRM.GetGvFor(code)); Assert.AreEqual(0xf8, ModRM.GetIndexFor(code)); }
public void EdiEbp4() { // mov edi,DWORD PTR [ebp-4] code = new Byte[] { 0x8b, 0x7d, 0xfc }; Assert.AreEqual(RegisterName.EBP, ModRM.GetEvFor(code)); Assert.AreEqual(RegisterName.EDI, ModRM.GetGvFor(code)); Assert.AreEqual(0xfc, ModRM.GetIndexFor(code)); }
public void EaxEbpPlusDword12() { const int INDEX = 0x0c; code = new Byte[] { 0x8b, 0x85, INDEX, 0x00, 0x00, 0x00 }; Assert.IsTrue(ModRM.HasIndex(code)); Assert.AreEqual(INDEX, ModRM.GetIndexFor(code)); }
public void EaxEbx4() { // mov eax,DWORD PTR [ebx-4] code = new Byte[] { 0x8b, 0x43, 0xfc }; Assert.AreEqual(RegisterName.EBX, ModRM.GetEvFor(code)); Assert.AreEqual(RegisterName.EAX, ModRM.GetGvFor(code)); Assert.AreEqual(0xfc, ModRM.GetIndexFor(code)); }
public void EbxEsp0() { // mov ebx,DWORD PTR [esp] code = new Byte[] { 0x8b, 0x1c, 0x24 }; //// Assert.AreEqual(RegisterName.ESP, ModRM.GetEvFor(code)); Assert.IsTrue(ModRM.HasSIB(code)); Assert.AreEqual(RegisterName.EBX, ModRM.GetGvFor(code)); Assert.IsFalse(ModRM.HasIndex(code)); }
public void EbxEbp12() { // mov ebx,DWORD PTR [ebp-12] code = new Byte[] { 0x8b, 0x5d, 0xf4 }; Assert.AreEqual(RegisterName.EBP, ModRM.GetEvFor(code)); Assert.AreEqual(RegisterName.EBX, ModRM.GetGvFor(code)); Assert.IsFalse(ModRM.HasSIB(code)); Assert.AreEqual(0xf4, ModRM.GetIndexFor(code)); }
public void TwoByteWithModRMWithOnlyOffset() { // movzx edx,BYTE PTR ds:0x80495e0 code = new Byte[] { 0x0f, 0xb6, 0x15, 0xe0, 0x95, 0x04, 0x08 }; Assert.AreEqual(RegisterName.EDX, ModRM.GetGvFor(code)); Assert.IsFalse(ModRM.HasIndex(code)); Assert.IsTrue(ModRM.IsEffectiveAddressDereferenced(code)); Assert.IsTrue(ModRM.HasOffset(code)); }
public void TwoByteWithModRMWithIndex() { // movzx eax,BYTE PTR [ebp-5] code = new Byte[] { 0x0f, 0xb6, 0x45, 0xfb }; Assert.AreEqual(RegisterName.EBP, ModRM.GetEvFor(code)); Assert.AreEqual(RegisterName.EAX, ModRM.GetGvFor(code)); Assert.AreEqual(0xfb, ModRM.GetIndexFor(code)); Assert.IsTrue(ModRM.IsEffectiveAddressDereferenced(code)); }
public void TwoByteWithModRMNoIndex() { // movzx ebx,BYTE PTR [eax] code = new Byte[] { 0x0f, 0xb6, 0x18 }; Assert.AreEqual(RegisterName.EAX, ModRM.GetEvFor(code)); Assert.AreEqual(RegisterName.EBX, ModRM.GetGvFor(code)); Assert.IsFalse(ModRM.HasIndex(code)); Assert.IsTrue(ModRM.IsEffectiveAddressDereferenced(code)); }
public void EaxEaxNoIndex() { // mov eax,DWORD PTR [eax] code = new Byte[] { 0x8b, 0x00 }; Assert.AreEqual(RegisterName.EAX, ModRM.GetEvFor(code)); Assert.AreEqual(RegisterName.EAX, ModRM.GetGvFor(code)); Assert.IsFalse(ModRM.HasIndex(code)); Assert.IsTrue(ModRM.IsEffectiveAddressDereferenced(code)); }
public void MovEbpEsp() { // mov ebp,esp code = new Byte[] { 0x89, 0xe5 }; Assert.AreEqual(RegisterName.EBP, ModRM.GetEvFor(code)); Assert.AreEqual(RegisterName.ESP, ModRM.GetGvFor(code)); Assert.IsFalse(ModRM.HasIndex(code)); Assert.IsFalse(ModRM.IsEffectiveAddressDereferenced(code)); }
public void EaxEbpPlusSByte12() { // mov eax,DWORD PTR [ebp+index] const int INDEX = 0x0c; code = new Byte[] { 0x8b, 0x45, INDEX }; Assert.AreEqual(RegisterName.EBP, ModRM.GetEvFor(code)); Assert.AreEqual(RegisterName.EAX, ModRM.GetGvFor(code)); Assert.AreEqual(INDEX, ModRM.GetIndexFor(code)); }
public static UInt32 GetScaler(Byte[] code) { if (!ModRM.HasSIB(code)) { throw new InvalidOperationException( "For ModRM that does not specify a SIB, usage of GetBaseRegister is invalid."); } var s = (Byte)((GetSIBFor(code) >> 6) & 3); return((UInt32)Math.Pow(2, s)); }
public static RegisterName GetBaseRegister(Byte[] code) { if (!ModRM.HasSIB(code)) { throw new InvalidOperationException( "For ModRM that does not specify a SIB, usage of GetBaseRegister is invalid."); } var sib = GetSIBFor(code); var register = (RegisterName)(sib & 7); return(register); }
public UInt32 GetImmediateFor(Byte[] code) { if (!HasImmediate(code)) { throw new InvalidOperationException("Can't get immediate from an opcode that doesn't have one"); } Byte valueIndex = 1; if (HasModRM(code)) { valueIndex++; if (ModRM.HasIndex(code)) { valueIndex++; } if (ModRM.HasSIB(code)) { valueIndex++; } } switch (GetEncodingFor(code)) { case OpcodeEncoding.EvIb: case OpcodeEncoding.EbIb: case OpcodeEncoding.Jb: { return(code[valueIndex]); } case OpcodeEncoding.EvIz: case OpcodeEncoding.rAxIz: case OpcodeEncoding.rAxIv: case OpcodeEncoding.Jz: case OpcodeEncoding.Iz: { return(BitMath.BytesToDword(code, valueIndex)); } default: { throw new NotImplementedException("Don't know how to get the immediate for this opcode: " + code[0]); } } }
public static RegisterName GetScaledRegister(Byte[] code) { if (!ModRM.HasSIB(code)) { throw new InvalidOperationException( "For ModRM that does not specify a SIB, usage of GetBaseRegister is invalid."); } var register = (RegisterName)GetIndexFor(code); if (register == RegisterName.ESP) { register = RegisterName.None; } return(register); }
private static String GetDestinationOperandFor(Byte[] code) { var destinationOperand = opcode.GetDestinationRegisterFor(code).ToString().ToLower(); var destinationIsEffectiveAddress = opcode.GetEncodingFor(code).ToString().StartsWith("Ev", StringComparison.Ordinal) || opcode.GetEncodingFor(code).ToString().StartsWith("Eb", StringComparison.Ordinal); if (destinationIsEffectiveAddress && ModRM.HasSIB(code)) { var baseRegister = SIB.GetBaseRegister(code).ToString().ToLower(); var scaled = SIB.GetScaledRegister(code).ToString().ToLower(); var scaler = SIB.GetScaler(code); if (SIB.GetScaledRegister(code) == RegisterName.None) { destinationOperand = baseRegister; } else if (scaler == 1) { destinationOperand = baseRegister + "+" + scaled; } else { destinationOperand = baseRegister + "+" + scaled + "*" + scaler; } destinationOperand = Encase(destinationOperand); } else if (opcode.HasModRM(code) && destinationIsEffectiveAddress) { if (ModRM.HasIndex(code)) { destinationOperand += "+" + ModRM.GetIndexFor(code); } var effectiveAddressIsDereferenced = ModRM.IsEffectiveAddressDereferenced(code); if (effectiveAddressIsDereferenced) { destinationOperand = Encase(destinationOperand); } } return(destinationOperand); }
public Byte GetInstructionLengthFor(Byte[] code) { var instructionLength = GetOpcodeLengthFor(code); if (HasModRM(code)) { instructionLength++; if (ModRM.HasSIB(code)) { instructionLength++; } if (ModRM.HasIndex(code)) { instructionLength += 1; } } if (HasOffset(code)) { instructionLength += 4; } if (HasImmediate(code)) { switch (GetEncodingFor(code)) { case OpcodeEncoding.EbIb: case OpcodeEncoding.EvIb: case OpcodeEncoding.Jb: instructionLength += 1; break; default: instructionLength += 4; break; } } return(instructionLength); }
private static string GetSourceRegisterFor(byte[] code) { var sourceOperand = opcode.GetSourceRegisterFor(code).ToString().ToLower(); if (SourceIsEffectiveAddress(code) && opcode.HasModRM(code)) { if (ModRM.HasIndex(code)) { sourceOperand += "+" + ModRM.GetIndexFor(code); } var effectiveAddressIsDereferenced = ModRM.IsEffectiveAddressDereferenced(code); if (effectiveAddressIsDereferenced) { sourceOperand = Encase(sourceOperand); } } return(sourceOperand); }
public Boolean HasOffset(Byte[] code) { var encoding = GetEncodingFor(code); if (encoding == OpcodeEncoding.ObAL || encoding == OpcodeEncoding.rAxOv) { return(true); } if (HasModRM(code)) { if (ModRM.HasOffset(code)) { return(true); } } return(false); }
public void IsEvDwordTrue() { code = new Byte[] { 0x31, 0x05 }; Assert.IsTrue(ModRM.IsEvDword(code)); }
public void MovEsp16() { // mov DWORD PTR [esp],0x10 code = new Byte[] { 0xc7, 0x04, 0x24, 0x10, 0x00, 0x00, 0x00 }; Assert.IsTrue(ModRM.HasSIB(code)); }
public void HasSIBWhenNoModRMPresent() { code = new Byte[] { 0x00 }; ModRM.HasSIB(code); }
public RegisterName GetSourceRegisterFor(Byte[] code) { var opcodeEncoding = GetEncodingFor(code); if (GetStackEffectFor(code) == StackEffect.Push) { switch (opcodeEncoding) { case OpcodeEncoding.rBP: { return(RegisterName.EBP); } case OpcodeEncoding.rSI: { return(RegisterName.ESI); } case OpcodeEncoding.rSP: { return(RegisterName.ESP); } case OpcodeEncoding.rAX: { return(RegisterName.EAX); } case OpcodeEncoding.rBX: { return(RegisterName.EBX); } case OpcodeEncoding.rCX: { return(RegisterName.ECX); } case OpcodeEncoding.rDX: { return(RegisterName.EDX); } } } switch (opcodeEncoding) { case OpcodeEncoding.EbGb: case OpcodeEncoding.EvGv: { return(ModRM.GetGvFor(code)); } case OpcodeEncoding.GvEb: case OpcodeEncoding.GvEv: case OpcodeEncoding.GvM: { if (ModRM.HasSIB(code)) { // MOV EAX,DWORD PTR DS:[EDX+EAX*4] // Since SIB does not have a single source register // it currently returns RegisterName.None return(RegisterName.None); } if (ModRM.IsEvDword(code)) { return(RegisterName.None); } return(ModRM.GetEvFor(code)); } default: { return(RegisterName.None); } } }
public void EvGvSIBNoIndexToEspFromEax() { code = new Byte[] { 0x89, 0x04, 0x24 }; Assert.IsTrue(ModRM.HasSIB(code)); Assert.AreEqual(RegisterName.ESP, SIB.GetBaseRegister(code)); }
private static MachineState EmulateOpcode(ICollection <ReportItem> reportItems, MachineState machineState, Byte[] code) { var state = machineState; RegisterName sourceRegister, destinationRegister; AbstractValue sourceValue; Int32 index; var encoding = opcode.GetEncodingFor(code); var op = opcode.GetOperatorEffectFor(code); switch (encoding) { case OpcodeEncoding.rAxIv: case OpcodeEncoding.rAxIz: { destinationRegister = opcode.GetDestinationRegisterFor(code); var immediate = opcode.GetImmediateFor(code); state = state.DoOperation(destinationRegister, op, new AbstractValue(immediate)); return(state); } case OpcodeEncoding.rAxOv: { state.Registers[RegisterName.EAX] = state.DataSegment[BitMath.BytesToDword(code, 1)]; return(state); } case OpcodeEncoding.rBP: case OpcodeEncoding.rSI: case OpcodeEncoding.rSP: case OpcodeEncoding.rAX: case OpcodeEncoding.rBX: case OpcodeEncoding.rCX: case OpcodeEncoding.rDX: case OpcodeEncoding.Iz: { return(emulateStackEffectFor(code, state)); } case OpcodeEncoding.EvIz: case OpcodeEncoding.EvIb: case OpcodeEncoding.EbIb: case OpcodeEncoding.EvGv: case OpcodeEncoding.EbGb: { destinationRegister = opcode.GetDestinationRegisterFor(code); index = 0; if (ModRM.HasIndex(code)) { index = ModRM.GetIndexFor(code); } if (opcode.HasImmediate(code)) { sourceValue = new AbstractValue(opcode.GetImmediateFor(code)); } else { sourceRegister = ModRM.GetGvFor(code); sourceValue = state.Registers[sourceRegister]; } ////if (ModRM.HasOffset(code)) ////{ //// UInt32 offset = ModRM.GetOffsetFor(code); //// state.DataSegment[offset] = sourceValue; //// return state; ////} if (ModRM.IsEffectiveAddressDereferenced(code)) { if (!state.Registers[destinationRegister].IsPointer) { throw new InvalidOperationException( "Trying to dereference non-pointer in register " + destinationRegister ); } state = state.DoOperation(destinationRegister, index, op, sourceValue); if (state.Registers[destinationRegister].PointsTo[index].IsOutOfBounds) { reportItems.Add(new ReportItem(state.InstructionPointer, sourceValue.IsTainted)); } } else { state = state.DoOperation(destinationRegister, op, sourceValue); if (state.Registers[destinationRegister].IsOutOfBounds) { reportItems.Add(new ReportItem(state.InstructionPointer, sourceValue.IsTainted)); } } return(state); } case OpcodeEncoding.GvEv: case OpcodeEncoding.GvEb: { sourceRegister = ModRM.GetEvFor(code); destinationRegister = ModRM.GetGvFor(code); sourceValue = state.Registers[sourceRegister]; if (ModRM.HasOffset(code)) { var offset = ModRM.GetOffsetFor(code); sourceValue = state.DataSegment[offset]; } else if (ModRM.IsEffectiveAddressDereferenced(code)) { if (!sourceValue.IsPointer) { throw new InvalidOperationException( String.Format("Trying to dereference null pointer in register {0}.", sourceRegister)); } index = 0; if (ModRM.HasIndex(code)) { index = ModRM.GetIndexFor(code); } sourceValue = sourceValue.PointsTo[index]; if (sourceValue.IsOutOfBounds) { reportItems.Add(new ReportItem(state.InstructionPointer, sourceValue.IsTainted)); } } state = state.DoOperation(destinationRegister, op, sourceValue); return(state); } case OpcodeEncoding.GvM: { // GvM, M may refer to [base register + offset] if (!ModRM.IsEffectiveAddressDereferenced(code)) { throw new InvalidOperationException("GvM must be dereferenced"); } destinationRegister = opcode.GetDestinationRegisterFor(code); AbstractValue baseRegisterValue; index = 0; // TODO: handle the [dword] special case if (ModRM.HasSIB(code)) { var scaledRegisterValue = state.Registers[SIB.GetScaledRegister(code)].Value; var scaler = SIB.GetScaler(code); baseRegisterValue = state.Registers[SIB.GetBaseRegister(code)]; index = (Int32)(scaledRegisterValue * scaler); } else { sourceRegister = ModRM.GetEvFor(code); if (ModRM.HasIndex(code)) { index = ModRM.GetIndexFor(code); } baseRegisterValue = state.Registers[sourceRegister]; } // TODO: review these casts of index for possible elimination sourceValue = new AbstractValue( baseRegisterValue.PointsTo.DoOperation( OperatorEffect.Add, new AbstractValue((UInt32)index) ) ); state = state.DoOperation(destinationRegister, OperatorEffect.Assignment, sourceValue); if (state.Registers[destinationRegister].IsOutOfBounds) { var reportItem = new ReportItem(state.InstructionPointer, sourceValue.IsTainted); reportItems.Add(reportItem); } return(state); } case OpcodeEncoding.ObAL: { var dwordValue = state.Registers[RegisterName.EAX]; var byteValue = dwordValue.TruncateValueToByte(); var offset = BitMath.BytesToDword(code, 1); if (!state.DataSegment.ContainsKey(offset)) { state.DataSegment[offset] = new AbstractValue(); } state = state.DoOperation(offset, op, byteValue); return(state); } case OpcodeEncoding.Jz: { // TODO: should push EIP + code.Length onto stack var contractSatisfied = false; var mallocContract = new MallocContract(); var glibcStartMainContract = new GLibcStartMainContract(); var contracts = new List <Contract> { mallocContract, glibcStartMainContract }; foreach (var contract in contracts) { if (contract.IsSatisfiedBy(state, code)) { contractSatisfied = true; state = contract.Execute(state); } } if (!contractSatisfied) { var returnAddress = state.InstructionPointer + (UInt32)code.Length; state = state.PushOntoStack(new AbstractValue(returnAddress)); state.InstructionPointer = opcode.GetEffectiveAddress(code, state.InstructionPointer); } return(state); } case OpcodeEncoding.Jb: { var offset = code[1]; state = state.DoOperation(op, new AbstractValue(offset)); state.InstructionPointer += opcode.GetInstructionLengthFor(code); return(state); } case OpcodeEncoding.None: { return(state); } default: { throw new InvalidOpcodeException(code); } } }
public OperatorEffect GetOperatorEffectFor(Byte[] code) { switch (code[0]) { case 0x05: return(OperatorEffect.Add); case 0x29: return(OperatorEffect.Sub); case 0x31: return(OperatorEffect.Xor); case 0x75: return(OperatorEffect.Jnz); case 0x83: { var rm = ModRM.GetOpcodeGroupIndexFor(code); switch (rm) { case 0: return(OperatorEffect.Add); case 4: return(OperatorEffect.And); case 5: return(OperatorEffect.Sub); case 7: return(OperatorEffect.Cmp); default: return(OperatorEffect.Unknown); } } case 0xc9: return(OperatorEffect.Leave); case 0xc3: return(OperatorEffect.Return); case 0x90: return(OperatorEffect.None); case 0xc1: { var rm = ModRM.GetOpcodeGroupIndexFor(code); switch (rm) { case 4: return(OperatorEffect.Shl); case 5: return(OperatorEffect.Shr); default: return(OperatorEffect.Unknown); } } case 0xe8: return(OperatorEffect.Call); default: return(OperatorEffect.Assignment); } }
public RegisterName GetDestinationRegisterFor(Byte[] code) { var opcodeEncoding = GetEncodingFor(code); if (GetStackEffectFor(code) == StackEffect.Pop) { switch (opcodeEncoding) { case OpcodeEncoding.rBP: { return(RegisterName.EBP); } case OpcodeEncoding.rSI: { return(RegisterName.ESI); } case OpcodeEncoding.rSP: { return(RegisterName.ESP); } case OpcodeEncoding.rAX: { return(RegisterName.EAX); } case OpcodeEncoding.rBX: { return(RegisterName.EBX); } case OpcodeEncoding.rCX: { return(RegisterName.ECX); } case OpcodeEncoding.rDX: { return(RegisterName.EDX); } } } switch (opcodeEncoding) { case OpcodeEncoding.GvM: case OpcodeEncoding.GvEv: case OpcodeEncoding.GvEb: { return(ModRM.GetGvFor(code)); } case OpcodeEncoding.rAxIv: case OpcodeEncoding.rAxIz: { return(RegisterName.EAX); } case OpcodeEncoding.EbGb: case OpcodeEncoding.EbIb: case OpcodeEncoding.EvGv: case OpcodeEncoding.EvIb: case OpcodeEncoding.EvIz: { if (ModRM.HasSIB(code)) { return(SIB.GetBaseRegister(code)); } return(ModRM.GetEvFor(code)); } default: { return(RegisterName.None); } } }