舒默哦 发表于 2020-9-23 19:36

【VC】【笔记】自写vmp壳子编写报告(一)

本帖最后由 舒默哦 于 2020-9-24 10:35 编辑

https://static.52pojie.cn/static/image/hrline/1.gif

前言:

[*]第一次设计vmp框架和编写,因设计得有点匆忙,导致后面茶饭不思,一直在改bug,现在基本上处理好了。在这里吐槽一下,如果时间充足,至少框架会设计的更好一点。
[*]因为要兼容64位,汇编引擎我用的是XEDParse,反汇编引擎用的BeaEngine。另外,这个vmp不能对驱动加vm,驱动vm的话,一些处理方法会不一样。
[*]在vmp设计中,我定义了几个模块:指令分析器,垃圾块指令构造器,IAT加密模块,反调试模块。
[*]这几个模块的说明篇幅有点长,这篇文章把指令分析器和垃圾块指令构造器做个说明。


https://static.52pojie.cn/static/image/hrline/3.gif
0x00有些问题的说明。
1、有些奇葩的指令现在仍然无法处理,如下:mov eax,nextcall   //nextcall是函数地址
mov ecx,nextaddr   //nextaddr是jmp ecx下一行的地址
push ecx
jmp eax
add esp,4

上面这些指令等价于:
mov eax,nextcall
call eax
add esp,4
都是可以处理的,归类于不可模拟指令。

但是下面这种情况,处理起来就有问题
mov ecx,nextaddr //nextaddr是jmp ecx下一行的地址
jmp ecx
add esp,4
....
这个jmp ecx是在函数内跳转,不能归于不可模拟指令。

在函数内跳转,一般情况是 jmp 后面跟的地址,比如
mov eax,nextcall
mov ecx,nextaddr
jmp L11
add esp,4
L11:
    ret
标号L11其实就是地址标号,在vm指令解析器解析指令的时候,L11是随着活动的进行可以传递的属性,方便加了垃圾指令之后,让新地址和旧地址进行匹配,
然后进行回填。而jmp ecx,“ecx”只是一个寄存器,不是地址,即使进行传递,那么在新地址和旧地址进行匹配的时候(即新地址和“ecx”匹配),无法匹配,会出BUG。
2、把一个函数vm的时候,要写开始地址和结尾地址,不写结尾地址的话,那么就要写一个函数来自动识别要vm的函数的结尾地址。以下函数就是自动识别要vm的函数的结尾地址,
主要功能是遇到跳转指令比如JCC或者JMP指令,就记录下来,与后面遇到的ret指令所在的地址进行比较,如果小于ret指令所在的地址,那么,这条ret就是结束地址,否则继续往下判断。
struct FUNCANDINSLENGTH
{
    int inslen = 0;//记录指令的条数
    int hcodelength = 0;//记录硬编码长度
    bool istrue = true;//读取指令是否成功
};

//计算函数的长度
FUNCANDINSLENGTH Disassembler_(DWORD virtualaddr,DWORD instruction)
{
    FUNCANDINSLENGTH fuclen;
    int inslength = 0;//记录指令的条数

    vector<DWORD>JccAddr;//记录JCC后面的地址

    DISASM disAsm = { 0 };

    // 3. 配置结构体,初始化反汇编的opcode
    disAsm.EIP = (UIntPtr)instruction;
    disAsm.VirtualAddr = virtualaddr; // opcode 指令的地址
    disAsm.Archi = 0; // 0 => 32 , 1 => 64
    disAsm.Options = 0x000; // masm 汇编指令格式

    int nCount = 0;// 用于记录在循环当中,反汇编了多少个字节
    int nLen = 0; // 用于记录当前的汇编指令的字节数

    while (true)
    {
      nLen = Disasm(&disAsm); // 每次只反汇编一条汇编指令, 并且返回当前得到的汇编指令的长度
      unsigned int uAddr = disAsm.VirtualAddr;

      printf("%08X | ", uAddr); // 打印地址
      printOpcode((const unsigned char*)disAsm.EIP, nLen); // 打印opcode
      printf(" | %s\n", disAsm.CompleteInstr); // 打印反汇编指令

      if (inslength == 0x1000)
      {//防止死循环
            MessageBoxA(NULL, "未知错误,读取指令失败!!", "提示", MB_OK);
            fuclen.istrue = false;
            return fuclen;
      }

      ++inslength;//记录指令的条数,为后面申请内存提供依据
      nCount += nLen; // 累加已经反汇编的字节数
      disAsm.EIP += nLen; // 定位到下一条汇编指令
      disAsm.VirtualAddr += nLen; // 设置到下一条汇编指令的地址

      //如果遇到jcc指令或者jmp指令,记录后面的地址
      for (int i = 0; i < JCCNUMSS; i++)
      {
            if (0 == stricmp(disAsm.Instruction.Mnemonic, JCCSTR))
            {
                DWORD tempaddr = 0;
                sscanf_s(disAsm.Argument1.ArgMnemonic, "%X", &tempaddr);
                JccAddr.push_back(tempaddr);
                break;
            }
      }

      if (
            (0 == stricmp(disAsm.Instruction.Mnemonic, "ret ")) ||
            (0 == stricmp(disAsm.Instruction.Mnemonic, "retn ")) ||
            (0 == stricmp(disAsm.Instruction.Mnemonic, "int3 "))
            )
      {
            int isretn = 1;
            for (int i = 0; i < JccAddr.size(); i++)
            {
                if ((*(JccAddr.begin()+i)) > disAsm.VirtualAddr- nLen)
                {
                  isretn = 0;
                  break;
                }
            }
            if (isretn || (0 == stricmp(disAsm.Instruction.Mnemonic, "int3 ")))
            {
                fuclen.hcodelength = nCount;
                fuclen.inslen = inslength;
                return fuclen;
            }
      }
    }
}
3、没有处理异常。另外,如果要保护的函数里有检查堆栈的函数,一定要注意标志寄存器的处理问题,比如退出虚拟机的时候,出栈完成了,
后面还有改变标志寄存器的指令,则可以使用xor ecx,ecx(返回值一般是eax,所有可以用ecx寄存器)这指令再平衡回来,因为检查堆栈的函数只检查ZF标志位。
https://static.52pojie.cn/static/image/hrline/4.gif

