Handler Type 2__

2handler的结构要清晰一些,如果不算2字节opcode中的重复部分,这类handler7个。特征是PCODE.OpcodeTail数据为3字节,操作数类型为RegReg/RegImm,即这类指令的dstVM_Context内的通用寄存器,srcVM_Context内的通用寄存器或立即数。

 

下面以Vm_MovReg为例说明。

 

这类handlerVM_Context.flag的初始值预置为0。解码byte1,对这个字节的使用与Type1中的byte2相似, b7位为1,使用VM_Context+60h,+64h2dword修改vm栈内由key1解码的OldArgument。由于这2dword似乎总为0,这里不会产生实质的影响。

 

解码byte2,byte3(不再费事去取名了,就是按解码的顺序编号)byte2b0,b1对应值为OperandSize,复制到flag.OperandSize域。b2,b3被复制到flagb3,b4,2位的含义下面说明。

 

 

解析源操作数。检测byte3b0,b01,Operand_Src为立即数(vm栈内的OldArgument),不需要额外处理,跳到解析Operand_Dst的代码。

 

否则,Operand_SrcVM_Context内的某个通用寄存器,byte3b2-b4 3,其对应值为该寄存器在通用寄存器环内的index。根据当前滚动字节数计算出实际地址,取其所指dword替换掉vm栈内的OldArgument

 

解析目的操作数。byte3b5-b7 3位代表Operand_Dst寄存器在环内的index,取其实际地址压栈。此时vm栈内为:

 

[esp]     -> Operand_Dst,VM_Context内通用寄存器地址

[esp+4]  -> Operand_Src,立即数或VM_Context内某个通用寄存器值

 

开始执行实际操作。检测flag.OperandSize,8位操作跳走。先看下面的8位操作。eax为源操作数,ecx为目的寄存器内的原值。对于MOV指令,这个原值并不需要,显然这些代码是程序生成的。

 

下面的代码要检测flagb3,b4,这里先给出Type2 handlerflag的解释。

 

 

b7

b6

b5

b4

b3

b2  b1

b0

 

 

 

DstUseHigher8B

对于8位操作,该位为1表示dst使用高8位字节

SrcUseHigher8B

对于8位操作,该位为1表示dst使用高8位字节

OperandSize

0 -> 8

1 -> 16

2 -> 32

 

 

b3,b4位只对8位操作才有用。注意eax,ecx的数据是dword形式。b4位对应目的操作数,b3对应源操作数。b4b31,代表使用高8位字节。这里的表达不大清楚,简单地说,b41表示真正的dstch,b31表示srcah

 

Vm_MovReg8位操作,不需要多解释了J

将栈内的结果写回VM_Context,这里还要检测1b4

 

下面看看16位操作,这个就直截了当了。

 

32位。