天天看點

加殼軟體測試,VMProtect2.04加殼程式從入門到精通

加殼軟體測試,VMProtect2.04加殼程式從入門到精通

類型:加殼脫殼大小:13.5M語言:中文 評分:4.2

标簽:

立即下載下傳

第 7 頁 虛拟執行環境與調試器檢測

3.3.虛拟執行環境與調試器檢測

在前面所有的節裡面的内容全部都是貫穿的,沒有一個地方遺漏下來的在解析,但是這一節和上一節的結尾并沒有連接配接在一起,不是我想藏着捏着搞流水賬脫文出來,實在是沒有精力一條一條的去說。我已經想吐了,沒有心情繼續寫下去了,越是想着全盤托出,有些地方老是更有壓力害怕遺漏了東西。還有一個是想趕快結稿的心理也有一些。再說,VMP的ANTI檢測是很有趣的一個部分,當你知道下面有一節很有趣,而一直繞在上面的基礎地方,實在也有點心急。總之,如果你發現我有遺漏了沒有解說的地方就自己去看好了。下面我們就直接來到ANTI部分:

3.3.1.VMware

0013F78C 00000000 ....

0013F790 0043B7B2 C. ; RETURN from NOTEPAD.00435E6A to NOTEPAD.0043B7B2

0013F794 0013FF98 .

VM_FS:[EBPSTACK] ;讀取FS:[0]的資料

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建構新的SEH。讀取FS:[0]的原來的SEH位址,然後放入新的進去VM_SEH僞指令裡實作的,不明白的自己去看SEH相關資料。建構好SEH後程式調用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

接下來程式在

0042536C . ED IN EAX,DX ; I/O command

這條指令這裡就卡死了。為什麼呢?因為VM_EXIT中有着給各個寄存器指派的操作,其中這裡他就建構了一個VMware的後門指令檢測。在這裡算是VMP的第一個正規的ANTI來了。執行這條指令時候的CPU狀态和VMware後門檢測的源碼:

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的後門指令檢測。這個麼不用問為什麼。這個就是後門

mov eax, 564D5868h

mov ebx, 00000000h

mov ecx, 0000000Ah

mov edx, 00005658h

in eax, dx

這個檢測很普通,由于隻有在VMware下這條指令才有傳回值,否則就是一次異常。而我們是在真實環境下的。這個太普通了。我根本沒有用什麼虛拟機。想深入了解的自己google資料看。

我是沒有在VMware調試VMP,是以它必定異常出錯,現在就可以看到剛才建構的SEH的作用了。去SEH位址下斷,然後忽略異常繼續調試。

0043B7B2 .^\E9 7DD2FFFF JMP 00438A34 ; VMware SEH

我們來到了這裡繼續調試,在SEH中,将儲存目前的結構,重新初始化一個VM,并在這個VM裡面修改掉context結構中EIP指針。要看懂修改的僞指令,還是複習一下SEH回調函數:

首先看好SEH回調函數的參數,它一共有4個參數:

SEH_Handler proc _lpExceptionRecord,_lpSEH,_lpContext,_lpDispatcherContext

對應VMP裡的SEH位址看看具體資料

0013F3C4 [7C9232A8 2| ; RETURN to ntdll.7C9232A8

0013F3C8 0013F4AC . ;第一個參數:ExceptionRecord指針

0013F3CC 0013F78C . ;第二個參數:SEH指針

0013F3D0 0013F4C0 . ;第三個參數:Context指針

0013F3D4 0013F480 . ;第四個參數:DispatcherContext指針

附CONTEXT結構環境:

代碼:typedefstruct_CONTEXT{

DWORD ContextFlags;

DWORD Dr0;

DWORD Dr1;

DWORD Dr2;

DWORD Dr3;

DWORD Dr6;

DWORD Dr7;

FLOATING_SAVE_AREAFloatSave;

DWORD SegGs;

DWORD SegFs;

DWORD SegEs;

DWORD SegDs;

DWORD Edi;

DWORD Esi;

DWORD Ebx;

DWORD Edx;

DWORD Ecx;

DWORD Eax;

DWORD Ebp;

DWORD Eip; ;B8的偏移量位置是Eip

DWORD SegCs;

DWORD EFlags;

DWORD Esp;

DWORD SegSs;

BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];

}CONTEXT;