0x01 指令分析器
1、指令分析器的功能就是把要保护的指令,翻译为中间表示,可以用一个结构体来保存这些中间表示和一些需要传递的属性,当然,也可以把指令分析器理解为一个有穷自动机(接收指令 -> 解析指令 -> 中间表示)。我用的是BeaEngine引擎,构造自动机来解析指令的时候就要遵循BeaEngine反汇编引擎的规则,指令分析器的主框架如下://解析要保护的指令,翻译为中间表示
void MiddleRepresent(DISASM disAsm)
{
/*----------------------------------------------------------------------------------*/
/*      1、是否有操作3                                                         */
/*----------------------------------------------------------------------------------*/
      if (NO_ARGUMENT != disAsm.Argument3.ArgType)
      {
                switch (disAsm.Argument3.ArgType & 0xF0000000)
                {
                case REGISTER_TYPE: //寄存器
                        break;
                case MEMORY_TYPE: //内存
                        break;
                case CONSTANT_TYPE://常数
                        break;
                default:
                        break;
                }
      }

/*----------------------------------------------------------------------------------*/
/*      2、是否有操作2                                                         */
/*----------------------------------------------------------------------------------*/
      if (NO_ARGUMENT != disAsm.Argument2.ArgType)
      {
                switch (disAsm.Argument2.ArgType & 0xF0000000)
                {
                case REGISTER_TYPE: //寄存器
                        break;
                case MEMORY_TYPE: //内存
                        break;
                case CONSTANT_TYPE://常数
                        break;
                default:
                        break;
                }
      }

/*----------------------------------------------------------------------------------*/
/*      3、是否有操作1                                                         */
/*----------------------------------------------------------------------------------*/
      if (NO_ARGUMENT != disAsm.Argument1.ArgType)
      {
                switch (disAsm.Argument1.ArgType & 0xF0000000)
                {
                case REGISTER_TYPE: //寄存器
                        break;
                case MEMORY_TYPE: //内存
                        break;
                case CONSTANT_TYPE://常数
                        break;
                default:
                        break;
                }
      }


/*----------------------------------------------------------------------------------*/
/*      4、处理普通handler                                                         */
/*----------------------------------------------------------------------------------*/

//省略...

/*----------------------------------------------------------------------------------*/
/*      5、判断是否有辅助handler                                                         */
/*----------------------------------------------------------------------------------*/
      if (
                0x10000000 != disAsm.Argument1.ArgType ||
                0x10000000 != disAsm.Argument2.ArgType ||
                0x10000000 != disAsm.Argument3.ArgType
                )
      {

            if (NO_ARGUMENT != disAsm.Argument1.ArgType)
                {
                  switch (disAsm.Argument1.ArgType & 0xF0000000)
                  {
                  case REGISTER_TYPE: //寄存器
                            break;
                  case MEMORY_TYPE: //内存
                            break;
                  case CONSTANT_TYPE://常数
                            break;
                  default:
                            break;
                  }
            }

   }
}

2、指令是从右往左解析的,比如:

mov eax,ecx
翻译为中间表示就是
vPushRegVR_ecx//操作2
vPushRegVR_eax //操作1
vMOV            //普通handler
vPopReg   VR_eax //辅助handler

3、整个指令解析器的构造,如下:

//处理内存操作,把内存翻译为中间表示
void VMLoader2::MemoryMiddle(DISASM disAsm,MEMORYTYPE memtype)
{
      /*
      * vPushImm4
      * vPushReg
      * vMUL_MEM //内存操作专用乘法handler
      * vPushReg
      * vAdd
      * vPushImm4
      * vAdd
      * vWriteMemDs4/2/1
      */
      MIDDLESTRUCT midstr;
      DATATABLE datatbl;
      midstr.originaddr = disAsm.VirtualAddr;
      if (memtype.Scale!=0)
      {
                char vpushreg4[] = "vPushImm4 ";
                printf("%s\n", vpushreg4);
                memcpy(midstr.vmfunc, vpushreg4, sizeof(vpushreg4));
                m_middle.push_back(midstr);//操作码压入中间表示      


                datatbl.data = memtype.Scale;
                datatbl.recodeOaddr = disAsm.VirtualAddr;
                m_datatable.push_back(datatbl);//数据压入数据表

                for (int i = 0; i < REGNUMS; i++)
                {
                        if (memtype.IndexRegister == tempreg.index)
                        {
                              char vpushreg4[] = "vPushReg4 ";
                              printf("%s\n", vpushreg4);
                              memcpy(midstr.vmfunc, vpushreg4, sizeof(vpushreg4));
                              m_middle.push_back(midstr);//操作码压入中间表示      

                              DATATABLE datatbl;
                              datatbl.data = i;
                              datatbl.recodeOaddr = disAsm.VirtualAddr;
                              m_datatable.push_back(datatbl);//数据压入数据表

                              break;
                        }
                }

                char vmul_mem[] = "vMUL_MEM ";
                printf("%s\n", vmul_mem);
                memcpy(midstr.vmfunc, vmul_mem, sizeof(vmul_mem));
                m_middle.push_back(midstr);//操作码压入中间表示      
      }
      
      int i = 0;
      for (; i < REGNUMS; i++)
      {
                if (memtype.BaseRegister == tempreg.index)
                {
                        char vpushreg4[] = "vPushReg4 ";
                        printf("%s\n", vpushreg4);
                        memcpy(midstr.vmfunc, vpushreg4, sizeof(vpushreg4));
                        m_middle.push_back(midstr);//操作码压入中间表示      

                        DATATABLE datatbl;
                        datatbl.data = i;
                        datatbl.recodeOaddr = disAsm.VirtualAddr;
                        m_datatable.push_back(datatbl);//数据压入数据表
                        break;
                }
      }

      if ((memtype.Scale != 0) && (i != REGNUMS))
      {
                char vadd[] = "vAdd4 ";
                printf("%s\n", vadd);
                memcpy(midstr.vmfunc, vadd, sizeof(vadd));
                m_middle.push_back(midstr);//操作码压入中间表示
      }
      

      if (0 != memtype.Displacement)
      {
                char vpushreg4[] = "vPushImm4 ";
                printf("%s\n", vpushreg4);
                memcpy(midstr.vmfunc, vpushreg4, sizeof(vpushreg4));
                m_middle.push_back(midstr);//操作码压入中间表示      

                datatbl.data = memtype.Displacement;
                m_datatable.push_back(datatbl);//数据压入数据表
      }
      

      if ((0 != memtype.Displacement) && (i != REGNUMS))
      {
                char vadd[] = "vAdd4 ";
                printf("%s\n", vadd);
                memcpy(midstr.vmfunc, vadd, sizeof(vadd));
                m_middle.push_back(midstr);//操作码压入中间表示
      }
}

