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)于A(yíng)DD指令,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)于A(yíng)ND邏輯運(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è)。