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

首頁(yè)西西教程軟件使用 → VMProtect2.04加殼程序從入門(mén)到精通

VMProtect2.04加殼程序從入門(mén)到精通

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

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

VMProtect UltimateV2.13.5 中文注冊(cè)版
  • 類(lèi)型:加殼脫殼大。13.5M語(yǔ)言:中文 評(píng)分:4.2
  • 標(biāo)簽:
立即下載

此文章是我學(xué)習(xí)VMProtect2.04加殼程序的心得。在調(diào)試的過(guò)程中,尤其是初期,參考和查閱了N多的網(wǎng)絡(luò)資料,在此一并表示感謝。在計(jì)算機(jī)書(shū)中,最著名的兩類(lèi)書(shū)名當(dāng)屬:XXXX從入門(mén)到精通和21天學(xué)會(huì)XXXX,我在仔細(xì)思考,最終覺(jué)得還是前者比較有吸引力。OD的UDD文件的使用,在D:盤(pán)下新建文件夾Unpack,把加殼記事本放入文件夾內(nèi),把UDD文件放入OD的UDD文件夾內(nèi)。OD打開(kāi)加殼記事本后,UDD文件會(huì)自動(dòng)生效。
聲明:本文在非盈利性用途可自由傳播。
軟件:正版VMProtect2.04加密的Win98記事本
加密選項(xiàng):除了 編譯--調(diào)試模式與水印 以外,全部打鉤;虛擬計(jì)算機(jī)--數(shù)量為默認(rèn)值1;編譯類(lèi)型:超級(jí)(變異+虛擬)
調(diào)試器:官網(wǎng)下載的OllyDbg2.0
加殼程序下載:NOTEPAD.rar下載此附件需要消耗2Kx,下載中會(huì)自動(dòng)扣除。
UDD文件:NOTEPAD-udd.rar下載此附件需要消耗2Kx,下載中會(huì)自動(dòng)扣除。(這是是整理了偽指令的UDD文件,后續(xù)還會(huì)更新)
本文的結(jié)構(gòu):
序言
文章簡(jiǎn)介
1.基礎(chǔ)知識(shí)
1.1.VMProtect虛擬機(jī)簡(jiǎn)介
1.2.VM堆棧
1.3.偽指令匯總
2.綜合運(yùn)用
2.1.常見(jiàn)偽指令組合
2.2.NAND(與非門(mén))
2.3.EFLAGS標(biāo)志位檢測(cè)+跳轉(zhuǎn)
3.NOTEPAD全程跟蹤
3.1.TLS
3.2.VMP外殼函數(shù)獲取
3.3.虛擬執(zhí)行環(huán)境與調(diào)試器檢測(cè)
3.4.HASH值分塊檢測(cè)與API獲取
3.5.重點(diǎn)解密循環(huán)
4.實(shí)驗(yà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部分,它通過(guò)讀取程序的bytecode,然后在DispatchiTable里面定位到不同的handler中執(zhí)行。絕大多數(shù)情況下,在一個(gè)handler中執(zhí)行完成后,程序?qū)⒒氐紻ispatch部分,然后到next handler中執(zhí)行。
http_imgload.jpg下載此附件需要消耗2Kx,下載中會(huì)自動(dòng)扣除。
在上面的框架中,核心的部件就是Dispatch部分,下面并列的部件就是handlers。
經(jīng)過(guò)VMP加密的X86指令,一條簡(jiǎn)單的指令被分解成數(shù)條VMP的偽指令,它按照自己的偽指令排列去實(shí)現(xiàn)原指令的功能,在加上其他的花指令混亂等等,你將完全看不到源程序指令。VMP自帶的各種機(jī)制都不再是以X86指令的形式去實(shí)現(xiàn),而是用自己的偽指令去測(cè)試。
在VMP的VM運(yùn)行過(guò)程中,各個(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讀取?梢(jiàn)ESI內(nèi)存塊里面是精心構(gòu)建的數(shù)據(jù)塊,只有VM自身執(zhí)行過(guò)程中,才能知道下一個(gè)數(shù)據(jù)是代表偽指令還是立即數(shù);在VM運(yùn)算中EAX寄存器很多時(shí)候通常只有AL參與運(yùn)算然后在存取時(shí)再以AX或EAX得方式存;EBX在很多加密數(shù)據(jù)運(yùn)算中,都會(huì)參與到EAX值的計(jì)算中,協(xié)助運(yùn)算中正確的值。而每次EAX的值運(yùn)算結(jié)束后,反過(guò)來(lái)會(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í)(比如說(shuō)調(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的值來(lái)獲取DispatchTable的數(shù)據(jù),讓VM執(zhí)行下一條偽指令。

1.2.VM堆棧
VMP的VM是基于堆棧的虛擬家,理解好VM的堆?臻g劃分和操作,是理解整個(gè)VM運(yùn)行的基礎(chǔ)。
VMProtect2.04加殼程序是從TLS開(kāi)始運(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)來(lái)時(shí)的棧頂
關(guān)于2個(gè)加密數(shù)據(jù)和初始化的過(guò)程我們后續(xù)來(lái)說(shuō),這里我們主要關(guān)注VM的堆棧劃分。
我把上面的EDI指向的堆棧稱(chēng)為EDISTACK,把EBP指向的堆棧稱(chēng)為EBPSTACK。在VM中,EBPSTACK是運(yùn)算區(qū),各類(lèi)數(shù)據(jù)的運(yùn)算操作在這里完成;EDISTACK是存儲(chǔ)區(qū)包括長(zhǎng)期存儲(chǔ)數(shù)據(jù)和臨時(shí)存儲(chǔ)EBPSTACK的運(yùn)算數(shù)。
下面我們來(lái)看一條數(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]的方式來(lái)存儲(chǔ)與獲取各個(gè)值。通過(guò)計(jì)算不同的EAX的值,可以到達(dá)EDISTACK中不同位置。在計(jì)算EAX值時(shí),實(shí)際真正計(jì)算的是AL的值,我們來(lái)考慮一下AL的最小值和最大值,AL=00時(shí)[EDI+EAX]=[0013F8BC+00000000]=0013F8BC,AL=FF時(shí)[EDI+EAX]=[0013F8BC+000000FF]=0013F9BB,這是使用[EDI+EAX]可以讀取的上下限。但是,在VM的AL值計(jì)算過(guò)程中,最后有一條AND AL,0x3C指令,0x3C=00111100bit由于這條指令的限制,無(wú)論AL為任何值(從00000000bit到11111111bit),通過(guò)AND操作,只能有1111bit的活動(dòng)空間大小,1111bit相當(dāng)于16,所以EDISTACK最多可以讀取16個(gè)dword;由于00111100bit最后兩個(gè)00位的限制,任何數(shù)字與它AND后,后兩位都必然為0,變成與4對(duì)齊的值,說(shuō)明VM都是按照0013F8BC 0013F8C0 0013F8C4 0013F8C8這樣的4對(duì)齊來(lái)讀取。在讀取時(shí),VM可以讀取byte word dword,但是VM將不會(huì)去讀取0013F8BE。
由于EDISTACK堆棧向下發(fā)展,EBPSTACK堆棧向上發(fā)展,EDISTACK有0x3C控制著范圍,而EBPSTACK是操作區(qū),沒(méi)有硬性的范圍控制。為了預(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跟蹤過(guò)程中,我沒(méi)有發(fā)現(xiàn)一次小于的情況。如果小于,也就是EBPSTACK棧頂已經(jīng)到達(dá)[EDI+50]位置,VM將會(huì)重新分配堆棧空間。0x50的偏移量比0x3C的偏移量多5個(gè)dword的緩沖區(qū)。我們來(lái)手動(dòng)修改EBP指針,看看VM的對(duì)于兩個(gè)堆棧空間即將相撞的處理情況:
CPU Disasm
Address Hex dump Command Comments
0043F092 |. 52 PUSH EDX ;
0043D6C1 |. 8D5424 08 LEA EDX,[ARG.2] ; *EDX獲得的是原來(lái)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 ; *在增加原來(lái)數(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)原來(lái)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è)堆?臻g即將相撞,VM都重新給EBP分配堆棧,并把原來(lái)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ù)的去向和來(lái)源,這是極其有用的。在很多復(fù)雜的運(yùn)算地方,你需要在草稿紙上記下,EDISTACK中一些空間的數(shù)據(jù)時(shí)來(lái)自于什么時(shí)候?比如標(biāo)志位ZF檢測(cè)+跳轉(zhuǎn)是VM的一個(gè)重要操作,而EFLAGS標(biāo)志數(shù)都是相差不多或類(lèi)似的00000286 00000246等等,如果你不能準(zhǔn)確知道[EDI+EAX]存儲(chǔ)或讀取的位置,你將無(wú)法理解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)于堆?臻g的介紹就結(jié)束了。對(duì)堆棧的理解是本文的根基。

1.3.偽指令匯總
調(diào)試VMP前期的一個(gè)重要的體力活是,識(shí)別出所有的偽指令,并根據(jù)它的用途給它相應(yīng)的命名。以后就可以在DISPATCH部件的最后跳轉(zhuǎn)地址:
0043E11F |. C2 5000 RETN 50
下斷點(diǎn),再盯著VM堆棧就可以知道VM的所有操作。
我們先來(lái)了解所有偽指令的DISPATCH(調(diào)遣)部件:
0043E6BF |. 8A46 FF MOV AL,BYTE PTR DS:[ESI-1] ; *
0043E6C4 |. 30D8 XOR AL,BL ; *
0043E6CE |. F6D0 NOT AL ; *
0043E6D6 |. FEC8 DEC AL ; *
0043E6DA |. C0C8 07 ROR AL,7 ; *
0043E6E1 |. 83EE 01 SUB ESI,1 ; *
0043E6ED |. 30C3 XOR BL,AL ; *
0043D02F |. 0FB6C0 MOVZX EAX,AL ; *

0043F124 |. 8B1485 DBE143 MOV EDX,DWORD PTR DS:[EAX*4+43E1DB] ; *
0043E100 |> /81C2 6B197FB6 ADD EDX,B67F196B ; *

0043E10A |. 895424 3C MOV DWORD PTR SS:[ESP+3C],EDX ; *
0043E11B |. FF7424 4C PUSH DWORD PTR SS:[ESP+4C] ; *
0043E11F |. C2 5000 RETN 50
首先從ESI中解密獲得下一條偽指令在DispatchTable(調(diào)遣表)中的偏移量,使用[EAX*4+43E1DB]來(lái)讀取出偽指令地址,簡(jiǎn)單的ADD解密后,把真正的偽指令地址壓入ESP棧頂,最后用RETN 50跳轉(zhuǎn)到相應(yīng)的偽指令。
MOV EDX,DWORD PTR DS:[EAX*4+43E1DB]給我們提供的信息:DispatchTable的起始地址是0043E1DB,最后一個(gè)dword的開(kāi)始地址是以AL的最大值FF作為偏移量[FF*4+43E1DB]=0043E5D7。我們把記事本0043E1DB--0043E5D7的數(shù)據(jù)粘貼:
CPU Dump
Address Hex dump ASCII
0043E1D0 09|BA C4 49 D0| .I
0043E1E0 BA C4 49 1E|B7 C4 49 E6|C4 C4 49 53|D1 C4 49 05| IIISI
0043E1F0 BE C4 49 75|D1 C4 49 D4|CE C4 49 0C|D6 C4 49 C3| IuII.I
0043E200 BD C4 49 7B|CE C4 49 67|BE C4 49 26|BF C4 49 EB| I{IgI&I
0043E210 C2 C4 49 82|D0 C4 49 3A|BA C4 49 1E|B5 C4 49 A8| II:II
0043E220 C4 C4 49 1E|B5 C4 49 2E|C8 C4 49 B9|BB C4 49 E9| II.II
0043E230 C3 C4 49 2D|B8 C4 49 95|C1 C4 49 82|D0 C4 49 75| I-IIIu
0043E240 D1 C4 49 C3|BE C4 49 16|B6 C4 49 2D|B8 C4 49 75| I鎂II-Iu
0043E250 D1 C4 49 95|C1 C4 49 EB|C2 C4 49 52|BF C4 49 B4| IIIRI
0043E260 D3 C4 49 8B|D3 C4 49 05|CE C4 49 52|BF C4 49 D4| IIIRI
0043E270 CE C4 49 E8|B8 C4 49 C3|BD C4 49 C3|BE C4 49 5E| II媒I鎂I^
0043E280 B4 C4 49 B1|B8 C4 49 61|BD C4 49 5D|BF C4 49 E9| IIaI]I
0043E290 C3 C4 49 26|BF C4 49 5F|D0 C4 49 B4|D3 C4 49 E6| I&I_II
0043E2A0 C4 C4 49 EC|B7 C4 49 1E|B5 C4 49 0D|C0 C4 49 0D| III.I.
0043E2B0 C0 C4 49 C3|BD C4 49 5D|BF C4 49 7B|CE C4 49 C3| I媒I]I{I
0043E2C0 BD C4 49 1E|B5 C4 49 82|D0 C4 49 8A|B9 C4 49 A6| IIII
0043E2D0 D1 C4 49 EB|C2 C4 49 D4|CE C4 49 61|BD C4 49 09| IIIaI.
0043E2E0 BA C4 49 53|D1 C4 49 61|BD C4 49 3A|BA C4 49 3A| ISIaI:I:
0043E2F0 D0 C4 49 0C|D6 C4 49 3A|BA C4 49 1E|B7 C4 49 05| I.I:II
0043E300 CE C4 49 0D|C0 C4 49 82|D0 C4 49 27|D2 C4 49 7C| I.II'I|
0043E310 BD C4 49 E8|B8 C4 49 41|C2 C4 49 E9|C3 C4 49 25| IIAII%
0043E320 CE C4 49 53|C6 C4 49 61|BD C4 49 53|C6 C4 49 83| ISIaISI
0043E330 D6 C4 49 53|C6 C4 49 5D|BF C4 49 53|C6 C4 49 A8| ISI]ISI
0043E340 C4 C4 49 53|C6 C4 49 5F|D0 C4 49 53|C6 C4 49 E6| ISI_ISI
0043E350 C4 C4 49 53|C6 C4 49 3A|BA C4 49 53|C6 C4 49 00| ISI:ISI.
0043E360 C7 C4 49 53|C6 C4 49 2D|B8 C4 49 53|C6 C4 49 25| ISI-ISI%
0043E370 CE C4 49 53|C6 C4 49 83|D6 C4 49 53|C6 C4 49 1E| ISIISI
0043E380 B7 C4 49 53|C6 C4 49 C3|BD C4 49 53|C6 C4 49 62| ISI媒ISIb
0043E390 CF C4 49 53|C6 C4 49 12|D3 C4 49 53|C6 C4 49 E8| ISIISI
0043E3A0 B8 C4 49 05|CE C4 49 1E|B7 C4 49 8A|B9 C4 49 B4| IIII
0043E3B0 D3 C4 49 B9|BB C4 49 A6|D1 C4 49 E8|B8 C4 49 FE| IIII
0043E3C0 C0 C4 49 82|D0 C4 49 53|D1 C4 49 2D|B8 C4 49 52| IISI-IR
0043E3D0 BF C4 49 3A|D0 C4 49 C3|BE C4 49 A6|C1 C4 49 C3| I:I鎂II
0043E3E0 BE C4 49 5E|B4 C4 49 82|D0 C4 49 7C|BD C4 49 C3| I^II|I
0043E3F0 BD C4 49 C3|BE C4 49 1E|B7 C4 49 61|BD C4 49 A6| I鎂IIaI
0043E400 C1 C4 49 82|D0 C4 49 12|D3 C4 49 FE|C0 C4 49 25| IIII%
0043E410 CE C4 49 0C|D6 C4 49 09|BA C4 49 2E|C8 C4 49 67| I.I.I.Ig
0043E420 BE C4 49 8A|B9 C4 49 EB|C2 C4 49 D4|CE C4 49 95| IIII
0043E430 C1 C4 49 D1|C7 C4 49 09|BA C4 49 00|C7 C4 49 B9| II.I.I
0043E440 BB C4 49 D1|C7 C4 49 B4|D3 C4 49 5E|B4 C4 49 D1| III^I
0043E450 C7 C4 49 A8|C4 C4 49 A6|C1 C4 49 12|D3 C4 49 B4| IIII
0043E460 D3 C4 49 D0|BA C4 49 41|C2 C4 49 82|D0 C4 49 B1| I瀉IAII
0043E470 B8 C4 49 1E|B5 C4 49 27|D2 C4 49 82|D0 C4 49 75| II'IIu
0043E480 D1 C4 49 5E|B4 C4 49 25|CE C4 49 16|B6 C4 49 7B| I^I%II{
0043E490 CE C4 49 7C|BD C4 49 EB|C2 C4 49 27|D2 C4 49 83| I|II'I
0043E4A0 D6 C4 49 12|D3 C4 49 2E|C8 C4 49 1E|B5 C4 49 E6| II.II
0043E4B0 C4 C4 49 C3|BD C4 49 95|C1 C4 49 1E|B5 C4 49 EC| I媒III
0043E4C0 B7 C4 49 B9|BB C4 49 5F|D0 C4 49 83|D6 C4 49 8A| II_II
0043E4D0 B9 C4 49 A6|C1 C4 49 D4|CE C4 49 8B|D3 C4 49 0D| IIII.
0043E4E0 C0 C4 49 E8|B8 C4 49 2D|B8 C4 49 61|BD C4 49 82| II-IaI
0043E4F0 D0 C4 49 12|D3 C4 49 1E|B5 C4 49 7C|BD C4 49 D1| III|I
0043E500 C7 C4 49 7C|BD C4 49 05|CE C4 49 A6|C1 C4 49 5F| I|III_
0043E510 D0 C4 49 1E|B7 C4 49 7B|CE C4 49 0C|D6 C4 49 05| II{I.I
0043E520 BE C4 49 9F|C2 C4 49 B9|BB C4 49 9F|C2 C4 49 D4| IIII
0043E530 CE C4 49 9F|C2 C4 49 EC|B7 C4 49 9F|C2 C4 49 62| IIIIb
0043E540 CF C4 49 9F|C2 C4 49 2D|B8 C4 49 9F|C2 C4 49 0C| II-II.
0043E550 D6 C4 49 9F|C2 C4 49 0D|C0 C4 49 9F|C2 C4 49 05| II.II
0043E560 BE C4 49 9F|C2 C4 49 C3|BD C4 49 9F|C2 C4 49 53| II媒IIS
0043E570 D1 C4 49 9F|C2 C4 49 75|D1 C4 49 9F|C2 C4 49 05| IIuII
0043E580 CE C4 49 9F|C2 C4 49 75|D1 C4 49 9F|C2 C4 49 27| IIuII'
0043E590 D2 C4 49 9F|C2 C4 49 09|BA C4 49 9F|C2 C4 49 B9| II.II
0043E5A0 B5 C4 49 E6|C4 C4 49 09|BA C4 49 8B|D3 C4 49 25| II.II%
0043E5B0 CE C4 49 0D|C0 C4 49 B9|B5 C4 49 E9|C3 C4 49 12| I.III
0043E5C0 D3 C4 49 FE|C0 C4 49 05|CE C4 49 83|D6 C4 49 0D| IIII.
0043E5D0 C0 C4 49 EC|B7 C4 49 D0|BA C4 49 II瀉I
雖然DispatchTable的數(shù)據(jù)很多,但是很多不同的偏移量指向的相同的數(shù)據(jù),這是一種保護(hù)方式。我們反過(guò)來(lái)想,如果DispatchTable中每個(gè)dword指向的是不同的偽指令,這就意味著每個(gè)EAX偏移量指向著唯一的一條偽指令,進(jìn)一步的來(lái)說(shuō)就是每個(gè)ESI值代表著唯一的一條偽指令。那么,如果有人逆向這個(gè)算法,就可以知道每個(gè)ESI值對(duì)應(yīng)的是哪個(gè)偽指令,這樣就可以直接讀取ESI值而了解VMP的執(zhí)行偽指令,基本等于半自動(dòng)識(shí)別VMP。一名對(duì)VMP經(jīng)驗(yàn)豐富的人,只要看著VM執(zhí)行的偽指令盯著EBPSTACK堆棧,就可以理解VM的情況,F(xiàn)在,由于多個(gè)ESI值指向相同的偽指令,還有動(dòng)態(tài)EBX解碼,將會(huì)艱難的多。
我們?cè)贠D中尋找一個(gè)空間,寫(xiě)一段循環(huán)代碼,把DispatchTable的數(shù)據(jù)全部解密出來(lái):
原來(lái)的代碼:
0043F11F \38F5 CMP CH,DH
0043F121 66:FFC2 INC DX
0043F124 8B1485 DBE14300 MOV EDX,DWORD PTR DS:[EAX*4+43E1DB] ; *
0043F12B F9 STC
0043F12C 84F4 TEST AH,DH
0043F12E 60 PUSHAD
0043F12F ^ E9 CC5EFCFF JMP 0043E100
把最后一條指令修改為:
0043F12F ^\E9 CC5EFCFF JMP 00405000
在00405000添加循環(huán)代碼:
CPU Disasm
Address Hex dump Command Comments
00405000 60 PUSHAD
00405001 BE DBE14300 MOV ESI,0043E1DB ; DispatchTable地址
00405006 BF 00514000 MOV EDI,00405100 ; 解密循環(huán)地址
0040500B B9 00010000 MOV ECX,100
00405010 31DB XOR EBX,EBX
00405012 8B0433 MOV EAX,DWORD PTR DS:[ESI+EBX]
00405015 05 6B197FB6 ADD EAX,B67F196B ; 解密指令只有1條ADD
0040501A 89043B MOV DWORD PTR DS:[EDI+EBX],EAX
0040501D 83C3 04 ADD EBX,4
00405020 49 DEC ECX
00405021 ^ 75 EF JNE SHORT 00405012
00405023 61 POPAD
00405024 E9 8E900200 JMP 0043E100
循環(huán)結(jié)束后,在00405100中就還原了整個(gè)DispatchTable:
CPU Dump
Address Hex dump ASCII
00405100 74 D3 43 00|3B D4 43 00|89 D0 43 00|51 DE 43 00| tC.;C.C.QC.
00405110 BE EA 43 00|70 D7 43 00|E0 EA 43 00|3F E8 43 00| C.pC.C.?C.
00405120 77 EF 43 00|2E D7 43 00|E6 E7 43 00|D2 D7 43 00| wC..C.C.C.
00405130 91 D8 43 00|56 DC 43 00|ED E9 43 00|A5 D3 43 00| C.VC.C.C.
00405140 89 CE 43 00|13 DE 43 00|89 CE 43 00|99 E1 43 00| C.C.C.C.
00405150 24 D5 43 00|54 DD 43 00|98 D1 43 00|00 DB 43 00| $C.TC.C..C.
00405160 ED E9 43 00|E0 EA 43 00|2E D8 43 00|81 CF 43 00| C.C..C.C.
00405170 98 D1 43 00|E0 EA 43 00|00 DB 43 00|56 DC 43 00| C.C..C.VC.
00405180 BD D8 43 00|1F ED 43 00|F6 EC 43 00|70 E7 43 00| C.C.C.pC.
00405190 BD D8 43 00|3F E8 43 00|53 D2 43 00|2E D7 43 00| C.?C.SC..C.
004051A0 2E D8 43 00|C9 CD 43 00|1C D2 43 00|CC D6 43 00| .C.C.C.C.
004051B0 C8 D8 43 00|54 DD 43 00|91 D8 43 00|CA E9 43 00| C.TC.C.C.
004051C0 1F ED 43 00|51 DE 43 00|57 D1 43 00|89 CE 43 00| C.QC.WC.C.
004051D0 78 D9 43 00|78 D9 43 00|2E D7 43 00|C8 D8 43 00| xC.xC..C.C.
004051E0 E6 E7 43 00|2E D7 43 00|89 CE 43 00|ED E9 43 00| C..C.C.C.
004051F0 F5 D2 43 00|11 EB 43 00|56 DC 43 00|3F E8 43 00| C.C.VC.?C.
00405200 CC D6 43 00|74 D3 43 00|BE EA 43 00|CC D6 43 00| C.tC.C.C.
00405210 A5 D3 43 00|A5 E9 43 00|77 EF 43 00|A5 D3 43 00| C.C.wC.C.
00405220 89 D0 43 00|70 E7 43 00|78 D9 43 00|ED E9 43 00| C.pC.xC.C.
00405230 92 EB 43 00|E7 D6 43 00|53 D2 43 00|AC DB 43 00| C.C.SC.C.
00405240 54 DD 43 00|90 E7 43 00|BE DF 43 00|CC D6 43 00| TC.C.C.C.
00405250 BE DF 43 00|EE EF 43 00|BE DF 43 00|C8 D8 43 00| C.C.C.C.
00405260 BE DF 43 00|13 DE 43 00|BE DF 43 00|CA E9 43 00| C.C.C.C.
00405270 BE DF 43 00|51 DE 43 00|BE DF 43 00|A5 D3 43 00| C.QC.C.C.
00405280 BE DF 43 00|6B E0 43 00|BE DF 43 00|98 D1 43 00| C.kC.C.C.
00405290 BE DF 43 00|90 E7 43 00|BE DF 43 00|EE EF 43 00| C.C.C.C.
004052A0 BE DF 43 00|89 D0 43 00|BE DF 43 00|2E D7 43 00| C.C.C..C.
004052B0 BE DF 43 00|CD E8 43 00|BE DF 43 00|7D EC 43 00| C.C.C.}C.
004052C0 BE DF 43 00|53 D2 43 00|70 E7 43 00|89 D0 43 00| C.SC.pC.C.
004052D0 F5 D2 43 00|1F ED 43 00|24 D5 43 00|11 EB 43 00| C.C.$C.C.
004052E0 53 D2 43 00|69 DA 43 00|ED E9 43 00|BE EA 43 00| SC.iC.C.C.
004052F0 98 D1 43 00|BD D8 43 00|A5 E9 43 00|2E D8 43 00| C.C.C..C.
00405300 11 DB 43 00|2E D8 43 00|C9 CD 43 00|ED E9 43 00| C..C.C.C.
00405310 E7 D6 43 00|2E D7 43 00|2E D8 43 00|89 D0 43 00| C..C..C.C.
00405320 CC D6 43 00|11 DB 43 00|ED E9 43 00|7D EC 43 00| C.C.C.}C.
00405330 69 DA 43 00|90 E7 43 00|77 EF 43 00|74 D3 43 00| iC.C.wC.tC.
00405340 99 E1 43 00|D2 D7 43 00|F5 D2 43 00|56 DC 43 00| C.C.C.VC.
00405350 3F E8 43 00|00 DB 43 00|3C E1 43 00|74 D3 43 00| ?C..C.<C.tC.
00405360 6B E0 43 00|24 D5 43 00|3C E1 43 00|1F ED 43 00| kC.$C.<C.C.
00405370 C9 CD 43 00|3C E1 43 00|13 DE 43 00|11 DB 43 00| C.<C.C.C.
00405380 7D EC 43 00|1F ED 43 00|3B D4 43 00|AC DB 43 00| }C.C.;C.C.
00405390 ED E9 43 00|1C D2 43 00|89 CE 43 00|92 EB 43 00| C.C.C.C.
004053A0 ED E9 43 00|E0 EA 43 00|C9 CD 43 00|90 E7 43 00| C.C.C.C.
004053B0 81 CF 43 00|E6 E7 43 00|E7 D6 43 00|56 DC 43 00| C.C.C.VC.
004053C0 92 EB 43 00|EE EF 43 00|7D EC 43 00|99 E1 43 00| C.C.}C.C.
004053D0 89 CE 43 00|51 DE 43 00|2E D7 43 00|00 DB 43 00| C.QC..C..C.
004053E0 89 CE 43 00|57 D1 43 00|24 D5 43 00|CA E9 43 00| C.WC.$C.C.
004053F0 EE EF 43 00|F5 D2 43 00|11 DB 43 00|3F E8 43 00| C.C.C.?C.
00405400 F6 EC 43 00|78 D9 43 00|53 D2 43 00|98 D1 43 00| C.xC.SC.C.
00405410 CC D6 43 00|ED E9 43 00|7D EC 43 00|89 CE 43 00| C.C.}C.C.
00405420 E7 D6 43 00|3C E1 43 00|E7 D6 43 00|70 E7 43 00| C.<C.C.pC.
00405430 11 DB 43 00|CA E9 43 00|89 D0 43 00|E6 E7 43 00| C.C.C.C.
00405440 77 EF 43 00|70 D7 43 00|0A DC 43 00|24 D5 43 00| wC.pC..C.$C.
00405450 0A DC 43 00|3F E8 43 00|0A DC 43 00|57 D1 43 00| .C.?C..C.WC.
00405460 0A DC 43 00|CD E8 43 00|0A DC 43 00|98 D1 43 00| .C.C..C.C.
00405470 0A DC 43 00|77 EF 43 00|0A DC 43 00|78 D9 43 00| .C.wC..C.xC.
00405480 0A DC 43 00|70 D7 43 00|0A DC 43 00|2E D7 43 00| .C.pC..C..C.
00405490 0A DC 43 00|BE EA 43 00|0A DC 43 00|E0 EA 43 00| .C.C..C.C.
004054A0 0A DC 43 00|70 E7 43 00|0A DC 43 00|E0 EA 43 00| .C.pC..C.C.
004054B0 0A DC 43 00|92 EB 43 00|0A DC 43 00|74 D3 43 00| .C.C..C.tC.
004054C0 0A DC 43 00|24 CF 43 00|51 DE 43 00|74 D3 43 00| .C.$C.QC.tC.
004054D0 F6 EC 43 00|90 E7 43 00|78 D9 43 00|24 CF 43 00| C.C.xC.$C.
004054E0 54 DD 43 00|7D EC 43 00|69 DA 43 00|70 E7 43 00| TC.}C.iC.pC.
004054F0 EE EF 43 00|78 D9 43 00|57 D1 43 00|3B D4 43 00| C.xC.WC.;C.
Intel的Little Endian(小尾)方式存儲(chǔ)讓我們看的非常的別扭。在OD的主窗口(CPU窗口)中來(lái)到00405000 .data段,看一下00405100的顯示:
004050F2 0000 ADD BYTE PTR DS:[EAX],AL
004050F4 0000 ADD BYTE PTR DS:[EAX],AL
004050F6 0000 ADD BYTE PTR DS:[EAX],AL
004050F8 0000 ADD BYTE PTR DS:[EAX],AL
004050FA 0000 ADD BYTE PTR DS:[EAX],AL
004050FC 0000 ADD BYTE PTR DS:[EAX],AL
004050FE 0000 ADD BYTE PTR DS:[EAX],AL
00405100 ^ 74 D3 JE SHORT 004050D5
00405102 43 INC EBX
00405103 003B ADD BYTE PTR DS:[EBX],BH
00405105 D4 43 AAM 43
00405110 BE EA430070 MOV ESI,700043EA
OD把我們的數(shù)據(jù)當(dāng)做代碼來(lái)顯示了。點(diǎn)擊右鍵-->Analysis-->Analyse code Ctrl + A ,彈出對(duì)話(huà)框是否分析,點(diǎn)擊確定。顯示如下:
004050FB 00 DB 00
004050FC 00 DB 00
004050FD 00 DB 00
004050FE 00 DB 00
004050FF 00 DB 00
00405100 . 74D34300 DD 0043D374
00405104 . 3BD44300 DD 0043D43B
00405108 . 89D04300 DD 0043D089
0040510C . 51DE4300 DD 0043DE51
00405110 . BEEA4300 DD 0043EABE
00405114 . 70D74300 DD 0043D770
00405118 . E0EA4300 DD 0043EAE0
0040511C . 3FE84300 DD 0043E83F
00405120 . 77EF4300 DD 0043EF77
00405124 . 2ED74300 DD 0043D72E
00405128 . E6E74300 DD 0043E7E6
0040512C . D2D74300 DD 0043D7D2
OD正確的以數(shù)據(jù)方式顯示,并且已經(jīng)按照我們?nèi)粘5牧?xí)慣把數(shù)據(jù)按照Big Endian(大尾)方式顯示。
對(duì)于DispatchTable中重復(fù)的數(shù)據(jù),我們也要把他清除,在剛才00405000的匯編代碼下面繼續(xù):
CPU Disasm
Address Hex dump Command Comments
00405000 60 PUSHAD
00405001 BE DBE14300 MOV ESI,0043E1DB ; DispatchTable地址
00405006 BF 00514000 MOV EDI,00405100 ; 解密循環(huán)地址
0040500B B9 00010000 MOV ECX,100
00405010 31DB XOR EBX,EBX
00405012 8B0433 MOV EAX,DWORD PTR DS:[ESI+EBX]
00405015 05 6B197FB6 ADD EAX,B67F196B ; 解密指令只有1條ADD
0040501A 89043B MOV DWORD PTR DS:[EDI+EBX],EAX
0040501D 83C3 04 ADD EBX,4
00405020 49 DEC ECX
00405021 ^ 75 EF JNE SHORT 00405012
00405023 61 POPAD
00405024 EB 03 JMP SHORT 00405029
00405026 90 NOP
00405027 90 NOP
00405028 90 NOP
00405029 60 PUSHAD
0040502A BE 00514000 MOV ESI,00405100 ; TispatchTable
0040502F BF 005A4000 MOV EDI,00405A00 ; new DispatchTable
00405034 B9 00010000 MOV ECX,100
00405039 BA 00000000 MOV EDX,0
0040503E 8D1C8D 00000000 LEA EBX,[ECX*4]
00405045 8B06 MOV EAX,DWORD PTR DS:[ESI]
00405047 83F8 00 CMP EAX,0
0040504A 74 1A JE SHORT 00405066
0040504C 8907 MOV DWORD PTR DS:[EDI],EAX
0040504E 83C7 04 ADD EDI,4
00405051 83C2 04 ADD EDX,4
00405054 39DA CMP EDX,EBX
00405056 74 0E JE SHORT 00405066
00405058 3B0432 CMP EAX,DWORD PTR DS:[ESI+EDX]
0040505B ^ 75 F4 JNE SHORT 00405051
0040505D C70432 00000000 MOV DWORD PTR DS:[ESI+EDX],0
00405064 ^ EB EB JMP SHORT 00405051
00405066 83C6 04 ADD ESI,4
00405069 49 DEC ECX
0040506A ^ 75 CD JNE SHORT 00405039
0040506C 61 POPAD
0040506D E9 8E900200 JMP 0043E100
第一部分是前面解密代碼,第二部分是分別比較00405100中的數(shù)據(jù),把相同的全部放00000000,同時(shí)把非0的數(shù)據(jù)存入00405A00中。
執(zhí)行完這些代碼后,00405A00中生成了VM中所有的偽指令,在通過(guò)OD把它按照數(shù)據(jù)顯示出來(lái)如下:
CPU Disasm
Address Hex dump Command Comments
00405A00 . \74D34300 DD 0043D374
00405A04 . 3BD44300 DD 0043D43B
00405A08 . 89D04300 DD 0043D089
00405A0C . 51DE4300 DD 0043DE51
00405A10 . BEEA4300 DD 0043EABE
00405A14 . 70D74300 DD 0043D770
00405A18 . E0EA4300 DD 0043EAE0
00405A1C . 3FE84300 DD 0043E83F
00405A20 . 77EF4300 DD 0043EF77
00405A24 . 2ED74300 DD 0043D72E
00405A28 . E6E74300 DD 0043E7E6
00405A2C . D2D74300 DD 0043D7D2
00405A30 . 91D84300 DD 0043D891
00405A34 . 56DC4300 DD 0043DC56
00405A38 . EDE94300 DD 0043E9ED
00405A3C . A5D34300 DD 0043D3A5
00405A40 . 89CE4300 DD 0043CE89
00405A44 . 13DE4300 DD 0043DE13
00405A48 . 99E14300 DD 0043E199
00405A4C . 24D54300 DD 0043D524
00405A50 . 54DD4300 DD 0043DD54
00405A54 . 98D14300 DD 0043D198
00405A58 . 00DB4300 DD 0043DB00
00405A5C . 2ED84300 DD 0043D82E
00405A60 . 81CF4300 DD 0043CF81
00405A64 . BDD84300 DD 0043D8BD
00405A68 . 1FED4300 DD 0043ED1F
00405A6C . F6EC4300 DD 0043ECF6
00405A70 . 70E74300 DD 0043E770
00405A74 . 53D24300 DD 0043D253
00405A78 . C9CD4300 DD 0043CDC9
00405A7C . 1CD24300 DD 0043D21C
00405A80 . CCD64300 DD 0043D6CC
00405A84 . C8D84300 DD 0043D8C8
00405A88 . CAE94300 DD 0043E9CA
00405A8C . 57D14300 DD 0043D157
00405A90 . 78D94300 DD 0043D978
00405A94 . F5D24300 DD 0043D2F5
00405A98 . 11EB4300 DD 0043EB11
00405A9C . A5E94300 DD 0043E9A5
00405AA0 . 92EB4300 DD 0043EB92
00405AA4 . E7D64300 DD 0043D6E7
00405AA8 . ACDB4300 DD 0043DBAC
00405AAC . 90E74300 DD 0043E790
00405AB0 . BEDF4300 DD 0043DFBE
00405AB4 . EEEF4300 DD 0043EFEE
00405AB8 . 6BE04300 DD 0043E06B
00405ABC . CDE84300 DD 0043E8CD
00405AC0 . 7DEC4300 DD 0043EC7D
00405AC4 . 69DA4300 DD 0043DA69
00405AC8 . 11DB4300 DD 0043DB11
00405ACC . 3CE14300 DD 0043E13C
00405AD0 . 0ADC4300 DD 0043DC0A
00405AD4 . 24CF4300 DD 0043CF24
這個(gè)VM一共有52條偽指令,在本節(jié)中我將一一列出這52條偽指令。每個(gè)分析VMP的人都有自己對(duì)偽指令的命名方式。
移動(dòng)到EBPSTACK的數(shù)據(jù)使用PUSH指令,移動(dòng)到EDISTACK的數(shù)據(jù)使用MOV指令。在VM中,對(duì)數(shù)據(jù)的操作包括byte和dword,而存儲(chǔ)的方式是word和dword,當(dāng)遇到byte和word交織在一起的時(shí)候,可以就把數(shù)據(jù)作為word操作來(lái)看。
下面我以:VM_PUSHw_MEMORYb為例說(shuō)明我的命名規(guī)則:
偽指令的命名統(tǒng)一使用VM_開(kāi)頭;并接上直觀的助記符PUSH;EBPSTACK是移動(dòng)的目的地;MEMORY是移動(dòng)的來(lái)源地;w代表word、b代表byte、dw代表dword;這條指令的表示:這是一條移動(dòng)指令,把1個(gè)byte的數(shù)據(jù)從內(nèi)存塊移動(dòng)到EBPSTACK,存儲(chǔ)時(shí)是按照word來(lái)存儲(chǔ)。
在VMP的偽指令中包含有大量的花指令和junk code,在本文列出的偽指令都是去除了這些無(wú)用代碼。
0043DC0A命名:
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 ; *
功能:
把EBPSTACK棧頂1個(gè)dword的數(shù)據(jù)存儲(chǔ)到EDISTACK

0043E7E6命名:
VM_MOVw_EDISTACKw_EBPSTACKw
代碼:
0043E7EC 0FB646 FF MOVZX EAX,BYTE PTR DS:[ESI-1] ; *
0043E7F6 28D8 SUB AL,BL ; *
0043E7FE C0C8 05 ROR AL,5 ; *
0043E80C F6D8 NEG AL ; *
0043E816 34 0E XOR AL,0E ; *
0043E822 28C3 SUB BL,AL ; *
0043E82E 66:8B55 00 MOV DX,WORD PTR SS:[EBP] ; *
0043E835 83C5 02 ADD EBP,2 ; *
0043F03F 4E DEC ESI ; *
0043F045 66:891438 MOV WORD PTR DS:[EDI+EAX],DX ; *
功能:
把EBPSTACK棧頂1個(gè)word的數(shù)據(jù)存儲(chǔ)到EDISTACK

0043D374命名:
VM_MOVb_EDISTACKb_EBPSTACKw
代碼:
0043D377 |. 8A46 FF MOV AL,BYTE PTR DS:[ESI-1] ; *
0043F148 /> \30D8 XOR AL,BL ; *
0043D460 |. FEC0 INC AL ; |*
0043D469 |. C0C8 07 ROR AL,7 ; |*
0043D473 |. FEC0 INC AL ; |*
0043D215 |. 30C3 XOR BL,AL ; *
0043EA9C |. 4E DEC ESI ; *
0043EAA0 |. 66:8B55 00 MOV DX,WORD PTR SS:[EBP] ; *
0043EAAC |. 83C5 02 ADD EBP,2 ; *
0043DBDA /> /881438 MOV BYTE PTR DS:[EDI+EAX],DL ; *
把EBPSTACK棧頂1個(gè)word的數(shù)據(jù)按照byte的方式存儲(chǔ)到EDISTACK

0043D21C命名:
VM_PUSHw_IMMEDIATEw
代碼:
0043D21F 66:8B46 FE MOV AX,WORD PTR DS:[ESI-2] ; *
0043D22D 86E0 XCHG AL,AH ; *
0043E01A 66:29D8 SUB AX,BX ; *
0043E022 66:05 71F2 ADD AX,0F271 ; *
0043E036 66:F7D8 NEG AX ; *
0043E03D 66:35 A61C XOR AX,1CA6 ; *
0043E054 66:29C3 SUB BX,AX ; *
0043E054 66:29C3 SUB BX,AX ; *
0043E976 8D76 FE LEA ESI,[ESI-2] ; *
0043D094 /66:8945 00 MOV WORD PTR SS:[EBP],AX ; *
功能:
從ESI數(shù)據(jù)中取得1個(gè)word的立即數(shù)壓入EBPSTACK

0043E83F命名:
VM_PUSHdw_IMMEDIATEdw
代碼:
0043E845 . 8B46 FC MOV EAX,DWORD PTR DS:[ESI-4] ; *
0043E84D . 0FC8 BSWAP EAX ; *
0043E852 . 01D8 ADD EAX,EBX ; *
0043E857 . C1C8 04 ROR EAX,4 ; *
0043D952 . 8D76 FC LEA ESI,[ESI-4] ; *
0043D956 . 2D E131FF38 SUB EAX,38FF31E1 ; *
0043D967 . C1C0 0A ROL EAX,0A ; |*
0043D96C . 01C3 ADD EBX,EAX ; |*
0043D970 . 83ED 04 SUB EBP,4 ; |*
0043D710 |$ 8945 00 MOV DWORD PTR SS:[EBP],EAX ; *
功能:
從ESI數(shù)據(jù)中獲得1個(gè)dword的立即數(shù),壓入EBPSTACK

0043DB11命名:
VM_PUSHdw_IMMEDIATEw
代碼:
0043DB1E 66:8B46 FE MOV AX,WORD PTR DS:[ESI-2] ; *
0043D171 /86E0 XCHG AL,AH ; *
0043E948 66:29D8 SUB AX,BX ; *
0043E951 66:05 71F2 ADD AX,0F271 ; *
0043E95C 66:F7D8 NEG AX ; *
0043E969 8D76 FE LEA ESI,[ESI-2] ; *
0043D62C 66:35 A61C XOR AX,1CA6 ; *
0043D640 \66:29C3 SUB BX,AX ; *
0043D648 98 CWDE ; *
0043D190 83ED 04 SUB EBP,4 ; *
0043D933 8945 00 MOV DWORD PTR SS:[EBP],EAX ; *
功能:
從ESI數(shù)據(jù)中獲得1個(gè)word的立即數(shù),按照dword的方式壓入EBPSTACK