//解析要保护的指令,翻译为中间表示
void VMLoader2::MiddleRepresent(DISASM disAsm)
{
      MIDDLESTRUCT midstr;
      midstr.originaddr = disAsm.VirtualAddr;
      bool IsSimulation = true;

      //vm的环境准备
      if (start_bool)
      {               
                char vresumestart[] = "VMStartVM_2 ";
                printf("%s\n", vresumestart);
                memcpy(midstr.vmfunc, vresumestart, sizeof(vresumestart));
                m_middle.push_back(midstr);//压入VMStartVM_2
                start_bool = false;
      }
      

/*----------------------------------------------------------------------------------*/
/*      0、判断是否是不可模拟                                                         */
/*----------------------------------------------------------------------------------*/
      for (int i = 0; i < FUNNUMS; i++)
      {
                if (stricmp(disAsm.Instruction.Mnemonic, g_FunName.s_opecode) == 0)
                {                        
                        IsSimulation = false;
                        break;
                }
      }
      if (0 == stricmp(disAsm.Instruction.Mnemonic, "jmp ") && ((disAsm.Argument1.ArgType & 0xF0000000)== MEMORY_TYPE)||
                0 == stricmp(disAsm.Instruction.Mnemonic, "push ") && ((disAsm.Argument2.ArgType & 0xF0000000) == MEMORY_TYPE)||
                0 == stricmp(disAsm.Instruction.Mnemonic, "pop ") && ((disAsm.Argument1.ArgType & 0xF0000000) == MEMORY_TYPE)
                )
      {
                IsSimulation = true;
      }
      //0、1 如果是不可模拟指令,处理好后直接返回
      if (IsSimulation)
      {
                char retnotaddr[] = "vRetnNOT_ ";
                printf("%s\n", retnotaddr);
                memcpy(midstr.vmfunc, retnotaddr, sizeof(retnotaddr));
                m_middle.push_back(midstr);//先压入vRetnNOT

                char notsimulate[] = "vNotSimulate ";
                char vresumestartaddr;
                sprintf(vresumestartaddr, "%X", m_vmps.vresumestartaddr);

                printf("%s\n", notsimulate);
                memcpy(midstr.vmfunc, notsimulate, sizeof(notsimulate));
                memcpy(midstr.param1, disAsm.CompleteInstr, STRUCTIONLENGTH);
                memcpy(midstr.param2, vresumestartaddr, OPECODELENGTH);
                m_middle.push_back(midstr);//再压入不可模拟指令的handler
               
                char vresumestart[] = "vResumeStart_ ";
                printf("%s\n", vresumestart);
                memcpy(midstr.vmfunc, vresumestart, sizeof(vresumestart));
                m_middle.push_back(midstr);//压入vResumeStart_

                return;
      }

/*----------------------------------------------------------------------------------*/
/*      1、是否有操作3                                                         */
/*----------------------------------------------------------------------------------*/
      if (NO_ARGUMENT != disAsm.Argument3.ArgType)
      {
                switch (disAsm.Argument3.ArgType & 0xF0000000)
                {
                case REGISTER_TYPE: //寄存器
                        break;
                case MEMORY_TYPE: //内存
                        break;
                case CONSTANT_TYPE://常数
                        break;
                default:
                        break;
                }
      }

/*----------------------------------------------------------------------------------*/
/*      2、是否有操作2                                                         */
/*----------------------------------------------------------------------------------*/
      if (NO_ARGUMENT != disAsm.Argument2.ArgType)
      {
                switch (disAsm.Argument2.ArgType & 0xF0000000)
                {
                case REGISTER_TYPE: //寄存器
                {
                        for (int i = 0; i < REGNUMS; i++)
                        {
                              if (tempreg.index == (disAsm.Argument2.ArgType & 0xFFFF))
                              {
                                        if (0x20 == disAsm.Argument2.ArgSize)
                                        {//32位
                                                char vpushreg4[] = "vPushReg4 ";
                                                printf("%s\n", vpushreg4);
                                                memcpy(midstr.vmfunc, vpushreg4, sizeof(vpushreg4));
                                                m_middle.push_back(midstr);//操作码压入中间表示                                                      
                                        }
                                        else if (0x10 == disAsm.Argument2.ArgSize)
                                        {//16位
                                                char vpushreg4[] = "vPushReg2 ";
                                                printf("%s\n", vpushreg4);
                                                memcpy(midstr.vmfunc, vpushreg4, sizeof(vpushreg4));
                                                m_middle.push_back(midstr);//操作码压入中间表示      
                                        }
                                        else
                                        {//8位(要判断高位还是低位)
                                                for (int i = 0; i < 14; i++)
                                                {
                                                      if (stricmp(disAsm.Argument2.ArgMnemonic, regname_) == 0)
                                                      {
                                                                if (i<=3)//小于等于3是低位
                                                                {
                                                                        char vpushreg4[] = "vPushReg1_low ";
                                                                        printf("%s\n", vpushreg4);
                                                                        memcpy(midstr.vmfunc, vpushreg4, sizeof(vpushreg4));
                                                                        m_middle.push_back(midstr);//操作码压入中间表示      
                                                                }
                                                                else
                                                                {
                                                                        char vpushreg4[] = "vPushReg1_above ";
                                                                        printf("%s\n", vpushreg4);
                                                                        memcpy(midstr.vmfunc, vpushreg4, sizeof(vpushreg4));
                                                                        m_middle.push_back(midstr);//操作码压入中间表示      
                                                                }
                                                                break;
                                                      }
                                                }
                                        }
                                        DATATABLE datatbl;
                                        datatbl.data = i;
                                        datatbl.recodeOaddr = disAsm.VirtualAddr;
                                        m_datatable.push_back(datatbl);//数据压入数据表
                                        break;
                              }
                        }
                        
                }
                        break;
                case MEMORY_TYPE: //内存
                {
                        if (0 == stricmp("pop ", disAsm.Instruction.Mnemonic)) break;
                        if (0 == stricmp("ret ", disAsm.Instruction.Mnemonic)) break;

                        MemoryMiddle(disAsm, disAsm.Argument2.Memory);
                        
                        if (0x20 == disAsm.Argument2.ArgSize)
                        {//32位
                              char vReadMem[] = "vReadMemDs4 ";
                              printf("%s\n", vReadMem);
                              memcpy(midstr.vmfunc, vReadMem, sizeof(vReadMem));
                        }
                        else if (0x10 == disAsm.Argument2.ArgSize)
                        {//16位
                              char vReadMem[] = "vReadMemDs2 ";
                              printf("%s\n", vReadMem);
                              memcpy(midstr.vmfunc, vReadMem, sizeof(vReadMem));
                        }
                        else
                        {//8位
                              char vReadMem[] = "vReadMemDs1 ";
                              printf("%s\n", vReadMem);
                              memcpy(midstr.vmfunc, vReadMem, sizeof(vReadMem));
                        }

                        memcpy(midstr.param1, disAsm.Instruction.Mnemonic, 16);//参数一
                        memcpy(midstr.param2, disAsm.Argument2.ArgMnemonic, 32);//参数二
                        m_middle.push_back(midstr);//操作码压入中间表示
                }
                        break;
                case CONSTANT_TYPE://常数
                {
                        DWORD constnums = 0;
                        sscanf(disAsm.Argument2.ArgMnemonic, "%X", &constnums);

                        char vpushimm4[] = "vPushImm4 ";
                        printf("%s\n", vpushimm4);

                        memcpy(midstr.vmfunc, vpushimm4, sizeof(vpushimm4));
                        m_middle.push_back(midstr);//操作码压入中间表示

                        DATATABLE datatbl;
                        datatbl.data = constnums;
                        datatbl.recodeOaddr = disAsm.VirtualAddr;
                        m_datatable.push_back(datatbl);//数据压入数据表

                }
                        break;
                default:
                        break;
                }
      }

/*----------------------------------------------------------------------------------*/
/*      3、是否有操作1                                                         */
/*----------------------------------------------------------------------------------*/
      if (NO_ARGUMENT != disAsm.Argument1.ArgType)
      {
                switch (disAsm.Argument1.ArgType & 0xF0000000)
                {
                case REGISTER_TYPE: //寄存器
                {
                        for (int i = 0; i < REGNUMS; i++)
                        {
                              if (tempreg.index == (disAsm.Argument1.ArgType & 0xFFFF))
                              {
                                        if (0x20 == disAsm.Argument1.ArgSize)
                                        {//32位
                                                char vpushreg4[] = "vPushReg4 ";
                                                printf("%s\n", vpushreg4);
                                                memcpy(midstr.vmfunc, vpushreg4, sizeof(vpushreg4));
                                                m_middle.push_back(midstr);//操作码压入中间表示                                                
                                        }
                                        else if (0x10 == disAsm.Argument1.ArgSize)
                                        {//16位
                                                char vpushreg4[] = "vPushReg2 ";
                                                printf("%s\n", vpushreg4);
                                                memcpy(midstr.vmfunc, vpushreg4, sizeof(vpushreg4));
                                                m_middle.push_back(midstr);//操作码压入中间表示
                                        }
                                        else
                                        {//8位(要判断高位还是低位)
                                                for (int i = 0; i < 14; i++)
                                                {
                                                      if (stricmp(disAsm.Argument1.ArgMnemonic, regname_) == 0)
                                                      {
                                                                if (i <= 3)//小于等于3是低位
                                                                {
                                                                        char vpushreg4[] = "vPushReg1_low ";
                                                                        printf("%s\n", vpushreg4);
                                                                        memcpy(midstr.vmfunc, vpushreg4, sizeof(vpushreg4));
                                                                        m_middle.push_back(midstr);//操作码压入中间表示      
                                                                }
                                                                else
                                                                {
                                                                        char vpushreg4[] = "vPushReg1_above ";
                                                                        printf("%s\n", vpushreg4);
                                                                        memcpy(midstr.vmfunc, vpushreg4, sizeof(vpushreg4));
                                                                        m_middle.push_back(midstr);//操作码压入中间表示      
                                                                }
                                                                break;
                                                      }
                                                }
                                        }
                                        DATATABLE datatbl;
                                        datatbl.data = i;
                                        datatbl.recodeOaddr = disAsm.VirtualAddr;
                                        m_datatable.push_back(datatbl);//数据压入数据表
                                        break;
                              }
                        }
                }
                        break;
                case MEMORY_TYPE: //内存(操作数1如果是内存,且操作数2不为空,则处理好后直接退出)
                {
                        if (0 == stricmp("push ",disAsm.Instruction.Mnemonic)) break;
      
                        MemoryMiddle(disAsm, disAsm.Argument1.Memory);                        

                        if (NO_ARGUMENT == disAsm.Argument2.ArgType) break;//这步是对待单个操作数的

                        if (0x20 == disAsm.Argument1.ArgSize)
                        {//32位
                              char vWriteMem[] = "vWriteMemDs4 ";
                              printf("%s\n", vWriteMem);
                              memcpy(midstr.vmfunc, vWriteMem, sizeof(vWriteMem));                              
                        }
                        else if (0x10 == disAsm.Argument1.ArgSize)
                        {//16位
                              char vWriteMem[] = "vWriteMemDs2 ";
                              printf("%s\n", vWriteMem);
                              memcpy(midstr.vmfunc, vWriteMem, sizeof(vWriteMem));
                        }
                        else
                        {//8位
                              char vWriteMem[] = "vWriteMemDs1 ";
                              printf("%s\n", vWriteMem);
                              memcpy(midstr.vmfunc, vWriteMem, sizeof(vWriteMem));
                        }
                        
                        memcpy(midstr.param1, disAsm.Instruction.Mnemonic, 16);//参数一
                        memcpy(midstr.param2, disAsm.Argument1.ArgMnemonic, 32);//参数二
                        m_middle.push_back(midstr);//操作码压入中间表示

                        return;
                }
                        break;
                case CONSTANT_TYPE://常数
                {
                        DWORD constnums = 0;
                        sscanf(disAsm.Argument1.ArgMnemonic, "%X", &constnums);

                        char vpushimm4[] = "vPushImm4 ";
                        printf("%s\n", vpushimm4);

                        memcpy(midstr.vmfunc, vpushimm4, sizeof(vpushimm4));
                        m_middle.push_back(midstr);//操作码压入中间表示

                        DATATABLE datatbl;
                        datatbl.data = constnums;
                        datatbl.recodeOaddr = disAsm.VirtualAddr;
                        m_datatable.push_back(datatbl);//数据压入数据表
                }
                        break;
                default:
                        break;
                }
      }

/*----------------------------------------------------------------------------------*/
/*      4、处理普通handler                                                         */
/*----------------------------------------------------------------------------------*/
      //4、1 如果是ret,直接返回
      if (0 == stricmp("ret ", disAsm.Instruction.Mnemonic))
      {
                if (disAsm.Argument1.ArgType == 0x10000000)
                {
                        char vpushreg[] = "vPushImm4 ";
                        printf("%s\n", vpushreg);
                        memcpy(midstr.vmfunc, vpushreg, sizeof(vpushreg));
                        m_middle.push_back(midstr);//压入vPushReg4

                        DATATABLE datatbl;
                        datatbl.data = 0;
                        datatbl.recodeOaddr = disAsm.VirtualAddr;
                        m_datatable.push_back(datatbl);//数据压入数据表
                }
                char callmem[] = "vRETN ";
                printf("%s\n", callmem);
                memcpy(midstr.vmfunc, callmem, sizeof(callmem));
                m_middle.push_back(midstr);//压入vRETN
                return;
      }


      //4、2 如果操作数2是内存(针对的是二地址指令),m_middle链表最后两个元素互换
      if ((disAsm.Argument2.ArgType & 0xF0000000) == MEMORY_TYPE)
      {
                if (0 != stricmp("pop ", disAsm.Instruction.Mnemonic))
                {
                        swap(m_middle, m_middle);
                        
                }
                goto ttttt__;
      }

      //4、3 如果是调用函数,则处理好后,直接返回
      if (0 == stricmp("call ", disAsm.Instruction.Mnemonic))
      {               
                //如果操作数1是内存
                if ((disAsm.Argument1.ArgType & 0xF0000000) == MEMORY_TYPE)
                {                        
                        char callmem[] = "vCallMem ";
                        printf("%s\n", callmem);
                        memcpy(midstr.vmfunc, callmem, sizeof(callmem));
                        m_middle.push_back(midstr);//先压入vCallMem
                }
                else
                {
                        //删除vPushImm4
                        m_middle.pop_back();
                }
                char retnotaddr[] = "vRetnNOT_ ";
                printf("%s\n", retnotaddr);
                memcpy(midstr.vmfunc, retnotaddr, sizeof(retnotaddr));
                m_middle.push_back(midstr);//压入vRetnNOT

                char vcall[] = "vCALL ";
                printf("%s\n", vcall);
                memcpy(midstr.vmfunc, vcall, sizeof(vcall));
                m_middle.push_back(midstr);

                char vresumestart[] = "vResumeStart_ ";
                printf("%s\n", vresumestart);
                memcpy(midstr.vmfunc, vresumestart, sizeof(vresumestart));
                m_middle.push_back(midstr);//压入vResumeStart_
                return;
      }

      //4、4 处理普通handler
      for (int i = 0; i < FUNNUMS; i++)
      {
                if (0 == stricmp(g_FunName.s_opecode,disAsm.Instruction.Mnemonic))
                {
                        printf("%s\n", g_FunName.vm_opcoed);
                        memcpy(midstr.vmfunc, g_FunName.vm_opcoed,OPECODELENGTH);
                        m_middle.push_back(midstr);//操作码压入中间表示
                        break;
                }

      }

/*----------------------------------------------------------------------------------*/
/*      5、判断是否有辅助handler                                                         */
/*----------------------------------------------------------------------------------*/
      if (
                0x10000000 != disAsm.Argument1.ArgType ||
                0x10000000 != disAsm.Argument2.ArgType ||
                0x10000000 != disAsm.Argument3.ArgType
                )
      {
                ttttt__:
                //5.1 判断这条指令是否改变操作数1的值,比如cmp和test操作数就不会改变操作数1的值,直接返回      
                for (int i = 0; i < NOTREGNUMS; i++)
                {
                        if (stricmp(cmp_opecode, disAsm.Instruction.Mnemonic) == 0)
                        {
                              return;
                        }
                }
               
                //5.2 判断是否是JCC或者JMP指令,是则处理好后直接返回
                for (int i = 0; i < JCCNUMS; i++)
                {//判断是否是JCC指令
                        if (0 == stricmp(disAsm.Instruction.Mnemonic, JCCstr))
                        {
                              //改变数据表的数据
                              m_datatable.at(m_datatable.size() - 1).originaddr = disAsm.VirtualAddr;
                              
                              //多压入一个空数据到数据表
                              DATATABLE datatbl;
                              datatbl.data = 0;
                              m_datatable.push_back(datatbl);//数据压入数据表

                              //再压入一个空数据到数据表
                              datatbl.data = 0;
                              m_datatable.push_back(datatbl);//数据压入数据表

                              //JCC指令前插入两个vPushImm4
                              char vpushimm4[] = "vPushImm4 ";
                              printf("%s\n", vpushimm4);
                              memcpy(midstr.vmfunc, vpushimm4, sizeof(vpushimm4));
                              m_middle.insert(m_middle.end()-1, midstr);//操作码压入中间表示
                              m_middle.insert(m_middle.end() - 1, midstr);//操作码压入中间表示
                              return;
                        }
                }

                //5.2 处理普通辅助handler
                switch (disAsm.Argument1.ArgType & 0xF0000000)
                {
                case REGISTER_TYPE://寄存器
                {
                        for (int i = 0; i < REGNUMS; i++)
                        {
                              if (tempreg.index == (disAsm.Argument1.ArgType & 0xFFFF))
                              {
                                        if (0x20 == disAsm.Argument1.ArgSize)
                                        {//32位
                                                char vpopreg4[] = "vPopReg4 ";
                                                printf("%s\n", vpopreg4);
                                                memcpy(midstr.vmfunc, vpopreg4, sizeof(vpopreg4));
                                                m_middle.push_back(midstr);//操作码压入中间表示                                                
                                        }
                                        else if (0x10 == disAsm.Argument1.ArgSize)
                                        {//16位
                                                char vpopreg4[] = "vPopReg2 ";
                                                printf("%s\n", vpopreg4);
                                                memcpy(midstr.vmfunc, vpopreg4, sizeof(vpopreg4));
                                                m_middle.push_back(midstr);//操作码压入中间表示      
                                        }
                                        else
                                        {//8位(要判断高位还是低位)
                                                for (int i = 0; i < 14; i++)
                                                {
                                                      if (stricmp(disAsm.Argument1.ArgMnemonic, regname_) == 0)
                                                      {
                                                                if (i <= 3)//小于等于3是低位
                                                                {
                                                                        char vpushreg4[] = "vPopReg1_low ";
                                                                        printf("%s\n", vpushreg4);
                                                                        memcpy(midstr.vmfunc, vpushreg4, sizeof(vpushreg4));
                                                                        m_middle.push_back(midstr);//操作码压入中间表示      
                                                                }
                                                                else
                                                                {
                                                                        char vpushreg4[] = "vPopReg1_above ";
                                                                        printf("%s\n", vpushreg4);
                                                                        memcpy(midstr.vmfunc, vpushreg4, sizeof(vpushreg4));
                                                                        m_middle.push_back(midstr);//操作码压入中间表示      
                                                                }
                                                                break;
                                                      }
                                                }
                                        }
                                        DATATABLE datatbl;
                                        datatbl.data = i;
                                        m_datatable.push_back(datatbl);//数据压入数据表
                              }
                        }

                        //如果操作1是esp,即改变栈大小,比如指令sub esp,0x100,
                        //则要调用vCheckESP()函数,检查VMContext是否被覆盖
                        if (16 == (disAsm.Argument1.ArgType & 0xFFFF))
                        {//16在BegEngine反汇编引擎约定的是esp寄存器
                              char vcheckesp[] = "VCheckESP ";
                              printf("%s\n", vcheckesp);
                              memcpy(midstr.vmfunc, vcheckesp, sizeof(vcheckesp));
                              m_middle.push_back(midstr);//操作码压入中间表示
                        }
                        //如果操作码是pop,把vPOP添加到m_middle链表,然后返回
                        if (0 == stricmp("pop ",disAsm.Instruction.Mnemonic))
                        {
                              if (0x20 == disAsm.Argument1.ArgSize)
                              {
                                        char vpushreg4[] = "vPOP4 ";
                                        printf("%s\n", vpushreg4);
                                        memcpy(midstr.vmfunc, vpushreg4, sizeof(vpushreg4));
                                        m_middle.push_back(midstr);//操作码压入中间表示      
                              }
                              else
                              {
                                        char vpushreg4[] = "vPOP2 ";
                                        printf("%s\n", vpushreg4);
                                        memcpy(midstr.vmfunc, vpushreg4, sizeof(vpushreg4));
                                        m_middle.push_back(midstr);//操作码压入中间表示      
                              }
                              return;
                        }
                }
                        break;

                case MEMORY_TYPE://内存
                {
                        //
                }
                break;
                case CONSTANT_TYPE:
                {
                        //
                }
                break;
                }               
      }
}


