You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

197 lines
9.4 KiB

#include "VirtualMachine.h"
XED_REG_ENUM VmOperandSizeToRegEnumBase(VM_OPERAND_SIZE_ENUM OperandSize)
{
switch (OperandSize)
{
case VM_OPSIZE_1: return XED_REG_GPR8_FIRST;
case VM_OPSIZE_2: return XED_REG_GPR16_FIRST;
case VM_OPSIZE_4: return XED_REG_GPR32_FIRST;
case VM_OPSIZE_8: return XED_REG_GPR64_FIRST;
}
return XED_REG_INVALID;
}
XED_REG_ENUM VmGetRegOfSize(XED_REG_ENUM Reg, VM_OPERAND_SIZE_ENUM OperandSize)
{
if (Reg >= XED_REG_GPR8_FIRST && Reg <= XED_REG_GPR8_LAST)
{
return (XED_REG_ENUM)(VmOperandSizeToRegEnumBase(OperandSize) + (Reg - XED_REG_GPR8_FIRST));
}
else if (Reg >= XED_REG_GPR16_FIRST && Reg <= XED_REG_GPR16_LAST)
{
return (XED_REG_ENUM)(VmOperandSizeToRegEnumBase(OperandSize) + (Reg - XED_REG_GPR16_FIRST));
}
if (Reg >= XED_REG_GPR32_FIRST && Reg <= XED_REG_GPR32_LAST)
{
return (XED_REG_ENUM)(VmOperandSizeToRegEnumBase(OperandSize) + (Reg - XED_REG_GPR32_FIRST));
}
else if (Reg >= XED_REG_GPR64_FIRST && Reg <= XED_REG_GPR64_LAST)
{
return (XED_REG_ENUM)(VmOperandSizeToRegEnumBase(OperandSize) + (Reg - XED_REG_GPR64_FIRST));
}
return XED_REG_INVALID;
}
XED_REG_ENUM VmIRegToXReg(VM_IREG_ENUM IReg, VM_OPERAND_SIZE_ENUM OperandSize)
{
switch (IReg)
{
case VM_IREG_0: return VmGetRegOfSize(XED_REG_RAX, OperandSize);
case VM_IREG_1: return VmGetRegOfSize(XED_REG_RBX, OperandSize);
case VM_IREG_2: return VmGetRegOfSize(XED_REG_RCX, OperandSize);
}
return XED_REG_INVALID;
//Less portable version.
/*if (OperandSize == VM_OPSIZE_1)
{
return (XED_REG_ENUM)(XED_REG_AL + IReg);
}
return (XED_REG_ENUM)(XED_REG_AX + (16 * (OperandSize - 1)) + IReg);*/
}
PUCHAR VmHandlerPrologue(UINT InstructionSize, PUINT OutSize, XED_REG_ENUM Vip, XED_REG_ENUM HandlerTableReg)
{
// add rdx, InstructionSize + Prologue Size
// movzx r8,byte ptr[rdx]
// jmp qword ptr[rsi+r8*8h]
XED_ENCODER_INSTRUCTION InstList[3];
InstructionSize += VM_HANDLER_PROLOGUE_SIZE;
XedInst2(&InstList[0], XedGlobalMachineState, XED_ICLASS_ADD, 64, XedReg(Vip), XedImm0(InstructionSize, 32));
XedInst2(&InstList[1], XedGlobalMachineState, XED_ICLASS_MOVZX, 64, XedReg(XED_REG_R8), XedMemB(Vip, 16));
XedInst1(&InstList[2], XedGlobalMachineState, XED_ICLASS_JMP, 64, XedMemBISD(HandlerTableReg, XED_REG_R8, 8, XedDisp(0, 0), 64));
PUCHAR Ret = XedEncodeInstructions(InstList, 3, OutSize);
if (*OutSize == VM_HANDLER_PROLOGUE_SIZE)
return Ret;
delete[] Ret;
InstructionSize -= VM_HANDLER_PROLOGUE_SIZE;
InstructionSize += *OutSize;
XedInst2(&InstList[0], XedGlobalMachineState, XED_ICLASS_ADD, 64, XedReg(Vip), XedImm0(InstructionSize, 32));
XedInst2(&InstList[1], XedGlobalMachineState, XED_ICLASS_MOVZX, 64, XedReg(XED_REG_R8), XedMemB(Vip, 16));
XedInst1(&InstList[2], XedGlobalMachineState, XED_ICLASS_JMP, 64, XedMemBISD(HandlerTableReg, XED_REG_R8, 8, XedDisp(0, 0), 64));
return XedEncodeInstructions(InstList, 3, OutSize);
}
PUCHAR VmHandlerIRegLoadMem_B(VM_IREG_ENUM IReg, VM_OPERAND_SIZE_ENUM OperandSize, PUINT OutSize)
{
/*
* movzx r8,byte ptr[rdx+2]
* mov r8, qword ptr[rbp+r8*8]
* mov (ireg), (size) ptr[r8]
*/
UINT OpSizeBits = VmOpSizeToBits(OperandSize);
XED_ENCODER_INSTRUCTION InstList[3];
XedInst2(&InstList[0], XedGlobalMachineState, XED_ICLASS_MOVZX, 64, XedReg(XED_REG_R8), XedMemBD(XED_REG_RDX, XedDisp(2, 8), 8));
XedInst2(&InstList[1], XedGlobalMachineState, XED_ICLASS_MOV, 64, XedReg(XED_REG_R8), XedMemBISD(XED_REG_RBP, XED_REG_R8, 8, XedDisp(0,0), 64));
XedInst2(&InstList[2], XedGlobalMachineState, XED_ICLASS_MOV, OpSizeBits, XedReg(VmIRegToXReg(IReg, OperandSize)), XedMemB(XED_REG_R8, OpSizeBits));
return XedEncodeInstructions(InstList, 3, OutSize);
}
PUCHAR VmHandlerIRegLoadMem_BO(VM_IREG_ENUM IReg, VM_OPERAND_SIZE_ENUM OperandSize, PUINT OutSize)
{
/*
* movzx r8,byte ptr[rdx+2]
* mov r8, qword ptr[rbp+r8*8]
* mov r9, dword ptr[rdx+3]
* mov (ireg), (size) ptr[r8+r9]
*/
UINT OpSizeBits = VmOpSizeToBits(OperandSize);
XED_ENCODER_INSTRUCTION InstList[4];
XedInst2(&InstList[0], XedGlobalMachineState, XED_ICLASS_MOVZX, 64, XedReg(XED_REG_R8), XedMemBD(XED_REG_RDX, XedDisp(2, 8), 8));
XedInst2(&InstList[1], XedGlobalMachineState, XED_ICLASS_MOV, 64, XedReg(XED_REG_R8), XedMemBISD(XED_REG_RBP, XED_REG_R8, 8, XedDisp(0, 0), 64));
XedInst2(&InstList[2], XedGlobalMachineState, XED_ICLASS_MOVSXD, 64, XedReg(XED_REG_R9), XedMemBD(XED_REG_RDX, XedDisp(3, 8), 32));
XedInst2(&InstList[3], XedGlobalMachineState, XED_ICLASS_MOV, OpSizeBits, XedReg(VmIRegToXReg(IReg, OperandSize)), XedMemBISD(XED_REG_R8, XED_REG_R9, 1, XedDisp(0, 0), OpSizeBits));
return XedEncodeInstructions(InstList, 4, OutSize);
}
PUCHAR VmHandlerIRegLoadMem_BIS(VM_IREG_ENUM IReg, VM_OPERAND_SIZE_ENUM OperandSize, PUINT OutSize)
{
/*
* movzx r8,byte ptr[rdx+2]
* mov r8, qword ptr[rbp+r8*8]
* movzx r9, byte ptr[rdx+3]
* mov r9, qword ptr[rbp+r9*8]
* movzx r10, byte ptr[rdx+4] ;load scale value(unsigned)
* imul r9,r10
* mov (ireg), (size) ptr[r8+r9]
*/
UINT OpSizeBits = VmOpSizeToBits(OperandSize);
XED_ENCODER_INSTRUCTION InstList[7];
XedInst2(&InstList[0], XedGlobalMachineState, XED_ICLASS_MOVZX, 64, XedReg(XED_REG_R8), XedMemBD(XED_REG_RDX, XedDisp(2, 8), 8));
XedInst2(&InstList[1], XedGlobalMachineState, XED_ICLASS_MOV, 64, XedReg(XED_REG_R8), XedMemBISD(XED_REG_RBP, XED_REG_R8, 8, XedDisp(0, 0), 64));
XedInst2(&InstList[2], XedGlobalMachineState, XED_ICLASS_MOVSX, 64, XedReg(XED_REG_R9), XedMemBD(XED_REG_RDX, XedDisp(3, 8), 8));
XedInst2(&InstList[3], XedGlobalMachineState, XED_ICLASS_MOV, 64, XedReg(XED_REG_R9), XedMemBISD(XED_REG_RBP, XED_REG_R9, 8, XedDisp(0, 0), 64));
XedInst2(&InstList[4], XedGlobalMachineState, XED_ICLASS_MOVSX, 64, XedReg(XED_REG_R10), XedMemBD(XED_REG_RDX, XedDisp(4, 8), 8));
XedInst2(&InstList[5], XedGlobalMachineState, XED_ICLASS_IMUL, 64, XedReg(XED_REG_R9), XedReg(XED_REG_R10));
XedInst2(&InstList[6], XedGlobalMachineState, XED_ICLASS_MOV, OpSizeBits, XedReg(VmIRegToXReg(IReg, OperandSize)), XedMemBISD(XED_REG_R8, XED_REG_R9, 1, XedDisp(0, 0), OpSizeBits));
return XedEncodeInstructions(InstList, 7, OutSize);
}
PUCHAR VmHandlerIRegLoadMem_BISO(VM_IREG_ENUM IReg, VM_OPERAND_SIZE_ENUM OperandSize, PUINT OutSize)
{
/*
* movzx r8, byte ptr[rdx+2]
* mov r8, qword ptr[rbp+r8*8]
* movzx r9, byte ptr[rdx+3]
* mov r9, qword ptr[rbp+r9*8]
* movzx r10, byte ptr[rdx+4] ;load scale value(unsigned)
* imul r9, r10
* movsxd r10, dword ptr[rdx+5] ;load immediate displacement
* add r9, r10 ;add immediate displacement
* mov (ireg), (size) ptr[r8+r9]
*/
UINT OpSizeBits = VmOpSizeToBits(OperandSize);
XED_ENCODER_INSTRUCTION InstList[9];
XedInst2(&InstList[0], XedGlobalMachineState, XED_ICLASS_MOVZX, 64, XedReg(XED_REG_R8), XedMemBD(XED_REG_RDX, XedDisp(2, 8), 8));
XedInst2(&InstList[1], XedGlobalMachineState, XED_ICLASS_MOV, 64, XedReg(XED_REG_R8), XedMemBISD(XED_REG_RBP, XED_REG_R8, 8, XedDisp(0, 0), 64));
XedInst2(&InstList[2], XedGlobalMachineState, XED_ICLASS_MOVSX, 64, XedReg(XED_REG_R9), XedMemBD(XED_REG_RDX, XedDisp(3, 8), 8));
XedInst2(&InstList[3], XedGlobalMachineState, XED_ICLASS_MOV, 64, XedReg(XED_REG_R9), XedMemBISD(XED_REG_RBP, XED_REG_R9, 8, XedDisp(0, 0), 64));
XedInst2(&InstList[4], XedGlobalMachineState, XED_ICLASS_MOVSX, 64, XedReg(XED_REG_R10), XedMemBD(XED_REG_RDX, XedDisp(4, 8), 8));
XedInst2(&InstList[5], XedGlobalMachineState, XED_ICLASS_IMUL, 64, XedReg(XED_REG_R9), XedReg(XED_REG_R10));
XedInst2(&InstList[6], XedGlobalMachineState, XED_ICLASS_MOVSXD, 64, XedReg(XED_REG_R10), XedMemBD(XED_REG_RDX, XedDisp(5, 8), 32));
XedInst2(&InstList[7], XedGlobalMachineState, XED_ICLASS_ADD, 64, XedReg(XED_REG_R9), XedReg(XED_REG_R10));
XedInst2(&InstList[8], XedGlobalMachineState, XED_ICLASS_MOV, OpSizeBits, XedReg(VmIRegToXReg(IReg, OperandSize)), XedMemBISD(XED_REG_R8, XED_REG_R9, 1, XedDisp(0, 0), OpSizeBits));
return XedEncodeInstructions(InstList, 9, OutSize);
}
PUCHAR VmHandlerIRegLoadReg(VM_IREG_ENUM IReg, VM_OPERAND_SIZE_ENUM OperandSize, PUINT OutSize)
{
/*
* movzx r8,byte ptr[rdx+2]
* mov (ireg), (size) ptr[rbp+r8*8]
*/
UINT OpSizeBits = VmOpSizeToBits(OperandSize);
XED_ENCODER_INSTRUCTION InstList[2];
XedInst2(&InstList[0], XedGlobalMachineState, XED_ICLASS_MOVZX, 64, XedReg(XED_REG_R8), XedMemBD(XED_REG_RDX, XedDisp(2, 8), 8));
XedInst2(&InstList[1], XedGlobalMachineState, XED_ICLASS_MOV, OpSizeBits, XedReg(VmIRegToXReg(IReg, OperandSize)), XedMemBISD(XED_REG_RBP, XED_REG_R8, 8, XedDisp(0, 0), OpSizeBits));
return XedEncodeInstructions(InstList, 2, OutSize);
}
PUCHAR VmHandlerIRegStoreReg(VM_IREG_ENUM IReg, VM_OPERAND_SIZE_ENUM OperandSize, PUINT OutSize)
{
/*
* movzx r8,byte ptr[rdx+2]
* mov (size) ptr[rbp+r8*8], (ireg)
*/
UINT OpSizeBits = VmOpSizeToBits(OperandSize);
XED_ENCODER_INSTRUCTION InstList[2];
XedInst2(&InstList[0], XedGlobalMachineState, XED_ICLASS_MOVZX, 64, XedReg(XED_REG_R8), XedMemBD(XED_REG_RDX, XedDisp(2, 8), 8));
XedInst2(&InstList[1], XedGlobalMachineState, XED_ICLASS_MOV, OpSizeBits, XedMemBISD(XED_REG_RBP, XED_REG_R8, 8, XedDisp(0, 0), OpSizeBits), XedReg(VmIRegToXReg(IReg, OperandSize)));
return XedEncodeInstructions(InstList, 2, OutSize);
}
PUCHAR VmHandlerIRegLoadImm(VM_IREG_ENUM IReg, VM_OPERAND_SIZE_ENUM OperandSize, PUINT OutSize)
{
/*
* mov (ireg), size ptr[rdx+2]
*/
UINT OpSizeBits = VmOpSizeToBits(OperandSize);
XED_ENCODER_INSTRUCTION InstList[1];
XedInst2(&InstList[0], XedGlobalMachineState, XED_ICLASS_MOV, OpSizeBits, XedReg(VmIRegToXReg(IReg, OperandSize)), XedMemBD(XED_REG_RDX, XedDisp(2, 8), OpSizeBits));
return XedEncodeInstructions(InstList, 1, OutSize);
}