对Windows Defender中虚拟机的逆向分析

微软的虚拟机跟qemu 的tcg类似,都是动态翻译.从上图可以看出,先翻译成IL中间码,然后再翻译成native代码。

OPCODE

DT il使用了0x40个

#define iCo_add        0x00
#define iCo_or         0x01
#define iCo_adc        0x02
#define iCo_sbb        0x03
#define iCo_and        0x04
#define iCo_sub        0x05
#define iCo_xor        0x06
#define iCo_mov        0x07
#define iCo_lea        0x08
#define iCo_xchg       0x09
#define iCo_inc        0x0A
#define iCo_dec        0x0B
#define iCo_mul        0x0c
#define iCo_imul       0x0D
#define iCo_div        0x0E
#define iCo_idiv       0x0F

#define ELF_SET_OP    0x10

#define iCo_setn     0x10
#define iCo_setna    0x11
#define iCo_setb     0x12
#define iCo_setnb    0x13
#define iCo_setz     0x14
#define iCo_setnz    0x15
#define iCo_setbe    0x16
#define iCo_setnbe   0x17
#define iCo_sets     0x18
#define iCO_setns    0x19
#define iCo_setp     0x1a
#define iCo_setnp    0x1B
#define iCo_setl     0x1c
#define iCo_setnl    0x1D
#define iCo_setle    0x1E
#define iCo_setnle   0x1F

#define SHIFT_OP     0x20

#define iCo_rol        0x20
#define iCo_ror        0x21
#define iCo_rcl        0x22
#define iCo_rcr        0x23
#define iCo_shl        0x24
#define iCo_shr        0x25
#define iCo_sal        0x26
#define iCo_sar        0x27

#define BIT_OP        0x28
/*8*(opc-0x28) +0xA3*/
#define iCo_bt         0x28
#define iCo_bts        0x29
#define iCo_btc        0x2A
#define iCo_btr        0x2B
#define iCo_bsf        0x2C
#define iCo_bsr        0x2D

#define iCo_jopz       0x30
#define iCo_fpu        0x3c
#define iCo_lop        0x3d
#define iCo_tx         0x3e
#define iCo_esc        0x3F

#define iCo_RF         0x40 #读EFLAGS
#define iCo_WF         0x80 #写EFLAGS

以x86为例,所有的add 都翻译成iCo_add指令。 Dt IL中只有一个跳转指令:iCo_jopz, 所有的FPU指令通过传递escID给iCo_fpu来调用。
而一些特殊指令比如CPUID之类使用native代码模拟,传递escID给iCo_esc来调用该函数。

不像x86/x64 opcode,不同的寻址方式 不同的操作大小需要用不同的指令.
DT IL统一使用tag_operand结构体来表示不同的类型

IL格式

IL 固定长度4bit

byte 0: opcode
byte 1: 操作数1 ID
byte 2: 操作数2 ID
byte 3: 目标操作数ID

比如 0x01020300 ,最低位为 0x00,即opcode iCo_add,其中操作数1为0x3,即寄存器ebx ,操作数2为 0x2,即edx,目标操作数为0x00,即ecx
最后该IL解释为iCo_add ebx,edx,ecx也就是ecx = ebx + edx

操作数

opcode的操作数都为索引,指向类型tag_operand;

union tag_operand {
    struct {
        /* 0x0000 */ uint32_t d0;
        /* 0x0004 */ uint32_t d1;
    }; /* size: 0x0008 */
    /* 0x0000 */ uint64_t d64;
}; /* size: 0x0008 */

内置操作数

为了方便模拟,把一些常见的数值或者寄存器写入固定值。

const tag_operand x86_init_operands[] = {
        {0x20000, 0x00}, /*0x00 eax*/
        {0x20000, 0x04}, /*0x01 ecx*/
        {0x20000, 0x08}, /*0x02 edx*/
        {0x20000, 0x0C}, /*0x03 ebx*/
        {0x20000, 0x10}, /*0x04 esp*/
        {0x20000, 0x14}, /*0x05 ebp*/
        {0x20000, 0x18}, /*0x06 esi*/
        {0x20000, 0x1C}, /*0x07 edi*/

        {0x10000, 0x00}, /*0x08 ax*/
        {0x10000, 0x04}, /*0x09 cx*/
        {0x10000, 0x08}, /*0x0A dx*/
        {0x10000, 0x0C}, /*0x0B bx*/
        {0x10000, 0x10}, /*0x0C sp*/
        {0x10000, 0x14}, /*0x0D bp*/
        {0x10000, 0x18}, /*0x0E si*/
        {0x10000, 0x1C}, /*0x0F di*/

        {0x00000, 0x00}, /*0x10 al*/
        {0x00000, 0x04}, /*0x11 cl*/
        {0x00000, 0x08}, /*0x12 dl*/
        {0x00000, 0x0C}, /*0x13 bl*/
        {0x00000, 0x01}, /*0x14 ah*/
        {0x00000, 0x05}, /*0x15 ch*/
        {0x00000, 0x09}, /*0x16 dh*/
        {0x00000, 0x0D}, /*0x17 bh*/

        {0x10000, 0x20}, /*0x18 es*/
        {0x10000, 0x22}, /*0x19 cs*/
        {0x10000, 0x24}, /*0x1A ss*/
        {0x10000, 0x26}, /*0x1B ds*/
        {0x10000, 0x28}, /*0x1C fs*/
        {0x10000, 0x2A}, /*0x1D gs*/


        {0x30005, 0x64}, //0x1E
        {0x30005, 0x6C}, //0x1F

        {0x20000, 0x44}, /*0x20 es_base*/
        {0x20000, 0x48}, /*0x21 cs_base*/
        {0x20000, 0x4C}, /*0x22 ss_base*/
        {0x20000, 0x50}, /*0x23 ds_base*/
        {0x20000, 0x54}, /*0x24 fs_base*/
        {0x20000, 0x58}, /*0x25 gs_base*/

        {0x20001, 1},
        {0x20001, 0xFFFFFFFF},

        {0x00000, 0x30}, /*0x28 FL*/
        {0x10000, 0x30}, /*0x29 FX*/
        {0x20000, 0x30}, /*0x2A EFX*/
        {0x00000, 0x31}, /*0x2B FH*/

        {0x00000, 0x34}, /*0x2c t8l*/
        {0x10000, 0x34}, /*0x2d t16l*/
        {0x20000, 0x34}, /*0x2e T32l*/
        {0x30000, 0x34}, /*0x2F T64*/
        {0x10000, 0x36}, /*0x30 T16h*/
        {0x20000, 0x38}, /*0x31 T32h*/

        {0x00000, 0x3C}, /*0x32 S8l*/
        {0x10000, 0x3C}, /*0x33 S16L*/
        {0x20000, 0x3C}, /*0x34 S32L*/
        {0x30000, 0x3C}, /*0x35 S64*/
        {0x10000, 0x3E}, /*0x36 s16H*/
        {0x20000, 0x40}, /*0x37 S32H*/

        {0x10000, 0x2C}, /*0x38 ip*/
        {0x20000, 0x2C}, /*0x39 eip*/
        {0x0000F, 0x00}, /*0x3A null*/
        {0x20001, 0x00}, /*0x3B 0*/
        {0x20000, 0x5C}, /*0x3C map_end*/
};
文章目录
  1. 1. OPCODE
    1. 1.1. IL格式
  2. 2. 操作数
    1. 2.1. 内置操作数
,