4、绝大多数情况下,都是零地址指令、一地址指令、二地址指令,很少有三地址指令,所以把操作3省略没有处理。
5、把handler操作和数据分开保存,如:

mov eax,ecx
翻译为中间表示就是
vPushRegVR_ecx//操作2
vPushRegVR_eax //操作1
vMOV            //普通handler
vPopReg   VR_eax //辅助handler

把VR_ecx、VR_eax、VR_eax分离出来保存在一个数据表的结构体中。
翻译就可以这样表示了:
vPushReg
vPushReg
vMOV         
vPopReg
   
6、内存操作处理起来比较麻烦,MemoryMiddle函数用来专门处理内存操作。例如这条指令 mov dword ptr,eax,可以译成如下的中间表示:vPushReg   //eax
vPushImm4//4
vPushReg4//ecx
vMUL_MEM//*
vPushReg4 //eax
vAdd4    //+
vPushImm4 //0x401000
vAdd   //+
vWriteMemDs4

4 ecx * 可以理解为后缀表示法,其实这是和handler设计和堆栈操作有关的。

7、局部变量的操作,如 mov dword ptr,eax,仍然用MemoryMiddle函数来翻译:

vPushImm4//0xFFFFFFF8
vPushReg4 //ebp
vAdd4
负8会被BeaEngine引擎解析为0xFFFFFFF8,ebp-0x8与0xFFFFFFF8+ebp是等价的