0043D978命名:
VM_PUSHw_IMMEDIATEb
代碼:
0043D979 . 0FB646 FF MOVZX EAX,BYTE PTR DS:[ESI-1] ; *
0043D97E . 30D8 XOR AL,BL ; *
0043D1ED . FEC8 DEC AL ; *
0043D1F0 . F6D8 NEG AL ; *
0043D1F7 . F6D0 NOT AL ; *
0043D1FD . 30C3 XOR BL,AL ; *
0043CEE8 > /83ED 02 SUB EBP,2 ; *
0043DD79 |. 66:8945 00 MOV WORD PTR SS:[EBP],AX ; |*
0043DD62 /$ 4E DEC ESI ; *
功能:
從ESI數(shù)據(jù)中獲得1個(gè)byte的立即數(shù),按照word的方式壓入EBPSTACK

0043D3A5命名:
VM_PUSHdw_IMMEDIATEb
代碼:
0043D3A7 0FB646 FF MOVZX EAX,BYTE PTR DS:[ESI-1] ; *
0043D3AC 30D8 XOR AL,BL ; *
0043D848 FEC8 DEC AL ; *
0043D855 F6D8 NEG AL ; *
0043D866 F6D0 NOT AL ; *
0043D86D 30C3 XOR BL,AL ; *
0043ED8C 66:98 CBW ; *
0043CF7B 98 CWDE ; *
0043EC00 8D76 FF LEA ESI,[ESI-1] ; *
0043DB94 83ED 04 SUB EBP,4 ; *
0043DB9F 8945 00 MOV DWORD PTR SS:[EBP],EAX ; *
功能:
從ESI數(shù)據(jù)中獲得1個(gè)byte的立即數(shù),按照dword的方式壓入EBPSTACK

0043CF24命名:
VM_ADDdw_EBPSTACK
代碼:
0043CF2F |. 8B45 00 MOV EAX,DWORD PTR SS:[EBP] ; *
0043EED3 |. 0145 04 ADD DWORD PTR SS:[EBP+4],EAX ; *
0043CE4F |. 9C PUSHFD ; *
0043CE50 |. 8F4424 3C POP DWORD PTR SS:[ESP+3C] ; *
0043D1BF /> \FF7424 3C PUSH DWORD PTR SS:[ESP+3C] ; *
0043D1C3 |. 8F45 00 POP DWORD PTR SS:[EBP] ; *
功能:
把EBPSTACK棧頂?shù)?個(gè)dword數(shù)據(jù)相加,結(jié)果存儲(chǔ)在[EBP+4],EFLAGS標(biāo)志存儲(chǔ)在棧頂。
例:
0013F97C 8021D2F0 !
0013F980 00000000 ....
VM_ADDdw_EBPSTACK
0013F97C 00000286 ..
0013F980 8021D2F0 !

0043D43B命名:
VM_PUSHdw_MEMORYdw
代碼:
0043D43F 8B45 00 MOV EAX,DWORD PTR SS:[EBP] ; *
0043D10A 8B00 MOV EAX,DWORD PTR DS:[EAX] ; *
0043D447 8945 00 MOV DWORD PTR SS:[EBP],EAX ; *
功能:
把EBPSTACK棧頂數(shù)據(jù)作為內(nèi)存地址,從中讀取1個(gè)dword的數(shù)據(jù)壓入EBPSTACK

0043E9CA命名:
VM_PUSHw_MEMORYw
代碼:
0043E9D0 8B45 00 MOV EAX,DWORD PTR SS:[EBP] ; *
0043E9D9 83C5 02 ADD EBP,2 ; *
0043DEBB 66:36:8B00 MOV AX,WORD PTR SS:[EAX] ; *
0043DDC4 66:8945 00 MOV WORD PTR SS:[EBP],AX ; *
功能:
把EBPSTACK棧頂數(shù)據(jù)作為內(nèi)存地址,從中讀取1個(gè)word的數(shù)據(jù)壓入EBPSTACK

0043D8BD命名:
VM_PUSHw_MEMORYb
代碼:
0043D57B |. 8B55 00 MOV EDX,DWORD PTR SS:[EBP]
0043D589 |. 83C5 02 ADD EBP,2 ; *
0043D591 |. 8A02 MOV AL,BYTE PTR DS:[EDX] ; *
0043E70B |. 66:8945 00 MOV WORD PTR SS:[EBP],AX ; *
功能:
把EBPSTACK棧頂數(shù)據(jù)作為內(nèi)存地址,從中讀取1個(gè)byte的數(shù)據(jù),按照word的方式壓入EBPSTACK

0043DC56命名:
VM_PUSHw_EDISTACKw
代碼:
0043DC5C 8A46 FF MOV AL,BYTE PTR DS:[ESI-1] ; *
0043DC66 28D8 SUB AL,BL ; *
0043DC6D C0C8 05 ROR AL,5 ; *
0043EADA 4E DEC ESI ; *
0043EE2E \F6D8 NEG AL ; *
0043EE34 34 0E XOR AL,0E ; *
0043E740 28C3 SUB BL,AL ; *
0043E746 66:8B0438 MOV AX,WORD PTR DS:[EDI+EAX] ; *
0043D9E4 83ED 02 SUB EBP,2 ; *
0043EE44 66:8945 00 MOV WORD PTR SS:[EBP],AX ; *
功能:
從EDISTACK中讀取1個(gè)word數(shù)據(jù)壓入EBPSTACK

0043CF81命名:
VM_PUSHw_EDISTACKb
代碼:
0043CF84 8A46 FF MOV AL,BYTE PTR DS:[ESI-1] ; *
0043CF8E 30D8 XOR AL,BL ; *
0043EE0A \FEC0 INC AL ; *
0043EE11 C0C8 07 ROR AL,7 ; *
0043EE1E FEC0 INC AL ; *
0043D59C 30C3 XOR BL,AL ; *
0043D2CE 4E DEC ESI ; *
0043D2D7 8A0438 MOV AL,BYTE PTR DS:[EDI+EAX] ; *
0043D2E6 83ED 02 SUB EBP,2 ; *
0043D075 66:8945 00 MOV WORD PTR SS:[EBP],AX ; *
功能:
從EDISTACK中讀取1個(gè)byte數(shù)據(jù),按照word方式壓入EBPSTACK

0043D72E命名:
VM_PUSHdw_EBP
代碼:
0043D72F /. 89E8 MOV EAX,EBP ; *
0043E613 /$ 83ED 04 SUB EBP,4 ; *
0043E61C |. 8945 00 MOV DWORD PTR SS:[EBP],EAX ; *
功能:
復(fù)制EBP指針到EBPSTACK棧頂
例:
EBP 0013F9AC
0013F9AC 00000000 ....
VM_PUSHdw_EBP
0013F9A8 0013F9AC .
0013F9AC 00000000 ....

0043EABE命名:
VM_COPYdw_EBPSTACK
代碼:
0043EACC 8B45 00 MOV EAX,DWORD PTR SS:[EBP] ; *
0043DE1B 36:8B00 MOV EAX,DWORD PTR SS:[EAX] ; *
0043DE25 8945 00 MOV DWORD PTR SS:[EBP],EAX ; *
功能:
把EBPSTACK棧頂數(shù)據(jù)作為堆棧地址,從中讀取一個(gè)dword的數(shù)據(jù)壓入EBPSTACK
例:
0013F998 F99E
0013F99C 02460013 .F
0013F9A0 0000 ...
VM_COPYdw_EBPSTACK
0013F998 0246
0013F99C 02460000 ..F
0013F9A0 0000 ...

0043E790命名:
VM_COPYw_EBPSTACK
代碼:
0043E79C |. 8B55 00 MOV EDX,DWORD PTR SS:[EBP] ; *
0043E7A7 |. 83C5 02 ADD EBP,2 ; *
0043E7AE |. 36:8A02 MOV AL,BYTE PTR SS:[EDX] ; *
0043D01B |. 66:8945 00 MOV WORD PTR SS:[EBP],AX ; *
功能:
把EBPSTACK棧頂數(shù)據(jù)作為堆棧地址,從中讀取一個(gè)byte的數(shù)據(jù),按照word的方式壓入EBPSTACK
例:
0013F9A8 0013F9AC .
0013F9AC 0000 ....
VM_COPYw_EBPSTACK
0013F9A8 0000
0013F9AC 0000 ....

0043D198命名:
VM_NANDdw
代碼:
0043D1A3 8B45 00 MOV EAX,DWORD PTR SS:[EBP] ; *
0043D1AD 8B55 04 MOV EDX,DWORD PTR SS:[EBP+4] ; *
0043DEAE F7D0 NOT EAX ; *
0043DDE1 /F7D2 NOT EDX ; *
0043CDC2 21D0 AND EAX,EDX ; *
0043E0F8 8945 04 MOV DWORD PTR SS:[EBP+4],EAX ; *
0043D0FB /9C PUSHFD ; *
0043D0FC 8F4424 2C POP DWORD PTR SS:[ESP+2C] ; *
0043EC46 FF7424 34 PUSH DWORD PTR SS:[ESP+34] ; *
0043EC4A 8F45 00 POP DWORD PTR SS:[EBP] ; *
功能:
dword版的與非門(mén),從EBPSTACK的棧頂讀取2個(gè)dword作為操作數(shù),結(jié)果存儲(chǔ)在第二個(gè)操作數(shù)位置,EFLAGS標(biāo)志存儲(chǔ)在棧頂。
例:
0013F9A8 00000286 ..
0013F9AC 00000286 ..
VM_NANDdw
0013F9A8 00000282 ..
0013F9AC FFFFFD79 y

0043EB92命名:
VM_NANDw
代碼:
0043EB94 |. 66:8B45 00 MOV AX,WORD PTR SS:[EBP] ; *
0043EBA5 |. 66:8B55 02 MOV DX,WORD PTR SS:[EBP+2] ; *
0043EBB3 |. F6D0 NOT AL ; *
0043EBBB |. F6D2 NOT DL ; *
0043EBC1 |. 83ED 02 SUB EBP,2 ; *
0043EBC5 |. 20D0 AND AL,DL ; *
0043EBCD |. 66:8945 04 MOV WORD PTR SS:[EBP+4],AX ; *
0043EBD5 |. 9C PUSHFD ; *
0043D26F |$ FF7424 28 PUSH DWORD PTR SS:[ESP+28] ; *
0043D273 |. 8F45 00 POP DWORD PTR SS:[EBP] ; *
功能:
word版的與非門(mén),從EBPSTACK的棧頂讀取2個(gè)word作為操作數(shù),結(jié)果存儲(chǔ)在第二個(gè)操作數(shù)位置,EFLAGS標(biāo)志存儲(chǔ)在棧頂。
例:
EBP 0013F9AA
0013F9A8 0000
0013F9AC 0000 ....
VM_NANDw
0013F9A8 00000286 ..
0013F9AC 00FF ...

0043EB11命名:
VM_ADDw_EBPSTACK
代碼:
0043EB14 |. 8A45 00 MOV AL,BYTE PTR SS:[EBP] ; *
0043EB1C |. 83ED 02 SUB EBP,2 ; *
0043EB21 |. 0045 04 ADD BYTE PTR SS:[EBP+4],AL ; *
0043EB26 |. 9C PUSHFD ; *
0043EB27 |. 8F4424 20 POP DWORD PTR SS:[ESP+20] ; *
0043E8F9 |> /FF7424 40 PUSH DWORD PTR SS:[ESP+40] ; *
0043E8FD |. |8F45 00 POP DWORD PTR SS:[EBP] ; *
功能:
把EBPSTACK棧頂?shù)?個(gè)word數(shù)據(jù)中的低byte相加,結(jié)果存儲(chǔ)在第二個(gè)操作數(shù)位置,EFLAGS標(biāo)志存儲(chǔ)在棧頂。
例:
0013F9AC 000000FF ...
VM_ADDw_EBPSTACK
0013F9A8 0286
0013F9AC 00FF0000 ...

0043DFBE命名:
VM_PUSHdw_EDISTACKdw
代碼:
0043DFC1 F6D8 NEG AL ; *
0043DFCD C0C8 07 ROR AL,7 ; *
0043DFDA 2C 20 SUB AL,20 ; *
0043DFDD 24 3C AND AL,3C ; *
0043CE6C 8B1438 MOV EDX,DWORD PTR DS:[EDI+EAX] ; *
0043CE71 83ED 04 SUB EBP,4 ; *
0043CE79 8955 00 MOV DWORD PTR SS:[EBP],EDX ; *
功能:
把1個(gè)dword的數(shù)據(jù)從EDISTACK壓入EBPSTACK

0043D7D2命名:
VM_SHRdw_EBPSTACK
代碼:
0043D7DA 8B45 00 MOV EAX,DWORD PTR SS:[EBP] ; *
0043D7E6 8A4D 04 MOV CL,BYTE PTR SS:[EBP+4] ; *
0043D4F8 83ED 02 SUB EBP,2 ; *
0043D504 D3E8 SHR EAX,CL ; *
0043F17D \8945 04 MOV DWORD PTR SS:[EBP+4],EAX ; *
0043EA2E 9C PUSHFD ; *
0043EA30 FF7424 20 PUSH DWORD PTR SS:[ESP+20] ; *
0043EA34 8F45 00 POP DWORD PTR SS:[EBP] ; *
功能:
把EBPSTACK棧頂1個(gè)dword作為操作數(shù),[EBP+4]作為移動(dòng)位數(shù),邏輯右移。結(jié)果dword存儲(chǔ)在第二個(gè)操作數(shù)和第一個(gè)操作數(shù)的高byte,EFLAGS標(biāo)志存儲(chǔ)在棧頂。
例:
0013F99C 0040
0013F9A0 00040000 ...
VM_SHRdw_EBPSTACK
0013F99C 00000202 ..
0013F9A0 00000004 ...

0043E9A5命名:
VM_SHLdw_EBPSTACK
代碼:
0043E9A9 8B45 00 MOV EAX,DWORD PTR SS:[EBP] ; *
0043E9B5 8A4D 04 MOV CL,BYTE PTR SS:[EBP+4] ; *
0043E0B2 >83ED 02 SUB EBP,2 ; *
0043E0BC D3E0 SHL EAX,CL ; *
0043CDEA 8945 04 MOV DWORD PTR SS:[EBP+4],EAX ; *
0043DD1A \9C PUSHFD
0043DD1B 8F4424 28 POP DWORD PTR SS:[ESP+28]
0043DD24 FF7424 2C PUSH DWORD PTR SS:[ESP+2C] ; *
0043DD28 8F45 00 POP DWORD PTR SS:[EBP] ; *
功能:
把EBPSTACK棧頂1個(gè)dword作為操作數(shù),[EBP+4]作為移動(dòng)位數(shù),邏輯左移。結(jié)果dword存儲(chǔ)在第二個(gè)操作數(shù)和第一個(gè)操作數(shù)的高byte,EFLAGS標(biāo)志存儲(chǔ)在棧頂。

0043DE51命名:
VM_SHRDdw_EBPSTACK
代碼:
0043DE5D 8B45 00 MOV EAX,DWORD PTR SS:[EBP] ; *
0043DE69 8B55 04 MOV EDX,DWORD PTR SS:[EBP+4] ; *
0043DE6E 8A4D 08 MOV CL,BYTE PTR SS:[EBP+8] ; *
0043DE73 83C5 02 ADD EBP,2 ; *
0043DE7A 0FADD0 SHRD EAX,EDX,CL ; *
0043D38F 8945 04 MOV DWORD PTR SS:[EBP+4],EAX ; *
0043D66C 9C PUSHFD ; *
0043D66D 8F4424 34 POP DWORD PTR SS:[ESP+34] ; *
0043D67F FF7424 40 PUSH DWORD PTR SS:[ESP+40] ; *
0043D683 8F45 00 POP DWORD PTR SS:[EBP] ; *
功能:
EBPSTACK雙精度右移指令,執(zhí)行完畢后,結(jié)果和EFLAGS存儲(chǔ)到EBPSTACK

0043D524命名:
VM_SHLDdw_EBPSTACK
代碼:
0043D529 8B45 00 MOV EAX,DWORD PTR SS:[EBP] ; *
0043D537 8B55 04 MOV EDX,DWORD PTR SS:[EBP+4] ; *
0043D545 8A4D 08 MOV CL,BYTE PTR SS:[EBP+8] ; *
0043D550 83C5 02 ADD EBP,2 ; *
0043D558 0FA5D0 SHLD EAX,EDX,CL ; *
0043D637 8945 04 MOV DWORD PTR SS:[EBP+4],EAX ; *
0043CED3 9C PUSHFD
0043D8F4 \FF7424 34 PUSH DWORD PTR SS:[ESP+34] ; *
0043D8F8 8F45 00 POP DWORD PTR SS:[EBP] ; *
功能:
EBPSTACK雙精度左移指令,執(zhí)行完畢后,結(jié)果和EFLAGS存儲(chǔ)到EBPSTACK

0043D089命名:
VM_JMP
代碼:
0043D722 8B75 00 MOV ESI,DWORD PTR SS:[EBP] ; *
0043EF1F \83C5 04 ADD EBP,4 ; *
0043E6A9 89F3 MOV EBX,ESI ; *
0043E6B8 0375 00 ADD ESI,DWORD PTR SS:[EBP] ; *
功能:
把EBPSTACK棧頂?shù)刂芬苿?dòng)到ESI,重新初始化EBX和ESI。

0043EF77命名:
VM_EBPSTACK_CALL
代碼:
0043EF7B 0FB646 FF MOVZX EAX,BYTE PTR DS:[ESI-1] ; *
0043EF82 30D8 XOR AL,BL ; *
0043EF8D FEC8 DEC AL ; *
0043EF99 F6D8 NEG AL ; *
0043EFAF 8D76 FF LEA ESI,[ESI-1] ; *
0043EFB3 F6D0 NOT AL ; *
0043EFC4 30C3 XOR BL,AL ; *
0043EFCD 0FB6C8 MOVZX ECX,AL ; *
0043EFDC 894D FC MOV DWORD PTR SS:[EBP-4],ECX ; *

0043ECEA 31C0 XOR EAX,EAX ; *
0043E0C6 87448D 00 XCHG DWORD PTR SS:[ECX*4+EBP],EAX ; * parameter
0043E0CD 894424 24 MOV DWORD PTR SS:[ESP+24],EAX ; *
0043EE89 83E9 01 SUB ECX,1 ; *
0043EE9C ^\0F85 3FFEFFFF JNE 0043ECE1 ; *
0043CF5B 29C0 SUB EAX,EAX ; *
0043CF6A C74424 04 B7EE4 MOV DWORD PTR SS:[ESP+4],0043EEB7 ; *
0043CF60 8745 00 XCHG DWORD PTR SS:[EBP],EAX ; *
0043DDF9 894424 08 MOV DWORD PTR SS:[ESP+8],EAX ; *
0043DDFD FF7424 04 PUSH DWORD PTR SS:[ESP+4] ; *
0043DE0C FF7424 34 PUSH DWORD PTR SS:[ESP+34] ; *
0043DE10 C2 3800 RETN 38 ; VM_APICALL
功能:
VM中最復(fù)雜的偽指令,用于系統(tǒng)API調(diào)用和程序過(guò)程調(diào)用。ESI數(shù)據(jù)中取得參數(shù)的個(gè)數(shù),EAX循環(huán)取得參數(shù),壓入ESP指針指向的常規(guī)堆棧。大量使用[ESP+X]的方式調(diào)用,摻雜著廢壓棧操作,靜態(tài)看代碼難以看出。返回地址是常量壓入的0043EEB7。這條偽指令涉及內(nèi)容眾多,分支龐大,系統(tǒng)API調(diào)用和程序過(guò)程調(diào)用的走向都是不同的,在后面章節(jié)詳述。我這里列舉的是一次只有1個(gè)參數(shù)的系統(tǒng)API調(diào)用

0043D891命名:
VM_MOVdw_MEMORYdw_EBPSTACKdw
代碼:
0043D897 8B45 00 MOV EAX,DWORD PTR SS:[EBP] ; *
0043D8A1 8B55 04 MOV EDX,DWORD PTR SS:[EBP+4] ; *
0043D8A6 83C5 08 ADD EBP,8 ; *
0043D8AA 8910 MOV DWORD PTR DS:[EAX],EDX ; *
功能:
EBPSTACK棧頂數(shù)據(jù)作為地址,把棧頂?shù)牡诙䝼(gè)dword存儲(chǔ)到地址內(nèi)

0043EFEE命名:
VM_MOVdw_MEMORYdw_EBPSTACKdw
代碼:
0043EFF3 8B45 00 MOV EAX,DWORD PTR SS:[EBP] ; *
0043F005 8B55 04 MOV EDX,DWORD PTR SS:[EBP+4] ; *
0043F010 83C5 08 ADD EBP,8 ; *
0043D335 36:8910 MOV DWORD PTR SS:[EAX],EDX ; *
功能:
EBPSTACK棧頂數(shù)據(jù)作為地址,把棧頂?shù)牡诙䝼(gè)dword存儲(chǔ)到地址內(nèi)。與上一條偽指令完全相同

0043D157命名:
VM_MOVdw_MEMORYdw_EBPSTACKdw
代碼:
0043D159 8B45 00 MOV EAX,DWORD PTR SS:[EBP] ; *
0043D169 8B55 04 MOV EDX,DWORD PTR SS:[EBP+4] ; *
0043CDF7 83C5 08 ADD EBP,8 ; *
0043CE09 26:8910 MOV DWORD PTR ES:[EAX],EDX ; *
EBPSTACK棧頂數(shù)據(jù)作為地址,把棧頂?shù)牡诙䝼(gè)dword存儲(chǔ)到地址內(nèi)。與上兩條偽指令完全相同

