轉(zhuǎn)帖|使用教程|編輯:楊鵬連|2021-06-22 10:00:51.233|閱讀 440 次
概述:?看了網(wǎng)上大神們寫了好多的vmp 虛擬代碼的分析 ,但是在對(duì)實(shí)在項(xiàng)目時(shí),插件總是提示不對(duì)或者未知版本,一直對(duì)vm代碼的還原有質(zhì)疑,于是就萌發(fā)了具體分析這個(gè)vm代碼是怎么回事,若有錯(cuò)誤,歡迎指出,能力有限只能分析皮毛,只談vm的代碼。
# 界面/圖表報(bào)表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
VMProtect是一種很可靠的工具,可以保護(hù)應(yīng)用程序代碼免受分析和破解,但只有在應(yīng)用程序內(nèi)保護(hù)機(jī)制正確構(gòu)建且沒有可能破壞整個(gè)保護(hù)的嚴(yán)重錯(cuò)誤的情況下,才能實(shí)現(xiàn)最好的效果。
VMProtect通過在具有非標(biāo)準(zhǔn)體系結(jié)構(gòu)的虛擬機(jī)上執(zhí)行代碼來保護(hù)代碼,這將使分析和破解軟件變得十分困難。除此之外,VMProtect還可以生成和驗(yàn)證序列號(hào),限制免費(fèi)升級(jí)等等。
VMProtect正版授權(quán)在線訂購享受最低價(jià),僅售801元起!還不趕緊加入你的訂購清單?>>更多詳情可點(diǎn)擊咨詢購買
相關(guān)鏈接:
代碼保護(hù)軟件VMP逆向分析虛擬機(jī)指令:初步認(rèn)識(shí)與環(huán)境搭建
代碼保護(hù)軟件VMP逆向分析虛擬機(jī)指令:VMP代碼的提取
三、詳細(xì)分析
我們先分析一下頭和尾,那我們?cè)趺粗滥睦锊攀且粋€(gè)VM指令的開始和結(jié)束呢?記得jmp reg 和 push + ret 沒,我們就由這兩個(gè)去確定一個(gè)VM指令的范圍
VM_Entry ---------------------------------------------------------------- 0044A580 Main PUSH 83819110 ; Key 你可以看做一個(gè)密文經(jīng)過解密 壓棧1 Key 0044A585 Main CALL vmptest_.0042FA52 ; Key 經(jīng)過解密后就是bytescode 壓找2 壓返回地址 0042FA52 Main PUSH EDX ; 壓棧3 EDX 0042FA53 Main JMP vmptest_.0042BF92 0042BF92 Main PUSHFD ; 壓棧4 eflags符號(hào)寄存器 0042BF93 Main TEST CX,SI 0042BF96 Main CMC 0042BF97 Main PUSH ECX ; 壓棧5 ECX 0042BF98 Main SHLD CX,SI,0BA 0042BF9D Main ADD CL,97 ; ECX=00000097 0042BFA0 Main PUSH EBX ; 壓棧6 EBX 0042BFA1 Main MOV CL,DL ; ECX=00000008 0042BFA3 Main SHR EBX,CL ; EBX=007FFDF0 0042BFA5 Main PUSH EBP ; 壓棧7 EBP 0042BFA6 Main PUSH ESI ; 壓棧8 ESI 0042BFA7 Main PUSH EAX ; 壓棧9 EAX 0042BFA8 Main PUSH EDI ; 壓棧10 EDI 0042BFA9 Main ADD ECX,173475C8 ; ECX=173475D0 0042BFAF Main MOV EAX,0 0042BFB4 Main XOR ESI,239C226E ; ESI=239C226E 0042BFBA Main PUSH EAX ; 壓棧11 0x00000000 0042BFBB Main SETLE BH ; EBX=007F00F0 0042BFBE Main MOV ESI,DWORD PTR SS:[ESP+28] ; ESI=83819110 取ESP+0x28地址的值 0x28/4= 10 往上數(shù)第10個(gè) 0042BFC2 Main LEA ESI,DWORD PTR DS:[ESI+D093E2F1] ; ESI=54157401 從0開始數(shù) 你看看是不是取到了Key的值 注意 0042BFC8 Main NEG ESI ; ESI=ABEA8BFF 注意這個(gè) [ESP + 0x28]這個(gè)特征 現(xiàn)在賦值給ESI 0042BFCA Main BTS BP,BX ; EBP=0012FF95 0042BFCE Main JMP vmptest_.00430A03 00430A03 Main ROR ESI,1 ; ESI=D5F545FF 00430A05 Main INC ESI ; ESI=D5F54600 00430A06 Main ADD EBP,64941F8C ; EBP=64A71F21 00430A0C Main ADC CX,SP ; ECX=17347530 00430A0F Main BTR EDI,73 00430A13 Main BSWAP ESI ; ESI=0046F5D5 00430A15 Main CMOVPE EBX,ESI ; EBX=0046F5D5 00430A18 Main BTC BP,8C ; EBP=64A70F21 00430A1D Main ADD ESI,EAX 00430A1F Main MOV EBP,ESP ; EBP=0012FF60 ;注意這里EBP的賦值 記住這里現(xiàn)在ebp是上面壓的棧頂 00430A21 Main SUB ESP,0C0 ; 和這里esp的開棧 其實(shí)這里是給vm_context開空間 00430A27 Main MOV EBX,ESI ;和給vm_ss開空間 00430A29 Main MOV ECX,0 ; ECX=00000000 ;注意這里有個(gè)mov ebx,esi 解密因子 我接下來就不 00430A2E Main OR EDI,EBP ; EDI=0012FF60 ;會(huì)去多提他 如果你要運(yùn)行程序你就要注意他 這個(gè)解密因子 往上看是不是Key解密而來的 00430A30 Main SUB EBX,ECX ;分析好幾個(gè)vm 分析ebx一直指向這個(gè)vm_decryptfactor 00430A32 Main ROL CX,CL ;我不知道這樣叫他對(duì)不對(duì) 不過這不是重點(diǎn) 00430A35 Main LEA EDI,DWORD PTR DS:[430A35] ; EDI=00430A35 ;知道他是干什么的就可以了 00430A3B Main SUB CX,SI ; ECX=00000A2B ;看到這里的LEA 本身這個(gè)指令上一個(gè)地址 沒錯(cuò)他就是vm_JumpBase 相對(duì)誰去跳到下一個(gè)地址 肯定是當(dāng)前 00430A3E Main OR CL,0D5 ; ECX=00000AFF 00430A41 Main ROL CX,23 ; ECX=000057F8 00430A45 Main MOV ECX,DWORD PTR DS:[ESI] ; ECX=B0D37F60 ;到這里 經(jīng)過解密之后ESI才是真正的vm_bytescode 00430A47 Main ADD ESI,4 ; ESI=0046F5D9 ;你或者叫他(ESI)為跳轉(zhuǎn)間隔 好像也沒什么錯(cuò) 00430A4D Main TEST EDI,EBX ; 取值后 ESI +=4 往后移 00430A4F Main XOR ECX,EBX ; ECX=B0958AB5 00430A51 Main JMP vmptest_.00439FEC 00439FEC Main LEA ECX,DWORD PTR DS:[ECX+DEFE95D9] ; ECX=8F94208E 00439FF2 Main CMP AX,25AD 00439FF6 Main TEST BH,90 00439FF9 Main NOT ECX ; ECX=706BDF71 00439FFB Main TEST AL,DL 00439FFD Main CMC 00439FFE Main CMP SP,7CB8 0043A003 Main NEG ECX ; ECX=8F94208F 0043A005 Main LEA ECX,DWORD PTR DS:[ECX+A504E271] ; ECX=34990300 0043A00B Main JMP vmptest_.00416562 00416562 Main BSWAP ECX ; ECX=00039934 00416564 Main XOR EBX,ECX ; EBX=00456CE1 00416566 Main CMP SI,130B 0041656B Main ADD EDI,ECX ; EDI=0046A369 ;上面說到了取bytescode鏈上的值 0041656D Main JMP vmptest_.0045F2B5 ; 經(jīng)過解密后 與JumpBase相加得到下一個(gè)指令的地址 0045F2B5 Main PUSH EDI ; 然后把這個(gè)地址壓棧 RET反彈給物理機(jī)EIP 0045F2B6 Main RETN ;或者這里你可能也會(huì)遇到j(luò)mp edi 他們是一樣的功能
上面這個(gè)我們沒有去混淆,我們直接分析了。那么肯定是有技巧的是吧,從上往下看,push 和pushfd肯定要保留,這個(gè)是重要的,然后從下往上分析,EDI是重要的,然后看到誰影響了EDI一直這樣往上找去,有關(guān)的提取出來。另外關(guān)于ESP寄存器的要保留下來,主要是ESP減0xC0這個(gè)開VM棧空間和VM_REG空間,還有ESP在減0xC0之前把值給了誰,誰就是VM_ESP即vm棧頂(棧底),當(dāng)然給的這個(gè)寄存器不在傳遞給其他寄存器的話才行,但目前我并沒有遇到還在傳遞的情況。我們是看了開始,我們?cè)诳纯淳o跟著的VM指令:
VM_PopReg32 vm_context->0x10 --------------------------------------------------------------------------------------------- 0046A369 Main MOV EAX,DWORD PTR SS:[EBP] ;返回上面看看我們說EBP是上面壓的物理環(huán)境的棧頂 0046A36D Main STC ; 0046A36E Main ROR DL,CL ; EDX=00401080 0046A370 Main LEA EBP,DWORD PTR SS:[EBP+4] ; EBP=0012FF64 ;這里EBP = EBP + 4 棧回縮是不 那不就是出棧的意思 0046A376 Main MOVZX EDX,BYTE PTR DS:[ESI] ; EDX=0000008D ;注意這種取1byte的指令類似這個(gè) 0046A379 Main CMP CX,BP 0046A37C Main ADD ESI,1 ; ESI=0046F5DA ;ESI+1 剛剛說了esi是bytescode 他也保存了寄存器 0046A382 Main CMP CX,4F65 ;編號(hào) 我們不是之前叫他跳轉(zhuǎn)間隔嗎 噢見鬼了 0046A387 Main CMP ECX,EBX ;反正我們知道他有這樣的能力就可以 這里ESI+=1 0046A389 Main XOR DL,BL ; EDX=0000006C ;有可能他不是正向走 可能是-1 那上面的也對(duì)應(yīng)-4 0046A38B Main TEST DI,5D07 ;這沒什么好爭論的不是嗎 具體看匯編就出來了 0046A390 Main STC ;為什么會(huì)這么說 是以為我之前有遇到是反向增長 0046A391 Main NOT DL ; EDX=00000093 ;看到上面的 xor dl,bl 記得我說的EBX是解密因子了沒 0046A393 Main CMP DI,2768 0046A398 Main JMP vmptest_.0043EDAF 0043EDAF Main SUB DL,8B ; EDX=00000008 0043EDB2 Main CMC 0043EDB3 Main ROR DL,1 ; EDX=00000004 0043EDB5 Main DEC DL ; EDX=00000003 0043EDB7 Main JMP vmptest_.00413DC1 00413DC1 Main NOT DL ; EDX=000000FC 00413DC3 Main CMP SP,6B29 00413DC8 Main JMP vmptest_.00416D48 00416D48 Main ADD DL,14 ; EDX=00000010 00416D4B Main STC 00416D4C Main XOR BL,DL ; EBX=00456CF1;而這里我們主要關(guān)心EDX的值不是嗎 這里是0x10 00416D4E Main MOV DWORD PTR SS:[ESP+EDX],EAX ; 發(fā)現(xiàn)EDX是從上面去esi地址1byte值經(jīng)過變化而來的 00416D51 Main AND DH,0F7 ; 而我們之前說的什么ESP指向的是vm_context是吧 00416D54 Main NEG DX ; EDX=0000FFF0;在結(jié)合我們上面的分析 這應(yīng)該是一個(gè)出棧的操作 00416D57 Main MOV EDX,DWORD PTR DS:[ESI] ; EDX=E45184BF;在次取ESI (bytescode)的值 關(guān)鍵 這個(gè)是跳轉(zhuǎn)間隔密文 00416D59 Main CMP ESI,EDI 00416D5B Main CMC 00416D5C Main JMP vmptest_.00419F08 00419F08 Main ADD ESI,4 ; ESI=0046F5DE;ESI += 4 00419F0E Main STC 00419F0F Main XOR EDX,EBX ; EDX=E414E84E 00419F11 Main TEST DH,36 00419F14 Main XOR EDX,29474E33 ; EDX=CD53A67D 00419F1A Main TEST ESP,EDX 00419F1C Main ADD EDX,64682765 ; EDX=31BBCDE2 00419F22 Main JMP vmptest_.00472890 00472890 Main NEG EDX ; EDX=CE44321E 00472892 Main TEST SI,BX 00472895 Main STC 00472896 Main ADD EDX,44017C67 ; EDX=1245AE85 0047289C Main JMP vmptest_.00463068 00463068 Main ROR EDX,1 ; EDX=8922D742 0046306A Main CMP CX,DI 0046306D Main STC 0046306E Main CMP DI,358A 00463073 Main NEG EDX ; EDX=76DD28BE 00463075 Main JMP vmptest_.0047F903 0047F903 Main BSWAP EDX ; EDX=BE28DD76 0047F905 Main INC EDX ; EDX=BE28DD77 0047F906 Main STC 0047F907 Main XOR EDX,41D507D0 ; EDX=FFFDDAA7 0047F90D Main XOR EBX,EDX ; EBX=FFB8B656;注意這里解密因子 ebx 改變 每一個(gè)vm指令都有這個(gè) 0047F90F Main CMP SP,BP 0047F912 Main TEST EDX,29E10AB5 ;解密因子的參與 接下來我就不多提他了 記得每個(gè)指令都有 0047F918 Main STC ;而且每運(yùn)行一個(gè)vm指令 他都會(huì)變 0047F919 Main ADD EDI,EDX ; EDI=00447E10;跳轉(zhuǎn)間隔經(jīng)過解密后 與JumpBase相加 0047F91B Main JMP vmptest_.00420B9F 00420B9F Main PUSH EDI 00420BA0 Main RETN ;跳轉(zhuǎn)到下一條指令地址 -------------------------------------------------------------------------------------------------然后針對(duì)VM指令非入口和出口的分析,也有方法,當(dāng)然可能這些方法這是適用我們當(dāng)前遇到的指令(即目前這個(gè)demo)。看到第一條指令是取VM_ESP位置的uint32_t值 ,然后VM_ESP回縮4byte,第一反應(yīng)就是這個(gè)應(yīng)該是pop操作,在往下看看,能不能看到MOV [ESP + REG1],REG2 這個(gè)樣子的匯編,OK能找到,那么明顯就是棧中彈數(shù)據(jù)到VM_REG中了。在往下看是取VM_Bytescode中的值然后解密與VM_JumpBase相加。無疑是VM_PopReg32了,但是那個(gè)寄存器呢?看到
00416D4E Main MOV DWORD PTR SS:[ESP+EDX],EAX ;往上看到EDX的值 看右邊的追蹤結(jié)果 EDX=0x10所以我們這里應(yīng)該翻譯為VM_PopReg32 vm_context->0x10 或者 VM_PopReg32 DwReg4 (0x10/4=4) 可能名字和別人不一樣,差不多就是這個(gè)意思。注意看看這個(gè)EDX的值也是從VM_Bytescode中得到解密出來的。然后緊跟著的幾條重要的VM指令我就不一一分析了,和上面是同理的,我直接貼分析出的VM指令
[---------VM_Init--------] 這里我們可以又把這幾條vm指令解釋為VM_Init 主要是把物理環(huán)境反彈到虛擬機(jī)里面 /---------------------------------------------------------------------- VM_PopReg32 vm_context->0x10 0x00000000 VM_PopReg32 vm_context->0x2C VM_PopReg32 vm_context->0x18 VM_PopReg32 vm_context->0x28 VM_PopReg32 vm_context->0x20 0x0012FF94 VM_PopReg32 vm_context->0x08 0x7FFDF000 VM_PopReg32 vm_context->0x24 0x00000000 VM_PopReg32 vm_context->0x3C 0x00000246 VM_PopReg32 vm_context->0x30 0x00401008 VM_PopReg32 vm_context->0x14 0x0044A58A 那我們很早之前說的上面壓棧是保存物理機(jī)環(huán)境就不太對(duì)了 VM_PopReg32 vm_context->0x0C 0x83819110 應(yīng)該說是 物理機(jī)環(huán)境映射到虛擬機(jī)的一個(gè)過渡 \-------------------------------------------------------------------------把物理環(huán)境彈入VM寄存器環(huán)境后,重新調(diào)整vm_bytescode的指向和之前的VM_REG亂序,就比如上面這個(gè)vm_context->0x14是push + call 中call的下一個(gè)地址 ,經(jīng)過調(diào)整后vm_context->0x14也就不是這個(gè)地址了(這個(gè)地址并不是退出VM后僅跟著的執(zhí)行真實(shí)匯編的地址),再比如EBP是vm_bytescode,變換后EBP可能就不是了,可能是EBX或者EAX等。我就不貼代碼了,之后會(huì)有整理。
VM_Exit /------------------------------------------------------------------------------ 0047A839 Main MOV ESP,EDI ;虛擬機(jī)棧給物理機(jī)esp棧 沒錯(cuò)了這里應(yīng)該是要 0047A83B Main OR AX,CX ; EAX=0000EFEA;返回物理機(jī)了 0047A83E Main POP ECX ; ECX=00000000;彈棧 ECX 0047A83F Main ROR DX,CL ;看到這么多pop 看來是真的要還原到物理機(jī)了 0047A842 Main CMP DH,DL ;在看看我們的進(jìn)度條 也到底了 終于分析完了 0047A844 Main POP EBP ; EBP=0012FF94;彈棧 EBP 0047A845 Main POP EAX ; EAX=00004545;彈棧 EAX 0047A846 Main POP EBX ; EBX=7FFDF000;彈棧 EBX 0047A847 Main OR DI,73E7 ; EDI=0012FFEF 0047A84C Main ADC DI,6287 ; EDI=00126276 0047A851 Main CMOVO SI,DI 0047A855 Main POP EDI ; EDI=00000000;彈棧 EDI 0047A856 Main CWD ; EDX=00120000 0047A858 Main POPFD ;彈棧 EFLAGS 符號(hào)寄存器 0047A859 Main POP ESI ; ESI=00000000;彈棧 ESI 0047A85A Main POP EDX ; EDX=00401008;彈棧 EDX 0047A85B Main RETN ;返回物理機(jī) Breakpoint at vmptest_.00401040 00401040 Main PUSH EAX ; <%04X> = 4545 返回物理機(jī)第一條匯編 Run trace closed我們可以看到ESP寄存器的值被EDI賦值了,然后從棧中彈出值到物理機(jī)(真實(shí)環(huán)境)的寄存器中。那么這個(gè)EDI應(yīng)該是被安排了真實(shí)環(huán)境的值,很可能他就是VM_ESP是吧。我們?cè)谕戏治鲆幌驴纯矗?我直接貼關(guān)鍵的VM指令
[---------VM_Destroy----------] 下面的這幾句你可以各類為新的vm指令 他其實(shí)就是準(zhǔn)備退出虛擬機(jī)時(shí)把 處理后的物理環(huán)境壓棧 /---------------------------------------------------------------------------------------- VM_PushImm32 0x00401040 retAddr VM_PushReg32 vm_context->0x14 0x00401008 VM_PushReg32 vm_context->0x30 0x00000000 VM_PushReg32 vm_context->0x18 0x00000202 VM_PushReg32 vm_context->0x24 0x00000000 VM_PushReg32 vm_context->0x04 0x7FFDF000 VM_PushReg32 vm_context->0x10 0x00004545 我們要的最終值 VM_PushReg32 vm_context->0x3C 0x0012FF94 VM_PushReg32 vm_context->0x28 0x00000000 \-------------------------------------------------------------------------------------------這里我就不展示EDI是VM_ESP了,我可以告訴你他是的。看看這個(gè)返回地址他是由VM_Bytescode中得到的,還記得我們VM_Entry進(jìn)來時(shí)壓的那個(gè)push + call 中 call指令后面的地址嗎,不是返回僅跟著CALL后面地址的位置,所以我們往往在那個(gè)地方下斷點(diǎn)就沒作用。
如果您對(duì)該加密/解密軟件感興趣,歡迎加入加密/解密QQ交流群:740060302
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請(qǐng)務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請(qǐng)郵件反饋至chenjj@fc6vip.cn
文章轉(zhuǎn)載自: