文章目录

  • 示例代码
  • VMP区段概览
  • VM基本流程跟踪
    • 步入虚拟机
    • 解密操作码
    • 取handler
    • VMP解码循环
    • 保存寄存器环境
  • 总结->VM寄存器的基本架构

示例代码

接下来通过一个简单的Demo来大概了解下VMP代码的整体流程,示例代码如下

#include <windows.h>int Calc(int a, int b)
{return a + b;
}int main()
{Calc(2, 3);system("pause");
}

这里只对Calc函数中的两条汇编指令进行VM加壳处理

右键新增节点,填入需要VM处理的地址0x401088

接着设置结束位置,只对两条指令进行保护

然后在Options中选择最强保护,按F9编译程序

OD加载VM后的程序,跳转到VM的开始地址0x401088。

VMP区段概览

VMP1.09加壳后的程序,会增加两个区段,这两个区段的具体作用如图:

其中VMP0用于保存虚拟机引擎代码,VMP1用于保存VMP的寄存器环境。

VM基本流程跟踪

我们在JMP的位置下断点,让程序执行到这个位置,然后F7单步。

第一条指令中的push的地址,是一个密钥,密钥指向的内存就是VM的指令流。

然后跳转到0x42B3E7的位置。这里就是步入虚拟机的开始

从这里开始就进入到了虚拟机的代码。

步入虚拟机

首先将寄存器环境压入到栈中,接着压入第二个密钥并将先前的第一个密钥保存到esi中。

接着将edi赋值为0x42B000

这个0x42B000就是vmp1区段的起始地址,用于保存VM_Context,VM的线程上下文,里面保存的是VM的寄存器环境。

然后将esi和ebx赋值为当前的密钥

而密钥指向的内存数据,就是VMP的指令流,相当于VM_EIP。接着开始解密指令流

解密操作码

接着VMP开始解密自己的指令集

首先取出esi的第一个字节放到al,并且将esi+1指向下一个操作码,当前al的值为0x27

再经过几步位运算以后,al操作码从0x27更新为了0xA7。后面的add bl,al,是为了更新解密key。

add bl,al;
al=当前VM的操作码
ebx=解密Key
ebx=解密Key+当前操作码

al在这里也起到一个校验码的作用,更新Key的作用是为了防止逆向人员暴力破解,如果强行改变EIP的指向,那么必然会导致下一个VM指令解密失败,整个程序就无法正常运行。

然后将eax的高位清0,令eax=0xA7,此时的eax就是VM解密后的操作码。

这里的eax已经解码完了,eax只是作为一个索引,在指令表里查找指令,真正有效的数据只有AL,因此VM最多只有256个指令。

取handler

这里的0x42B4AF指向的内存地址,就是VMP的handler,handler就是VM指令实现的具体过程。根据解密出来的指令跳转到对应的handler,执行handler代码

接着取出VM指令流中的0xC0,此时指令流EAX=0xC0

经过一系列解密过程后,eax为真实的指令0x2,然后再次更新EBX解密KEY

VMP解码循环

edi指向的地址是之前保存进来的VM_Context,这里将第二个解密Key保存到VM_Conetxt+8的位置

接着又跳转到之前解密指令流的位置

这就是最著名的VMP解码循环,如图:

其中

  • 伪码地址对应密钥内存中的指令流
  • 跳转表对应Handler
  • 最下面的Handler是具体的实现过程

保存寄存器环境

当操作数为A7时的Handler作用的保存当前寄存器环境到VM_Context,A7这个handler会执行多次,保存前的堆栈如下:

当前堆栈
$ ==>    > 00000000--->第二个密钥
$+4      > 0019FED0--->EDI
$+8      > 00401520--->ESI
$+C      > 0019FED0--->EBP
$+10     > 0019FE7C--->ESP
$+14     > 00309000--->EBX
$+18     > 021E0FC0--->EDX
$+1C     > 00000000--->ECX
$+20     > CCCCCCCC--->EAX
$+24     > 00000206--->EFlags

保存后的VM_Context如下:

VM_Context
$ ==>    >CCCCCCCC--->EAX
$+4      >00000206--->EFlags
$+8      >0019FED0--->EDI
$+C      >00000000--->第二个密钥
$+10     >00000000--->ECX
$+14     >02210FC0--->EDX
$+18     >000B8FA5--->
$+1C     >F609851D--->
$+20     >E654F2EE--->
$+24     >0019FED0--->EBP
$+28     >003CA000--->EBX
$+2C     >00401520--->ESI

保存现场,ESP为什么不用保存呢?因为在VMP的架构里,ESP是直接使用的,在任何时候都可以获得真正的ESP

总结->VM寄存器的基本架构

