VMP分析之VM解码循环与基本架构(一)
文章目錄
- 示例代碼
- VMP區(qū)段概覽
- VM基本流程跟蹤
- 步入虛擬機(jī)
- 解密操作碼
- 取handler
- VMP解碼循環(huán)
- 保存寄存器環(huán)境
- 總結(jié)->VM寄存器的基本架構(gòu)
示例代碼
接下來(lái)通過(guò)一個(gè)簡(jiǎn)單的Demo來(lái)大概了解下VMP代碼的整體流程,示例代碼如下
#include <windows.h>int Calc(int a, int b) {return a + b; }int main() {Calc(2, 3);system("pause"); }這里只對(duì)Calc函數(shù)中的兩條匯編指令進(jìn)行VM加殼處理
右鍵新增節(jié)點(diǎn),填入需要VM處理的地址0x401088
接著設(shè)置結(jié)束位置,只對(duì)兩條指令進(jìn)行保護(hù)
然后在Options中選擇最強(qiáng)保護(hù),按F9編譯程序
OD加載VM后的程序,跳轉(zhuǎn)到VM的開(kāi)始地址0x401088。
VMP區(qū)段概覽
VMP1.09加殼后的程序,會(huì)增加兩個(gè)區(qū)段,這兩個(gè)區(qū)段的具體作用如圖:
其中VMP0用于保存虛擬機(jī)引擎代碼,VMP1用于保存VMP的寄存器環(huán)境。
VM基本流程跟蹤
我們?cè)贘MP的位置下斷點(diǎn),讓程序執(zhí)行到這個(gè)位置,然后F7單步。
第一條指令中的push的地址,是一個(gè)密鑰,密鑰指向的內(nèi)存就是VM的指令流。
然后跳轉(zhuǎn)到0x42B3E7的位置。這里就是步入虛擬機(jī)的開(kāi)始
從這里開(kāi)始就進(jìn)入到了虛擬機(jī)的代碼。
步入虛擬機(jī)
首先將寄存器環(huán)境壓入到棧中,接著壓入第二個(gè)密鑰并將先前的第一個(gè)密鑰保存到esi中。
接著將edi賦值為0x42B000
這個(gè)0x42B000就是vmp1區(qū)段的起始地址,用于保存VM_Context,VM的線程上下文,里面保存的是VM的寄存器環(huán)境。
然后將esi和ebx賦值為當(dāng)前的密鑰
而密鑰指向的內(nèi)存數(shù)據(jù),就是VMP的指令流,相當(dāng)于VM_EIP。接著開(kāi)始解密指令流
解密操作碼
接著VMP開(kāi)始解密自己的指令集
首先取出esi的第一個(gè)字節(jié)放到al,并且將esi+1指向下一個(gè)操作碼,當(dāng)前al的值為0x27
再經(jīng)過(guò)幾步位運(yùn)算以后,al操作碼從0x27更新為了0xA7。后面的add bl,al,是為了更新解密key。
add bl,al; al=當(dāng)前VM的操作碼 ebx=解密Key ebx=解密Key+當(dāng)前操作碼al在這里也起到一個(gè)校驗(yàn)碼的作用,更新Key的作用是為了防止逆向人員暴力破解,如果強(qiáng)行改變EIP的指向,那么必然會(huì)導(dǎo)致下一個(gè)VM指令解密失敗,整個(gè)程序就無(wú)法正常運(yùn)行。
然后將eax的高位清0,令eax=0xA7,此時(shí)的eax就是VM解密后的操作碼。
這里的eax已經(jīng)解碼完了,eax只是作為一個(gè)索引,在指令表里查找指令,真正有效的數(shù)據(jù)只有AL,因此VM最多只有256個(gè)指令。
取handler
這里的0x42B4AF指向的內(nèi)存地址,就是VMP的handler,handler就是VM指令實(shí)現(xiàn)的具體過(guò)程。根據(jù)解密出來(lái)的指令跳轉(zhuǎn)到對(duì)應(yīng)的handler,執(zhí)行handler代碼
接著取出VM指令流中的0xC0,此時(shí)指令流EAX=0xC0
經(jīng)過(guò)一系列解密過(guò)程后,eax為真實(shí)的指令0x2,然后再次更新EBX解密KEY
VMP解碼循環(huán)
edi指向的地址是之前保存進(jìn)來(lái)的VM_Context,這里將第二個(gè)解密Key保存到VM_Conetxt+8的位置
接著又跳轉(zhuǎn)到之前解密指令流的位置
這就是最著名的VMP解碼循環(huán),如圖:
其中
- 偽碼地址對(duì)應(yīng)密鑰內(nèi)存中的指令流
- 跳轉(zhuǎn)表對(duì)應(yīng)Handler
- 最下面的Handler是具體的實(shí)現(xiàn)過(guò)程
保存寄存器環(huán)境
當(dāng)操作數(shù)為A7時(shí)的Handler作用的保存當(dāng)前寄存器環(huán)境到VM_Context,A7這個(gè)handler會(huì)執(zhí)行多次,保存前的堆棧如下:
當(dāng)前堆棧 $ ==> > 00000000--->第二個(gè)密鑰 $+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--->第二個(gè)密鑰 $+10 >00000000--->ECX $+14 >02210FC0--->EDX $+18 >000B8FA5---> $+1C >F609851D---> $+20 >E654F2EE---> $+24 >0019FED0--->EBP $+28 >003CA000--->EBX $+2C >00401520--->ESI保存現(xiàn)場(chǎng),ESP為什么不用保存呢?因?yàn)樵赩MP的架構(gòu)里,ESP是直接使用的,在任何時(shí)候都可以獲得真正的ESP
總結(jié)->VM寄存器的基本架構(gòu)
80x86的寄存器中,每一個(gè)寄存器都有特定的作用,例如eax用于保存返回值,ESI用于保存源操作數(shù),而VM的寄存器也不例外。
- ESI:保存VM_EIP
- EDI:指向虛擬機(jī)通用寄存器的地址
- EBP:等于VM_ESP,指向虛擬機(jī)堆棧的棧頂
- EAX:計(jì)算將要執(zhí)行的指令流和選擇虛擬機(jī)通用寄存器,指令執(zhí)行時(shí)用作中間變量,其他時(shí)候用作花指令
- EDX:執(zhí)行時(shí)通常用作中間變量,其他時(shí)候用作花指令
- EBX:bl用來(lái)保存校驗(yàn)碼,更新密鑰
- ECX:shld,shrd時(shí)用作中間變量,其他大部分時(shí)間用來(lái)做花指令
- ESP:指向垃圾指令,這個(gè)寄存器在虛擬機(jī)中用于迷惑分析者
總結(jié)
以上是生活随笔為你收集整理的VMP分析之VM解码循环与基本架构(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 020 Android之so文件动态调试
- 下一篇: VMP分析之VMP1.09虚拟化架构分析