8、下面举个完整的例子:

void _declspec(naked) _stdcallcode_vm_test(int x)
{
    //MessageBoxA(NULL, 0, 0, 0);
    _asm {
      sub esp,0x150
      push eax
      push ecx
      push edx
      lea ecx, code_vm_test
      add ecx,10h      
      push ecx
      pop dword ptr
      jmp L14
      sub esp,0x150
      L14:      
      mov ecx,1      
      xor eax,eax
      mov ah,10h
      mov bl,30h
      L13:
      add ecx,1
      add ah,bl
      cmp ecx,0x10
      jle L13
      //je L11
      add eax,0x432
       mov ebx,4
       mov ecx,1
       mov byte ptr,ah
      //mov word ptr,ax      
      //mov dword ptr,eax
      jmp L12
       //L11:
      mov g_num,eax

      call test2
       L12:
      mov eax, 01h   //eax=1:取CPU序列号
      xor edx, edx
      cpuid
      mov acpuid, eax
      mov dl,byte ptr
      mov lcpuid, edx

      pop edx
      pop ecx
      pop eax
      add esp,0x150
      retn 4
    }
}

上面这个函数,翻译为中间表示如下:

VMStartVM_2
vPushImm4
vPushReg4
vSUB4
vPopReg4
VCheckESP
vPushReg4
vPUSH
vPushReg4
vPUSH
vPushReg4
vPUSH
vPushImm4
vReadMemDs4
vPushReg4
vPopReg4
vPushImm4
vPushReg4
vAdd4
vPopReg4
vPushReg4
vPUSH
vRetnNOT_
vNotSimulate
vResumeStart_
vPushImm4
vJMP
vPushImm4
vPushImm4
vPushReg4
vSUB4
vPopReg4
VCheckESP
vPushImm4
vPushReg4
vMOV4
vPopReg4
vPushReg4
vPushReg4
vXOR4
vPopReg4
vPushImm4
vPushReg1_above
vMOV4
vPopReg1_above
vPushImm4
vPushReg1_low
vMOV4
vPopReg1_low
vPushImm4
vPushReg4
vAdd4
vPopReg4
vPushReg1_low
vPushReg1_above
vAdd4
vPopReg1_above
vPushImm4
vPushReg4
vCMP
vPushImm4
vJLE
vPushImm4
vPushImm4
vPushReg4
vAdd4
vPopReg4
vPushImm4
vPushReg4
vMOV4
vPopReg4
vPushImm4
vPushReg4
vMOV4
vPopReg4
vPushReg1_above
vPushImm4
vPushReg4
vMUL_MEM
vPushReg4
vAdd4
vPushImm4
vAdd4
vWriteMemDs1
vPushImm4
vJMP
vPushImm4
vPushReg4
vPushImm4
vWriteMemDs4
vPushImm4
vRetnNOT_
vCALL
vResumeStart_
vPushImm4
vPushReg4
vMOV4
vPopReg4
vPushReg4
vPushReg4
vXOR4
vPopReg4
vRetnNOT_
vNotSimulate
vResumeStart_
vPushReg4
vPushImm4
vWriteMemDs4
vPushImm4
vReadMemDs1
vPushReg1_low
vPopReg1_low
vPushReg4
vPushImm4
vWriteMemDs4
vPushReg4
vPopReg4
vPOP4
vPushReg4
vPopReg4
vPOP4
vPushReg4
vPopReg4
vPOP4
vPushImm4
vPushReg4
vAdd4
vPopReg4
VCheckESP
vPushImm4
vRETN

