#include "Virtualizer.h" #include "VirtualMachine.h" #define VmIRegLoadMemHandlerId(IReg, MemOpType) (VM_ICLASS_LD_IREG_MEM_START + VM_MEMOP_TYPE_COUNT * (IReg) + (MemOpType)) #define VmIRegStoreMemHandlerId(IReg, MemOpType) (VM_ICLASS_ST_IREG_MEM_START + VM_MEMOP_TYPE_COUNT * (IReg) + (MemOpType)) #define VmIRegLoadRegHandlerId(IReg) (VM_ICLASS_LD_IREG_REG_START + (IReg)) #define VmIRegStoreRegHandlerId(IReg) (VM_ICLASS_ST_IREG_REG_START + (IReg)) #define VmIRegLoadImmHandlerId(IReg) (VM_ICLASS_LD_IREG_IMM_START + (IReg)) PVM_HANDLER ViGetVmHandler(PVIRTUALIZER Virt, UINT Id) { if (Virt->HandlerMap[Id] == 0) { Virt->Handlers.push_back(new VM_HANDLER()); Virt->HandlerMap[Id] = (USHORT)(Virt->Handlers.size() - 1); } return Virt->Handlers[Virt->HandlerMap[Id]]; } CONST CHAR* ViIClassToString(UINT IClass) { if (IClass >= VM_ICLASS_ENTER) return VmIClassToString((VM_ICLASS_ENUM)IClass); return XedIClassEnumToString((XED_ICLASS_ENUM)IClass); } BOOL ViCanHandleInst(PNATIVE_CODE_LINK Link) { switch (XedDecodedInstGetIClass(&Link->XedInstruction)) { case XED_ICLASS_MOV: return TRUE; } return FALSE; } BOOL ViValidateNativeCodeBlock(PVIRTUALIZER Virt, PNATIVE_CODE_BLOCK Block) { for (PNATIVE_CODE_LINK T = Block->Start; T && T != Block->End->Next; T = T->Next) { if (!ViCanHandleInst(T)) return FALSE; //Cant handle RIP relative instructions. CONST XED_INST* Inst = XedDecodedInstInst(&T->XedInstruction); UINT OperandCount = XedDecodedInstNumOperands(&T->XedInstruction); for (UINT i = 0; i < OperandCount; i++) { XED_OPERAND_ENUM OperandName = XedOperandName(XedInstOperand(Inst, i)); if ((OperandName == XED_OPERAND_MEM0 || OperandName == XED_OPERAND_MEM1) && XedDecodedInstGetBaseReg(&T->XedInstruction, OperandName - XED_OPERAND_MEM0) == XED_REG_RIP) return FALSE; } } return TRUE; } BOOL ViVirtualizeInst(PVIRTUALIZER Virt, XED_DECODED_INST* DecodedInst, PVM_CODE_BLOCK Block) { VM_CODE_BLOCK Prologue = { }; VM_CODE_BLOCK Epilogue = { }; CONST XED_INST* Inst = XedDecodedInstInst(DecodedInst); UINT OperandCount = XedDecodedInstNumOperands(DecodedInst); XED_ICLASS_ENUM IClass = XedDecodedInstGetIClass(DecodedInst); STDVECTOR Operands = {}; VM_OPERAND_SIZE_ENUM OpSize[3] = { VM_OPSIZE_8 }; for (UINT i = 0; i < OperandCount; i++) { CONST XED_OPERAND* Operand = XedInstOperand(Inst, i); XED_OPERAND_ENUM OperandName = XedOperandName(Operand); if (XedOperandIsRegister(OperandName) && XED_REG_RFLAGS == XedDecodedInstGetReg(DecodedInst, OperandName)) continue; Operands.push_back(Operand); OpSize[Operands.size() - 1] = (VM_OPERAND_SIZE_ENUM)(log2(XedDecodedInstOperandLength(DecodedInst, i))); } for (UINT i = 0; i < Operands.size(); i++) { CONST XED_OPERAND* Operand = Operands[i]; XED_OPERAND_ENUM OperandName = XedOperandName(Operand); VM_IREG_ENUM IReg = (VM_IREG_ENUM)(VM_IREG_1 + i); if (XedOperandIsRegister(OperandName)) { if (XedOperandRead(Operand)) { USHORT HandlerId = VmIRegLoadRegHandlerId(IReg); PVM_HANDLER_DESCRIPTOR Desc = ViGetVmHandler(Virt, HandlerId)->GetDesc(OpSize); if (!Desc->Data) Desc->Data = VmHandlerIRegReg(IReg, OpSize[i], TRUE, &Desc->DataSize); PVM_CODE_LINK Link = new VM_CODE_LINK(); Link->HandlerId = HandlerId; Link->Flags |= CODE_FLAG_IREG_OPERATION; Link->Reg.Register = VmXRegToVRegId(XedDecodedInstGetReg(DecodedInst, OperandName)); VcAppendToBlock(&Prologue, Link); } if (XedOperandWritten(Operand)) { USHORT HandlerId = VmIRegStoreRegHandlerId(IReg); PVM_HANDLER_DESCRIPTOR Desc = ViGetVmHandler(Virt, HandlerId)->GetDesc(OpSize); if (!Desc->Data) Desc->Data = VmHandlerIRegReg(IReg, OpSize[i], FALSE, &Desc->DataSize); PVM_CODE_LINK Link = new VM_CODE_LINK(); Link->HandlerId = HandlerId; Link->Flags |= CODE_FLAG_IREG_OPERATION; Link->Reg.Register = VmXRegToVRegId(XedDecodedInstGetReg(DecodedInst, OperandName)); VcAppendToBlock(&Epilogue, Link); } } else if (OperandName == XED_OPERAND_MEM0/* || OperandName == XED_OPERAND_MEM1*/) { UINT MemOpIndex = OperandName - XED_OPERAND_MEM0; XED_REG_ENUM Base = XedDecodedInstGetBaseReg(DecodedInst, MemOpIndex); XED_REG_ENUM Index = XedDecodedInstGetIndexReg(DecodedInst, MemOpIndex); UINT Scale = XedDecodedInstGetScale(DecodedInst, MemOpIndex); LONGLONG Displacement = XedDecodedInstGetMemoryDisplacement(DecodedInst, MemOpIndex); UINT MemOpType = VM_MEMOP_TYPE_COUNT; if (Base != XED_REG_INVALID) MemOpType = VM_MEMOP_B; if (Index != XED_REG_INVALID) MemOpType = VM_MEMOP_BIS; if (Displacement != 0) MemOpType += 1; if (XedOperandRead(Operand)) { USHORT HandlerId = VmIRegLoadMemHandlerId(IReg, MemOpType); PVM_HANDLER_DESCRIPTOR Desc = ViGetVmHandler(Virt, HandlerId)->GetDesc(OpSize); if (!Desc->Data) Desc->Data = VmHandlerIRegMem((VM_MEMOP_TYPE_ENUM)MemOpType, IReg, OpSize[i], TRUE, &Desc->DataSize); PVM_CODE_LINK Link = new VM_CODE_LINK(); Link->HandlerId = HandlerId; Link->Flags |= CODE_FLAG_IREG_OPERATION; Link->Mem.Base = VmXRegToVRegId(Base); Link->Mem.Index = VmXRegToVRegId(Index); Link->Mem.Scale = Scale; Link->Mem.Displacement = Displacement; VcAppendToBlock(&Prologue, Link); } if (XedOperandWritten(Operand)) { USHORT HandlerId = VmIRegStoreMemHandlerId(IReg, MemOpType); PVM_HANDLER_DESCRIPTOR Desc = ViGetVmHandler(Virt, HandlerId)->GetDesc(OpSize); if (!Desc->Data) Desc->Data = VmHandlerIRegMem((VM_MEMOP_TYPE_ENUM)MemOpType, IReg, OpSize[i], FALSE, &Desc->DataSize); PVM_CODE_LINK Link = new VM_CODE_LINK(); Link->HandlerId = HandlerId; Link->Flags |= CODE_FLAG_IREG_OPERATION; Link->Mem.Base = VmXRegToVRegId(Base); Link->Mem.Index = VmXRegToVRegId(Index); Link->Mem.Scale = Scale; Link->Mem.Displacement = Displacement; VcAppendToBlock(&Epilogue, Link); } } else if (OperandName == XED_OPERAND_IMM0) { USHORT HandlerId = VmIRegLoadImmHandlerId(IReg); if (Operands.size() > 1) OpSize[i] = OpSize[i - 1]; else OpSize[i] = VM_OPSIZE_64; //assume 16 for 1 operand imm instructions PVM_HANDLER_DESCRIPTOR Desc = ViGetVmHandler(Virt, HandlerId)->GetDesc(OpSize); if (!Desc->Data) Desc->Data = VmHandlerIRegImm(IReg, OpSize[i], &Desc->DataSize); PVM_CODE_LINK Link = new VM_CODE_LINK(); Link->HandlerId = HandlerId; Link->Flags |= CODE_FLAG_IREG_OPERATION; if (XedDecodedInstGetImmediateIsSigned(DecodedInst)) Link->Imm.Immediate.i64 = (INT64)XedDecodedInstGetSignedImmediate(DecodedInst); else Link->Imm.Immediate.u64 = XedDecodedInstGetUnsignedImmediate(DecodedInst); /*else { ULONG64 ImmRaw = xed_decoded_inst_get_unsigned_immediate(DecodedInst); memcpy(&Link->Imm.Immediate.Raw, &ImmRaw, VmOpSizeToBytes(OpSize[i])); }*/ VcAppendToBlock(&Prologue, Link); } } switch (IClass) { default: PVM_CODE_LINK Link = new VM_CODE_LINK(); Link->HandlerId = IClass; Link->Flags |= CODE_FLAG_NATIVE_OPERATION; PVM_HANDLER_DESCRIPTOR Desc = ViGetVmHandler(Virt, IClass)->GetDesc(OpSize); if (!Desc->Data) { switch (Operands.size()) { case 1: Desc->Data = VmHandlerEncode1(IClass, OpSize[0], &Desc->DataSize); break; case 2: Desc->Data = VmHandlerEncode2(IClass, OpSize[0], OpSize[1], &Desc->DataSize); break; case 3: Desc->Data = VmHandlerEncode3(IClass, OpSize[0], OpSize[1], OpSize[2], &Desc->DataSize); break; } } VcAppendToBlock(&Prologue, Link); } if (Epilogue.Start) { Prologue.End->Next = Epilogue.Start; Epilogue.Start = Prologue.End; Prologue.End = Epilogue.End; } Block->Start = Prologue.Start; Block->End = Prologue.End; return TRUE; }