VMP分析之VM解码循环与基本架构(一)
文章目錄
- 示例代碼
- 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解码循环与基本架构(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 020 Android之so文件动态调试
- 下一篇: VMP分析之VMP1.09虚拟化架构分析