【文章标题】: 理解VM 一个CraCkMe的VM简单分析
【文章作者】: eASYVm
【作者主页】:
【软件名称】: crackme.exe_BY_KuNgBiM
【下载地址】:
http://bbs.pediy.com/showthread.php?threadid=40679
【编写语言】: asm
【使用工具】: OD
【软件介绍】: 一个带有微小完整虚拟机引擎crackme
【作者声明】: 仅是感兴趣...
--------------------------------------------------------------------------------
【详细过程】
最近的日子实在是太无聊了...
看不到一点曙光 于是决定学习一下虚拟机运作原理了 搜索了大量的网上文章并拜读之
深感受益匪浅 故成此文 仅作菜虫学习过程之心得~无他...
各位大侠不要笑我炒冷饭 这确是我第一个分析的VM
所以选择这个程序来联系 一是因为asm编写结构清晰 二是伪指令并不多 据某大侠说该虚拟机配备了一个基于堆栈 单操作数的伪指令系统 虽比不上商业保护的VM复杂程度 但是也算样样俱全~
学习VM 首先你要对VM有个理解
VM就是虚拟机的意思 但是这里的虚拟机并不同于VMware Workstation中的那种虚拟机 在这里的虚拟机只是说一个环境 这个环境可以使你自己的代码脱离计算机CPU的寄存器 堆栈等等运行 而其使用的是你自己定义的一套环境 其中包括所要用到的寄存器 堆栈 甚至还有可能是数据区 而这些可以在你的代码段里 可以在你的数据段里 也可以在CPU的堆栈里分配空间 进行使用...今天分析的这个程序就是一个典型的堆栈机 它将自己的环境以临时变量的形式分配在了子函数的临时变量空间...
00401060 <> $ 55 push ebp ; VMproc
00401061 . 8BEC mov ebp,esp
00401063 . 81C4 D0FEFFFF add esp,-130 ; 分配临时变量空间储存虚拟机环境配置
可以看出 在调用这个虚拟机的时候 子函数分配了0x130个字节的空间来存放 VM的环境 其中包括一些自定义的通用寄存器 自定义标志寄存器 还有一些其他指针
00401069 . C745 E4 00000000 mov dword ptr ss:[ebp-1C],0 ; \VMedi
00401070 . C745 E8 00000000 mov dword ptr ss:[ebp-18],0 ; |VMecx
00401077 . C745 F1 00000000 mov dword ptr ss:[ebp-F],0 ; |VMesp
0040107E . C645 FD 00 mov byte ptr ss:[ebp-3],0 ; |标志寄存器S
00401082 . C645 FE 00 mov byte ptr ss:[ebp-2],0 ; |标志寄存器Z
00401086 . C745 F5 00000000 mov dword ptr ss:[ebp-B],0 ; |VMeax
0040108D . 8D85 D0FEFFFF lea eax,dword ptr ss:[ebp-130] ; |lpVMstack指针
00401093 . 8945 F1 mov dword ptr ss:[ebp-F],eax ; |虚拟机环境初始化;lpVMstack入VMesp
00401096 . 8B45 14 mov eax,dword ptr ss:[ebp+14] ; |
00401099 . 8945 E0 mov dword ptr ss:[ebp-20],eax ; |
0040109C . 8B45 08 mov eax,dword ptr ss:[ebp+8] ; |
0040109F . 8945 D0 mov dword ptr ss:[ebp-30],eax ; |
004010A2 . 8B45 0C mov eax,dword ptr ss:[ebp+C] ; |
004010A5 . 8945 D8 mov dword ptr ss:[ebp-28],eax ; |
004010A8 . C745 DC 00000000 mov dword ptr ss:[ebp-24],0 ; |
004010AF . C745 D4 00000000 mov dword ptr ss:[ebp-2C],0 ; /
以上是该虚拟机环境的初始化过程 后面的注释是我自己加的 你也可以不叫这个名字 但是因为大家都比较熟悉现有的计算机机制 为了后面便于分析 所以用了这些记号 我们可以看出来 这些代码把通用寄存器和标志寄存器都置0 还把一些指针放入了对应的寄存器里 因为编写VM的大侠也是在用现在的计算机机制 所以我猜测 这样分析起来会比较轻松~这也告诉我们 假如那天自己要编写VM 在能够完成我们自己需要的功能前提下 离现有机制越远应该越不容易被分析~
环境准备完毕 下面一步就要开始虚拟机循环了 循环第一步就是取出VM的伪指令
004010B6 . 8B45 10 mov eax,dword ptr ss:[ebp+10] ; \读取伪指令指针
004010B9 . 8945 EC mov dword ptr ss:[ebp-14],eax ; |伪指令指针入VMeip
004010BC > FF45 EC inc dword ptr ss:[ebp-14] ; |VMeip +1 ;VMentry
004010BF . 8B45 EC mov eax,dword ptr ss:[ebp-14] ; |
004010C2 . 8A00 mov al,byte ptr ds:[eax] ; |读取伪指令 置al
004010C4 . 8845 F0 mov byte ptr ss:[ebp-10],al ; |传al置VMcode(VM环境)
004010C7 . B8 00204000 mov eax,crackme.00402000 ; |传VMJMPbase置eax
004010CC . 0FB65D F0 movzx ebx,byte ptr ss:[ebp-10] ; |VMcode拓展
004010D0 . C1E3 02 shl ebx,2 ; |VMcode*4
004010D3 . 03C3 add eax,ebx ; |VMcode*4+VMJMPbase
004010D5 . FF20 jmp dword ptr ds:[eax] ; /跳转至VM函数
以上代码完成了这个过程 我们来看一下 首先读取指向伪指令区域的指针 之后把这个指针放到了VM环境的VMeip里 在读取这个指针所指的"字节码“我们也可以叫做伪指令 这个伪指令通过运算变换计算出她所代表的过程偏移 该偏移加上VM过程跳转表基址VMJMPbase就得到了该VM过程的偏移地址 之后JMP过去执行……………………等到执行该过程结束后 再由一条指令跳回 伪指令指针加1后 继续循环
该指令如下
jmp short crackme.004010BC ; JMPtoVMentry
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课