9、中间表示的设计非常的重要,它牵涉到后面的一系列的操作,需要好好考虑,这个指令解析器其实可以推翻重新设计的,我总感觉有点混乱,但时间原因,没弄了。
或者先不分离数据到数据表,把数据放到中间表示的数据结构里面,到后面再处理?
见仁见智,有初学者看到这篇文章的话可以少走一些弯路。
https://static.52pojie.cn/static/image/hrline/4.gif

0x02 垃圾指令构造器
垃圾指令构造器的设计非常简单,难点在于垃圾指令的选择,有些指令是不能作为垃圾指令的,改变普通寄存器的指令不能用,比如AAA指令,会改变eax寄存器的值。具体参考Intel手册。
下面是垃圾指令的构造器

//VMTABEL表的元素个数
#define VMTABLEMAXLEN                              0x1000
//没有用到寄存器
#define NONE      -1
//操作数类型

#define SEG_UNDEF   -1                           //没有段寄存器
#define SEG_ES         0               // Indexes of segment/selector registers
#define SEG_CS         1
#define SEG_SS         2
#define SEG_DS         3
#define SEG_FS         4
#define SEG_GS         5

enum optype
{
      NONETYPE,
      IMMTYPE,
      REGTYPE,
      MEMTYPE,
      CSTYPE,
      DSTYPE,
      ESTYPE,
      SSTYPE,
      FSTYPE,
      GSTYPE,
};

struct VMTable
{
      char      VMInstrName;                //VM命令名称
      char      strInstruction;                        //相对的汇编指令
      int                OperandNum;                                        //操作数个数
      int                Segment;                                        //段前缀
      int                optype;                                        //操作类型(寄存器,立即数,内存数)
      int                bitnum;                                        //位数

