西西軟件園多重安全檢測(cè)下載網(wǎng)站、值得信賴的軟件下載站!
軟件
軟件
文章
搜索

首頁西西教程軟件使用 → VMProtect2.04加殼程序從入門到精通

VMProtect2.04加殼程序從入門到精通

相關(guān)軟件相關(guān)文章發(fā)表評(píng)論 來源:本站整理時(shí)間:2010/11/2 18:59:10字體大。A-A+

作者:佚名點(diǎn)擊:3925次評(píng)論:0次標(biāo)簽: VMProtect 加殼

VMProtect UltimateV2.13.5 中文注冊(cè)版
  • 類型:加殼脫殼大。13.5M語言:中文 評(píng)分:4.2
  • 標(biāo)簽:
立即下載
2 頁 VMProtect虛擬機(jī)簡(jiǎn)介

1.基礎(chǔ)知識(shí)
1.1.VMProtect虛擬機(jī)簡(jiǎn)介
虛擬機(jī)加密,是指像VMP這樣的保護(hù)程序,它會(huì)把源程序的X86指令變成自定義的偽指令,等到執(zhí)行的時(shí)候,VMP內(nèi)置在保護(hù)程序中的VM就會(huì)啟動(dòng),讀取偽指令,然后解析執(zhí)行。
VMP是一個(gè)堆棧虛擬機(jī),它的一切操作都是基于堆棧傳遞的。在VMP中,每一個(gè)偽指令就是一個(gè)handler,VM中有一個(gè)核心的Dispatch部分,它通過讀取程序的bytecode,然后在DispatchiTable里面定位到不同的handler中執(zhí)行。絕大多數(shù)情況下,在一個(gè)handler中執(zhí)行完成后,程序?qū)⒒氐紻ispatch部分,然后到next handler中執(zhí)行。
http_imgload.jpg下載此附件需要消耗2Kx,下載中會(huì)自動(dòng)扣除。
在上面的框架中,核心的部件就是Dispatch部分,下面并列的部件就是handlers。
經(jīng)過VMP加密的X86指令,一條簡(jiǎn)單的指令被分解成數(shù)條VMP的偽指令,它按照自己的偽指令排列去實(shí)現(xiàn)原指令的功能,在加上其他的花指令混亂等等,你將完全看不到源程序指令。VMP自帶的各種機(jī)制都不再是以X86指令的形式去實(shí)現(xiàn),而是用自己的偽指令去測(cè)試。
在VMP的VM運(yùn)行過程中,各個(gè)寄存器的基本用途是:EBP和EDI是VM堆棧指針(不是常規(guī)的堆棧);ESI是偽指令指針(相當(dāng)于常規(guī)的EIP);EAX是VM解密數(shù)據(jù)的主運(yùn)算寄存器;EBX是VM解密數(shù)據(jù)的輔運(yùn)算寄存器;ECX是常規(guī)的循環(huán)計(jì)數(shù)器;ESP是常規(guī)的堆棧棧頂指針。EDX是讀取偽指令表數(shù)據(jù);
EDI、EBP分別指向VM堆棧的上下限位置,EBP指向堆棧的下限并向上發(fā)展,EDI指向堆棧的上限并使用[EDI+EAX]的方式向下發(fā)展;ESI指向的內(nèi)存塊里包括要執(zhí)行的偽指令序列,而不同的是,當(dāng)VM要是使用到立即數(shù)時(shí),也是從ESI讀取。可見ESI內(nèi)存塊里面是精心構(gòu)建的數(shù)據(jù)塊,只有VM自身執(zhí)行過程中,才能知道下一個(gè)數(shù)據(jù)是代表偽指令還是立即數(shù);在VM運(yùn)算中EAX寄存器很多時(shí)候通常只有AL參與運(yùn)算然后在存取時(shí)再以AX或EAX得方式存。籈BX在很多加密數(shù)據(jù)運(yùn)算中,都會(huì)參與到EAX值的計(jì)算中,協(xié)助運(yùn)算中正確的值。而每次EAX的值運(yùn)算結(jié)束后,反過來會(huì)計(jì)算好下一次運(yùn)算中EBX的值。所以EBX的數(shù)據(jù)一旦出錯(cuò),下一個(gè)數(shù)據(jù)解密必然錯(cuò)誤;在VM運(yùn)行中,通常一切操作都是在VM堆棧內(nèi)完成的,所以絕大多數(shù)情況下對(duì)ESP的操作都是花指令或junk code。在一些虛擬與現(xiàn)實(shí)(比如說調(diào)用系統(tǒng)函數(shù))交接的地方,系統(tǒng)并不知道VM堆棧的存在,這就需要把數(shù)據(jù)(比如系統(tǒng)函數(shù)的調(diào)用參數(shù))移動(dòng)到常規(guī)ESP棧頂。EDX是一個(gè)較少使用的寄存器,只在一些解密循環(huán)里面參與運(yùn)算。而它的一個(gè)主要的運(yùn)用是在DISPATCH部件里,根據(jù)ESI的值來獲取DispatchTable的數(shù)據(jù),讓VM執(zhí)行下一條偽指令。

