為了提高開發的軟件産品安全性,大部分選擇的方案防護方案是,通過用成熟的加固軟件進行對自己研發的軟件做防護,從而達到對軟件搭建一個安全防護牆。加固軟件主要做的兩件事,對軟件中關鍵代碼的保護以及提高對軟件逆向反編譯的門檻。
那麼軟件安全性防護牆的第一道門那就是反調試。反調試技術又細分為靜态反調試和動态反調試。下面就針對window端的進行梳理反調試檢測方案。
進程環境塊BeingDebugged檢測通過讀取進程環境塊PEB中,是否設置BeingDebugged标志(其實這個标志IsDebuggerPreseNt跟這個函數内部執行效果是一樣的),這個PEB(進程環境塊)指針指向的值。
在x86環境下通過FS:[0x30]獲取PEB的值;
在X64環境下通過GS:[0x60]獲取PEB值;
當這個值等于0的情況下,表示沒被調試,否則就處于調試狀态。
進程環境塊NtGlobalFlag檢測
進程環境塊PEB中NtGlobalFlag是一個DWORD值,這個值包含操作系統設置的許多标志,這些标志會影響進程的運行方式。這個字段在程序正常運行的情況下值默認為0,在被調試器調試的時候(如ollydbg動态調試),這個字段為0x70(注意:ollydbg附加狀态下是沒改變的)。
進程環境塊HeapFlags檢測當程序在調試下運行,并使用調試器進程創建标志創建時,HeapFlags标志更正常程序運行的标志值是不一緻的。
對于X86系統,Vista以上版本的HeapFlags位于0x40偏移, 低于Vista版本的位于0x0C
對于X64系統,Vista以上版本的HeapFlags位于0x70偏移,低于Vista版本的位于0x14偏移
如果這個HeapFlags的值大于2,那麼表示處于被調試狀态,如果這個值等于2,那麼屬于正常狀态。
進程環境塊ForceFlags檢測當程序在調試下運行,并使用調試器進程創建标志創建時,ForceFlags标志跟正常運行的程序是不一緻的。
對于X86系統,Vista以上版本的HeapFlags位于0x44偏移, 低于Vista版本的位于0x10偏移
對于X64系統,Vista以上版本的HeapFlags位于0x74偏移,低于Vista版本的位于0x18偏移
如果這個ForceFlags的值大于0,那麼表示處于被調試狀态,如果這個值等于2,那麼屬于正常狀态。
IsDebuggerPresent 檢測通過直接利用系統 IsDebuggerPresent函數,進行判斷當前程序是否處于調試狀态。
如果程序處于調試狀态的情況下,那麼這個函數的返回返回真,否則返回假。
CheckRemoteDebuggerPresent 檢測
它是微軟公開的系統函數,通過利用它可以用于檢測,軟件是否正在調試遠程進程(同一機器上的不同進程中,是否附加到當前進程)。
我們還可以将其用作另一種方法來檢測,軟件是否處于正在調試。此函數在内部調用NTDLL模塊的導出PROCESSINFOCLASS設置為NtQueryInformationProcess函數7(進程調試端口)。本質上是通過NtQueryInformationProcess函數查詢是否使用調試端口。
NtQueryInformationProcess 檢測
這個是微軟未公開的函數,下面是這個函數的參數信息,可以利用這個函數的第三個參數值,也就是利用PROCESSINFOCLASS值,進行判斷是否處于調試狀态。
當程序處于調試狀态時,系統會給它分配一個調試端口(Debug Port),當程序正常運行狀态時ProcessDebugPort的值為0,當程序處于調試狀态ProcessDebugPort的值為0xFFFFFFFF。
當程序處于調試狀态時,這個PROCESSINFOCLASS指向ProcessDebugObjectHandle的值是一個句柄值,當程序處于正常狀态這個ProcessDebugObjectHandle值為NULL值。
當程序處于調試狀态時,這個PROCESSINFOCLASS指向ProcessDebugFlags的值為0,當程序處于正常狀态 時,這個ProcessDebugFlags值為1。
SetUnhandleExceptionFilte 檢測
通過利用SetUnhandledExceptionFilter,可以注冊一個異常處理函數,當一個異常産生,而且我們的 try - catch(或 try - expect)異常捕獲中,沒有處理處理這個異常時,異常會轉交給 SetUnhandledExceptionFilter 。如果程序存在調試器狀态,則調試器就會接管這個異常,那麼這個異常就不會走到 SetUnhandledExceptionFilter 注冊的異常處理函數。
原理:通過設置一個SetUnhandledExceptionFilter。然後利用RaiseException提出一個異常交給異常處理機制 由于沒有設置相應的異常處理程序, 當程序被調試時,會通知進程的調試器,而不會調用UnhandledExceptionFilter。
SetHandleInformation 檢測
通過創建一個互斥體對象,利用# SetHandleInformation将互斥體對象句柄标志改為HANDLE_FLAG_PROTECT_FROM_CLOSE,然後關閉句柄,如果是在調試器狀态下,它會抛出EXCEPTION_EXECUTE_HANDLER異常,隻要捕獲到異常那麼就表示程序被調試。
CloseHandle 檢測
利用異常捕獲機制,給CloseHandle函數一個無效的句柄作為輸入參數,在程序在沒有被調試時,将會返回一個錯誤代碼;而程序被調試器調試時,将會觸發一個EXCEPTION_INVALID_HANDLE的異常。
父進程反調試檢測
在window系統中explorer是程序管理器或者文件管理器,一般雙擊運行的進程,它的父進程就都是explorer程序,如果是被調試進程啟動的話那麼父進程是調速器進程。通過利用CreateToolhelp32Snapshot函數或ZwQueryInformationProcess函數進行檢測進程的父進程名稱。
硬件斷點反調試檢測
硬件斷點是intel在其處理器體系結構中實現的一種技術,通過使用Dr0-Dr7的特殊寄存器進行控制。在32位寄存器中Dr0-Dr3是保存斷點地址,隻要識别Dr0-Dr3寄存器的值不為0,那麼就屬于調試狀态。
軟件斷點反調試檢測在IA-32指令集中使用操作碼0xCC,表示軟件斷點,也就是INT3斷點。
通過Int3産生異常中斷的反調試相對比較經典。Ollydbg的斷點機制就是利用這個機制, 當INT3 被執行到時, 如果程序未被調試, 将會異常處理器程序繼續執行。而INT3指令常被調試器用于設置軟件斷點,int 3會導緻調試器誤認為這是一個自己的斷點,從而不會進入異常處理程序。
其他反調試檢測通過利用FindWindow(),GetWindowLongA(),EnumWindow()等函數,進行遍曆檢測調試器的的窗口及控件相關信息;
通過CreateToolhelp32Snapshot等函數遍曆運行進程,檢測調試器相關的進程名信息,
通過查找注冊表的方式,檢測調試器的信息。
通過檢測驅動設備名稱,檢測調試器的特征碼等相關信息。
總結以上梳理的應用層反調試方案建議結合使用,可以同時提高對應的難點。反調試隻是一定情況下提高軟件安全門檻,因為雖然有反調試方案,但同時也會有過掉反調試的方案。一般過掉反調試檢測方案,通過将關鍵的反調試檢測地方給 nop掉或者hook掉關鍵函數。反調試和反反調試的方案都是相對的,并不是絕對的安全。反而調試強度更高的方案在于驅動層去檢測實現。
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!