80x86的寄存器中,每一个寄存器都有特定的作用,例如eax用于保存返回值,ESI用于保存源操作数,而VM的寄存器也不例外。

  • ESI:保存VM_EIP
  • EDI:指向虚拟机通用寄存器的地址
  • EBP:等于VM_ESP,指向虚拟机堆栈的栈顶
  • EAX:计算将要执行的指令流和选择虚拟机通用寄存器,指令执行时用作中间变量,其他时候用作花指令
  • EDX:执行时通常用作中间变量,其他时候用作花指令
  • EBX:bl用来保存校验码,更新密钥
  • ECX:shld,shrd时用作中间变量,其他大部分时间用来做花指令
  • ESP:指向垃圾指令,这个寄存器在虚拟机中用于迷惑分析者

VMP分析之VM解码循环与基本架构(一)相关推荐

  1. VMP分析之VMP2.13流程分析(三)

    文章目录 VMP2.X版本特点 VMP2.13加壳 VMP2.13代码分析 进入VM虚拟机 保存堆栈 保存eflags和edx 保存ecx和edi 保存ebx 保存eax 保存ebx ebp和esi ...

  2. VMP分析之VMP1.09虚拟化架构分析(二)

    文章目录 示例代码 VM完整流程分析 VM解码循环 保存寄存器环境 压入EBP和偏移 执行函数 恢复寄存器环境 总结 示例代码 示例代码如下: #include "stdafx.h" ...

  3. VMP分析之VMP2.13插件化分析(四)

    文章目录 Zeus插件 相关介绍 初始化Key并解密 加载操作码 解密操作码 取handler 解密handler 进入handler 保存堆栈 指令流解密Key VMP分析插件 相关介绍 VM分析插 ...

  4. FFmpeg的H.264解码器源代码简单分析:宏块解码(Decode)部分-帧间宏块(Inter)

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

  5. FFmpeg的H.264解码器源代码简单分析:宏块解码(Decode)部分-帧内宏块(Intra)

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

  6. Tiny Jpeg Decoder (JPEG解码程序) 源代码分析 2:解码数据

    注:分析Tiny Jpeg Decoder源代码的文章: Tiny Jpeg Decoder (JPEG解码程序) 源代码分析 1:解码文件头 Tiny Jpeg Decoder (JPEG解码程序) ...

  7. FFmpeg的H.264解码器源代码简单分析:宏块解码(Decode)部分-帧间宏块(Inter)...

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

  8. FFmpeg的H.264解码器源代码简单分析:宏块解码(Decode)部分-帧内宏块(Intra)...

    ===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...

  9. Tiny Jpeg Decoder (JPEG解码程序) 源代码分析 1:解码文件头

    注:分析Tiny Jpeg Decoder源代码的文章: Tiny Jpeg Decoder (JPEG解码程序) 源代码分析 1:解码文件头 Tiny Jpeg Decoder (JPEG解码程序) ...

最新文章

  1. 同等学力计算机综合难吗,报考2018年同等学力申硕计算机在职研究生毕业很困难吗...
  2. mysql 正则 java 区别_MySQL中的正则表达式
  3. vue --- 使用vue-router获取带参数的路由
  4. ad网络标号怎么批量设置_网络打印机怎么设置 网络打印机安装方法【详细步骤】...
  5. 解决Conda install tensorflow弹窗Python.exe已经停止工作的问题
  6. php mysql社工库_社工库源码 PHP ASP,持续更新
  7. 禅道的下载与安装教程
  8. win10计算机桌面天气,win10电脑桌面显示时间和天气日期怎么设置
  9. 互联网下一个风口 国务院印发《促进大数据发展行动纲要》
  10. 铁矿石再次冲高回落,豆粕认购大涨,纯碱09-01季节性反套?2022.4.21
  11. 遇到问题---linux--crontab输出重定向不生效最全可能原因收集和解决
  12. python battleship_一个python初学者的作业,battleship
  13. 日常使用计算机如何进行病毒防范,电脑日常生活中怎么防范电脑病毒
  14. 苹果公司:苹果商店App价格将调整 多个国家地区受影响
  15. C++语法学习笔记十四:派生类-调用顺序-访问等级-函数遮蔽
  16. Android 模拟器 连接局域网
  17. NodeBB – 基于 Node.js 的开源论坛系统
  18. QCustomPlot 示例实践--sinc离散序列
  19. 2021年如何选购华强北AirPods(一次翻车到下车的经历总结的经验)
  20. ArcGIS中WGS84转为西安80(无自带转换参数的坐标系转换)

热门文章

  1. DL之LSTM:基于tensorflow框架利用LSTM算法对气温数据集训练并回归预测
  2. 成功解决 ValueError: feature_names mismatch training data did not have the following fields
  3. ML之SVM:调用(sklearn的lfw_people函数在线下载55个外国人图片文件夹数据集)来精确实现人脸识别并提取人脸特征向量
  4. TF之DCGAN:基于TF利用DCGAN测试自己的数据集并进行生成过程全记录
  5. DL之Keras:基于Keras框架建立模型实现【预测】功能的简介、设计思路、案例分析、代码实现之详细攻略(经典,建议收藏)
  6. Linux常用命令 积累
  7. 集成学习-Boosting集成学习算法AdaBoost
  8. rcmd: socket: Permission denied
  9. mysql主从复制同步
  10. c#FileStream文件读写(转)