轉帖|使用教程|編輯:楊鵬連|2021-06-30 09:25:48.143|閱讀 765 次
概述:?看了網上大神們寫了好多的vmp 虛擬代碼的分析 ,但是在對實在項目時,插件總是提示不對或者未知版本,一直對vm代碼的還原有質疑,于是就萌發了具體分析這個vm代碼是怎么回事,若有錯誤,歡迎指出,能力有限只能分析皮毛,只談vm的代碼。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
VMProtect是一種很可靠的工具,可以保護應用程序代碼免受分析和破解,但只有在應用程序內保護機制正確構建且沒有可能破壞整個保護的嚴重錯誤的情況下,才能實現最好的效果。
VMProtect通過在具有非標準體系結構的虛擬機上執行代碼來保護代碼,這將使分析和破解軟件變得十分困難。除此之外,VMProtect還可以生成和驗證序列號,限制免費升級等等。
VMProtect正版授權在線訂購享受最低價,僅售801元起!還不趕緊加入你的訂購清單?>>更多詳情可點擊咨詢購買
相關鏈接:
代碼保護軟件VMP逆向分析虛擬機指令:初步認識與環境搭建(一)
代碼保護軟件VMP逆向分析虛擬機指令:VMP代碼的提取(二)
代碼保護軟件VMP逆向分析虛擬機指令:分析那4條匯編被VM的VM指令
五、分析VM的一些細節
我們差不多講完基礎分析是吧,基本上可以說是可以動手分析了,但是在那之前我們有些東西好像還沒講清楚,一些細節。
1、VM的棧問題
有個地方我們還沒講 ,就是如果壓棧時 , 如果超出了棧大小 (就目前我們看到的還沒有超棧的情況),占用到了vm_context怎么辦下面是我截取的匯編, 所以你看到地址有時候很奇怪 。我們來分析一下如果壓棧超出了棧空間怎么辦
00433391 8D4424 60 lea eax,dword ptr ss:[esp+0x60] 00433395 F6C5 65 test ch,0x65 00433398 3BC9 cmp ecx,ecx 0043339A 66:81FD EA79 cmp bp,0x79EA 0043339F 3BE8 cmp ebp,eax 004333A1 E9 0F3A0000 jmp vmptest_.00436DB5 00436DB5 /0F87 F2C80200 ja vmptest_.004636AD ;看到這里我們之前都是跳了 我們追蹤代碼 00436DBB |8BC4 mov eax,esp ;的時候下面的代碼就被跳過了,直接到了 00436DBD |8ACB mov cl,bl ;vmtest_.004636AD 接下來我們重點講沒跳 00436DBF |B9 40000000 mov ecx,0x40 ;過的這部分代碼 00436DC4 |0FC0F6 xadd dh,dh 00436DC7 |8D5425 80 lea edx,dword ptr ss:[ebp-0x80] 00436DCB |3BFF cmp edi,edi 00436DCD ^|E9 101CFEFF jmp vmptest_.004189E2 004189E2 81E2 FCFFFFFF and edx,0xFFFFFFFC 004189E8 F9 stc 004189E9 66:F7C7 8465 test di,0x6584 004189EE 2BD1 sub edx,ecx 004189F0 ^ E9 38D1FFFF jmp vmptest_.00415B2D 00415B2D 8BE2 mov esp,edx 00415B2F 57 push edi 00415B30 66:BF CD59 mov di,0x59CD 00415B34 0FBFF8 movsx edi,ax 00415B37 E9 FA590400 jmp vmptest_.0045B536 0045B536 56 push esi 0045B537 ^ E9 058AFEFF jmp vmptest_.00443F41 00443F41 9C pushfd 00443F42 66:0FCE bswap si 00443F45 8BF0 mov esi,eax 00443F47 66:0F46FB cmovbe di,bx 00443F4B 8BFA mov edi,edx 00443F4D E9 490E0400 jmp vmptest_.00484D9B 00484D9B FC cld 00484D9C ^ E9 9513F9FF jmp vmptest_.00416136 00416136 F3:A4 rep movs byte ptr es:[edi],byte ptr ds:[esi] 00416138 C1E6 B0 shl esi,0xB0 0041613B C1C7 FA rol edi,0xFA 0041613E 66:0FBAFF 16 btc di,0x16 00416143 9D popfd 00416144 5E pop esi 00416145 66:0FCF bswap di 00416148 8BFB mov edi,ebx 0041614A 5F pop edi 0041614B E9 5DD50400 jmp vmptest_.004636AD 004636AD FFE7 jmp edi我們先去混淆一下看看,按之前的方法
00433391 8D4424 60 lea eax,dword ptr ss:[esp+0x60] 0043339F 3BE8 cmp ebp,eax ;比較棧頂 與vm_context末尾位置 00436DB5 /0F87 F2C80200 ja vmptest_.004636AD ;如果棧頂 大于 vm_context最末尾位置 證明棧還沒有頂到vm_context 00436DBB |8BC4 mov eax,esp ;eax記錄一下vm_context位置 00436DBF |B9 40000000 mov ecx,0x40 00436DC7 |8D5425 80 lea edx,dword ptr ss:[ebp-0x80] 004189E2 81E2 FCFFFFFF and edx,0xFFFFFFFC ;讓后2位為0 地址對齊 004189EE 2BD1 sub edx,ecx ;其實就是棧頂 -0xC0 00415B2D 8BE2 mov esp,edx ;把vm_context 與棧底 拉高0xC0個字節 主要是棧底不動 vm_context動 00415B2F 57 push edi ;這一方面也是看出來為什么每次都要和esp+0x60比較 0045B536 56 push esi ------------------------------------- 00443F41 9C pushfd ;備份 edi 、esi、和eflags值 00443F45 8BF0 mov esi,eax 00443F4B 8BFA mov edi,edx 00416136 F3:A4 rep movs byte ptr es:[edi],byte ptr ds:[esi] ;然后把舊vm_context線上值 拷貝到新vm_context上 00416143 9D popfd --------------------------------------- 00416144 5E pop esi ;還原 edi、esi、和eflags值 0041614A 5F pop edi 004636AD FFE7 jmp edi然后你發現了什么問題, 在最后的rep movs中, 我們是拷貝byte為單位, 拷貝的長度是由ecx決定的,但是ecx=0x40, 而我們之前很早之前說 esp+0x60我們推出寄存器有 0x60/4=0x18 個, 蕪湖!!!!!!!那么我們現在怎么解釋呢? 這里我們應該可以看出來 vm_context應該只有16個寄存器。 即0x10個寄存器而多出來的 0x20個byte(8 int32) 應該是給壓棧時緩沖用的, 比如像這里他是先壓棧, 在判斷棧是否報棧了 ,那么如果爆棧了, 假如vm_context是0x18個寄存器, 他就會覆蓋到第0x17編號寄存器,那么他就沒辦法回縮 還原vm_context上被感染的寄存器值(如果要能還原 帶價太大) 所以這里多出的8 int32 應該是緩沖用的。
所以說分析問題 往往都是 ,從假設開始 ,你之前看到的可能 會被后面的又重新定義 ,然后你會發現
你之前的好像不太嚴謹 ,往后看這個就嚴謹了 ,好像一切 就 豁然開朗了。
2、寄存器輪轉機制
VM_PushImm32 0x00002222 ;執行下面的VM_Add后 | dwResult 0x00005555 VM_PushReg32 vm_context->0x00 ;0x00003333 | eflags 0x00000206 VM_Add VM_PopReg32 vm_context->0x1C ;0x00000206 EFLAGS VM_PopReg32 vm_context->0x1C ;0x00005555 VM_PushImm32 0x00001010 VM_PushReg32 vm_context->0x1C ;0x00005555 dwResult 上一次Add的結果 VM_PushReg32 vm_context->0x1C ;0x00005555 VM_Nand ;執行后 [ESP] = EFLAGS = 0x286 [ESP+4]=0xFFFFAAAA VM_PopReg32 vm_context->0x00 ;0x286 彈出這個后 現在棧上應該是[ESP]=0xFFFFAAAA [ESP+4]=0x0x00001010 VM_Add ;執行這個這里后 [ESP] = EFLAGS = 0x282 [ESP+4]=0xFFFFBABA VM_PopReg32 vm_context->0x0C ;0x282 eflags VM_PushReg32 vm_esp ;現在[ESP] = ESP+4 即保存這個地址 這個地址對應的值是 0xFFFFBABA 沒問題吧 VM_SSReadMemSS ;把棧頂的值當mem讀 值返回到自身 [ESP]=[[ESP]] = [ESP + 4] = 0xFFFFBABA VM_Nand ;還沒運行這個指令時[ESP]=0xFFFFBABA [ESP+4]=0xFFFFBABA VM_PopReg32 vm_context->0x20 ;0x202 eflags VM_PopReg32 vm_context->0x10 ;0x00004545 到這里 可以說這4句匯編已經運行完畢了我們可以看到 0x2222 + 0x3333 = 0x5555 如果按我們的那4句匯編來的話, 這個0x5555應該是在eax寄存器上,如果說vm_context 的某個偏移值與我們物理機的寄存器是絕對對應關系的話, 那么往下走得到的最終結果應該也是在 0x5555所在的這個寄存器上即 vm_context->0x1C, 但是我們發現不是了, 而是vm_context + 0x10上。這就是VMP所謂的寄存器輪轉機制, 這個輪轉是在程序編譯期間有一張表, 所以現在你是無法看到這個對應關系的轉變。
3、同一條指令的不同比較
------------------------------------------------------------------------------------------- VM_PushReg32 vm_context->0x1C VM_PushReg32 vm_context->0x1C /------------------------------------------------------------------------------------------ 0042E1A7 LEA ESI,DWORD PTR DS:[ESI-1] 0043B877 SUB ESI,1 0042E1AD MOVZX EAX,BYTE PTR DS:[ESI] 0043B87D ROL EAX,CL 0042E1B0 SHR DX,CL 0043B87F MOVSX ECX,DX 0042E1B3 MOVZX EDX,BX 0043B882 MOVZX EAX,BYTE PTR DS:[ESI] 0042E1B6 CDQ 0043B885 BTC CX,BX 0042E1B7 XOR AL,BL 0043B889 BTS ECX,EBX 0042E1B9 ADD ECX,605116AB 0043B88C OR DH,64 0042E1BF CMP DH,87 0043B88F XOR AL,BL 0042E1C2 ADD AL,19 0043B891 ADD AL,19 0042E1C4 ROR AL,1 0043B893 MOVZX CX,DH 0042E1C6 CMOVNB EDX,ESI 0043B897 ROR AL,1 0042E1C9 XCHG CX,DX 0043B899 JMP vmptest_.0045256F 0042E1CC MOV EDX,EBP 0045256F INC AL 0042E1CE INC AL 00452571 XOR AL,49 0042E1D0 AND DX,53E2 00452573 ROR DH,CL 0042E1D5 XOR AL,49 00452575 XOR BL,AL 0042E1D7 BSF CX,BX 00452577 MOVSX EDX,SP 0042E1DB SBB ECX,EBP 0045257A BTR ECX,ESP 0042E1DD XOR BL,AL 0045257D SUB EDX,1D2A7287 0042E1DF SAR DX,CL 00452583 MOV EDX,DWORD PTR SS:[ESP+EAX] 0042E1E2 MOV EDX,DWORD PTR SS:[ESP+EA 00452586 NOT ECX 0042E1E5 MOV CL,1A 00452588 LEA EDI,DWORD PTR DS:[EDI-4] 0042E1E7 RCR CH,CL 0045258E MOV DWORD PTR DS:[EDI],EDX 0042E1E9 MOVSX ECX,CX 00452590 SUB ESI,4 0042E1EC LEA EDI,DWORD PTR DS:[EDI-4] 00452596 DEC CX 0042E1F2 MOV DWORD PTR DS:[EDI],EDX 00452599 JMP vmptest_.00410D3E 0042E1F4 XOR CH,0A4 00410D3E MOV ECX,DWORD PTR DS:[ESI] 0042E1F7 BTS ECX,EBX 00410D40 CMC 0042E1FA SUB ESI,4 00410D41 STC 0042E200 MOV ECX,DWORD PTR DS:[ESI] 00410D42 CLC 0042E202 STC 00410D43 XOR ECX,EBX 0042E203 TEST DH,DH 00410D45 CMP EDI,ESP 0042E205 XOR ECX,EBX 00410D47 NOT ECX 0042E207 CLC 00410D49 CMP DL,0F7 0042E208 CMC 00410D4C STC 0042E209 NOT ECX 00410D4D ADD ECX,1B2352AE 0042E20B CLC 00410D53 BSWAP ECX 0042E20C ADD ECX,1B2352AE 00410D55 TEST ESP,4D941F4C 0042E212 CMC 00410D5B XOR ECX,26A7DD4 0042E213 CLC 00410D61 STC 0042E214 BSWAP ECX 00410D62 XOR EBX,ECX 0042E216 TEST EDI,EDI 00410D64 CLC 0042E218 STC 00410D65 CMP BP,11E1 0042E219 XOR ECX,26A7DD4 00410D6A CMC 0042E21F CMP CX,BX 00410D6B ADD EBP,ECX 0042E222 XOR EBX,ECX 00410D6D JMP vmptest_.0047F0F3 0042E224 STC 0047F0F3 JMP vmptest_.00472E41 0042E225 TEST ECX,ESI 00472E41 LEA EDX,DWORD PTR SS:[ESP+60] 0042E227 ADD EBP,ECX 00472E45 TEST DH,AL 0042E229 JMP vmptest_.00409E73 00472E47 CLC 00409E73 JMP vmptest_.00472E41 00472E48 CMP EDI,EDX 00472E41 LEA EDX,DWORD PTR SS:[ESP+60] 00472E4A JMP vmptest_.0046EE86 00472E45 TEST DH,AL 0046EE86 JA vmptest_.00480A05 00472E47 CLC 00480A05 JMP EBP 00472E48 CMP EDI,EDX 00472E4A JMP vmptest_.0046EE86 0046EE86 JA vmptest_.00480A05 00480A05 JMP EBP \---------------------------------------------------------------------------------指令與壓哪個寄存器無關,我這里只是恰巧找了兩個壓了相同VM寄存器的。 你看他們的主要代碼是不是一樣的, 去混淆一下, 就發現是一模一樣的, 解密都一樣,不過可能存在亂序(在不影響經結果的情況下), 而每次vmp加殼同一個程序這些同vm指令解密都不一樣。去混淆我就不去了, 很簡單 1-2min的事情 從vm的環境去提取關鍵匯編就可以了。不過我相信現在你用肉眼就已經看出來了。那么我們上面分析的東西材料我都放在demo文件夾下了。
六、簡單總結一下過程
總結就是 :
1.VM_Entry 進入虛擬機
2.VM_Init 物理環境映射虛擬機
3.VM_Init_bytescode vm的代碼解析環境初始化
4.執行VM的代碼
5.VM_Destroy 虛擬機環境壓棧
6.VM_Exit 物理環境從棧上彈出
在整個過程中我們并沒有看到有一個大循環, 心臟去驅動 去取指令, 然后解析指令是吧。 這個就是vmp3與vmp1和vmp2的最大區別,解析bytescode不在由VMDispatcher 分發下一個指令執行什么了(每個指令記為一個handle) 而是有vm_bytescode掌管,執行上一個指令才能得到下一個指令地址 這樣一來代碼的膨脹可想而知。在VM_Instruct內部應該是沒有CALL指令的。
如果您對該加密/解密軟件感興趣,歡迎加入vmpQQ交流群:740060302
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自: