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

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

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

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

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

VMProtect UltimateV2.13.5 中文注冊版
  • 類型:加殼脫殼大小:13.5M語言:中文 評分:4.2
  • 標(biāo)簽:
立即下載
6 頁 VMP外殼函數(shù)獲取

3.2.VMP外殼函數(shù)獲取
00437817 . 68 B59DF9FC PUSH FCF99DB5
在00437817把程序攔截下來后,和TLS相似,VMP開始初始化VM等等操作,這里不再復(fù)述。VM運(yùn)行后還是先進(jìn)行0000與[00427D51]中的0000進(jìn)行比較+跳轉(zhuǎn)。接下來把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堆棧的重新分配(詳情請查閱1.2.VM堆棧)
來到新的VM堆棧0013F798中,EF標(biāo)志位也將再次的置1,一切都和TLS里相同。
3.2.1.動態(tài)鏈接庫
接下來就要進(jìn)入大規(guī)模的anti檢測了,在進(jìn)入之前還有一個(gè)準(zhǔn)備工作,在接下來的使用中,需要使用到一個(gè)buffer(緩沖區(qū))用于存儲API函數(shù)的返回值,動態(tài)鏈接庫名字等等內(nèi)容,VM采用的方式是0013FF98-10=0013FF88,這樣就在0013FF88----0013FF98之間分配好了buffer,4個(gè)dword:
0013FF88 00000212 ..
0013FF8C 00000282 ..
0013FF90 00000202 ..
0013FF94 0013F798 . ; UNICODE "er"
0013FF98
在后面的anti檢測中,很多都會使用到這個(gè)buffer空間。接下來就開始往buffer內(nèi)寫入常量數(shù)據(jù):
0013F790 0013FF88 .
0013F794 6E72656B kern
VM_MOVdw_MEMORYdw_EBPSTACKdw ;寫入kern
VM_PUSHdw_IMMEDIATEdw
0013F78C 0013FF88 .
0013F790 00000004 ...
0013F794 32336C65 el32
VM_ADDdw_EBPSTACK ;buffer存儲地址+4
0013F790 0013FF8C .
0013F794 32336C65 el32
VM_MOVdw_MEMORYdw_EBPSTACKdw ;寫入el32
VM_PUSHdw_IMMEDIATEdw
0013F78C 00000008 ...
0013F790 0013FF88 .
0013F794 6C6C642E .dll
VM_ADDdw_EBPSTACK ;buffer存儲地址+8
0013F790 0013FF90 .
0013F794 6C6C642E .dll
VM_MOVdw_MEMORYdw_EBPSTACKdw ;寫入.dll
VM_PUSHdw_IMMEDIATEdw
0013F78C 0000000C ....
0013F790 0013FF88 .
0013F794 00000000 ....
VM_ADDdw_EBPSTACK ;buffer存儲地址+C
0013F790 0013FF94 .
0013F794 00000000 ....
VM_MOVdw_MEMORYdw_EBPSTACKdw ;寫入00000000
現(xiàn)在我們來看看buffer中整體寫入的數(shù)據(jù):
0013FF88 6E72656B kern
0013FF8C 32336C65 el32
0013FF90 6C6C642E .dll
0013FF94 00000000 ....
kernel32.dll鏈接庫,多么熟悉的字眼呀,VM寫入這個(gè)數(shù)據(jù)后,會開始進(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終于來到ANTI檢測和VM后期將要不斷調(diào)用的偽指令VM_EBPSTACK_CALL,用于API函數(shù)和程序自身過程調(diào)用,兩者的操作都是離開虛擬機(jī)環(huán)境的。API函數(shù)調(diào)用將進(jìn)入系統(tǒng)空間,必然需要離開虛擬機(jī)環(huán)境,而這里的過程調(diào)用也是離開虛擬機(jī)環(huán)境的。離開虛擬機(jī)環(huán)境其實(shí)很簡單,只需要堆棧上變換一下,本來都是在VM堆棧的數(shù)據(jù)參數(shù)需要移動到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)于這條偽指令,我再來詳細(xì)解說一下,首先它通過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)里面通過[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,我們來看看00428275處是什么樣的代碼,那里只有一條跳轉(zhuǎn)指令:
00428275 -/FF25 E47D4300 JMP DWORD PTR DS:[<&KERNEL32.LoadLibrary
現(xiàn)在就很清晰了,這次call是使用LoadLibrary函數(shù)來獲取Kernel32.dll鏈接庫句柄。我們在call return address處0043EEB7處下斷,然后就可以F9運(yùn)行,直接攔截下系統(tǒng)調(diào)用結(jié)束后返回的結(jié)果EAX=7C800000�,F(xiàn)在又要回到虛擬機(jī)中了,反過來就需要把數(shù)據(jù)放回到VM堆棧中,按照VM運(yùn)行方式讓它在VM堆棧中操作。
在返回VM的過程中,首先是把原來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] ; *釋放掉對應(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的空間出來,使用上面的方式往新的buffer空間寫入數(shù)據(jù)。4個(gè)dword寫入完成后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)到新的地方,接下來毫無疑問的是繼續(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è)過程調(diào)用,我們下面來看00421C48的代碼:
00421C4E 55 PUSH EBP ; *
00421C58 8D6C24 04 LEA EBP,[ESP+4] ; *下面要使用EBP來讀取參數(shù),先保存后定位
00421C76 56 PUSH ESI ; *
00421C80 893C24 MOV DWORD PTR SS:[ESP],EDI ; *
00421C85 53 PUSH EBX ; *
00421C8C 52 PUSH EDX ; *
該保存的保存起來
00421C92 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8] ; *讀取第一個(gè)參數(shù)kernel32.dll句柄7C800000
接下來的部分和TLS中的PE文件頭定位相似,不過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)出表開始位置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 ; * 保存起來
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 指向輸入序列號數(shù)組
0041EE8B 01C7 ADD EDI,EAX ; * 輸入序列號數(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)備就緒開始讀取導(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 ; *
接下來就是比較
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)方式是通過JL和JA方式一起實(shí)現(xiàn),上面的是比較失敗后的循環(huán)。如果相同的話,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 ; *
出來到外循環(huán)看是不是已經(jīng)比較到尾部,還沒有就回去比較第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 ; *
解說不過來了,大家不明白的去復(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.
我們在平時(shí)的代碼中也經(jīng)常可以看到,call調(diào)用完畢后檢測一下是不是0,VMP也是一樣的,只是用偽指令來實(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)志位來進(jìn)行ZF位檢測+跳轉(zhuǎn)VM_JMP指令
接下來VM將會進(jìn)行一次CC碼檢測,看看VirtualProtect函數(shù)開始地址有沒有下斷點(diǎn),此部分不再復(fù)述,記錄關(guān)鍵數(shù)據(jù):
0013F78C 1AD4
0013F790 00CC7C80 |.
0013F794 00427C45 E|B.
讀取出7C801AD4函數(shù)的首字節(jié),與CC碼進(jìn)行一次減法操作,獲取其中的標(biāo)志位,進(jìn)行ZF位檢測+跳轉(zhuǎn)
在前面的EBPSTACK中一直附帶著00427C45這個(gè)數(shù)據(jù)而沒有動靜,現(xiàn)在在確定一切安全沒有問題,VM再次調(diào)用VM_JMP控制VM跳轉(zhuǎn)到00427C45位置,下面我們就來看看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子程序過程是把得到的系統(tǒng)地址加密起來存放,不讓它按照明碼的方式存儲。到這里完成了一個(gè)系統(tǒng)函數(shù)獲取到存儲的全過程,接下來程序回到 3.2.2.循環(huán) 的開頭,開始新的函數(shù)獲取,從往0013FF78壓入4個(gè)dword開始,接著就退出00427C45這個(gè)VM子程序過程。當(dāng)kernel32.dll結(jié)束后又進(jìn)入下一個(gè)DLL文件,程序回到 3.2.1.動態(tài)鏈接庫 這一部分不再復(fù)述,接下來直接粘貼獲取的函數(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 ;明碼存儲00425E60 7C92D92E到這里所有的外殼函數(shù)獲取結(jié)束,VM執(zhí)行VM_JMP跳轉(zhuǎn)走,由于最后的1條系統(tǒng)函數(shù)地址是存儲在內(nèi)存中,00425E60進(jìn)行加法操作,不讓他以明碼出現(xiàn),同時(shí)VM作為堆棧虛擬機(jī),還是喜歡堆棧的存儲方式,所以再找一個(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

    相關(guān)評論

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

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

    熱門評論

    最新評論

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

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