      int                NeedReg;                                        //执行命令前要使用的寄存器
      int                SaveReg;                                        //执行命令后要保存的指令
      BOOL      Reg2Esp;                                        //第2个寄存器是否恢复,一般为0不恢复
};

VMTable vmtable32 =
{   
    //MOV
      {"VMOV_REG08_REG08","MOV",2, SEG_UNDEF, REGTYPE, REGTYPE,8,8,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_REG16_REG16","MOV",2, SEG_UNDEF, REGTYPE, REGTYPE,16,16,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_REG32_REG32","MOV",2, SEG_UNDEF, REGTYPE, REGTYPE,32,32,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_REG08_IMM32","MOV",2, SEG_UNDEF, REGTYPE, IMMTYPE,8,8,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_REG16_IMM32","MOV",2, SEG_UNDEF, REGTYPE, IMMTYPE,16,16,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_REG32_IMM32","MOV",2, SEG_UNDEF, REGTYPE, IMMTYPE,32,32,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_REG08_MEM08","MOV",2, SEG_UNDEF, REGTYPE, MEMTYPE,8,8,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_REG16_MEM16","MOV",2, SEG_UNDEF, REGTYPE, MEMTYPE,16,16,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_REG32_MEM32","MOV",2, SEG_UNDEF, REGTYPE, MEMTYPE,32,32,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_MEM08_REG08","MOV",2, SEG_UNDEF, MEMTYPE, REGTYPE,8,8,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_MEM16_REG16","MOV",2, SEG_UNDEF, MEMTYPE, REGTYPE,16,16,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_MEM32_REG32","MOV",2, SEG_UNDEF, MEMTYPE, REGTYPE,32,32,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_MEM08_IMM32","MOV",2, SEG_UNDEF, MEMTYPE, IMMTYPE,8,8,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_MEM16_IMM32","MOV",2, SEG_UNDEF, MEMTYPE, IMMTYPE,16,16,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_MEM32_IMM32","MOV",2, SEG_UNDEF, MEMTYPE, IMMTYPE,32,32,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_FSMEM08_IMM32","MOV",2, SEG_FS, MEMTYPE, IMMTYPE,8,8,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_FSMEM16_IMM32","MOV",2, SEG_FS, MEMTYPE, IMMTYPE,16,16,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_FSMEM32_IMM32","MOV",2, SEG_FS, MEMTYPE, IMMTYPE,32,32,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_GSMEM08_IMM32","MOV",2, SEG_GS, MEMTYPE, IMMTYPE,8,8,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_GSMEM16_IMM32","MOV",2, SEG_GS, MEMTYPE, IMMTYPE,16,16,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_GSMEM32_IMM32","MOV",2, SEG_GS, MEMTYPE, IMMTYPE,32,32,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_REG08_FSMEM08","MOV",2, SEG_FS, REGTYPE, MEMTYPE,8,8,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_REG16_FSMEM16","MOV",2, SEG_FS, REGTYPE, MEMTYPE,16,16,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_REG32_FSMEM32","MOV",2, SEG_FS, REGTYPE, MEMTYPE,32,32,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_REG08_GSMEM08","MOV",2, SEG_GS, REGTYPE, MEMTYPE,8,8,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_REG16_GSMEM16","MOV",2, SEG_GS, REGTYPE, MEMTYPE,16,16,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_REG32_GSMEM32","MOV",2, SEG_GS, REGTYPE, MEMTYPE,32,32,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_FSMEM08_REG08","MOV",2, SEG_FS, MEMTYPE, REGTYPE,8,8,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_FSMEM16_REG16","MOV",2, SEG_FS, MEMTYPE, REGTYPE,16,16,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_FSMEM32_REG32","MOV",2, SEG_FS, MEMTYPE, REGTYPE,32,32,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_GSMEM08_REG08","MOV",2, SEG_GS, MEMTYPE, REGTYPE,8,8,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_GSMEM16_REG16","MOV",2, SEG_GS, MEMTYPE, REGTYPE,16,16,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      {"VMOV_GSMEM32_REG32","MOV",2, SEG_GS, MEMTYPE, REGTYPE,32,32,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
   
   { "VCMC","CMC",0, SEG_UNDEF, NONETYPE, NONETYPE,0,0,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      { "VNOP","NOP",0, SEG_UNDEF, NONETYPE, NONETYPE,0,0,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      { "VSTC","STC",0, SEG_UNDEF, NONETYPE, NONETYPE,0,0,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      { "VSTD","STD",0, SEG_UNDEF, NONETYPE, NONETYPE,0,0,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      { "VCLC","CLC",0, SEG_UNDEF, NONETYPE, NONETYPE,0,0,          RT_Eax,NONE,NONE,NONE,                RT_Eax,NONE,NONE,NONE },
   { "VNOT","NOT",1, SEG_UNDEF, REGTYPE, NONETYPE,8,0,         NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      { "VNOT","NOT",1, SEG_UNDEF, REGTYPE, NONETYPE,16,0,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      { "VNOT","NOT",1, SEG_UNDEF, REGTYPE, NONETYPE,32,0,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },
      { "VCLD","CLD",0, SEG_UNDEF, NONETYPE, NONETYPE,0,0,          NONE,NONE,NONE,NONE,                NONE,NONE,NONE,NONE },


......等等

         //结束标志
      {"end","end",0, 0, 0, 0,0x520000,0,0,0,0,0,0,0,0,0 }
}


//获取随机数(范围在Min_到MAX_)
      DWORD SrandNum(int Min_, int Max_)
      {
                return rand() % (Max_ - Min_) + Min_;
      }

//求vmtable32结构体数组的长度
int VMLoader2::VMLength()
{
      for (int i = 0; i < VMTABLEMAXLEN; i++)
      {
                if (vmtable32.bitnum == 0x520000)
                {
                        return i;
                }
      }
      return 0;
}

//vmtable32结构体数组的长度
      int m_vmlength = 0;

//生成垃圾指令
CString VMLoader2::ProduceRubbishOpecode(char* reg04, char* reg05)
{
      VMTable vmtbl = vmtable32;
      CString str = vmtbl.strInstruction;
      //1、目的操作
      switch (vmtbl.optype)
      {
      case NONETYPE://没有操作数
                break;
      case IMMTYPE://立即数
      {
                if (8 == vmtbl.bitnum)
                {
                        str = str + " " + 4;
                }
                else if (16 == vmtbl.bitnum)
                {
                        str = str + " " + 4;
                }
                else
                {
                        str = str + " " + 8;
                }
               
      }
                break;
      case REGTYPE://寄存器
      {

                if (8 == vmtbl.bitnum)
                {
                        for (int i = 0; i < 14; i++)
                        {
                              if (stricmp(reg04, regname_) == 0)
                              {
                                        str = str + " " + regname_;
                                        break;
                              }
                        }                        
                }
                else if (16 == vmtbl.bitnum)
                {
                        for (int i = 0; i < 14; i++)
                        {
                              if (stricmp(reg05, regname_) == 0)
                              {
                                        str = str + " " + regname_;
                                        break;
                              }
                        }
                }
                else
                {
                        str = str + " " + reg05;
                }
      }
                break;
      case MEMTYPE://内存
      {//随机选择vmp1节中没有用到的内存
                DWORD dnum = SrandNum(m_vmps.vmp1_startaddr+0x4000, m_vmps.vmp1_startaddr+0x5000);
                CString memstr = dnum;
                if (8 == vmtbl.bitnum)
                {
                        str = str + " byte ptr[" + memstr.GetString() + "]";
                }
                else if (16 == vmtbl.bitnum)
                {
                        str = str + " word ptr[" + memstr.GetString() + "]";
                }
                else
                {
                        str = str + " dword ptr[" + memstr.GetString() + "]";
                }
      }
                break;
      default:
                break;
      }

      //2、源操作数
      switch (vmtbl.optype)
      {
      case NONETYPE://没有操作数
                break;
      case IMMTYPE://立即数
      {
                if (8 == vmtbl.bitnum)
                {
                        str = str + "," + 4;
                }
                else if (16 == vmtbl.bitnum)
                {
                        str = str + "," + 8;
                }
                else
                {
                        str = str + "," + 4;
                }
      }
                break;
      case REGTYPE://寄存器(操作数2的寄存器可以在8个寄存器中任意选择)
      {
                if (0 == stricmp(vmtbl.strInstruction,"xchg"))
                {//如果是xchg,寄存器则选择reg04,或者reg05
                        if (8 == vmtbl.bitnum)
                        {
                              for (int i = 0; i < 14; i++)
                              {
                                        if (stricmp(reg05, regname_) == 0)
                                        {
                                                str = str + "," + regname_;
                                                break;
                                        }
                              }

                        }
                        else if (16 == vmtbl.bitnum)
                        {
                              for (int i = 0; i < 14; i++)
                              {
                                        if (stricmp(reg04, regname_) == 0)
                                        {
                                                str = str + "," + regname_;
                                                break;
                                        }
                              }
                        }
                        else
                        {
                              str = str + "," + reg04;
                        }
                        break;
                }
                if (8 == vmtbl.bitnum)
                {
                        str = str + "," + regname_;
                }
                else if (16 == vmtbl.bitnum)
                {
                        str = str + "," + regname_;
                }
                else
                {
                        str = str + "," + regname_;
                }
      }
                break;
      case MEMTYPE://内存
      {//随机选择vmp1节内的地址,或者选esp寄存器
                DWORD dnum = SrandNum(m_vmps.vmp1_startaddr, m_vmps.vmstartaddr);
                CString memstr = dnum;
                const char* memchr = { memstr.GetString(),"esp+20","esp+28","esp+0x30","esp+0x14" };
                const char* srandstr = memchr;

                if (8 == vmtbl.bitnum)
                {
                        str = str + ",byte ptr[" + srandstr + "]";
                }
                else if (16 == vmtbl.bitnum)
                {
                        str = str + ",word ptr[" + srandstr + "]";
                }
                else
                {
                        str = str + ",dword ptr[" + srandstr + "]";
                }
      }
                break;
      default:
                break;
      }

      return str;
}

每调用一次ProduceRubbishOpecode就可以构造一条垃圾指令,其实这个垃圾指令构造器还可以细化。想要怎么设计,看需求。
https://static.52pojie.cn/static/image/hrline/4.gif

0x03
handler的设计可以把要用到的handler放到一个表格中归类。
举个vJAE的例子,如下:

CString vJAE(char* VR0, char* VR1)//jae jnc jnb(无符号 大于等于跳转 CF=0)
{
      CString str = "push dword ptr\n";
      str = str + "pop "+ VR0 +"\n";
      str = str + "mov " + VR1 + ",0\n";

      str = str + "and "+ VR0 +",1\n";
      str = str + "mov "+ VR0 +",dword ptr\n";
      str = str + "cmove " + VR1 + ",dword ptr\n";
      str = str + "cmove "+ VR0 +",dword ptr\n";
      str = str + "add ebp," + VR1 + "\n";
      str = str + "add esi,"+ VR0 +"\n";
      str = str + "add esp,0xC\n";
      return str;
}


佚名24 发表于 2020-11-5 16:49

感谢大佬

wanghualina 发表于 2020-10-25 10:43

感谢分享 ,学习了

知足常乐999 发表于 2020-10-20 09:00

强大,学习中,非常好的资料。

gh0st_ 发表于 2020-10-18 07:55

厉害大佬 学习了

wlsk888 发表于 2020-10-16 16:53

厉害,即使我确实看明白了些理论。。。然而这辈子估计是没有这个动力和耐心了。。。
加油加油,52pj大神!

menggg 发表于 2020-10-14 08:42

大神真厉害,感谢分享

aikoz88 发表于 2020-10-7 10:00

感谢分享 起码我就做不到

leonalewis 发表于 2020-10-6 10:38

膜拜…学习一波

yuelingge 发表于 2020-10-4 21:59

站里大神超多,很棒,有用,收藏起来!!!

紫娑之 发表于 2020-10-5 09:47

又是一个拨头发的利器:'(weeqw

ycs 发表于 2020-9-23 20:49

牛人。感谢分享。

度娘灬魂手 发表于 2020-9-23 21:07

论坛里的大佬是真的有时间,我看一下就头晕了

舒默哦 发表于 2020-9-23 21:23

度娘灬魂手 发表于 2020-9-23 21:07
论坛里的大佬是真的有时间,我看一下就头晕了

{:301_997:}我也没学多久,离大佬差太远了,努力就有收获,慢慢赶吧

liu5653250 发表于 2020-9-23 21:47

厉害?? 厉害?? ,我到现在还一头雾水!

见见不能说 发表于 2020-9-23 21:49

站里大神超多,很棒,有用,收藏起来!!!

yhym599 发表于 2020-9-23 23:36

好文,楼主好有耐心和时间。

度娘灬魂手 发表于 2020-9-23 23:59

舒默哦 发表于 2020-9-23 21:23
我也没学多久,离大佬差太远了,努力就有收获,慢慢赶吧

我光PE结构就学到半途而废,这些是真的不敢碰了,头发都快没了

舒默哦 发表于 2020-9-24 10:19

度娘灬魂手 发表于 2020-9-23 23:59
我光PE结构就学到半途而废,这些是真的不敢碰了,头发都快没了

哈哈。。。。

巅峰Clown 发表于 2020-10-1 05:53

站里大神超多,很棒,有用,收藏起来!!!
页: [1] 2 3 4 5 6
查看完整版本: 【VC】【笔记】自写vmp壳子编写报告(一)