1.2.VM堆棧
VMP的VM是基于堆棧的虛擬家,理解好VM的堆棧空間劃分和操作,是理解整個(gè)VM運(yùn)行的基礎(chǔ)。
VMProtect2.04加殼程序是從TLS開始運(yùn)行的,我們首先點(diǎn)擊OD的options菜單,修改Startup and exit選項(xiàng),讓OD中斷在TLS callback里。加殼程序運(yùn)行后,VMP初始化VM,并進(jìn)入DISPATCH部分。這里我們就以初始化后的堆棧為例。
VM的堆棧一共使用61個(gè)DWORD,上下分別有2個(gè)堆棧指針,下面為EBP指針,上面為EDI指針。下面是VM初始化時(shí),給EDI和EBP指針賦值后的堆棧。
EDI=0013F8BC
EBP=0013F9B0
CPU Stack
Locked Value ASCII Comments
0013F8BC 009539E8 9. ;這里是EDI指向
0013F8C0 00950000 ...
0013F8C4 00150000 ...
0013F8C8 00000080 ...
0013F8CC 019314D6
0013F8D0 0013F8A8 .
0013F8D4 7C92E920 |
0013F8D8 00000000 ....
0013F8DC 00000000 ....
0013F8E0 00000000 ....
0013F8E4 FFFFFFFF
0013F8E8 7C98FEFF |
0013F8EC 7C00ADE7 .|
0013F8F0 00000000 ....
0013F8F4 00150000 ...
0013F8F8 0013F6F0 .
0013F8FC 0013F940 @.
0013F900 0013F944 D.
0013F904 7C92E920 |
0013F908 7C9301E0 |
0013F90C FFFFFFFF
0013F910 7C9301DB |
0013F914 7C9314D6 |
0013F918 7C931514 |
0013F91C 7C99E120 |
0013F920 7C9314EA |
0013F924 5ADF1158 XZ
0013F928 00000001 ...
0013F92C 00000000 ....
0013F930 7FFDA000 .
0013F934 7FFDF000 .
0013F938 00158070 p.
0013F93C 0013F890 .
0013F940 00000000 ....
0013F944 0043D759 YC.
0013F948 0000E9ED ..
0013F94C 409B0002 .@
0013F950 00000020 ...
0013F954 0013F9CC .
0013F958 0013F96C l.
0013F95C 0043E9ED C.
0013F960 000359F4 Y.
0013F964 00000020 ...
0013F968 004253CD SB.
0013F96C 409B0000 ..@
0013F970 00000020 ...
0013F974 0013F9CC .
0013F978 0013F98C .
0013F97C 00000000 .... ;這里是EBP指向
0013F980 00000000 .... ;這里是VM初始化保存的各個(gè)寄存器
0013F984 00000246 F..
0013F988 000359F4 Y.
0013F98C 00000020 ...
0013F990 00000000 ....
0013F994 0013F9CC .
0013F998 004253CD SB.
0013F99C 000359F4 Y.
0013F9A0 00400000 ..@.
0013F9A4 0013F9C0 .
0013F9A8 C456C619 V ;這里是VMP的2個(gè)加密數(shù)據(jù)
0013F9AC 2EF6420A .B.
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;這里是TLS進(jìn)來時(shí)的棧頂
關(guān)于2個(gè)加密數(shù)據(jù)和初始化的過程我們后續(xù)來說,這里我們主要關(guān)注VM的堆棧劃分。
我把上面的EDI指向的堆棧稱為EDISTACK,把EBP指向的堆棧稱為EBPSTACK。在VM中,EBPSTACK是運(yùn)算區(qū),各類數(shù)據(jù)的運(yùn)算操作在這里完成;EDISTACK是存儲(chǔ)區(qū)包括長(zhǎng)期存儲(chǔ)數(shù)據(jù)和臨時(shí)存儲(chǔ)EBPSTACK的運(yùn)算數(shù)。
下面我們來看一條數(shù)據(jù)移動(dòng)偽指令:
命名:
VM_MOVdw_EDISTACKdw_EBPSTACKdw
代碼:
0043DC19 |. F6D8 NEG AL ; *
0043DC26 |. C0C8 07 ROR AL,7 ; *
0043DC34 |. 2C 20 SUB AL,20 ; *
0043DC41 |. 24 3C AND AL,3C ; *

0043E080 |$ 8B55 00 MOV EDX,DWORD PTR SS:[EBP] ; *
0043E086 |. 83C5 04 ADD EBP,4 ; *

0043D3D7 /> /891438 MOV DWORD PTR DS:[EDI+EAX],EDX ; *
功能:
把1個(gè)dword的數(shù)據(jù)從EBPSTAK棧頂移動(dòng)到EDISTACK,使用EAX作為偏移量

在EDISTACK的數(shù)據(jù)移動(dòng)中,使用[EDI+EAX]的方式來存儲(chǔ)與獲取各個(gè)值。通過計(jì)算不同的EAX的值,可以到達(dá)EDISTACK中不同位置。在計(jì)算EAX值時(shí),實(shí)際真正計(jì)算的是AL的值,我們來考慮一下AL的最小值和最大值,AL=00時(shí)[EDI+EAX]=[0013F8BC+00000000]=0013F8BC,AL=FF時(shí)[EDI+EAX]=[0013F8BC+000000FF]=0013F9BB,這是使用[EDI+EAX]可以讀取的上下限。但是,在VM的AL值計(jì)算過程中,最后有一條AND AL,0x3C指令,0x3C=00111100bit由于這條指令的限制,無論AL為任何值(從00000000bit到11111111bit),通過AND操作,只能有1111bit的活動(dòng)空間大小,1111bit相當(dāng)于16,所以EDISTACK最多可以讀取16個(gè)dword;由于00111100bit最后兩個(gè)00位的限制,任何數(shù)字與它AND后,后兩位都必然為0,變成與4對(duì)齊的值,說明VM都是按照0013F8BC 0013F8C0 0013F8C4 0013F8C8這樣的4對(duì)齊來讀取。在讀取時(shí),VM可以讀取byte word dword,但是VM將不會(huì)去讀取0013F8BE。
由于EDISTACK堆棧向下發(fā)展,EBPSTACK堆棧向上發(fā)展,EDISTACK有0x3C控制著范圍,而EBPSTACK是操作區(qū),沒有硬性的范圍控制。為了預(yù)防兩個(gè)空間相撞,在每次往EBPSTACK移動(dòng)數(shù)據(jù)后,VM都有相應(yīng)的邊界檢測(cè)指令如下:
0043CE5A |. 8D47 50 LEA EAX,[EDI+50] ; *
0043EE5D |. 39C5 CMP EBP,EAX ; *
0043F08C |.^\0F87 29F6FFFF JA 0043E6BB ; *
比較結(jié)果 大于 ,這個(gè)正常的情況,在這個(gè)VM跟蹤過程中,我沒有發(fā)現(xiàn)一次小于的情況。如果小于,也就是EBPSTACK棧頂已經(jīng)到達(dá)[EDI+50]位置,VM將會(huì)重新分配堆?臻g。0x50的偏移量比0x3C的偏移量多5個(gè)dword的緩沖區(qū)。我們來手動(dòng)修改EBP指針,看看VM的對(duì)于兩個(gè)堆?臻g即將相撞的處理情況:
CPU Disasm
Address Hex dump Command Comments
0043F092 |. 52 PUSH EDX ;
0043D6C1 |. 8D5424 08 LEA EDX,[ARG.2] ; *EDX獲得的是原來EDI指針地址0013F8BC
0043DF38 |. 8D4F 40 LEA ECX,[EDI+40] ; *0x40的偏移量是0x3C的偏移量數(shù)據(jù)1個(gè)dword結(jié)束后的位置
0043DF46 |. 29D1 SUB ECX,EDX ; *減法計(jì)算出數(shù)據(jù)存儲(chǔ)量
0043DF4B |. 8D45 80 LEA EAX,[EBP-80] ; *增加0x80的空間
0043DF5C |. 24 FC AND AL,FC ; *按4對(duì)齊
0043DF68 |. 29C8 SUB EAX,ECX ; *在增加原來數(shù)據(jù)大小的堆?臻g
0043DF6E |. 89C4 MOV ESP,EAX ; *
0043DF7E |. 56 PUSH ESI ; |Arg1 = NOTEPAD.425748, *
0043DF87 |. 89D6 MOV ESI,EDX ; |*
0043DB3A /$ 8D7C01 C0 LEA EDI,[EAX+ECX-40] ; *
0043EC1E . 89C7 MOV EDI,EAX ; *
0043EEED |. F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ ; *移動(dòng)原來EDISTACK中存儲(chǔ)的數(shù)據(jù)
0043EEF7 |. 8B7C24 10 MOV EDI,DWORD PTR SS:[ESP+10] ; *
0043EEFF |. 8B7424 10 MOV ESI,DWORD PTR SS:[ESP+10] ; *
這里我們可以看到,每次發(fā)現(xiàn)兩個(gè)堆棧空間即將相撞,VM都重新給EBP分配堆棧,并把原來EDISTACK存儲(chǔ)的數(shù)據(jù)移動(dòng)到新的空間內(nèi)。
下面是使用OD跟蹤VM堆棧的幾個(gè)小技巧:
在OD中跟蹤VM數(shù)據(jù)移動(dòng)時(shí),雙擊0013F8BC地址,OD將會(huì)以0013F8BC為基址,顯示上下各個(gè)地址與它的偏移量,如圖:
CPU Stack
Locked Value ASCII Comments
$-C 759D0000 ..u
$-8 00000001 ...
$-4 0013F8FC .
$ ==> 009539E8 9. ;這里是0013F8BC,雙擊后的效果
$+4 00950000 ...
$+8 00150000 ...
$+C 00000080 ...
$+10 019314D6
在跟蹤VM時(shí),在數(shù)據(jù)移動(dòng)偽指令中的AND AL,0x3C的下一條指令下斷點(diǎn),這樣每次進(jìn)行數(shù)據(jù)移動(dòng),你都可以在這個(gè)斷點(diǎn)看到,數(shù)據(jù)的去向和來源,這是極其有用的。在很多復(fù)雜的運(yùn)算地方,你需要在草稿紙上記下,EDISTACK中一些空間的數(shù)據(jù)時(shí)來自于什么時(shí)候?比如標(biāo)志位ZF檢測(cè)+跳轉(zhuǎn)是VM的一個(gè)重要操作,而EFLAGS標(biāo)志數(shù)都是相差不多或類似的00000286 00000246等等,如果你不能準(zhǔn)確知道[EDI+EAX]存儲(chǔ)或讀取的位置,你將無法理解VM的操作。這非常的重要,請(qǐng)牢記!必要時(shí)連OD得數(shù)據(jù)窗口也一起配合顯示VM堆棧

把OD里的堆棧窗口拉高,讓它竟可能多的顯示數(shù)據(jù),在高分辨率的電腦上,最好是能夠顯示出整個(gè)VM的堆棧。默認(rèn)情況下,堆棧窗口是隨著ESP指針的變化而自動(dòng)顯示的,這對(duì)于我們要時(shí)刻盯著VM堆棧的需求不相符,在堆棧窗口-->右鍵-->Lock address 打鉤,這樣OD就會(huì)鎖定堆棧窗口。
到這里,關(guān)于堆棧空間的介紹就結(jié)束了。對(duì)堆棧的理解是本文的根基。

    相關(guān)評(píng)論

    閱讀本文后您有什么感想? 已有人給出評(píng)價(jià)!

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過難過
    • 5 囧
    • 3 圍觀圍觀
    • 2 無聊無聊

    熱門評(píng)論

    最新評(píng)論

    發(fā)表評(píng)論 查看所有評(píng)論(0)

    昵稱:
    表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
    字?jǐn)?shù): 0/500 (您的評(píng)論需要經(jīng)過審核才能顯示)