先用理論來說一下:

1)第三個參數得到context結構位址0013F4C0。

2)context結構基位址+B8得到Eip存儲位址。

3)把安全的傳回位址放入Eip位置。

4)SEH異常傳回,程式從新的Eip位址開始執行。

下面來看僞指令的操作過程:

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獲得參數的位置,加C獲得第三個參數:

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結構位址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結構B8偏移量位置是Eip位置

VM_MOVdw_MEMORYdw_EBPSTACKdw

這是3)階段,本來Eip位置是發生異常的指令位址:

0013F578 0042536C lSB. ; RETURN from NOTEPAD.00426E8B to NOTEPAD.0042536C

經過修改後,放入了傳回後的執行位址:

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)階段。最後調用VM_EXIT傳回,裡面給寄存器指派,讓系統從SEH傳回,而傳回後eip指針被修改,我們就需要從新放入的位址00436C7D攔截程式跟蹤。接下來重新初始化VM。我們繼續走起了。現在前面放置的SEH已經無用了,釋放掉恢複原來的SEH,直接放僞指令的實作過程了,不明白的查SEH資料:

0013F788 00000000 ....

VM_FS:[EBPSTACK] ;FS:[O]的值取出來,得到目前的SEH結構存儲位址

0013F788 0013F78C .

VM_MOVdw_EBPreg_EBPSTACK ;移動EBP指針下去,到達SEH結構存執位址

0013F788 00000000 ....

0013F78C 0013FFE0 . ; Pointer to next SEH record

0013F790 0043B7B2 C. ; SE handler

VM_SEH ;恢複原來的SEH,0013FFE0放入FS:[0]

3.3.2.單步模式

這個檢測方法用僞指令來實作可以說是非常非常的猥瑣。這招對于一般的人來說毫無意義,因為都是直接運作或者從來不進僞指令裡面去,很容易就過了,反倒是碰到我這樣F7單步走VM的人來說,不小心就中招了。總之十分猥瑣的方法。

0013F78C 00000000 ....

0013F790 0041F070 pA. ; RETURN from NOTEPAD.00423165 to NOTEPAD.0041F070

0013F794 0013FF98 .

VM_FS:[EBPSTACK] ;讀取FS:[0]的值目前SEH結構

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 .

建構新的SEH結構,現在的異常處理程式位址是0041F070

下面VM會進行一次OR操作,标志位00000293 OR 00000100=00000393并把結果壓入EFLAGS寄存器,僞指令過程如下:

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中,最後一個資料00000393是

00428173 9D POPFD ; *

被壓入了EFLAGS寄存器,現在我們可以看看00000100這個OR操作數影響的是Trap Flag(TF)位,這個過程就是把标志位的TF位置1。根據Intel資料:

TF (bit 8) Trap flag — Set to enable single-step mode for debugging;

clear to disable single-step mode.

也就是VM設定單步模式(single-step mode)。下面我們來回頭進好好看看00428173這個過程的詳細代碼:

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走下去,完全沒有問題。能夠一直走到JMP 004384DD這裡,然後程式就開始初始化VM,看不到任何的問題。而事實上你已經中招了。接下來就等着看被VMP發現的提示框吧。

而如果你直接在進入這個00428173的過程前來一個F9,比如說VM_EXIT僞指令處。你就會發現程式被攔截下來了

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指令這裡,程式就被攔截下來了。看一下OD下角的提示框顯示:

Break on single-step trap set by application - Shift+Run/Step to pass exception to the program

來說說原理,由于OD這樣的Ring3調試器,F7單步靠的就是TF标志位,是以如果你單步走這段代碼。VM程式設定的TF位就會和OD調試器的TF位相同,OD以為是自己的單步調試,就不會觸發這個異常,而一旦你F9運作程式,OD才會發現:哦,原來這裡調試的程式自己設定一個TF單步異常!注意看OD給的提示消息:中斷在應用程式設定的單步陷阱-Shift+Run/Step跳過程式異常