0043E9ED命名:
VM_MOVw_MEMORYw_EBPSTACKw
代碼:
0043E9F7 8B45 00 MOV EAX,DWORD PTR SS:[EBP] ; *
0043E9FD 66:8B55 04 MOV DX,WORD PTR SS:[EBP+4] ; *
0043EA02 83C5 06 ADD EBP,6 ; *
0043EA0D 66:8910 MOV WORD PTR DS:[EAX],DX ; *
功能:
EBPSTACK棧頂數(shù)據(jù)作為地址,把棧頂?shù)牡诙䝼(gè)word存儲(chǔ)到地址內(nèi)

0043D6CC命名:
VM_MOVb_MEMORYb_EBPSTACKb
代碼:
0043D6D3 8B45 00 MOV EAX,DWORD PTR SS:[EBP] ; *
0043D6DB 8A55 04 MOV DL,BYTE PTR SS:[EBP+4] ; *
0043EC6C 83C5 06 ADD EBP,6 ; *
0043D495 36:8810 MOV BYTE PTR SS:[EAX],DL ; *
功能:
EBPSTACK棧頂數(shù)據(jù)作為地址,把棧頂?shù)牡诙䝼(gè)byte存儲(chǔ)到地址內(nèi)

0043CE89命名:
VM_HASH
代碼:
0043CE98 8B55 00 MOV EDX,DWORD PTR SS:[EBP] ; *
0043CEA0 83C5 04 ADD EBP,4 ; *
0043CEA6 31C0 XOR EAX,EAX ; *
0043DCC0 89C1 MOV ECX,EAX ; *
0043E6FA C1E0 07 SHL EAX,7 ; *
0043E701 C1E9 19 SHR ECX,19 ; *
0043D2BD /09C8 OR EAX,ECX ; *
0043D7EF \3202 XOR AL,BYTE PTR DS:[EDX] ; *
0043D7F2 42 INC EDX ; *
0043DD12 FF4D 00 DEC DWORD PTR SS:[EBP] ; *
0043F023 ^\0F85 7FDEFFFF JNE 0043CEA8 ; *
0043D9FA 8945 00 MOV DWORD PTR SS:[EBP],EAX ; *
功能:
計(jì)算一段數(shù)據(jù)的HASH值,EBPSTACK棧頂?shù)谝粋(gè)dword是數(shù)據(jù)地址,第二個(gè)dword是數(shù)據(jù)大小

0043DE13命名:
VM_MOVdw_EBPreg_EBPSTACK
代碼:
0043F134 \8B6D 00 MOV EBP,DWORD PTR SS:[EBP] ; *
功能:
給EBP寄存器賦值EBPSTACK棧頂數(shù)據(jù)

0043DD54命名:
VM_FS:[EBPSTACK]
代碼:
0043DD5A 8B45 00 MOV EAX,DWORD PTR SS:[EBP] ; *
0043F10E 64:8B00 MOV EAX,DWORD PTR FS:[EAX] ; *
0043F112 8945 00 MOV DWORD PTR SS:[EBP],EAX ; *
功能:
讀取FS[X]數(shù)據(jù),X=EBPSTACK棧頂數(shù)據(jù)

0043D8C8命名:
VM_SEH
代碼:
0043D8CF 8B45 00 MOV EAX,DWORD PTR SS:[EBP] ; *
0043D8DE 8B55 04 MOV EDX,DWORD PTR SS:[EBP+4] ; *
0043D8E7 83C5 08 ADD EBP,8 ; *
0043D243 64:8910 MOV DWORD PTR FS:[EAX],EDX ; *
功能:
給FS[X]傳遞Y數(shù)據(jù),X=EBPSTACK棧頂數(shù)據(jù),Y=EBPSTACK棧頂?shù)?個(gè)數(shù)據(jù)。在實(shí)踐中都是用于給FS[0]賦值,構(gòu)建SEH

0043DA69命名:
VM_EXIT
代碼:
0043DA6F 89EC MOV ESP,EBP ; *
0043DA73 58 POP EAX ; *
0043DA7E 59 POP ECX ; *
0043DA87 9D POPFD ; *
0043DA8D 5D POP EBP ; *
0043CDB1 /59 POP ECX ; *
0043CDB8 8B5C24 08 MOV EBX,DWORD PTR SS:[ESP+8] ; *
0043F068 8B6C24 14 MOV EBP,DWORD PTR SS:[ESP+14] ; *
0043F06D 8B4424 38 MOV EAX,DWORD PTR SS:[ESP+38] ; *
0043F06D 8B4424 38 MOV EAX,DWORD PTR SS:[ESP+38] ; *
0043DC99 8B7C24 44 MOV EDI,DWORD PTR SS:[ESP+44] ; *
0043DCA7 5E POP ESI ; *
0043DCB6 FF7424 04 PUSH DWORD PTR SS:[ESP+4] ; *
0043DCBA C2 0800 RETN 8 ; *
功能:
給各個(gè)寄存器賦值EBPSTACK中的數(shù)據(jù),EBPSTACK中的最后一個(gè)數(shù)據(jù)是跳轉(zhuǎn)地址

0043EC7D命名:
VM_MOVdw_EFLreg_EBPSTACK
代碼:
0043EC80 FF75 00 PUSH DWORD PTR SS:[EBP] ; *
0043EC83 8F4424 08 POP DWORD PTR SS:[ESP+8] ; *
0043EC8E FF7424 28 PUSH DWORD PTR SS:[ESP+28] ; *
0043EC92 9D POPFD ; *
功能:
給EFLAGE寄存器賦值EBPSTACK棧頂數(shù)據(jù)

在F7跟蹤加殼記事本的過(guò)程中,并不是所有的偽指令都使用到了,以下是沒(méi)有被執(zhí)行到的偽指令:
00405A14 . 70D74300 DD 0043D770
00405A18 . E0EA4300 DD 0043EAE0
00405A48 . 99E14300 DD 0043E199
00405A58 . 00DB4300 DD 0043DB00
00405A5C . 2ED84300 DD 0043D82E
00405A68 . 1FED4300 DD 0043ED1F
00405A6C . F6EC4300 DD 0043ECF6
00405A70 . 70E74300 DD 0043E770
00405A74 . 53D24300 DD 0043D253
00405A78 . C9CD4300 DD 0043CDC9
00405A94 . F5D24300 DD 0043D2F5
00405AA4 . E7D64300 DD 0043D6E7
00405AA8 . ACDB4300 DD 0043DBAC
00405AB8 . 6BE04300 DD 0043E06B
00405ABC . CDE84300 DD 0043E8CD
00405ACC . 3CE14300 DD 0043E13C
由于沒(méi)有實(shí)際的走過(guò)這些偽指令,靜態(tài)分析后覺(jué)得,有個(gè)別偽指令的代碼怕提取錯(cuò)了。把這些指令寫(xiě)成簡(jiǎn)介模式:
0043D770
EBPSTACK的byte邏輯右移指令
0043EAE0
VM_JMP跳轉(zhuǎn)指令,重新給ESI賦值EBPSTACK棧頂數(shù)據(jù)
0043E199
復(fù)制EBPSTACK棧頂1個(gè)word的數(shù)據(jù)
0043DB00
把EBPSTACK棧頂數(shù)據(jù)作為地址,讀取其中1個(gè)word的數(shù)據(jù)壓入EBPSTACK
0043D82E
VM_DIV除法指令
0043ED1F
CPUID指令,結(jié)果壓入EBPSTACK。
0043ECF6
把EBPSTACK數(shù)據(jù)1個(gè)byte移動(dòng)到棧頂內(nèi)存地址內(nèi)
0043E770
給EBP寄存器的低word位賦值棧頂數(shù)據(jù)
0043D253
把SS段寄存器壓入EBPSTACK棧頂
0043CDC9
另一種方式的word版NAND,不過(guò)這個(gè)是在EBPSTACK堆棧內(nèi)完成運(yùn)算過(guò)程
0043D2F5
EBPSTACK的byte邏輯左移指令
0043D6E7
EBPSTACK的word邏輯左移指令
0043DBAC
EBPSTACK的word邏輯右移指令
0043E06B
EBPSTACK的word加法
0043E8CD
把EAX和EDX壓入EBPSTACK
0043E13C
把EBPSTACK數(shù)據(jù)1個(gè)word移動(dòng)到棧頂內(nèi)存地址內(nèi)

到這里,所有的偽指令都羅列完畢,真的是體力活呀!
2.綜合運(yùn)用
2.1.常見(jiàn)偽指令組合
在VMP的偽指令的執(zhí)行中有一些常見(jiàn)的組合套路,熟悉它們能讓我們?cè)诟橵MP時(shí)更加的得心應(yīng)手。這些組合與操作數(shù)的長(zhǎng)度是無(wú)關(guān)的,下面的偽指令將去掉b w dw等標(biāo)記。在例子部分,我將使用dword操作數(shù)來(lái)舉例,直觀明了。
2.1.1.
VM_PUSH_EBP ;復(fù)制EBP指針到EBPSTACK棧頂
VM_COPY_EBPSTACK ;把EBPSTACK棧頂數(shù)據(jù)作為堆棧地址,從中讀取一個(gè)數(shù)據(jù)壓入EBPSTACK
這兩條指令是VMP中結(jié)合的極其緊密的組合,它們幾乎總是一起出現(xiàn)的,用于把EBPSTACK堆棧中的數(shù)據(jù)復(fù)制起來(lái)到EBPSTACK。而很多情況下它們復(fù)制的就是原來(lái)的棧頂數(shù)據(jù)。在使用NAND來(lái)完成NOT(A)的運(yùn)算中,它們是必備的前奏。凡是需要把操作數(shù)一個(gè)變兩個(gè)的地方都有它們的身影。
例:
EBP 0013F9AC
0013F9AC 00000000 ....
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_PUSH_EBP
EBP 0013F9A8
0013F9A8 0013F9AC .
0013F9AC 00000000 ....
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_COPY_EBPSTACK
EBP 0013F9A8
0013F9A8 00000000 ....
0013F9AC 00000000 ....
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
2.1.2.
VM_NAND|VM_ADD_EBPSTACK|VM_SHLD_EBPSTACK|VM_SHR_EBPSTACK等等
VM_MOV_EDISTACK_EBPSTACK ;把1個(gè)數(shù)據(jù)從EBPSTAK棧頂移動(dòng)到EDISTACK,使用EAX作為偏移量
在VMP所有的運(yùn)算偽指令中都是統(tǒng)一的模式,運(yùn)算后的EFLAGS寄存器值位于EBPSTACK棧頂,運(yùn)算結(jié)果位于緊接棧頂?shù)腫EBP+4]。在運(yùn)算結(jié)束后,跟上一條VM_MOV_EDISTACK_EBPSTACK把運(yùn)算后的標(biāo)志位移動(dòng)到EDISTACK,在很多時(shí)候,這都是一條廢指令操作,純粹是為去掉棧頂數(shù)據(jù),以便繼續(xù)操作運(yùn)算結(jié)果。
如果接下來(lái)VM進(jìn)行檢測(cè)標(biāo)志位的相關(guān)操作,這條指令就變得異常重要。例如:在對(duì)系統(tǒng)函數(shù)的CC碼int3斷點(diǎn)檢測(cè)中,取出系統(tǒng)函數(shù)開(kāi)頭的第一個(gè)byte數(shù)據(jù)XX,把它與CC相減,再跟上一個(gè)ZF標(biāo)志位檢測(cè)+跳轉(zhuǎn)。在這個(gè)時(shí)候反過(guò)來(lái),運(yùn)算結(jié)果完全無(wú)用,而我們一定要在移動(dòng)指令的EAX偏移量哪里下好斷點(diǎn),觀察好EFLAGS寄存器值的走向與來(lái)源。
2.1.3.
在進(jìn)行跳轉(zhuǎn)時(shí),圍繞VM_JMP的前后,有大量無(wú)價(jià)值的數(shù)據(jù)移動(dòng)操作。假設(shè)現(xiàn)在我們剛進(jìn)行了一次條件判斷,VM剛剛把要跳轉(zhuǎn)的地址確定并解密出來(lái):
EBP 0013F9A8
0013F9A8 00000202 .. ;最后一次解密運(yùn)算得到的EFLAGS
0013F9AC 0043651A eC. ;跳轉(zhuǎn)地址
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_MOVdw_EDISTACKdw_EBPSTACKdw
VM_MOVdw_EDISTACKdw_EBPSTACKdw
EBP 0013F9B0
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_PUSHdw_EDISTACKdw
VM_PUSHdw_EDISTACKdw
VM_PUSHdw_EDISTACKdw
VM_PUSHdw_EDISTACKdw
VM_PUSHdw_EDISTACKdw
VM_PUSHdw_EDISTACKdw
VM_PUSHdw_EDISTACKdw
VM_PUSHdw_EDISTACKdw
VM_PUSHdw_EDISTACKdw
VM_PUSHdw_EDISTACKdw
VM_PUSHdw_EDISTACKdw
VM_PUSHdw_EDISTACKdw
EBP 0013F980
0013F980 8021D2F0 !
0013F984 0013F9C0 .
0013F988 00000246 F..
0013F98C 00000020 ...
0013F990 000359F4 Y.
0013F994 0013F9CC .
0013F998 00400000 ..@. ; OFFSET NOTEPAD
0013F99C 00000000 ....
0013F9A0 004253CD SB. ; RETURN from NOTEPAD.004255DB to NOTEPAD.004253CD
0013F9A4 000359F4 Y.
0013F9A8 00400000 ..@. ; 該帶著走的數(shù)據(jù)都要在EBPSTACK里面帶著走,到這里還沒(méi)有完畢的。
0013F9AC 0043651A eC. ;還有其他的數(shù)據(jù)要放入,8021D2F0要隱藏一下
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_PUSHdw_IMMEDIATEdw
0013F97C 7FDE2D10 -
0013F980 8021D2F0 !
0013F984 0013F9C0
VM_ADDdw_EBPSTACK
0013F97C 00000247 G..
0013F980 00000000 ....
0013F984 0013F9C0
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F980 00000000 ....
0013F984 0013F9C0
VM_PUSHdw_EDISTACKdw
VM_PUSHdw_EDISTACKdw
0013F978 0043651A eC.
0013F97C 00000000 ....
0013F980 00000000 ....
0013F984 0013F9C0 .
0013F988 00000246 F..
0013F98C 00000020 ...
0013F990 000359F4 Y.
0013F994 0013F9CC .
0013F998 00400000 ..@. ; OFFSET NOTEPAD
0013F99C 00000000 ....
0013F9A0 004253CD SB. ; RETURN from NOTEPAD.004255DB to NOTEPAD.004253CD
0013F9A4 000359F4 Y.
0013F9A8 00400000 ..@. ; OFFSET NOTEPAD.B
0013F9AC 0043651A eC.
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A

VM_JMP ;帶著14個(gè)數(shù)據(jù),VM終于跳轉(zhuǎn),除了棧頂0043651A放入ESI,其他13個(gè)數(shù)據(jù)要重新保存

VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F980 00000000 ....
0013F984 0013F9C0 .
VM_PUSHdw_IMMEDIATEdw
0013F97C 8021D2F0 !
0013F980 00000000 ....
0013F984 0013F9C0 .
VM_ADDdw_EBPSTACK
0013F97C 00000286 ..
0013F980 8021D2F0 !
0013F984 0013F9C0 . ;重新恢復(fù)出來(lái)
VM_MOVdw_EDISTACKdw_EBPSTACKdw
VM_MOVdw_EDISTACKdw_EBPSTACKdw
VM_MOVdw_EDISTACKdw_EBPSTACKdw
VM_MOVdw_EDISTACKdw_EBPSTACKdw
VM_MOVdw_EDISTACKdw_EBPSTACKdw ;到這里停一下,搞個(gè)小運(yùn)算,原EDX=000359F4 XOR 4DFD2FC2
0013F990 000359F4 Y.
0013F994 0013F9CC .
0013F998 00400000 ..@. ; OFFSET NOTEPAD.B
0013F99C 00000000 ....
0013F9A0 004253CD SB. ; RETURN from NOTEPAD.004255DB to NOTEPAD.004253CD
0013F9A4 000359F4 Y.
0013F9A8 00400000 ..@. ; OFFSET NOTEPAD.B
0013F9AC 0043651A eC.
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_PUSHdw_EBP
0013F98C 0013F990 .
0013F990 000359F4 Y.
0013F994 0013F9CC .
VM_COPYdw_EBPSTACK
0013F98C 000359F4 Y.
0013F990 000359F4 Y.
0013F994 0013F9CC .
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F990 000359F4 Y.
0013F994 0013F9CC .
VM_PUSHdw_EBP
0013F98C 0013F990 .
0013F990 000359F4 Y.
0013F994 0013F9CC .
VM_COPYdw_EBPSTACK
0013F98C 000359F4 Y.
0013F990 000359F4 Y.
0013F994 0013F9CC .
VM_NANDdw
0013F98C 00000282 ..
0013F990 FFFCA60B
0013F994 0013F9CC .
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F990 FFFCA60B
0013F994 0013F9CC .
VM_PUSHdw_IMMEDIATEdw
0013F98C B202D03D =
0013F990 FFFCA60B
0013F994 0013F9CC .
VM_NANDdw
0013F98C 00000206 ..
0013F990 000109C0 ..
0013F994 0013F9CC .
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F990 000109C0 ..
0013F994 0013F9CC .
VM_PUSHdw_IMMEDIATEdw
0013F98C 4DFD2FC2 /M
0013F990 000109C0 ..
0013F994 0013F9CC .
VM_PUSHdw_EDISTACKdw
0013F988 000359F4 Y.
0013F98C 4DFD2FC2 /M
0013F990 000109C0 ..
0013F994 0013F9CC .
VM_NANDdw
0013F988 00000286 ..
0013F98C B2008009 ..
0013F990 000109C0 ..
0013F994 0013F9CC .
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F98C B2008009 ..
0013F990 000109C0 ..
0013F994 0013F9CC .
VM_NANDdw
0013F98C 00000206 ..
0013F990 4DFE7636 6vM
0013F994 0013F9CC .
VM_MOVdw_EDISTACKdw_EBPSTACKdw
VM_MOVdw_EDISTACKdw_EBPSTACKdw
VM_MOVdw_EDISTACKdw_EBPSTACKdw
VM_MOVdw_EDISTACKdw_EBPSTACKdw
VM_MOVdw_EDISTACKdw_EBPSTACKdw
VM_MOVdw_EDISTACKdw_EBPSTACKdw
VM_MOVdw_EDISTACKdw_EBPSTACKdw
VM_MOVdw_EDISTACKdw_EBPSTACKdw
VM_MOVdw_EDISTACKdw_EBPSTACKdw
EBP 0013F9B0
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
每一次VM_JMP跳轉(zhuǎn),都要帶著14個(gè)數(shù)據(jù)轉(zhuǎn),而其中呢VM還要搞上一點(diǎn)暗碼轉(zhuǎn)移。以后看到是VM_JMP跳轉(zhuǎn)的狀況,就是看著EBP指針,嘩嘩嘩的讓它執(zhí)行,完畢了才停下來(lái)。中間的操作完全可以無(wú)視,我也是為了完整的表達(dá)才把它粘貼出了代碼,實(shí)際看的時(shí)候,不用管。整個(gè)過(guò)程:要帶著走的數(shù)據(jù)移到EBPSTACK-->VM_JMP跳轉(zhuǎn)-->重新把數(shù)據(jù)保存到EDISTACK。關(guān)于其中000359F4 XOR 4DFD2FC2的過(guò)程,請(qǐng)參考下一節(jié)2.2.NAND。

由于其他的組合都和NAND或標(biāo)志位檢測(cè)+跳轉(zhuǎn)相關(guān),放在下兩節(jié)中。這一節(jié)中的3個(gè)組合熟悉后,已經(jīng)可以無(wú)視掉一部分VM的操作。

2.2.NAND(與非門(mén))
本文的兩節(jié)重頭戲來(lái)了,NAND(與非門(mén))與EFLAGS標(biāo)志位檢測(cè)+跳轉(zhuǎn),理解完了這兩節(jié)后,對(duì)于VM就可以無(wú)視了,一切偽指令在你眼里都是正常的指令。跟蹤VMP就和跟蹤普通程序一樣,想看API獲取就看API獲取,想看看程序的anti方式就看anti方式。一切都回到了正常,你可以看穿VM(虛擬機(jī))這個(gè)嚇人的外衣。
2.2.1.NAND起源
NAND(與非門(mén))和NOR(或非門(mén))來(lái)源于de Morgan's Laws(德·摩根定律),運(yùn)用于邏輯、數(shù)字電路等方面,本節(jié)專(zhuān)注于它與and or xor not 之間的聯(lián)系。
德·摩根定律是屬于邏輯學(xué)的定律。 德·摩根定律(或稱(chēng)德·摩根定理)是形式邏輯中有關(guān)否定所描述的系統(tǒng)方式中的邏輯運(yùn)算符對(duì)偶對(duì)的一系列法則。由此引出的關(guān)系也就被稱(chēng)為“德·摩根二重性”。
奧古斯都·德·摩根首先發(fā)現(xiàn)了在命題邏輯中存在著下面這些關(guān)系:
非(P 且 Q)=(非 P)或(非 Q)
非(P 或 Q)=(非 P)且(非 Q)
德·摩根的發(fā)現(xiàn)影響了喬治·布爾從事的邏輯問(wèn)題代數(shù)解法的研究,這鞏固了德·摩根作為該規(guī)律的發(fā)現(xiàn)者的地位,盡管亞里士多德也曾注意到類(lèi)似現(xiàn)象、且這也為古希臘與中世紀(jì)的邏輯學(xué)家熟知(引自Bocheński《形式邏輯歷史》)。(引自維基百科,關(guān)鍵字:德·摩根定律)
我們?cè)賮?lái)看它在數(shù)學(xué)邏輯中的表示:
1.jpg下載此附件需要消耗2Kx,下載中會(huì)自動(dòng)扣除。
(引自:MathWorld,關(guān)鍵字:de Morgan's Laws)
由于不是用我們熟悉的計(jì)算機(jī)方式來(lái)表達(dá),上面的兩段解說(shuō)比較抽象,請(qǐng)看2.2.2.
2.2.2.NAND與邏輯運(yùn)算
在加殼記事本中使用的是NAND,下面部分將專(zhuān)注于NAND。對(duì)于NOR,理論都是一樣的,只是不用NAND來(lái)實(shí)現(xiàn)。
NAND(A,B):
NOT(A)
NOT(B)
ADN(A,B)
這就是NAND的操作方式。NAND的價(jià)值在于:使用NAND可以實(shí)現(xiàn)NOT AND OR XOR這4個(gè)邏輯運(yùn)算。
NOT(A):
NAND(A,A)
AND(A,B):
NAND(NAND(A,A),NAND(B,B))
OR(A,B):
NAND(NAND(A,B),NAND(A,B))
XOR(A,B):
NAND(NAND(NAND(A,A),NAND(B,B)),NAND(A,B))
2.2.3.VMP偽指令執(zhí)行過(guò)程
NOT(4DBE4AD8):
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_PUSHdw_EBP
0013F9A8 0013F9AC .
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_COPYdw_EBPSTACK
0013F9A8 4DBE4AD8 JM
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_NANDdw
0013F9A8 00000286 ..
0013F9AC B241B527 'A
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;NAND(A,A)
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F9AC B241B527 'A
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
NOT(4DBE4AD8)=B241B527

AND(4DBE4AD8,4DFD2FC2):
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_PUSHdw_EBP
0013F9A8 0013F9AC .
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_COPYdw_EBPSTACK
0013F9A8 4DBE4AD8 JM
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_NANDdw
0013F9A8 00000286 ..
0013F9AC B241B527 'A
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;NAND(NAND(A,A),NAND(B,B))
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F9AC B241B527 'A
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_PUSHdw_IMMEDIATEdw
0013F9A8 B202D03D =
0013F9AC B241B527 'A
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;NAND(NAND(A,A),NAND(B,B))**B202D03D=NAND(B,B)**
VM_NANDdw
0013F9A8 00000206 ..
0013F9AC 4DBC0AC0 .M
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;NAND(NAND(A,A),NAND(B,B))VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F9AC 4DBC0AC0 .M
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VMP的B數(shù)據(jù)是直接傳遞它的相反數(shù)B202D03D給VM,相當(dāng)于隱藏了一次NAND(B,B)的過(guò)程。AND(4DBE4AD8,4DFD2FC2)=4DBC0AC0

OR (00000293,00000100):
0013F780 00000293 ..
0013F784 00000100 ...
VM_NANDdw ;NAND(NAND(A,B),NAND(A,B))
0013F784 FFFFFC6C l
VM_PUSHdw_EBP
VM_COPYdw_EBPSTACK ;復(fù)制結(jié)果,就相當(dāng)于NAND(NAND(A,B),NAND(A,B))
0013F780 FFFFFC6C l
0013F784 FFFFFC6C l
VM_NANDdw ;NAND(NAND(A,B),NAND(A,B))
0013F784 00000393 ..
OR (00000293,00000100)=00000393

XOR(4DBE4AD8,4DFD2FC2):
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_PUSHdw_EBP
0013F9A8 0013F9AC .
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_COPYdw_EBPSTACK
0013F9A8 4DBE4AD8 JM
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_NANDdw
0013F9A8 00000286 ..
0013F9AC B241B527 'A
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;NAND(NAND(NAND(A,A),NAND(B,B)),NAND(A,B))
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F9AC B241B527 'A
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_PUSHdw_IMMEDIATEdw
0013F9A8 B202D03D =
0013F9AC B241B527 'A
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;NAND(NAND(NAND(A,A),NAND(B,B)),NAND(A,B))**B202D03D=NAND(B,B)**
VM_NANDdw
0013F9A8 00000206 ..
0013F9AC 4DBC0AC0 .M
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;NAND(NAND(NAND(A,A),NAND(B,B)),NAND(A,B))
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F9AC 4DBC0AC0 .M
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_PUSHdw_EDISTACKdw
0013F9A8 4DBE4AD8 JM
0013F9AC 4DBC0AC0 .M
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_PUSHdw_IMMEDIATEdw
0013F9A4 4DFD2FC2 /M
0013F9A8 4DBE4AD8 JM
0013F9AC 4DBC0AC0 .M
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_NANDdw
0013F9A4 00000282 ..
0013F9A8 B2009025 %.
0013F9AC 4DBC0AC0 .M
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;NAND(NAND(NAND(A,A),NAND(B,B)),NAND(A,B))
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F9A8 B2009025 %.
0013F9AC 4DBC0AC0 .M
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_NANDdw
0013F9A8 00000202 ..
0013F9AC 0043651A eC.
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;NAND(NAND(NAND(A,A),NAND(B,B)),NAND(A,B))
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F9AC 0043651A eC.
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
上面這條XOR指令,就是VM在確定跳轉(zhuǎn)地址后的解密指令。加密地址是A數(shù)據(jù)4DBE4AD8,XOR運(yùn)算后得到ESI跳轉(zhuǎn)地址0043651A。

在VMP中,減法是采用迂回的方式實(shí)現(xiàn)的:
A-B:
NOT(A)
A=A+B
NOT(A)
而NOT運(yùn)算又要使用NAND來(lái)完成
A-B:
NAND(A,A)
A=A+B
NAND(A,A)

2.3.EFLAGS標(biāo)志位檢測(cè)+跳轉(zhuǎn)
這一節(jié)看完后,就可以暢通無(wú)阻的瀏覽VMP的偽指令了。
2.3.1.判斷兩個(gè)數(shù)是否相同
舉例數(shù)據(jù):
把立即數(shù)0000和內(nèi)存00427D51中的1個(gè)word數(shù)據(jù)比較,檢測(cè)是否為0。
整個(gè)過(guò)程分為兩個(gè)階段:
第一階段:執(zhí)行減法運(yùn)算
A-B:
NAND(A,A) ;這里的標(biāo)志位是無(wú)用的
A=A+B ;獲得標(biāo)志位A
NAND(A,A) ;獲得標(biāo)志位B
第二階段:合并兩個(gè)標(biāo)志位
A=AND(A,00000815)
B=AND(B,FFFFF7EA)
A=A+B
第三階段:檢測(cè)ZF位+跳轉(zhuǎn)
構(gòu)建跳轉(zhuǎn)地址結(jié)構(gòu)
檢測(cè)ZF位
獲得加密跳轉(zhuǎn)地址
解密跳轉(zhuǎn)地址
調(diào)用VM_JMP
在開(kāi)始這個(gè)部分前,把所有VM_MOV_EDISTACK_EBPSTACK偽指令中的AND AL,3C指令的下一條指令處下好斷點(diǎn),我們要記錄下各個(gè)標(biāo)志位的走向!000000286-->14(表示EFL存儲(chǔ)到偏移量14的[EDI+EAX]位置)
第一階段:
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_PUSHw_IMMEDIATEb
0013F9AC 0000
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;立即數(shù)IMM0000
VM_PUSHdw_IMMEDIATEdw
0013F9A8 7D51
0013F9AC 00000042 B...
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_PUSHw_MEMORYb
0013F9AC 00000000
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;內(nèi)存數(shù)MEM0000。很明顯,我們看到兩個(gè)數(shù)是相同的
VM_PUSHdw_EBP
0013F9A8 0013F9AC .
0013F9AC 00000000 ....
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_COPYw_EBPSTACK
0013F9A8 0000
0013F9AC 00000000 ....
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;復(fù)制內(nèi)存數(shù)MEM0000
VM_NANDw
0013F9A8 00000286 ..
0013F9AC 000000FF ...
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;NOT(MEM0000)=MEM00FF
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F9AC 000000FF ...
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;000000286-->14(表示EFL存儲(chǔ)到偏移量14的[EDI+EAX]位置)
VM_ADDb_EBPSTACK
0013F9A8 0286
0013F9AC 00FF0000 ...
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;00FF=IMM0000+MEM00FF
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F9AC 00FF
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;標(biāo)志位A 000000286-->04
VM_PUSHdw_EBP
0013F9A8 F9AE
0013F9AC 00FF0013 ..
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_COPYw_EBPSTACK
0013F9AC 00FF00FF ..
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_NANDw
0013F9A8 0246
0013F9AC 00000000 ....
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;NOT(00FF)
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F9AC 0000
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;標(biāo)志位B 00000246-->3C
VM_MOVw_EDISTACKb_EBPSTACKw
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;
第一階段結(jié)束。
兩個(gè)操作數(shù)都是0000,很明顯這次判斷將是兩個(gè)數(shù)相同,減法后的ZF位置1。
運(yùn)算的結(jié)果都是無(wú)用的,關(guān)鍵在于它的標(biāo)志位,繼續(xù)看標(biāo)志位ZF的檢測(cè)+跳轉(zhuǎn)
第二階段:
VM_PUSHdw_EDISTACKdw
0013F9AC 00000286 ..
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;標(biāo)志位A 000000286<--04
VM_PUSHdw_EDISTACKdw
0013F9A8 00000286 ..
0013F9AC 00000286 ..
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;再來(lái)一次標(biāo)志位A
VM_NANDdw
0013F9A8 00000282 ..
0013F9AC FFFFFD79 y
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;NAND(A,A)=NOT(A)=FFFFFD79
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F9AC FFFFFD79 y
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_PUSHdw_IMMEDIATEw
0013F9A8 FFFFF7EA
0013F9AC FFFFFD79 y
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;NAND(X,X)=NOT(00000815)=FFFFF7EA 傳遞相反數(shù),隱藏NOT(00000815)
VM_NANDdw
0013F9A8 00000202 ..
0013F9AC 00000004 ...
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;NAND(NAND(A,A),NAND(X,X))=標(biāo)志位A 00000286 AND 00000815
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F9AC 00000004 ...
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_PUSHdw_EDISTACKdw
0013F9A8 00000246 F..
0013F9AC 00000004 ...
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;標(biāo)志位B 00000246<--3C
VM_PUSHdw_EDISTACKdw
0013F9A4 00000246 F..
0013F9A8 00000246 F..
0013F9AC 00000004 ...
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;再來(lái)一次標(biāo)志位B
VM_NANDdw
0013F9A4 00000282 ..
0013F9A8 FFFFFDB9
0013F9AC 00000004 ...
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;NAND(B,B)=NOT(B)=FFFFFDB9
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F9A8 FFFFFDB9
0013F9AC 00000004 ...
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_PUSHdw_IMMEDIATEw
0013F9A4 00000815 ..
0013F9A8 FFFFFDB9
0013F9AC 00000004 ...
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;NAND(Y,Y)=NOT(FFFFF7EA)=00000815 傳遞相反數(shù),隱藏NOT(FFFFF7EA)
VM_NANDdw
0013F9A4 00000206 ..
0013F9A8 00000242 B..
0013F9AC 00000004 ...
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;NAND(NAND(B,B),NAND(Y,Y))=標(biāo)志位B 00000246 AND FFFFF7EA
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F9A8 00000242 B..
0013F9AC 00000004 ...
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_ADDdw_EBPSTACK
0013F9A8 00000202 ..
0013F9AC 00000246 F..
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;兩個(gè)AND后的標(biāo)志位相加
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F9AC 00000246 F..
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;00000246-->00 暫存結(jié)果
第二階段結(jié)束
現(xiàn)在VMP已經(jīng)把兩個(gè)標(biāo)志位合并成了一個(gè),關(guān)于標(biāo)志位合并的解析結(jié)束后再來(lái)看。繼續(xù)看第三階段:檢測(cè)ZF+跳轉(zhuǎn),注意看好堆棧數(shù)據(jù)的構(gòu)造,堆棧虛擬機(jī)的跳轉(zhuǎn)判斷有他獨(dú)特的地方!同時(shí)它巧妙的運(yùn)用了ZF位在EFLAGS中的位置。
第三階段:
VM_PUSHdw_IMMEDIATEdw
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;跳轉(zhuǎn)地址1
VM_PUSHdw_IMMEDIATEdw
0013F9A8 4DBE49D5 IM
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;跳轉(zhuǎn)地址2
VM_PUSHdw_EBP
0013F9A4 0013F9A8 .
0013F9A8 4DBE49D5 IM
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;跳轉(zhuǎn)地址指針
VM_PUSHw_IMMEDIATEb
0013F9A0 0004
0013F9A4 0013F9A8 .
0013F9A8 4DBE49D5 IM
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;傳遞4,看好堆棧的構(gòu)造,下面的幾個(gè)操作是獨(dú)立的
VM_PUSHdw_EDISTACKdw
0013F99C 0246
0013F9A0 00040000 ...
0013F9A4 0013F9A8 .
0013F9A8 4DBE49D5 IM
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;第二階段結(jié)果00000246<--00
VM_PUSHdw_EBP
0013F998 F99E
0013F99C 02460013 .F
0013F9A0 00040000 ...
0013F9A4 0013F9A8 .
0013F9A8 4DBE49D5 IM
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_COPYdw_EBPSTACK
0013F998 0246
0013F99C 02460000 ..F
0013F9A0 00040000 ...
0013F9A4 0013F9A8 .
0013F9A8 4DBE49D5 IM
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;復(fù)制標(biāo)志位
VM_NANDdw
0013F998 0282
0013F99C FDB90000 ..
0013F9A0 0004FFFF .
0013F9A4 0013F9A8 .
0013F9A8 4DBE49D5 IM
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;NAND(A,A)=NOT(A)=NOT(00000246)=FFFFFDB9
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F99C FDB9
0013F9A0 0004FFFF .
0013F9A4 0013F9A8 .
0013F9A8 4DBE49D5 IM
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_PUSHdw_IMMEDIATEb
0013F998 FFBF
0013F99C FDB9FFFF
0013F9A0 0004FFFF .
0013F9A4 0013F9A8 .
0013F9A8 4DBE49D5 IM
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;NAND(B,B)=NOT(00000040)=FFFFFFBF 傳遞相反數(shù),隱藏NOT(000000040)
VM_NANDdw
0013F998 0202
0013F99C 00400000 ..@. ; OFFSET NOTEPAD.B
0013F9A0 00040000 ...
0013F9A4 0013F9A8 .
0013F9A8 4DBE49D5 IM
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;NAND(NAND(B,B),NAND(B,B))=標(biāo)志位 00000246 AND 00000040
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F99C 0040
0013F9A0 00040000 ...
0013F9A4 0013F9A8 .
0013F9A8 4DBE49D5 IM
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;AND結(jié)果是00000040,說(shuō)明ZF位是1,兩個(gè)數(shù)相等;想想如果不相等,結(jié)果是00000000
VM_SHRdw_EBPSTACKb
0013F99C 00000202 ..
0013F9A0 00000004 ...
0013F9A4 0013F9A8 .
0013F9A8 4DBE49D5 IM
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;右移4位剛好把00000040移動(dòng)成00000004;如果不相等,右移后是00000000
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F9A0 00000004 ...
0013F9A4 0013F9A8 .
0013F9A8 4DBE49D5 IM
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_ADDdw_EBPSTACK
0013F9A0 00000206 ..
0013F9A4 0013F9AC .
0013F9A8 4DBE49D5 IM
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;00000004+0013F9A8=0013F9AC;如果不相等,00000000+0013F9A8=0013F9A8
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F9A4 0013F9AC .
0013F9A8 4DBE49D5 IM
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;跳轉(zhuǎn)地址指針指向的就是判斷后的跳轉(zhuǎn)地址
VM_COPYdw_EBPSTACK
0013F9A4 4DBE4AD8 JM
0013F9A8 4DBE49D5 IM
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;跳轉(zhuǎn)地址指針指向的跳轉(zhuǎn)地址復(fù)制出來(lái)
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F9A8 4DBE49D5 IM
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;把最終的跳轉(zhuǎn)地址暫存到EDISTACK,4DBE4AD8-->18
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;掃尾工作,釋放EBPSTACK
VM_MOVdw_EDISTACKdw_EBPSTACKdw
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;掃尾工作,釋放EBPSTACK
VM_PUSHdw_EDISTACKdw
0013F9AC 4DBE4AD8 JM
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A ;壓入判斷的跳轉(zhuǎn)地址4DBE4AD8<--18
第三階段結(jié)束
接下來(lái)VM將使用一次XOR運(yùn)算解密4DBE4AD8數(shù)據(jù)(詳見(jiàn)2.2.3.XOR舉例),然后是VM_JMP指令調(diào)用的組合(詳見(jiàn)2.1.3.舉例),全過(guò)程結(jié)束。
兩個(gè)操作數(shù)都是0000,1個(gè)來(lái)自?xún)?nèi)存空間,一個(gè)來(lái)自ESI的編譯數(shù)據(jù),同時(shí)這段代碼是在VM剛剛啟動(dòng)就進(jìn)行的了,都是定量。但是VM還要進(jìn)行檢測(cè),說(shuō)明兩個(gè)數(shù)據(jù)是不確定的,VM在運(yùn)行過(guò)程中要知道它是不是0,可以把它猜測(cè)為VMP內(nèi)部的一個(gè)信號(hào)。VM一開(kāi)始就要知道到底應(yīng)該走向哪個(gè)分支。到后面我們會(huì)進(jìn)行測(cè)試,如果這個(gè)信號(hào)比較結(jié)果不為0,VM的走向是怎樣的。
下面我們來(lái)詳解上面的操作過(guò)程,從第二階段合并標(biāo)志位來(lái)看
第一階段:執(zhí)行減法運(yùn)算
IMM0000-MEM0000:
NAND(IMM0000,IMM0000) ;這里的標(biāo)志位是無(wú)用的
00FF=IMM00FF+MEM0000 ;獲得標(biāo)志位A 000000286
NAND(00FF,00FF) ;獲得標(biāo)志位B 000000246
第二階段:合并兩個(gè)標(biāo)志位
00000004=AND(00000286,00000815)
00000242=AND(00000246,FFFFF7EA)
00000246=00000004+00000242
把兩個(gè)標(biāo)志位分別AND后相加,AND操作時(shí)用于保留想要的標(biāo)志位,加法把它合并起來(lái)。
關(guān)于EFLAGS標(biāo)志位,Intel的資料顯示:
3.jpg下載此附件需要消耗2Kx,下載中會(huì)自動(dòng)扣除。
各個(gè)標(biāo)志位的詳細(xì)說(shuō)明,請(qǐng)查閱Intel 64 and IA-32 Architectures Software Developer's Mannual(Intel 64位與IA-32體系結(jié)構(gòu)軟件開(kāi)發(fā)者指南)中卷1的3.4.3 EFLAGS Register
關(guān)于ADD指令,Intel的資料顯示:
ADD—Add
Operation

DEST DEST SRC;

Flags Affected

The OF, SF, ZF, AF, CF, and PF flags are set according to the result.

把00000286 AND 00000815使用二進(jìn)制表示:
0000 0000 0000 0000 0000 0010 1000 0110
AND 0000 0000 0000 0000 0000 1000 0001 0101
我們現(xiàn)在就可以看到,VM要保留的是 OF AF PF CF 位。那么,SF和ZF位為什么不在這里保留呢?我們要想到,由于這里并不是A-B的最后結(jié)果,SF 和 ZF位要等到最后的運(yùn)算完成才能知道。在標(biāo)志位A中,PF位為1,PF位被保留。
第一個(gè)AND數(shù)00000815與第二個(gè)AND數(shù)FFFFF7EA之間是有內(nèi)在聯(lián)系的。00000815+FFFFF7EA=FFFFFFFF,也就是說(shuō),這兩個(gè)這兩個(gè)AND操作時(shí)可以把所有的標(biāo)志位都保留下來(lái)的,不會(huì)出現(xiàn)遺漏。而把它分開(kāi)的話(huà),是由于變換了減法的運(yùn)算方式不進(jìn)行保留對(duì)應(yīng)的保留。
最后的NAND(A,A):
NOT A ;第一個(gè)操作數(shù)
NOT A ;第二個(gè)操作數(shù)
AND A,A ;最終標(biāo)志位B 00000246是來(lái)自這里
關(guān)于AND邏輯運(yùn)算,Intel的資料顯示:
AND—Logical AND
Operation

DEST DEST AND SRC;

Flags Affected

The OF and CF flags are cleared; the SF, ZF, and PF flags are set according to the
result. The state of the AF flag is undefined.

把00000246 AND FFFFF7EA使用二進(jìn)制表示:
0000 0000 0000 0000 0000 0010 0100 0110
AND 1111 1111 1111 1111 1111 0111 1110 1010
VM要把除了上面00000815保留了的 OF AF PF CF 以外的標(biāo)志位都保留了下來(lái)。在標(biāo)志位B中,IF ZF PF 和第二位是Intel的保留位默認(rèn)為1 這4個(gè)標(biāo)志位為1,所以IF ZF PF被保留。
兩個(gè)標(biāo)志位相加后,最終合并成為兩個(gè)操作數(shù)SUB指令后的標(biāo)志位00000246
下面我們來(lái)看第三階段:
構(gòu)建跳轉(zhuǎn)結(jié)構(gòu):
0013F9A0 0004
0013F9A4 0013F9A8 .
0013F9A8 4DBE49D5 IM
0013F9AC 4DBE4AD8 JM
把兩個(gè)跳轉(zhuǎn)地址4DBE49D5與4DBE4AD8壓入堆棧。0013F9A8成為跳轉(zhuǎn)地址指針,指向第一個(gè)跳轉(zhuǎn)地址。如果0013F9A8指針+4,它就會(huì)指向第二個(gè)指針。最后還有1個(gè)0004,它并不是用于給指針+4的操作數(shù),它要參與到巧妙判斷ZF位的運(yùn)算中。
接下來(lái),VM用NAND執(zhí)行一次AND操作,操作數(shù)是:標(biāo)志位00000246與00000040 (在NAND操作中,VM不意外的隱藏了一次NAND(B,B)操作,直接傳遞00000040的相反數(shù)FFFFFFBF)
0013F998 FFBF
0013F99C FDB9FFFF
0013F9A0 FFFF .
0013F9A0 0004 ;為了清晰變現(xiàn),把它分開(kāi)顯示
0013F9A4 0013F9A8 .
0013F9A8 4DBE49D5 IM
0013F9AC 4DBE4AD8 JM
VM_NANDdw
0013F99C 0040 ;運(yùn)算結(jié)果為00000040
0013F9A0 00040000 ...
0013F9A4 0013F9A8 .
0013F9A8 4DBE49D5 IM
0013F9AC 4DBE4AD8 JM
NAND操作是:
NOT(A)
NOT(B)
AND(A,B)
所以,在這條偽指令的內(nèi)部,00000246 AND 0000040
把00000246 AND 00000040使用二進(jìn)制表示:
0000 0000 0000 0000 0000 0010 0100 0110
AND 0000 0000 0000 0000 0000 0000 0100 0000
唯一的檢測(cè)ZF位,如果ZF位為1,那么結(jié)果將是00000040,否則是00000000。由于ZF位剛好是在byte的4的位置,把它和前面的跳轉(zhuǎn)地址指針相加,0013F9A8+0則是不變,指向第一個(gè)地址,+4就指向第二個(gè)地址,所以剛好可以讓AND后的結(jié)果與指針0013F9A8進(jìn)行1次加法運(yùn)算,如果ZF位是1,0013F9A8+4將指向4DBE4AD8完成判斷跳轉(zhuǎn)。由于ZF位的前面還有1個(gè)byte的數(shù)據(jù)0,就是00000040中最后的1個(gè)byte0,如果直接和0013F9A8相加,就變成+40,所以要先進(jìn)行1次4個(gè)bit的右移,00000040變?yōu)?0000004,這樣才正確。

ZF位為1,AND 00000040后: ZF位為0,AND 00000040后:
00000040 00000000
SHR(4) 00000004 SHR(4) 00000000
ADD 0013F9A8 ADD 0012F9A8
結(jié)果 0013F9AC 結(jié)果 0013F9A8
0013F9A4 0013F9AC . 0013F9A4 0013F9A8 .
0013F9A8 4DBE49D5 IM 0013F9A8 4DBE49D5 IM
0013F9AC 4DBE4AD8 JM 0013F9AC 4DBE4AD8 JM
ZF位的不同帶來(lái)跳轉(zhuǎn)地址的不同,把相應(yīng)的跳轉(zhuǎn)地址解密后,使用VM_JMP給VM的指令指針ESI賦值,全程結(jié)束。
進(jìn)行ZF位比較的話(huà),只需要比較最后的標(biāo)志位B就可以了,而且可以進(jìn)行直接的比較,不需要這樣截取+拼接,那么為什么VMP還需要在整個(gè)過(guò)程中截取了所有的標(biāo)志位呢?我想,可以這么來(lái)考慮,在VMP中標(biāo)志位的截取+拼接在代碼中是屬于一個(gè)模塊,不管VMP要檢測(cè)哪個(gè)標(biāo)志位,它都是先調(diào)用這個(gè)模塊然后再進(jìn)行標(biāo)志位檢測(cè)。雖然在單純的ZF位檢測(cè)中,有了很多的不必要的操作,但是它增加了通用性,只要調(diào)用了這個(gè)模塊,VMP在后面可以接上任意標(biāo)志位的檢測(cè)。



3.NOTEPAD全程跟蹤
在這一章里,我們將全過(guò)程瀏覽NOTEPAD.EXE文件。本章顯示的代碼,外殼的花指令將全部跳過(guò),VM的偽指令則部份跳過(guò)。
3.1.TLS
3.1.1.到達(dá)Dispatch部份
VMProtect2.04加殼程序是從TLS開(kāi)始運(yùn)行的,我們首先點(diǎn)擊OD的options菜單,修改Startup and exit選項(xiàng),讓OD中斷在TLS callback里。載入NOTOPAD.EXE后,程序停在這里:
004253CD $ 68 9AA597B7 PUSH B797A59A ; TLS callback function
當(dāng)前的寄存器值:
EAX 004253CD NOTEPAD.004253CD
ECX 00000020
EDX 000359F4
EBX 00000000
ESP 0013F9B0
EBP 0013F9CC
ESI 0013F9C0
EDI 00400000 NOTEPAD.
進(jìn)入VM之前,VMP要保存當(dāng)前的各個(gè)寄存器值,VM堆棧要分配,同時(shí)給偽指令指針寄存器ESI賦值等等,初始化結(jié)束后,進(jìn)入Dispatch部份VM開(kāi)始運(yùn)行。F7單步下去:
0043BD02 . C74424 40 0A4 MOV DWORD PTR SS:[ESP+40],2EF6420A ; |*
00429088 |> \C74424 44 19C MOV DWORD PTR SS:[ARG.17],C456C619 ; *
;壓入VM的兩個(gè)定量。
0043DCD2 |. 893424 MOV DWORD PTR SS:[ESP],ESI ; *
0043CF0D . 57 PUSH EDI ; *
0043CF17 . 891424 MOV DWORD PTR SS:[ESP],EDX ; *
0043CF1D . 50 PUSH EAX ; *
0043E17A |. 896C24 04 MOV DWORD PTR SS:[ARG.1],EBP ; *
0043D741 |> /871C24 XCHG DWORD PTR SS:[ESP],EBX ; *
0043D746 |. 894C24 20 MOV DWORD PTR SS:[ESP+20],ECX ; *
;7個(gè)寄存器保存完畢
0043D750 |. 875424 40 XCHG DWORD PTR SS:[ESP+40],EDX ; |Arg17, *
0043E62E /$ 9C PUSHFD ; *
0043E62F |. 8F4424 40 POP DWORD PTR SS:[ESP+40] ; *
0043E636 |. FF35 89D24300 PUSH DWORD PTR DS:[43D289] ; *
0043E63C |. 8F4424 3C POP DWORD PTR SS:[ESP+3C] ; *
0043E646 |. C74424 38 000 MOV DWORD PTR SS:[ESP+38],0 ; *
;多保存1個(gè)寄存器,由于ESP是動(dòng)態(tài)的,這個(gè)位置相當(dāng)于是ESP寄存器的位置;EFLAGS;內(nèi)存地址[43D289];常量0;一共保存13個(gè)數(shù)據(jù)
0013F97C 00000000 .... ;常量0 20
0013F980 00000000 .... ;[43D289] 24 8121D2F0相加
0013F984 00000246 F.. ;EFLAGS 0C
0013F988 000359F4 Y. ;EDX(給ESP寄存器的位置) 00
0013F98C 00000020 ... ;ECX 08
0013F990 00000000 .... ;EBX 1C
0013F994 0013F9CC . ;EBP 28
0013F998 004253CD SB. ;EAX 10
0013F99C 000359F4 Y. ;EDX 2C
0013F9A0 00400000 ..@. ;EDI 30
0013F9A4 0013F9C0 . ;ESI 38
0013F9A8 C456C619 V ;常量B 3C
0013F9AC 2EF6420A .B. ;常量A 18
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
0043E65B |. 8B7424 68 MOV ESI,DWORD PTR SS:[ESP+68] ; *
;這里讀取的是常量A=2EF6420A,以下是解密2EF6420A的過(guò)程:
0043E665 |. 0FCE BSWAP ESI ; *
0043E66E |. 4E DEC ESI ; *
0043E67D |. 81F6 63A1000A XOR ESI,0A00A163 ; *
;結(jié)束,ESI=0042574E,這里就是VM的指令序列
0043E68C |. 8D6C24 34 LEA EBP,[ESP+34]
0043E692 |. 81EC 8C000000 SUB ESP,8C ; *
0043E69C |. 89E7 MOV EDI,ESP ; *
;第一條指令EBP取得的地址是0013F97C的位置,也就是13個(gè)保存數(shù)據(jù)的結(jié)束地址,要在這個(gè)的基礎(chǔ)上分配VM堆棧
;保存的13個(gè)dword=34byte,ESP在執(zhí)行減法前,位于0013F9FC的34個(gè)byte位置,減法分配8Cbyte;34+34+8C=F4byte=61dword
;VM堆棧的詳細(xì)分析請(qǐng)查閱1.2.VM堆棧
0043E6A9 |. 89F3 MOV EBX,ESI ; *
;EBX是VM解密數(shù)據(jù)的輔運(yùn)算寄存器,初始化為VM的指令序列地址0042574E
0043E6B8 |. 0375 00 ADD ESI,DWORD PTR SS:[EBP] ; *
;ESI的地址還要和常量0相加,相加會(huì)改變VM指令序列的地址,決定VM第一次運(yùn)行后要執(zhí)行的指令
;常量0可以看作是VM內(nèi)部的一個(gè)修正量,在NOTEPAD里它是0
到這里,一切初始化完成,程序已經(jīng)到達(dá)Dispatch(調(diào)遣)部份。整個(gè)過(guò)程概括為:保存數(shù)據(jù)、分配VM堆棧、給ESI賦值。下一條指令就是所有偽指令執(zhí)行完成后的返回地址0043E6BB。
0043E6BB |> >66:0FA5FA SHLD DX,DI,CL ; Dispatch 花指令,沒(méi)有什么意義
3.1.2.Dispatch部份解析
下面是第1條偽指令的獲取過(guò)程:
0043E6BF |. 8A46 FF MOV AL,BYTE PTR DS:[ESI-1] ; *
;開(kāi)始讀取偽指令序列號(hào),以下是解密偽指令序列號(hào)C0的過(guò)程:
0043E6C4 |. 30D8 XOR AL,BL
0043E6CE |. F6D0 NOT AL ; *
0043E6D6 |. FEC8 DEC AL ; *
0043E6DA |. C0C8 07 ROR AL,7 ; *
;結(jié)束,AL=E0,它將用于在DispatchTable(調(diào)遣表)中定位出偽指令地址。
0043E6E1 |. 83EE 01 SUB ESI,1 ; *
0043E6ED |. 30C3 XOR BL,AL ; *
;指令序列減1,計(jì)算好下一次BL的值
0043D02F |. 0FB6C0 MOVZX EAX,AL ; *
0043F124 |. 8B1485 DBE143 MOV EDX,DWORD PTR DS:[EAX*4+43E1DB] ; *
;取出偽指令地址49C4C29F,以下是解密49C4C29F的過(guò)程:
;DispatchTable的詳細(xì)分析請(qǐng)查閱1.3.偽指令匯總
0043E100 |> /81C2 6B197FB6 ADD EDX,B67F196B ; *
;只有1條解密指令,加上常量B67F196B,EDX=0043DC0A
0043E10A |. 895424 3C MOV DWORD PTR SS:[ESP+3C],EDX ; *
0043E11B |. FF7424 4C PUSH DWORD PTR SS:[ESP+4C] ; *
0043E11F |. C2 5000 RETN 50 ; Enter
;由于是使用RET指令來(lái)跳轉(zhuǎn),需要使用到真實(shí)堆棧指針ESP,在暫存EDX地址時(shí),VM使用的空間是EDISTACK的上一個(gè)位置:
0013F8B8 0043DC0A .C. ; RETURN from NOTEPAD.0043D5C7 to NOTEPAD.0043DC0A
0013F8BC 00953F38 8?. ;這里是EDISTACK的上限

到這里,VM將進(jìn)入執(zhí)行第一條偽指令。整個(gè)過(guò)程:初始化、從ESI指針獲得偽指令序列號(hào)、從DispatchTable獲得偽指令地址、跳轉(zhuǎn)執(zhí)行偽指令。Dispatch部份是VM中將會(huì)不斷重復(fù)重復(fù)再重復(fù)的執(zhí)行,所有的偽指令完畢后,都是返回到這里獲得下一條偽指令。
3.1.3.anti方式初現(xiàn)
通過(guò)前面章節(jié)的介紹,在這一節(jié)里,我將對(duì)NOTEPAD從TLS回調(diào)函數(shù)到TLS退出進(jìn)行一次概論。這個(gè)過(guò)程將不再出現(xiàn)任何的x86指令代碼,前面介紹的偽指令組合和相關(guān)內(nèi)容將會(huì)被縮短和鏈接后跳過(guò)。
1.初始化(請(qǐng)查閱3.1.初始化)
NOTEPAD在TLS回調(diào)函數(shù)中斷后,經(jīng)過(guò)初始化過(guò)程后,開(kāi)始執(zhí)行偽指令。VM將會(huì)把所有EBPSTACK中帶過(guò)來(lái)的13個(gè)初始化保留數(shù)據(jù)暫存至EDISTACK。
2.ESI數(shù)據(jù)0000與[00427D51]=0000進(jìn)行比較+跳轉(zhuǎn)(請(qǐng)查閱2.3.1.判斷相同)
3.VMP將根據(jù)PE文件結(jié)構(gòu)讀取出程序入口的第一個(gè)字節(jié)進(jìn)行CC碼檢測(cè)。VM會(huì)去到另外的堆棧空間操作整個(gè)過(guò)程,把ESP指針從0013F994-40=0013F954,在開(kāi)頭構(gòu)建2個(gè)0013F954進(jìn)行NAND(A,A)中,和前面稍有不同,這里不再詳述。過(guò)程:
0013F994-40=0013F954
MOV EBP,0013F954
0013F988 0013F994 .
0013F98C 0013F994 .
0013F990 00000040 @...
0013F994 0013F9C0 . ;計(jì)算前的EBP指針
VM_NANDdw
0013F98C FFEC066B k
0013F990 00000040 @...
0013F994 0013F9C0 .
VM_ADDdw_EBPSTACK
0013F990 FFEC06AB
0013F994 0013F9C0 .
VM_PUSHdw_EBP
VM_COPYw_EBPSTACK
0013F98C FFEC06AB
0013F990 FFEC06AB
0013F994 0013F9C0 .
VM_NANDdw
0013F990 0013F954 T.
0013F994 0013F9C0 .
VM_MOVdw_EBPreg_EBPSTACK
EBP 0013F954
堆棧移動(dòng)到0013F954后,
VM_PUSHdw_IMMEDIATEdw ;壓入00427D51
開(kāi)始從程序的入口地址根據(jù)PE文件格式定位:
VM_PUSHdw_IMMEDIATEdw ;壓入00400000,NOTEPAD程序的文件頭地址,OD數(shù)據(jù)窗口跟蹤
00400000 4D 5A 90 00|03 00 00 00|04 00 00 00|FF FF 00 00| MZ.........
00400010 B8 00 00 00|00 00 00 00|40 00 00 00|00 00 00 00| .......@.......
00400020 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| ................
00400030 00 00 00 00|00 00 00 00|00 00 00 00|80 00 00 00| ...............
00400040 0E 1F BA 0E|00 B4 09 CD|21 B8 01 4C|CD 21 54 68| ..!L!Th
00400050 69 73 20 70|72 6F 67 72|61 6D 20 63|61 6E 6E 6F| is program canno
00400060 74 20 62 65|20 72 75 6E|20 69 6E 20|44 4F 53 20| t be run in DOS
00400070 6D 6F 64 65|2E 0D 0D 0A|24 00 00 00|00 00 00 00| mode....$.......
00400080 50 45 00 00|4C 01 09 00|65 91 46 35|00 00 00 00| PE..L..eF5....
00400090 00 00 00 00|E0 00 0F 01|0B 01 03 0A|00 F0 03 00| .....
004000A0 00 74 00 00|00 00 00 00|17 78 03 00|00 10 00 00| .t......x....
004000B0 00 50 00 00|00 00 40 00|00 10 00 00|00 10 00 00| .P....@.......
004000C0 04 00 00 00|00 00 00 00|04 00 00 00|00 00 00 00| ..............
004000D0 00 50 04 00|00 04 00 00|CE 59 03 00|02 00 00 00| .P....Y....
004000E0 00 00 10 00|00 10 00 00|00 00 10 00|00 10 00 00| ............
004000F0 00 00 00 00|10 00 00 00|FC 1D 02 00|50 0C 00 00| ........P...
00400100 18 66 03 00|A0 00 00 00|00 00 04 00|00 50 00 00| f........P..
00400110 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| ................
00400120 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| ................
00400130 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| ................
00400140 F4 59 03 00|20 00 00 00|00 00 00 00|00 00 00 00| Y. ...........
00400150 00 00 00 00|00 00 00 00|B0 7D 03 00|4C 00 00 00| ........}.L...
00400160 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| ................
00400170 00 00 00 00|00 00 00 00|2E 74 65 78|74 00 00 00| .........text...
00400180 9C 3E 00 00|00 10 00 00|00 00 00 00|00 00 00 00| >.............
00400190 00 00 00 00|00 00 00 00|00 00 00 00|20 00 00 60| ............ ..`
004001A0 2E 64 61 74|61 00 00 00|4C 08 00 00|00 50 00 00| .data...L...P..
004001B0 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| ................
004001C0 00 00 00 00|40 00 00 C0|2E 69 64 61|74 61 00 00| ....@...idata..
004001D0 E8 0D 00 00|00 60 00 00|00 00 00 00|00 00 00 00| ....`..........
004001E0 00 00 00 00|00 00 00 00|00 00 00 00|40 00 00 40| ............@..@
004001F0 2E 76 6D 70|31 00 00 00|B8 4F 00 00|00 70 00 00| .vmp1...O...p..
00400200 00 50 00 00|00 10 00 00|00 00 00 00|00 00 00 00| .P.............
00400210 00 00 00 00|60 00 00 60|2E 76 6D 70|30 00 00 00| ....`..`.vmp0...
00400220 9C 0A 00 00|00 C0 00 00|00 00 00 00|00 00 00 00| ..............
00400230 00 00 00 00|00 00 00 00|00 00 00 00|60 00 00 60| ............`..`
00400240 2E 76 6D 70|32 00 00 00|A0 FD 00 00|00 D0 00 00| .vmp2........
00400250 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| ................
00400260 00 00 00 00|20 00 00 20|2E 74 6C 73|00 00 00 00| .... .. .tls....
00400270 18 00 00 00|00 D0 01 00|00 10 00 00|00 60 00 00| .........`..
00400280 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 C0| ...............
00400290 2E 76 6D 70|33 00 00 00|85 11 02 00|00 E0 01 00| .vmp3......
004002A0 00 20 02 00|00 70 00 00|00 00 00 00|00 00 00 00| . ..p..........
004002B0 00 00 00 00|20 00 00 E2|2E 72 73 72|63 00 00 00| .... ...rsrc...
004002C0 B0 4F 00 00|00 00 04 00|00 50 00 00|00 90 02 00| O......P....
004002D0 00 00 00 00|00 00 00 00|00 00 00 00|40 00 00 40| ............@..@
004002E0 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| ................
004002F0 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| ................
00400300 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| ................
00400310 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| ................
00400320 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| ................
00400330 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| ................
00400340 00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| ................
..........................................................................

0013F94C 0000003C <...
0013F950 00400000 ..@. ; OFFSET NOTEPAD. ;DOS_header_addr
VM_ADDdw_EBPSTACK
0013F950 0040003C <.@. ;e_magic
VM_PUSHdw_MEMORYdw
0013F950 00000080 ...
取得e_magic的數(shù)值,獲取PE文件頭位置
0013F94C 00000080 ...
0013F950 00400000 ..@. ; OFFSET NOTEPAD
VM_ADDdw_EBPSTACK
0013F950 00400080 .@. ; ASCII "PE" ;IMAGE_NT_HEADERS

0013F94C 00400080 .@. ; ASCII "PE"
0013F950 00000028 (...
VM_ADDdw_EBPSTACK
0013F950 004000A8 .@. ;AddressOfEntryPoint
VM_PUSHdw_MEMORYdw
0013F950 00037817 x.
PE文件頭28偏移量的位置是屬于IMAGE_OPTIONAL_HEADER32結(jié)構(gòu)的AddressOfEntryPoint字段,程序執(zhí)行入口RVA00037817
0013F94C 00037817 x.
0013F950 00400000 ..@. ; OFFSET NOTEPAD
VM_ADDdw_EBPSTACK
0013F950 00437817 xC. ; NOTEPAD.
現(xiàn)在已經(jīng)獲得NOTEPAD的程序執(zhí)行入口地址
VM_PUSHw_IMMEDIATEb
0013F950 00CC

0013F94C 7817
0013F950 00CC0043 C..
VM_PUSHw_MEMORYb
0013F950 00CC0068 h..
從執(zhí)行入口地址讀取字節(jié)和CC進(jìn)行比較,我沒(méi)有在入口地址下INT3斷點(diǎn),取得的字節(jié)是68,接下來(lái)VMP進(jìn)行減法和標(biāo)志位ZF檢測(cè),這里不再?gòu)?fù)述,在VM_JMP組合執(zhí)行完畢后,恢復(fù)EBPSTACK重新回到0013F994。
4.IF標(biāo)志位置1
VM使用NAND進(jìn)行1次AND操作,AND操作數(shù)的一個(gè)是700,截取的是DF,IF,TF位,另一個(gè)操作數(shù)是246,這樣保留的就是Interrupt Enable Flag(IF)位。最后通過(guò)偽指令VM_MOVdw_EFLreg_EBPSTACK把結(jié)果壓入EFlags寄存器。
0013F9A8 00000246 F..
0013F9AC 00000246 F..
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_NANDdw
0013F9AC FFFFFDB9
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_PUSHdw_IMMEDIATEw
0013F9A8 000008FF ..
0013F9AC FFFFFDB9
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_NANDdw
0013F9AC 00000200 ...
0013F9B0 7C92118A | ; RETURN to ntdll.7C92118A
VM_MOVdw_EFLreg_EBPSTACK
3.1.4.TLS退出
0013F990 8021D2F0 !
0013F994 8021D2F0 !
0013F998 00000246 F..
0013F99C F6F93A39 9:
0013F9A0 00000020 ...
0013F9A4 00000000 ....
0013F9A8 0013F994 .
0013F9AC 004253CD SB. ; RETURN from NOTEPAD.004255DB to NOTEPAD.004253CD
0013F9B0 000359F4 Y.
0013F9B4 00400000 ..@. ; OFFSET NOTEPAD.B
0013F9B8 0013F9C0 .
0013F9BC 7C92118A | ; RETURN to ntdll.7C92118A
VM_EXIT
程序返回進(jìn)入7C92118A,程序要從TLS中返回,我們?nèi)ラ_(kāi)始地址00437817地址下斷點(diǎn),在程序執(zhí)行地址攔截下程序。
7C92118A 8BE6 MOV ESP,ESI
7C92118C 5B POP EBX
7C92118D 5F POP EDI
7C92118E 5E POP ESI
7C92118F 5D POP EBP
7C921190 C2 1000 RETN 10

 

3.2.VMP外殼函數(shù)獲取
00437817 . 68 B59DF9FC PUSH FCF99DB5
在00437817把程序攔截下來(lái)后,和TLS相似,VMP開(kāi)始初始化VM等等操作,這里不再?gòu)?fù)述。VM運(yùn)行后還是先進(jìn)行0000與[00427D51]中的0000進(jìn)行比較+跳轉(zhuǎn)。接下來(lái)把VM堆棧重新分配和TLS里的相似:
0013FF8C 0013FF98
0013FF90 0013FF98
VM_NANDdw
0013FF90 FFEC0067 g.
0013FF94 00000800 ...
VM_ADDdw_EBPSTACK
0013FF94 FFEC0867 g
VM_PUSHdw_EBP
0013FF90 0013FF94 .
0013FF94 FFEC0867 g
VM_COPYdw_EBPSTACK
0013FF90 FFEC0867 g
0013FF94 FFEC0867 g
VM_NANDdw
0013FF94 0013F798 . ; UNICODE "er"
VM_MOVdw_EBPreg_EBPSTACK
偽指令進(jìn)行了一次減法操作0013FF98-800=0013F798,最終把0013F798賦值給EBPSTACK,在這條指令里進(jìn)行的邊界檢查中,將觸發(fā)這個(gè)VM堆棧的重新分配(詳情請(qǐng)查閱1.2.VM堆棧)
來(lái)到新的VM堆棧0013F798中,EF標(biāo)志位也將再次的置1,一切都和TLS里相同。
3.2.1.動(dòng)態(tài)鏈接庫(kù)
接下來(lái)就要進(jìn)入大規(guī)模的anti檢測(cè)了,在進(jìn)入之前還有一個(gè)準(zhǔn)備工作,在接下來(lái)的使用中,需要使用到一個(gè)buffer(緩沖區(qū))用于存儲(chǔ)API函數(shù)的返回值,動(dòng)態(tài)鏈接庫(kù)名字等等內(nèi)容,VM采用的方式是0013FF98-10=0013FF88,這樣就在0013FF88----0013FF98之間分配好了buffer,4個(gè)dword:
0013FF88 00000212 ..
0013FF8C 00000282 ..
0013FF90 00000202 ..
0013FF94 0013F798 . ; UNICODE "er"
0013FF98
在后面的anti檢測(cè)中,很多都會(huì)使用到這個(gè)buffer空間。接下來(lái)就開(kāi)始往buffer內(nèi)寫(xiě)入常量數(shù)據(jù):
0013F790 0013FF88 .
0013F794 6E72656B kern
VM_MOVdw_MEMORYdw_EBPSTACKdw ;寫(xiě)入kern
VM_PUSHdw_IMMEDIATEdw
0013F78C 0013FF88 .
0013F790 00000004 ...
0013F794 32336C65 el32
VM_ADDdw_EBPSTACK ;buffer存儲(chǔ)地址+4
0013F790 0013FF8C .
0013F794 32336C65 el32
VM_MOVdw_MEMORYdw_EBPSTACKdw ;寫(xiě)入el32
VM_PUSHdw_IMMEDIATEdw
0013F78C 00000008 ...
0013F790 0013FF88 .
0013F794 6C6C642E .dll
VM_ADDdw_EBPSTACK ;buffer存儲(chǔ)地址+8
0013F790 0013FF90 .
0013F794 6C6C642E .dll
VM_MOVdw_MEMORYdw_EBPSTACKdw ;寫(xiě)入.dll
VM_PUSHdw_IMMEDIATEdw
0013F78C 0000000C ....
0013F790 0013FF88 .
0013F794 00000000 ....
VM_ADDdw_EBPSTACK ;buffer存儲(chǔ)地址+C
0013F790 0013FF94 .
0013F794 00000000 ....
VM_MOVdw_MEMORYdw_EBPSTACKdw ;寫(xiě)入00000000
現(xiàn)在我們來(lái)看看buffer中整體寫(xiě)入的數(shù)據(jù):
0013FF88 6E72656B kern
0013FF8C 32336C65 el32
0013FF90 6C6C642E .dll
0013FF94 00000000 ....
kernel32.dll鏈接庫(kù),多么熟悉的字眼呀,VM寫(xiě)入這個(gè)數(shù)據(jù)后,會(huì)開(kāi)始進(jìn)行一次VM_JMP的相關(guān)操作,準(zhǔn)備跳轉(zhuǎn)到新的地方繼續(xù),下面是VM_JMP偽指令的數(shù)據(jù):
0013F75C 0042816C lB.
0013F760 00000000 ....
0013F764 7FF224A8 $
0013F768 7C92E514 | ; ntdll.KiFastSystemCallRet
0013F76C 7FFD8000 .
0013F770 00000202 ..
0013F774 00000000 ....
0013F778 0013FFB0 .
0013F77C 00000202 ..
0013F780 0013FF98 .
0013F784 0013FF88 . ; ASCII "kernel32.dll"
0013F788 7FF224A8 $
0013F78C 0013FF88 . ; ASCII "kernel32.dll"
0013F790 00000282 ..
0013F794 004389FB C. ; Entry point of procedure
VM_JMP
最終VM終于來(lái)到ANTI檢測(cè)和VM后期將要不斷調(diào)用的偽指令VM_EBPSTACK_CALL,用于API函數(shù)和程序自身過(guò)程調(diào)用,兩者的操作都是離開(kāi)虛擬機(jī)環(huán)境的。API函數(shù)調(diào)用將進(jìn)入系統(tǒng)空間,必然需要離開(kāi)虛擬機(jī)環(huán)境,而這里的過(guò)程調(diào)用也是離開(kāi)虛擬機(jī)環(huán)境的。離開(kāi)虛擬機(jī)環(huán)境其實(shí)很簡(jiǎn)單,只需要堆棧上變換一下,本來(lái)都是在VM堆棧的數(shù)據(jù)參數(shù)需要移動(dòng)到ESP指針的堆?臻g內(nèi),正常的程序執(zhí)行它是使用ESP指針的,不懂得到VM堆棧內(nèi)取數(shù)據(jù)。
0013F78C 00428275 uB. ; RETURN from NOTEPAD.00436E08 to NOTEPAD.00428275
0013F790 0013FF88 . ; ASCII "kernel32.dll"
0013F794 004389FB C. ; Entry point of procedure
VM_EBPSTACK_CALL
關(guān)于這條偽指令,我再來(lái)詳細(xì)解說(shuō)一下,首先它通過(guò)VM的ESI數(shù)據(jù)獲得這次函數(shù)調(diào)用的參數(shù)個(gè)數(shù)。這次它的參數(shù)是1個(gè),然后把1給ECX,下面是這條偽指令內(nèi)部獲取參數(shù)的指令:
0043E0C6 87448D 00 XCHG DWORD PTR SS:[ECX*4+EBP],EAX ; *
0043E0CD 894424 24 MOV DWORD PTR SS:[ESP+24],EAX ; *
EBP=0013F78C,在循環(huán)里面通過(guò)[ECX*4+EBP]的方式,ECX的值就決定了要取出多少個(gè)參數(shù),取出的參數(shù)壓入ESP指向的堆棧,在這里顯示的是[ESP+24],24的偏移是因?yàn)橛谢ㄖ噶,不用考慮。一切準(zhǔn)備好后,就跳轉(zhuǎn)到00428275。最后的跳轉(zhuǎn)指令數(shù)據(jù)截。
$ ==> 00428275 uB. ; RETURN from NOTEPAD.00436E08 to NOTEPAD.00428275
$+4 9AF17581 u
$+8 14415549 IUA
$+C 0013F6D8 .
$+10 00428137 7B.
$+14 0013F78C .
$+18 0013F6C0 .
$+1C 80A6D7DB 爪
$+20 0043EF77 wC.
$+24 00000000 ....
$+28 00428275 uB. ; RETURN from NOTEPAD.00436E08 to NOTEPAD.00428275
$+2C 0043EED7 C.
$+30 00000246 F..
$+34 0043EED7 C.
$+38 00428275 uB. ; RETURN from NOTEPAD.00436E08 to NOTEPAD.00428275
$+3C 0043EEB7 C. ; RETURN from NOTEPAD.0043D111 to NOTEPAD.0043EEB7 ;執(zhí)行這條指令,去除38垃圾數(shù)據(jù)后跳轉(zhuǎn)數(shù)據(jù)
$+40 0013FF88 . ; ASCII "kernel32.dll"
0043DE10 C2 3800 RETN 38 ; Call Enter
既然是跳轉(zhuǎn)到00428275,我們來(lái)看看00428275處是什么樣的代碼,那里只有一條跳轉(zhuǎn)指令:
00428275 -/FF25 E47D4300 JMP DWORD PTR DS:[<&KERNEL32.LoadLibrary
現(xiàn)在就很清晰了,這次call是使用LoadLibrary函數(shù)來(lái)獲取Kernel32.dll鏈接庫(kù)句柄。我們?cè)赾all return address處0043EEB7處下斷,然后就可以F9運(yùn)行,直接攔截下系統(tǒng)調(diào)用結(jié)束后返回的結(jié)果EAX=7C800000,F(xiàn)在又要回到虛擬機(jī)中了,反過(guò)來(lái)就需要把數(shù)據(jù)放回到VM堆棧中,按照VM運(yùn)行方式讓它在VM堆棧中操作。
在返回VM的過(guò)程中,首先是把原來(lái)EBPSTACK中的參數(shù)占據(jù)的位置釋放:
0043ED41 8B4D FC MOV ECX,DWORD PTR SS:[EBP-4] ; *這里是保存的本次call的參數(shù)個(gè)數(shù)
0043ED46 8D6C8D 00 LEA EBP,[ECX*4+EBP] ; *釋放掉對(duì)應(yīng)的空間
把EAX中的結(jié)果保存到EBPSTACK
EAX=7C800000
0043ED50 8945 00 MOV DWORD PTR SS:[EBP],EAX ; *
0013F790 7C800000 ..|
返回VM后,進(jìn)行一次VM_JMP調(diào)用

3.2.2.循環(huán)
分配新的buffer空間,0013FF88-10=0013FF78再分配4個(gè)dword的空間出來(lái),使用上面的方式往新的buffer空間寫(xiě)入數(shù)據(jù)。4個(gè)dword寫(xiě)入完成后buffer空間的數(shù)據(jù)如下:
0013FF78 8D7E029C ~
0013FF7C 8F81160C .
0013FF80 048DFF7E ~
0013FF84 00C78D05 .
0013FF88 6E72656B kern
0013FF8C 32336C65 el32
0013FF90 6C6C642E .dll
0013FF94 00000000 ....
調(diào)用VM_JMP跳轉(zhuǎn)到新的地方,接下來(lái)毫無(wú)疑問(wèn)的是繼續(xù)進(jìn)行call調(diào)用
0013F788 00421C48 HB. ; Entry point of procedure
0013F78C 7C800000 ..|
0013F790 0013FF78 x.
0013F794 00427C45 E|B.
VM_EBPSTACK_CALL
這次是帶著kernel32.dll的句柄7C800000和0013FF78兩個(gè)參數(shù)調(diào)用00421C48,這次是一個(gè)過(guò)程調(diào)用,我們下面來(lái)看00421C48的代碼:
00421C4E 55 PUSH EBP ; *
00421C58 8D6C24 04 LEA EBP,[ESP+4] ; *下面要使用EBP來(lái)讀取參數(shù),先保存后定位
00421C76 56 PUSH ESI ; *
00421C80 893C24 MOV DWORD PTR SS:[ESP],EDI ; *
00421C85 53 PUSH EBX ; *
00421C8C 52 PUSH EDX ; *
該保存的保存起來(lái)
00421C92 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8] ; *讀取第一個(gè)參數(shù)kernel32.dll句柄7C800000
接下來(lái)的部分和TLS中的PE文件頭定位相似,不過(guò)TLS是使用偽指令實(shí)現(xiàn)的,這里用常規(guī)指令實(shí)現(xiàn)。
00436B42 8B70 3C MOV ESI,DWORD PTR DS:[EAX+3C] ; *
00436B4E 01C6 ADD ESI,EAX ; *
00436B5C 8B56 78 MOV EDX,DWORD PTR DS:[ESI+78] ; * 78偏移是導(dǎo)出表結(jié)構(gòu)位置,kernel32.dll的導(dǎo)出表RVA
0043A773 01C2 ADD EDX,EAX ; * 獲得導(dǎo)出表開(kāi)始位置7C80262C
0043A77D 8B4E 7C MOV ECX,DWORD PTR DS:[ESI+7C] ; * 78偏移是導(dǎo)出表結(jié)構(gòu)位置,kernel32.dll的導(dǎo)出表大小
00435CB9 01D1 ADD ECX,EDX ; * 獲得導(dǎo)出表結(jié)束位置7C809345
00435CBE 894D F0 MOV DWORD PTR SS:[EBP-10],ECX ; * 保存起來(lái)
00435CCB 8B4D 0C MOV ECX,DWORD PTR SS:[EBP+0C] ; * 這里獲取的是第二個(gè)參數(shù)0013FF78
0041EE80 8B7A 24 MOV EDI,DWORD PTR DS:[EDX+24] ; * 導(dǎo)出表24偏移的是AddressOfNamesOrdinals 指向輸入序列號(hào)數(shù)組
0041EE8B 01C7 ADD EDI,EAX ; * 輸入序列號(hào)數(shù)組地址7C804424
0041EE8F 8B5A 20 MOV EBX,DWORD PTR DS:[EDX+20] ; * 導(dǎo)出表20偏移的是AddressOfNames 函數(shù)名字的指針的地址
0041EE9B 01C3 ADD EBX,EAX ; * 函數(shù)名字的指針地址7C80353C
0041EEB1 8B4A 18 MOV ECX,DWORD PTR DS:[EDX+18] ; * 導(dǎo)出表18偏移的是NumberOfNames AddressOfNames數(shù)組的項(xiàng)數(shù)
一切準(zhǔn)備就緒開(kāi)始讀取導(dǎo)出表函數(shù)比較
0041EED5 83E9 01 SUB ECX,1 ; * 計(jì)數(shù)器第1個(gè)word減去
0041EEDF 894D FC MOV DWORD PTR SS:[EBP-4],ECX ; *
0041EEF0 8B4D F8 MOV ECX,DWORD PTR SS:[EBP-8] ; * 整個(gè)程序的載入偏移量
00428D66 034D FC ADD ECX,DWORD PTR SS:[EBP-4] ; *
00428D6B D1E9 SHR ECX,1 ; * 計(jì)數(shù)器除以2,按照word方式
00428D72 8B3C8B MOV EDI,DWORD PTR DS:[ECX*4+EBX] ; *
00428514 /01C7 ADD EDI,EAX ; *
EDI 7C806FB2 ASCII "GetVDMCurrentDirectories",到這里就得到API函數(shù)名了
0042851E 8B75 0C MOV ESI,DWORD PTR SS:[EBP+0C] ; * 0013FF78
0043A156 AC LODS BYTE PTR DS:[ESI] ; *
0043A159 F6D0 NOT AL ; *
0043A165 F6D8 NEG AL ; *
00435255 /FEC0 INC AL ; *
0043525C 34 37 XOR AL,37 ; *
0043552A FEC0 INC AL ; *
00435530 D0C0 ROL AL,1 ; *
0041E634 FEC0 INC AL ; *
接下來(lái)就是比較
004388E1 3A07 CMP AL,BYTE PTR DS:[EDI] ; *
004388E7 ^\0F8C 35EAFFFF JL 00437322 ; *
004388ED 8D7F 01 LEA EDI,[EDI+1] ; *
004219F2 /0F87 9A6B0100 JA 00438592 ; *
00425FB3 3B4D FC CMP ECX,DWORD PTR SS:[EBP-4] ; *
00425FC4 83C1 01 ADD ECX,1 ; *
00425FCD 894D F8 MOV DWORD PTR SS:[EBP-8],ECX ; *
注意好它的跳轉(zhuǎn)方式是通過(guò)JL和JA方式一起實(shí)現(xiàn),上面的是比較失敗后的循環(huán)。如果相同的話(huà),JL和JA這里都不能跳轉(zhuǎn),我們?nèi)A的下一條指令攔截比較相同的情況:
004219F2 /0F87 9A6B0100 JA 00438592 ; *
004219F8 |E8 2B480000 CALL 00426228 ;F4這里
現(xiàn)在我們就找到第一個(gè)字母比較相同的函數(shù)是VirtualAlloc
0042968E 807F FF 00 CMP BYTE PTR DS:[EDI-1],0 ; *
0043712D ^\0F85 F213FFFF JNE 00428525 ; *
出來(lái)到外循環(huán)看是不是已經(jīng)比較到尾部,還沒(méi)有就回去比較第2個(gè)字節(jié),我們直接跳出循環(huán)看結(jié)果
0043712D ^\0F85 F213FFFF JNE 00428525 ; *
00437133 0FBAEF 16 BTS EDI,16 ;F4這里,所有字節(jié)都相同的函數(shù)是VirtualProtect
到這里比較完畢,要找的函數(shù)是VirtualProtect
0043C9C1 8B7A 24 MOV EDI,DWORD PTR DS:[EDX+24] ; * AddressOfNamesOrdinals
0043C9C7 01C7 ADD EDI,EAX ; *
0043C9CC 0FB70C4F MOVZX ECX,WORD PTR DS:[ECX*2+EDI] ; *
0043C9D6 29CF SUB EDI,ECX ; *
0043C9DB 8B7A 1C MOV EDI,DWORD PTR DS:[EDX+1C] ; * AddressOfFunctions
0043C9E3 01C7 ADD EDI,EAX ; *
0042862B /8B3C8F MOV EDI,DWORD PTR DS:[ECX*4+EDI] ; *
00438A9F \01F8 ADD EAX,EDI ; *
解說(shuō)不過(guò)來(lái)了,大家不明白的去復(fù)習(xí)PE文件格式的導(dǎo)出表部分吧,上面的指令結(jié)束后,得到了VirtualProtect的系統(tǒng)地址7C801AD4
0043EEB7 89D1 MOV ECX,EDX ; call return address
回到call返回地址,數(shù)據(jù)壓入EBPSTACK這里等于0013F790
0013F790 7C801AD4 | ; kernel32.VirtualProtect
0013F794 00427C45 E|B.
我們?cè)谄綍r(shí)的代碼中也經(jīng)?梢钥吹,call調(diào)用完畢后檢測(cè)一下是不是0,VMP也是一樣的,只是用偽指令來(lái)實(shí)現(xiàn)
0013F78C 7C801AD4 | ; kernel32.VirtualProtect
0013F790 7C801AD4 | ; kernel32.VirtualProtect
0013F794 00427C45 E|B.
VM_NANDdw
0013F790 837FE52B +
0013F794 00427C45 E|B.
VM_PUSHdw_EBP
VM_COPYdw_EBPSTACK
0013F78C 837FE52B +
0013F790 837FE52B +
0013F794 00427C45 E|B.
VM_NANDdw
0013F790 7C801AD4 | ; kernel32.VirtualProtect
0013F794 00427C45 E|B.
兩個(gè)NOT指令為的就是要它的標(biāo)志位來(lái)進(jìn)行ZF位檢測(cè)+跳轉(zhuǎn)VM_JMP指令
接下來(lái)VM將會(huì)進(jìn)行一次CC碼檢測(cè),看看VirtualProtect函數(shù)開(kāi)始地址有沒(méi)有下斷點(diǎn),此部分不再?gòu)?fù)述,記錄關(guān)鍵數(shù)據(jù):
0013F78C 1AD4
0013F790 00CC7C80 |.
0013F794 00427C45 E|B.
讀取出7C801AD4函數(shù)的首字節(jié),與CC碼進(jìn)行一次減法操作,獲取其中的標(biāo)志位,進(jìn)行ZF位檢測(cè)+跳轉(zhuǎn)
在前面的EBPSTACK中一直附帶著00427C45這個(gè)數(shù)據(jù)而沒(méi)有動(dòng)靜,現(xiàn)在在確定一切安全沒(méi)有問(wèn)題,VM再次調(diào)用VM_JMP控制VM跳轉(zhuǎn)到00427C45位置,下面我們就來(lái)看看00427C45是干什么操作的
0013F790 C9058E9B
0013F794 7C801AD4 | ; kernel32.VirtualProtect
VM_ADDdw_EBPSTACK
0013F794 4585A96F oE

0013F78C 0013F798
0013F790 00000020
0013F794 4585A96F oE
VM_ADDdw_EBPSTACK
0013F790 0013F7B8 .
0013F794 4585A96F oE
VM_MOVb_MEMORYb_EBPSTACKb
現(xiàn)在我們看清楚,00427C45這個(gè)VM子程序過(guò)程是把得到的系統(tǒng)地址加密起來(lái)存放,不讓它按照明碼的方式存儲(chǔ)。到這里完成了一個(gè)系統(tǒng)函數(shù)獲取到存儲(chǔ)的全過(guò)程,接下來(lái)程序回到 3.2.2.循環(huán) 的開(kāi)頭,開(kāi)始新的函數(shù)獲取,從往0013FF78壓入4個(gè)dword開(kāi)始,接著就退出00427C45這個(gè)VM子程序過(guò)程。當(dāng)kernel32.dll結(jié)束后又進(jìn)入下一個(gè)DLL文件,程序回到 3.2.1.動(dòng)態(tài)鏈接庫(kù) 這一部分不再?gòu)?fù)述,接下來(lái)直接粘貼獲取的函數(shù)匯總
kernel32.dll:
0013F780 7C801AD4 | ; kernel32.VirtualProtect ;加密后0013F7B8 4585A96F oE
0013F790 7C809AF1 | ; kernel32.VirtualAlloc ;加密后0013F7C0 7ED1C93F ?~
0013F790 7C801A28 (| ; kernel32.CreateFileA ;加密后0013F7DC 45E78F5A ZE
0013F778 7C809BE7 鐩| ; kernel32.CloseHandle ;加密后0013F7D8 877DBA31 1}
0013F790 7C810B17 | ; kernel32.GetFileSize ;加密后0013F7E4 05F84F8C O
0013F790 7C80950A .| ; kernel32.CreateFileMappingA ;加密后0013F7F4 8B5A496C lIZ
0013F790 7C80B9A5 | ; kernel32.MapViewOfFile ;加密后0013F7C4 C2DC4B94 K
0013F790 7C80BA14 | ; kernel32.UnmapViewOfFile ;加密后0013F798 230A53C4 S.#
0013F790 7C80B741 A| ; kernel32.GetModuleHandleA ;加密后0013F7CC 058C4D40 @M
0013F794 7C813133 31| ; kernel32.IsDebuggerPresent ;加密后0013F7EC 9C056A3F ?j
0013F794 7C85AAF2 | ; kernel32.CheckRemoteDebuggerPresent ;加密后0013F7F8 77ED7C33 3|w
0013F790 7C863FCA ?| ; kernel32.UnhandledExceptionFilter ;加密后0013F7D0 35B5E8D3 5
ntdll.dll:
0013F794 7C92D7FE 讙| ; ntdll.ZwQueryInformationProcess ;加密后0013F7B0 D324C5FE $
0013F794 7C92DCAE 軖| ; ntdll.NtSetInformationThread ;加密后0013F7A8 E42D06B3 -
0013F794 7C92D92E .賿| ; ntdll.NtQuerySystemInformation ;明碼存儲(chǔ)00425E60 7C92D92E到這里所有的外殼函數(shù)獲取結(jié)束,VM執(zhí)行VM_JMP跳轉(zhuǎn)走,由于最后的1條系統(tǒng)函數(shù)地址是存儲(chǔ)在內(nèi)存中,00425E60進(jìn)行加法操作,不讓他以明碼出現(xiàn),同時(shí)VM作為堆棧虛擬機(jī),還是喜歡堆棧的存儲(chǔ)方式,所以再找一個(gè)堆?臻g0013F7E8,把暗碼地址放進(jìn)去:
0013F790 03DDEA1E
0013F794 00425E64 d^B.
VM_ADDdw_EBPSTACK
0013F794 04204882 H

0013F78C 00000050 P...
0013F790 0013F798 .
0013F794 04204882 H
VM_ADDdw_EBPSTACK
0013F790 0013F7E8 .
0013F794 04204882 H
VM_MOVdw_MEMORYdw_EBPSTACKdw

3.3.虛擬執(zhí)行環(huán)境與調(diào)試器檢測(cè)
在前面所有的節(jié)里面的內(nèi)容全部都是貫穿的,沒(méi)有一個(gè)地方遺漏下來(lái)的在解析,但是這一節(jié)和上一節(jié)的結(jié)尾并沒(méi)有連接在一起,不是我想藏著捏著搞流水賬脫文出來(lái),實(shí)在是沒(méi)有精力一條一條的去說(shuō)。我已經(jīng)想吐了,沒(méi)有心情繼續(xù)寫(xiě)下去了,越是想著全盤(pán)托出,有些地方老是更有壓力害怕遺漏了東西。還有一個(gè)是想趕快結(jié)稿的心理也有一些。再說(shuō),VMP的ANTI檢測(cè)是很有趣的一個(gè)部分,當(dāng)你知道下面有一節(jié)很有趣,而一直繞在上面的基礎(chǔ)地方,實(shí)在也有點(diǎn)心急?傊,如果你發(fā)現(xiàn)我有遺漏了沒(méi)有解說(shuō)的地方就自己去看好了。下面我們就直接來(lái)到ANTI部分:
3.3.1.VMware
0013F78C 00000000 ....
0013F790 0043B7B2 C. ; RETURN from NOTEPAD.00435E6A to NOTEPAD.0043B7B2
0013F794 0013FF98 .
VM_FS:[EBPSTACK] ;讀取FS:[0]的數(shù)據(jù)
0013F78C |0013FFE0 .
0013F790 \0043B7B2 C. ; RETURN from NOTEPAD.00435E6A to NOTEPAD.0043B7B2
0013F794 0013FF98 .

0013F784 00000000 ....
0013F788 0013F78C .
0013F78C 0013FFE0 .
0013F790 0043B7B2 C. ; RETURN from NOTEPAD.00435E6A to NOTEPAD.0043B7B2
0013F794 0013FF98 .
VM_SEH
0013F78C |0013FFE0 . ; Pointer to next SEH record
0013F790 \0043B7B2 C. ; SE handler
0013F794 0013FF98 .
這是VM構(gòu)建新的SEH。讀取FS:[0]的原來(lái)的SEH地址,然后放入新的進(jìn)去VM_SEH偽指令里實(shí)現(xiàn)的,不明白的自己去看SEH相關(guān)資料。構(gòu)建好SEH后程序調(diào)用VM_EXIT,
0013F770 00000000 ....
0013F774 0013FF98 .
0013F778 564D5868 hXMV
0013F77C 00005658 XV..
0013F780 [0042536C lSB. ; RETURN from NOTEPAD.00426E8B to NOTEPAD.0042536C
0013F784 31921C56 V1
0013F788 0042536C lSB. ; RETURN from NOTEPAD.00426E8B to NOTEPAD.0042536C
0013F78C 0013FFE0 . ; Pointer to next SEH record
0013F790 0043B7B2 C. ; SE handler
0013F794 0013FF98 .
VM_EXIT
接下來(lái)程序在
0042536C . ED IN EAX,DX ; I/O command
這條指令這里就卡死了。為什么呢?因?yàn)閂M_EXIT中有著給各個(gè)寄存器賦值的操作,其中這里他就構(gòu)建了一個(gè)VMware的后門(mén)指令檢測(cè)。在這里算是VMP的第一個(gè)正規(guī)的ANTI來(lái)了。執(zhí)行這條指令時(shí)候的CPU狀態(tài)和VMware后門(mén)檢測(cè)的源碼:
CPU - main thread, module NOTEPAD
EAX 564D5868
ECX 0000000A
EDX 00005658
EBX 00000000
ESP 0013F78C
EBP 0013FF98
ESI 0013FF8C ASCII "ntdll.dll"
EDI 0013FF70
EIP 0042536C NOTEPAD.0042536C
VMware的后門(mén)指令檢測(cè)。這個(gè)么不用問(wèn)為什么。這個(gè)就是后門(mén)
   mov eax, 564D5868h
   mov ebx, 00000000h
   mov ecx, 0000000Ah
   mov edx, 00005658h
   in eax, dx
這個(gè)檢測(cè)很普通,由于只有在VMware下這條指令才有返回值,否則就是一次異常。而我們是在真實(shí)環(huán)境下的。這個(gè)太普通了。我根本沒(méi)有用什么虛擬機(jī)。想深入了解的自己google資料看。
我是沒(méi)有在VMware調(diào)試VMP,所以它必定異常出錯(cuò),現(xiàn)在就可以看到剛才構(gòu)建的SEH的作用了。去SEH地址下斷,然后忽略異常繼續(xù)調(diào)試。
0043B7B2 .^\E9 7DD2FFFF JMP 00438A34 ; VMware SEH
我們來(lái)到了這里繼續(xù)調(diào)試,在SEH中,將保存當(dāng)前的結(jié)構(gòu),重新初始化一個(gè)VM,并在這個(gè)VM里面修改掉context結(jié)構(gòu)中EIP指針。要看懂修改的偽指令,還是復(fù)習(xí)一下SEH回調(diào)函數(shù):
首先看好SEH回調(diào)函數(shù)的參數(shù),它一共有4個(gè)參數(shù):
SEH_Handler proc _lpExceptionRecord,_lpSEH,_lpContext,_lpDispatcherContext
對(duì)應(yīng)VMP里的SEH地址看看具體數(shù)據(jù)
0013F3C4 [7C9232A8 2| ; RETURN to ntdll.7C9232A8
0013F3C8 0013F4AC . ;第一個(gè)參數(shù):ExceptionRecord指針
0013F3CC 0013F78C . ;第二個(gè)參數(shù):SEH指針
0013F3D0 0013F4C0 . ;第三個(gè)參數(shù):Context指針
0013F3D4 0013F480 . ;第四個(gè)參數(shù):DispatcherContext指針

附CONTEXT結(jié)構(gòu)環(huán)境:
代碼:typedefstruct_CONTEXT{
/*000*/DWORD ContextFlags;
/*004*/DWORD Dr0;
/*008*/DWORD Dr1;
/*00C*/DWORD Dr2;
/*010*/DWORD Dr3;
/*014*/DWORD Dr6;
/*018*/DWORD Dr7;
/*01C*/FLOATING_SAVE_AREAFloatSave;
/*08C*/DWORD SegGs;
/*090*/DWORD SegFs;
/*094*/DWORD SegEs;
/*098*/DWORD SegDs;
/*09C*/DWORD Edi;
/*0A0*/DWORD Esi;
/*0A4*/DWORD Ebx;
/*0A8*/DWORD Edx;
/*0AC*/DWORD Ecx;
/*0B0*/DWORD Eax;
/*0B4*/DWORD Ebp;
/*0B8*/DWORD Eip; ;B8的偏移量位置是Eip
/*0BC*/DWORD SegCs;
/*0C0*/DWORD EFlags;
/*0C4*/DWORD Esp;
/*0C8*/DWORD SegSs;
/*0CC*/ BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];
/*2CC*/}CONTEXT;
先用理論來(lái)說(shuō)一下:
1)第三個(gè)參數(shù)得到context結(jié)構(gòu)地址0013F4C0。
2)context結(jié)構(gòu)基地址+B8得到Eip存儲(chǔ)地址。
3)把安全的返回地址放入Eip位置。
4)SEH異常返回,程序從新的Eip地址開(kāi)始執(zhí)行。
下面來(lái)看偽指令的操作過(guò)程:
0013F3C4 7C9232A8 2| ; RETURN to ntdll.7C9232A8
VM_PUSHdw_IMMEDIATEb
0013F3C0 0000000C ....
0013F3C4 7C9232A8 2| ; RETURN to ntdll.7C9232A8
VM_PUSHdw_IMMEDIATEb
0013F3BC 00000008 ...
0013F3C0 0000000C ....
0013F3C4 7C9232A8 2| ; RETURN to ntdll.7C9232A8
VM_PUSHdw_EBP
0013F3B8 0013F3BC .
0013F3BC 00000008 ...
0013F3C0 0000000C ....
0013F3C4 7C9232A8 2| ; RETURN to ntdll.7C9232A8
VM_ADDdw_EBPSTACK
0013F3BC 0013F3C4 .
0013F3C0 0000000C ....
0013F3C4 7C9232A8 2| ; RETURN to ntdll.7C9232A8
VM_ADDdw_EBPSTACK
0013F3C0 0013F3D0 .
0013F3C4 7C9232A8 2| ; RETURN to ntdll.7C9232A8
這是1)階段,加8獲得參數(shù)的位置,加C獲得第三個(gè)參數(shù):
0013F3C0 0013F3D0 .
0013F3C4 7C9232A8 2| ; RETURN to ntdll.7C9232A8
0013F3C8 0013F4AC .
0013F3CC 0013F78C .
0013F3D0 0013F4C0 .
0013F3D4 0013F480 .
VM_COPYdw_EBPSTACK
0013F3C0 0013F4C0 .
0013F3C4 7C9232A8 2| ; RETURN to ntdll.7C9232A8
這是1)階段,獲得context結(jié)構(gòu)地址0013F4C0
0013F3B8 0013F4C0 .
0013F3BC 000000B8 ...
0013F3C0 00436C7D }lC.
0013F3C4 7C9232A8 2| ; RETURN to ntdll.7C9232A8
VM_ADDdw_EBPSTACK
0013F3BC 0013F578 x. ; ASCII "lSB"
0013F3C0 00436C7D }lC.
0013F3C4 7C9232A8 2| ; RETURN to ntdll.7C9232A8
這是2)階段,context結(jié)構(gòu)B8偏移量位置是Eip位置
VM_MOVdw_MEMORYdw_EBPSTACKdw
這是3)階段,本來(lái)Eip位置是發(fā)生異常的指令地址:
0013F578 0042536C lSB. ; RETURN from NOTEPAD.00426E8B to NOTEPAD.0042536C
經(jīng)過(guò)修改后,放入了返回后的執(zhí)行地址:
0013F578 00436C7D }lC.

0013F398 F32B430A .C+
0013F39C 00000000 ....
0013F3A0 00000246 F..
0013F3A4 7C9232BC 2|
0013F3A8 0013F4C0 .
0013F3AC 00000000 ....
0013F3B0 0013F3E4 .
0013F3B4 00000000 ....
0013F3B8 7C9232BC 2|
0013F3BC 00000000 ....
0013F3C0 00000000 ....
0013F3C4 7C9232A8 2| ; RETURN to ntdll.7C9232A8
VM_EXIT
這是4)階段。最后調(diào)用VM_EXIT返回,里面給寄存器賦值,讓系統(tǒng)從SEH返回,而返回后eip指針被修改,我們就需要從新放入的地址00436C7D攔截程序跟蹤。接下來(lái)重新初始化VM。我們繼續(xù)走起了。現(xiàn)在前面放置的SEH已經(jīng)無(wú)用了,釋放掉恢復(fù)原來(lái)的SEH,直接放偽指令的實(shí)現(xiàn)過(guò)程了,不明白的查SEH資料:
0013F788 00000000 ....
VM_FS:[EBPSTACK] ;FS:[O]的值取出來(lái),得到當(dāng)前的SEH結(jié)構(gòu)存儲(chǔ)地址
0013F788 0013F78C .
VM_MOVdw_EBPreg_EBPSTACK ;移動(dòng)EBP指針下去,到達(dá)SEH結(jié)構(gòu)存執(zhí)地址
0013F788 00000000 ....
0013F78C 0013FFE0 . ; Pointer to next SEH record
0013F790 0043B7B2 C. ; SE handler
VM_SEH ;恢復(fù)原來(lái)的SEH,0013FFE0放入FS:[0]

3.3.2.單步模式
這個(gè)檢測(cè)方法用偽指令來(lái)實(shí)現(xiàn)可以說(shuō)是非常非常的猥瑣。這招對(duì)于一般的人來(lái)說(shuō)毫無(wú)意義,因?yàn)槎际侵苯舆\(yùn)行或者從來(lái)不進(jìn)偽指令里面去,很容易就過(guò)了,反倒是碰到我這樣F7單步走VM的人來(lái)說(shuō),不小心就中招了。總之十分猥瑣的方法。
0013F78C 00000000 ....
0013F790 0041F070 pA. ; RETURN from NOTEPAD.00423165 to NOTEPAD.0041F070
0013F794 0013FF98 .
VM_FS:[EBPSTACK] ;讀取FS:[0]的值當(dāng)前SEH結(jié)構(gòu)
0013F78C |0013FFE0 .
0013F790 \0041F070 pA. ; RETURN from NOTEPAD.00423165 to NOTEPAD.0041F070
0013F794 0013FF98 .

0013F784 00000000 ....
0013F788 0013F78C .
0013F78C 0013FFE0 .
0013F790 0041F070 pA. ; RETURN from NOTEPAD.00423165 to NOTEPAD.0041F070
0013F794 0013FF98 .
VM_SEH
0013F78C |0013FFE0 . ; Pointer to next SEH record
0013F790 \0041F070 pA. ; SE handler
0013F794 0013FF98 .
構(gòu)建新的SEH結(jié)構(gòu),現(xiàn)在的異常處理程序地址是0041F070

下面VM會(huì)進(jìn)行一次OR操作,標(biāo)志位00000293 OR 00000100=00000393并把結(jié)果壓入EFLAGS寄存器,偽指令過(guò)程如下:
0013F77C 0013F780 .
0013F780 00000008 ...
0013F784 00000100 ...
0013F788 00000293 ..
0013F78C 0013FFE0 . ; Pointer to next SEH record
0013F790 0041F070 pA. ; SE handler
0013F794 0013FF98 .
VM_ADDdw_EBPSTACK
0013F780 0013F788 .
0013F784 00000100 ...
0013F788 00000293 ..
VM_COPYdw_EBPSTACK
0013F780 00000293 ..
0013F784 00000100 ...
0013F788 00000293 ..
VM_NANDdw
0013F784 FFFFFC6C l
0013F788 00000293 ..
VM_PUSHdw_EBP
VM_COPYdw_EBPSTACK
0013F780 FFFFFC6C l
0013F784 FFFFFC6C l
0013F788 00000293 ..
VM_NANDdw
0013F784 00000393 ..
0013F788 00000293 ..
VM_PUSHdw_EBP
0013F780 0013F784 .
0013F784 00000393 ..
0013F788 00000293 ..
VM_PUSHdw_IMMEDIATEb
0013F77C 00000004 ...
0013F780 0013F784 .
0013F784 00000393 ..
0013F788 00000293 ..
VM_ADDdw_EBPSTACK
0013F780 0013F788 .
0013F784 00000393 ..
0013F788 00000293 ..
VM_MOVdw_MEMORYdw_EBPSTACKdw
0013F788 00000393 ..

0013F758 00000286 ..
0013F75C 0013FF8C . ; ASCII "ntdll.dll"
0013F760 00000206 ..
0013F764 00426C00 .lB.
0013F768 0000000A ....
0013F76C 00000000 ....
0013F770 0013FF98 .
0013F774 00000000 ....
0013F778 00005658 XV..
0013F77C 0013FF70 p.
0013F780 0013FF8C . ; ASCII "ntdll.dll"
0013F784 00428173 sB.
0013F788 00000393 ..
VM_EXIT
在VM_EXIT中,最后一個(gè)數(shù)據(jù)00000393是
00428173 9D POPFD ; *
被壓入了EFLAGS寄存器,現(xiàn)在我們可以看看00000100這個(gè)OR操作數(shù)影響的是Trap Flag(TF)位,這個(gè)過(guò)程就是把標(biāo)志位的TF位置1。根據(jù)Intel資料:
TF (bit 8) Trap flag — Set to enable single-step mode for debugging;
clear to disable single-step mode.
也就是VM設(shè)置單步模式(single-step mode)。下面我們來(lái)回頭進(jìn)好好看看00428173這個(gè)過(guò)程的詳細(xì)代碼:
00428173 |. 9D POPFD ; *
00428174 |. 0F31 RDTSC
00428176 |. 90 NOP
00428177 |. 9C PUSHFD
00428178 |. C70424 0A429C MOV DWORD PTR SS:[ESP],489C420A
0042817F |. 9C PUSHFD
00428180 \. E9 58030100 JMP 004384DD
這段代碼你要是一條一條的F7走下去,完全沒(méi)有問(wèn)題。能夠一直走到JMP 004384DD這里,然后程序就開(kāi)始初始化VM,看不到任何的問(wèn)題。而事實(shí)上你已經(jīng)中招了。接下來(lái)就等著看被VMP發(fā)現(xiàn)的提示框吧。
而如果你直接在進(jìn)入這個(gè)00428173的過(guò)程前來(lái)一個(gè)F9,比如說(shuō)VM_EXIT偽指令處。你就會(huì)發(fā)現(xiàn)程序被攔截下來(lái)了
00428173 |. 9D POPFD ; * single-step mode
00428174 |. 0F31 RDTSC
00428176 |. 90 NOP ;*************************
00428177 |. 9C PUSHFD
00428178 |. C70424 0A429C MOV DWORD PTR SS:[ESP],489C420A
0042817F |. 9C PUSHFD
00428180 \. E9 58030100 JMP 004384DD
在NOP指令這里,程序就被攔截下來(lái)了?匆幌翺D下角的提示框顯示:
Break on single-step trap set by application - Shift+Run/Step to pass exception to the program
來(lái)說(shuō)說(shuō)原理,由于OD這樣的Ring3調(diào)試器,F(xiàn)7單步靠的就是TF標(biāo)志位,所以如果你單步走這段代碼。VM程序設(shè)置的TF位就會(huì)和OD調(diào)試器的TF位相同,OD以為是自己的單步調(diào)試,就不會(huì)觸發(fā)這個(gè)異常,而一旦你F9運(yùn)行程序,OD才會(huì)發(fā)現(xiàn):哦,原來(lái)這里調(diào)試的程序自己設(shè)置一個(gè)TF單步異常!注意看OD給的提示消息:中斷在應(yīng)用程序設(shè)置的單步陷阱-Shift+Run/Step跳過(guò)程序異常

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

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

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過(guò)難過(guò)
    • 5 囧
    • 3 圍觀圍觀
    • 2 無(wú)聊無(wú)聊

    熱門(mén)評(píng)論

    最新評(píng)論

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

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