【文章标题】: 简单的虚拟机伪代码解析
【文章作者】: BUG
【作者邮箱】: bughoho@hotmail.com
【作者QQ号】: 393277421
【下载地址】: 无
【使用工具】: VC 2003
【操作平台】: XP SP2
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  晚上没事做偷窥了VMProtect一点点代码,结果止不住内心的兴奋,于是写了份关于虚拟机解析的代码(softworm的教程出来的时候没有看懂,于是现在才激动- -!),
  另外我写的仅仅是虚拟机的冰山一角,更多的资料还望大牛们多爆爆料。
  
  向softworm致敬。
  
  感谢LaraCraft
  
  执行虚拟机代码之前都得先声明一个虚拟机环境结构存放数据
  
  //虚拟机环境结构
  struct VMMachine
  {
          DWORD eax;
          DWORD ecx;
          DWORD edx;
          DWORD ebx;
          DWORD* esp;
          DWORD ebp;
          DWORD esi;
          DWORD edi;
          DWORD eip;
          BYTE CF;
          BYTE PF;
          BYTE AF;
          BYTE ZF;
          BYTE SF;
          BYTE OF;
          BYTE DF;
          //********************************
          BYTE p_code;//伪代码
          DWORD lpVMStack[1024*1024*2];//虚拟机堆栈基地址
  };
  
  然后就是关于解析伪代码的JUMP表
  
  //命令JUMP表
  DWORD VMJumpCode[] = 
  {
          (DWORD)VReturn,//退出虚拟机
          (DWORD)VNop,   //NOP语句
  
          (DWORD)VPUSHImm,//PUSH操作数
          (DWORD)VPUSHReg,//压入寄存器
          (DWORD)VPUSHMem,//压入内存数
  
          (DWORD)VPOPReg,//弹出到寄存器
          (DWORD)VPOPMem,//弹出到内存
  
          (DWORD)VMovRegReg,//寄存器和寄存器赋值
          (DWORD)VMovRegImm,//寄存器和操作数赋值
          (DWORD)VMovRegMem,//寄存器和内存数赋值
  
          (DWORD)VADDRegReg,//寄存器与寄存器相加
          (DWORD)VADDRegImm,//寄存器与操作数相加
          (DWORD)VADDRegMem,//寄存器与内存数相加
  
          (DWORD)VSUBRegReg,//寄存器与寄存器相减
          (DWORD)VSUBRegImm,//寄存器与操作数相减
          (DWORD)VSUBRegMem,//寄存器与内存数相减
  
          (DWORD)VMulEaxReg,//寄存器与寄存器相乘
  
          (DWORD)VDivEaxReg,//寄存器与寄存器相除
  
          (DWORD)VAndRegReg,//寄存器与寄存器做与操作
          (DWORD)VAndRegImm,//寄存器与操作数做与操作
          (DWORD)VAndRegMem,//寄存器与内存数做与操作
  
          (DWORD)VorRegReg,//寄存器与寄存器做或操作
          (DWORD)VorRegImm,//寄存器与操作数做或操作
          (DWORD)VorRegMem,//寄存器与内存数做或操作
          (DWORD)VJmp      //无条件转移
  };
  
  
  void VMExecuteMachine( DWORD VM_code )
  {
          //初始化标志
          vmmachine.AF = 0;
          vmmachine.ZF = 0;
          vmmachine.SF = 0;
          vmmachine.OF = 0;
          vmmachine.DF = 0;
          //初始化寄存器
          vmmachine.eax = 0;
          vmmachine.ecx = 0;
          vmmachine.edx = 0;
          vmmachine.ebx = 0;
          vmmachine.esp = vmmachine.lpVMStack;
          vmmachine.esi = 0;
          vmmachine.edi = 0;
          vmmachine.eip = VM_code;
          vmmachine.p_code = 0;
          memset( vmmachine.lpVMStack,0,sizeof(vmmachine.lpVMStack) );//初始化堆栈
  
          while(TRUE)
          {
                  vmmachine.p_code = *(BYTE*)vmmachine.eip;//取出伪代码
                  DWORD func = VMJumpCode[vmmachine.p_code];//执行当前语句
                  if( func == (DWORD)VReturn )//不用说了,我知道这里写得很烂
                          return;
                  _asm
                  {
                          call func
                  }
          }
          return;
  }
  void Addcode(BYTE n)//EIP向前走n字节
  {
          //vmmachine.eip += n - 1;
          vmmachine.eip += n;
  }
  //nop;01
  void VNop()//NOP语句
  {
          Addcode(1);
          return;
  }
  //push 2000; 02 00 20 00 00
  void VPUSHImm()//PUSH操作数
  {
          vmmachine.eip++;
          DWORD imm32 = *(DWORD*)vmmachine.eip;
          
          Addcode(4);//跳过这个操作数
          
          vmmachine.esp++;
          *vmmachine.esp = imm32;
  }
  //push ecx; 03 01
  void VPUSHReg()//PUSH寄存器
  {
          vmmachine.eip++;
          BYTE regflag = *(BYTE*)vmmachine.eip;
          
          Addcode(1);//跳过这个操作数
          
          if( regflag < 8 )//除开特殊寄存器EIP
          {
                  DWORD imm32 = ((DWORD*)&vmmachine)[regflag];
                  vmmachine.esp++;//放入堆栈
                  *vmmachine.esp = imm32;
          }
          else
          {
                  MessageBox(0,"超出已知寄存器或未认可寄存器","VM",MB_OK);
          }
  }
  //push [401000]; 04 00 10 40 00
  void VPUSHMem()//压入内存中数
  {
          vmmachine.eip++;
          DWORD mem32 = *(DWORD*)vmmachine.eip;
          DWORD imm32 = *(DWORD*)mem32;
          
          Addcode(4);//跳过这个操作数
  
          vmmachine.esp++;//放入堆栈
          *vmmachine.esp = imm32;
  }
  //pop edx; 05 02
  void VPOPReg()//弹出到寄存器
  {
          vmmachine.eip++;
          BYTE regflag = *(BYTE*)vmmachine.eip;
  
          Addcode(1);//跳过这个操作数
  
          if( regflag < 8 )//除开特殊寄存器EIP
          {
                  DWORD imm32 = *vmmachine.esp;
                  vmmachine.esp--;//出栈
                  ((DWORD*)&vmmachine)[regflag] = imm32;//把imm32放到寄存器
          }
          else
          {
                  MessageBox(0,"超出已知寄存器或未认可寄存器","VM",MB_OK);
          }
  }
  //pop [401000]; 06 00 10 40 00
  void VPOPMem()//弹出到内存
  {
          DWORD imm32 = *vmmachine.esp;
          vmmachine.esp--;//出栈
  
          DWORD mem32 = *(DWORD*)vmmachine.eip;
  
          Addcode(4);//跳过这个操作数
          
          *(DWORD*)mem32 = imm32;
  }
  //mov eax,ebx; 07 00 03
  void VMovRegReg()//寄存器与寄存器赋值
  {
          vmmachine.eip++;
          BYTE destreg = *(BYTE*)vmmachine.eip;//目的寄存器
          Addcode(1);//跳过这个操作数
          BYTE srcreg = *(BYTE*)vmmachine.eip;//源寄存器
          Addcode(1);//跳过这个操作数
          if( srcreg < 8 && destreg < 8 )
          {
                  ((DWORD*)&vmmachine)[destreg] = ((DWORD*)&vmmachine)[srcreg];//赋值
          }
          else
          {
                  MessageBox(0,"超出已知寄存器或未认可寄存器","VM",MB_OK);
          }
  }
  //mov ecx,401000; 08 01 00 10 40 00
  void VMovRegImm()//寄存器和操作数赋值
  {
          vmmachine.eip++;
          BYTE destreg = *(BYTE*)vmmachine.eip;//目的寄存器
          Addcode(1);//跳过这个操作数
          DWORD Imm32 = *(DWORD*)vmmachine.eip;//操作数
          Addcode(4);//跳过这个操作数
          if( destreg < 8 )
          {
                  ((DWORD*)&vmmachine)[destreg] = Imm32;//赋值
          }
          else
          {
                  MessageBox(0,"超出已知寄存器或未认可寄存器","VM",MB_OK);
          }
  }
  //mov ecx,[401000]; 09 01 00 10 40 00
  void VMovRegMem()//寄存器和内存数赋值
  {
          vmmachine.eip++;
          BYTE destreg = *(BYTE*)vmmachine.eip;//目的寄存器
          Addcode(1);//跳过这个操作数
          DWORD Mem32 = *(DWORD*)vmmachine.eip;//内存数
          DWORD Imm32 = *(DWORD*)Mem32;
          Addcode(4);//跳过这个操作数
          if( destreg < 8 )
          {
                  ((DWORD*)&vmmachine)[destreg] = Imm32;//赋值
          }
          else
          {
                  MessageBox(0,"超出已知寄存器或未认可寄存器","VM",MB_OK);
          }
  }
  //add eax,ebx; 0A 00 03
  void VADDRegReg()//寄存器与寄存器相加
  {
          vmmachine.eip++;
          BYTE destreg = *(BYTE*)vmmachine.eip;//目的寄存器
          Addcode(1);//跳过这个操作数
          BYTE srcreg = *(BYTE*)vmmachine.eip;//源寄存器
          Addcode(1);//跳过这个操作数
          if( srcreg < 8 && destreg < 8 )
          {
                  ((DWORD*)&vmmachine)[destreg] += ((DWORD*)&vmmachine)[srcreg];//相加
          }
          else
          {
                  MessageBox(0,"超出已知寄存器或未认可寄存器","VM",MB_OK);
          }
  }
  //add eax,1234; 0B 00 34 12 00 00
  void VADDRegImm()//寄存器与操作数相加
  {
          vmmachine.eip++;
          BYTE destreg = *(BYTE*)vmmachine.eip;//目的寄存器
          Addcode(1);//跳过这个操作数
          DWORD Imm32 = *(DWORD*)vmmachine.eip;//操作数
          Addcode(4);//跳过这个操作数
          if( destreg < 8 )
          {
                  ((DWORD*)&vmmachine)[destreg] += Imm32;//赋值
          }
          else
          {
                  MessageBox(0,"超出已知寄存器或未认可寄存器","VM",MB_OK);
          }
  }
  //add eax,[401000]; 0C 00 00 10 40 00
  void VADDRegMem()//寄存器与内存数相加
  {
          vmmachine.eip++;
          BYTE destreg = *(BYTE*)vmmachine.eip;//目的寄存器
          Addcode(1);//跳过这个操作数
          DWORD Mem32 = *(DWORD*)vmmachine.eip;//内存数
          DWORD Imm32 = *(DWORD*)Mem32;
          Addcode(4);//跳过这个操作数
          if( destreg < 8 )
          {
                  ((DWORD*)&vmmachine)[destreg] += Imm32;//赋值
          }
          else
          {
                  MessageBox(0,"超出已知寄存器或未认可寄存器","VM",MB_OK);
          }
  }
  //sub eax,ebx; 0D 00 03
  void VSUBRegReg()//寄存器与寄存器相减
  {
          vmmachine.eip++;
          BYTE destreg = *(BYTE*)vmmachine.eip;//目的寄存器
          Addcode(1);//跳过这个操作数
          BYTE srcreg = *(BYTE*)vmmachine.eip;//源寄存器
          Addcode(1);//跳过这个操作数
          if( srcreg < 8 && destreg < 8 )
          {
                  ((DWORD*)&vmmachine)[destreg] -= ((DWORD*)&vmmachine)[srcreg];//相加
          }
          else
          {
                  MessageBox(0,"超出已知寄存器或未认可寄存器","VM",MB_OK);
          }
  }
  //sub eax,1234; 0E 00 34 12 00 00
  void VSUBRegImm()//寄存器与操作数相减
  {
          vmmachine.eip++;
          BYTE destreg = *(BYTE*)vmmachine.eip;//目的寄存器
          Addcode(1);//跳过这个操作数
          DWORD Imm32 = *(DWORD*)vmmachine.eip;//操作数
          Addcode(4);//跳过这个操作数
          if( destreg < 8 )
          {
                  ((DWORD*)&vmmachine)[destreg] -= Imm32;//赋值
          }
          else
          {
                  MessageBox(0,"超出已知寄存器或未认可寄存器","VM",MB_OK);
          }
  }
  //sub eax,[401000]; 0F 00 00 10 40 00
  void VSUBRegMem()//寄存器与内存数相减
  {
          vmmachine.eip++;
          BYTE destreg = *(BYTE*)vmmachine.eip;//目的寄存器
          Addcode(1);//跳过这个操作数
          DWORD Mem32 = *(DWORD*)vmmachine.eip;//内存数
          DWORD Imm32 = *(DWORD*)Mem32;
          Addcode(4);//跳过这个操作数
          if( destreg < 8 )
          {
                  ((DWORD*)&vmmachine)[destreg] -= Imm32;//赋值
          }
          else
          {
                  MessageBox(0,"超出已知寄存器或未认可寄存器","VM",MB_OK);
          }
  }
  
  //mul ebx; 10 03
  void VMulEaxReg()//EAX与寄存器相乘
  {
          vmmachine.eip++;
          BYTE srcreg = *(BYTE*)vmmachine.eip;//源寄存器
          Addcode(1);//跳过这个操作数
          if( srcreg < 8 )
          {
                  vmmachine.eax *= ((DWORD*)&vmmachine)[srcreg];//相乘
          }
          else
          {
                  MessageBox(0,"超出已知寄存器或未认可寄存器","VM",MB_OK);
          }
  }
  
  //div ebx; 11 03
  void VDivEaxReg()//寄存器与寄存器相除
  {
          vmmachine.eip++;
          BYTE srcreg = *(BYTE*)vmmachine.eip;//源寄存器
          Addcode(1);//跳过这个操作数
          if( srcreg < 8 )
          {
                  vmmachine.eax /= ((DWORD*)&vmmachine)[srcreg];//相除
                  vmmachine.edx = vmmachine.eax % ((DWORD*)&vmmachine)[srcreg];//余数..
          }
          else
          {
                  MessageBox(0,"超出已知寄存器或未认可寄存器","VM",MB_OK);
          }
  }
  //and eax,ecx; 12 00 01
  void VAndRegReg()//寄存器与寄存器做与操作
  {
          vmmachine.eip++;
          BYTE destreg = *(BYTE*)vmmachine.eip;//目的寄存器
          Addcode(1);//跳过这个操作数
          BYTE srcreg = *(BYTE*)vmmachine.eip;//源寄存器
          Addcode(1);//跳过这个操作数
          if( srcreg < 8 && destreg < 8 )
          {
                  ((DWORD*)&vmmachine)[destreg] &= ((DWORD*)&vmmachine)[srcreg];//and
          }
          else
          {
                  MessageBox(0,"超出已知寄存器或未认可寄存器","VM",MB_OK);
          }
  }
  //and eax,1234; 13 00 34 12
  void VAndRegImm()//寄存器与操作数做与操作
  {
          vmmachine.eip++;
          BYTE destreg = *(BYTE*)vmmachine.eip;//目的寄存器
          Addcode(1);//跳过这个操作数
          DWORD Imm32 = *(DWORD*)vmmachine.eip;//操作数
          Addcode(4);//跳过这个操作数
          if( destreg < 8 )
          {
                  ((DWORD*)&vmmachine)[destreg] &= Imm32;//赋值
          }
          else
          {
                  MessageBox(0,"超出已知寄存器或未认可寄存器","VM",MB_OK);
          }
  }
  //and eax,[401000]; 14 00 00 10 40 00
  void VAndRegMem()//寄存器与内存数做与操作
  {
          vmmachine.eip++;
          BYTE destreg = *(BYTE*)vmmachine.eip;//目的寄存器
          Addcode(1);//跳过这个操作数
          DWORD Mem32 = *(DWORD*)vmmachine.eip;//内存数
          DWORD Imm32 = *(DWORD*)Mem32;
          Addcode(4);//跳过这个操作数
          if( destreg < 8 )
          {
                  ((DWORD*)&vmmachine)[destreg] &= Imm32;//赋值
          }
          else
          {
                  MessageBox(0,"超出已知寄存器或未认可寄存器","VM",MB_OK);
          }
  }
  
  //or eax,ecx; 15 00 01
  void VorRegReg()//寄存器与寄存器做或操作
  {
          vmmachine.eip++;
          BYTE destreg = *(BYTE*)vmmachine.eip;//目的寄存器
          Addcode(1);//跳过这个操作数
          BYTE srcreg = *(BYTE*)vmmachine.eip;//源寄存器
          Addcode(1);//跳过这个操作数
          if( srcreg < 8 && destreg < 8 )
          {
                  ((DWORD*)&vmmachine)[destreg] |= ((DWORD*)&vmmachine)[srcreg];//or
          }
          else
          {
                  MessageBox(0,"超出已知寄存器或未认可寄存器","VM",MB_OK);
          }
  }
  //or eax,1234; 16 00 34 12
  void VorRegImm()//寄存器与操作数做或操作
  {
          vmmachine.eip++;
          BYTE destreg = *(BYTE*)vmmachine.eip;//目的寄存器
          Addcode(1);//跳过这个操作数
          DWORD Imm32 = *(DWORD*)vmmachine.eip;//操作数
          Addcode(4);//跳过这个操作数
          if( destreg < 8 )
          {
                  ((DWORD*)&vmmachine)[destreg] |= Imm32;//赋值
          }
          else
          {
                  MessageBox(0,"超出已知寄存器或未认可寄存器","VM",MB_OK);
          }
  }
  //or eax,[401000]; 17 00 00 10 40 00
  void VorRegMem()//寄存器与内存数做或操作
  {
          vmmachine.eip++;
          BYTE destreg = *(BYTE*)vmmachine.eip;//目的寄存器
          Addcode(1);//跳过这个操作数
          DWORD Imm32 = *(DWORD*)vmmachine.eip;//操作数
          Addcode(4);//跳过这个操作数
          if( destreg < 8 )
          {
                  ((DWORD*)&vmmachine)[destreg] |= Imm32;//赋值
          }
          else
          {
                  MessageBox(0,"超出已知寄存器或未认可寄存器","VM",MB_OK);
          }
  }
  
  //jmp 00401000; 18 00 10 40 00
  void VJmp()//无条件跳转
  {
          vmmachine.eip++;
          DWORD imm32 = *(DWORD*)vmmachine.eip;
  
          vmmachine.eip = imm32;//EIP指向这个地址
  }
  void VReturn()//退出虚拟机.只是一个标记而已
  {
  }
  
  BYTE vm_code[32] = 
  {
          0x02,0x00,0x20,0x00,0x00,      //push 2000
          0x03,0x00,                     //push eax
          0x0B,0x00,0x34,0x12,0x00,0x00,  //add eax,1234
          0x0E,0x00,0x10,0x00,0x00,0x00,  //sub eax,10
          0x00                           //exit
  };
  
  int _tmain(int argc, _TCHAR* argv[])
  {
          VMExecuteMachine((DWORD)vm_code);
          return 0;
  }
  
  这一晚上就写了这么多,基本上都是对寄存器和堆栈的操作,还未对标志寄存器做任何操作..不然可以连条件语句也加上去.
  
  另外代码因为我赶着睡觉于是我草草的测试了一遍没问题就发上来了,如有失误还请包涵.
  
--------------------------------------------------------------------------------
【经验总结】
  今晚上算有点收获,对VM有了点认识.
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2007年03月13日 5:06:55