静态反调试技术(3)
文章目錄
- ZwSetInformationThread
- 破解方法
- **調試程序代碼**:
- 利用TLS回調函數(詳情通過以下鏈接查看)
- ETC
- 破解之法
- **調試程序代碼**:
- 篇章大總結:
- 反調試技術系列:
ZwSetInformationThread
強制分離(Detach)被調試者和調試器的技術。利用ZwSetInformationThread()API,被調試者可將自身從調試器中分離出來
typedef enum _THREAD_INFORMATION_CLASS {ThreadBasicInformation,ThreadTimes,ThreadPriority,ThreadBasePriority,ThreadAffinityMask,ThreadImpersonationToken,ThreadDescriptorTableEntry,ThreadEnableAlignmentFaultFixup,ThreadEventPair,ThreadQuerySetWin32StartAddress,ThreadZeroTlsCell,ThreadPerformanceCount,ThreadAmILastThread,ThreadIdealProcessor,ThreadPriorityBoost,ThreadSetTlsArrayAddress,ThreadIsIoPending,ThreadHideFromDebugger // 17 (0x11)} THREAD_INFORMATION_CLASS, *PTHREAD_INFORMATION_CLASS;typedef NTSTATUS (WINAPI* ZWSETINFORMATIONTHREAD)(HANDLE ThreadHandle,THREAD_INFORMATION_CLASS ThreadInformationClass,PVOID ThreadInformation,ULONG ThreadInformationLength);ZwSetInformationThread()函數是一個系統原生API(System Native API),它是用來為線程設置信息的。該函數有2個參數,第一個參數ThreadHandle用來接收當前線程的句柄,第二個參數ThreadInformationClass表示線程信息類型,若其值設置為ThreadHideFromDebugger(0x11),調用該函數后,調試進程就會被分離出來。ZwSetInformationThread() API不會對正常的程序(非調試運行)產生任何影響,但若運行的是調試程序,調用該API將使調試器終止運行,同時終止自身進程。
破解方法
簡單的破解思路就是:調用0x00DA1823 地址處的ntdll.ZwSetInformationThreadAPI前,查找存儲在棧中的第二個參數ThreadInformationClass值,若值為ThreadHideFromDebugger(0x11),則修改為0后繼續運行即可
當然也可以勾取ZwSetInformationThread()API,并以同樣的方式操作函數的參數。
提示:
利用ZwSetInformationThread()進行反調試的工作原理是:將線程隱藏起來,調試器就接受不到信息,從而無法調試。另外,Windows XP 以后新增了 DebugActiveProcessStop()API
DebugActiveProcessStop()API用來分離調試器和被調試進程從而停止調試。而前面介紹的ZwSetInformationThread()API則是用來隱藏當前線程,使調試器無法再接收到該線程的調試事件,最終停止調試。
調試程序代碼:
#include "stdio.h" #include "windows.h" #include "tchar.h"void DetachDebugger() {//強制分離被調試者和調試器的技術。調試器與被調試進程同時終止typedef enum _THREAD_INFORMATION_CLASS {ThreadBasicInformation,ThreadTimes,ThreadPriority,ThreadBasePriority,ThreadAffinityMask,ThreadImpersonationToken,ThreadDescriptorTableEntry,ThreadEnableAlignmentFaultFixup,ThreadEventPair,ThreadQuerySetWin32StartAddress,ThreadZeroTlsCell,ThreadPerformanceCount,ThreadAmILastThread,ThreadIdealProcessor,ThreadPriorityBoost,ThreadSetTlsArrayAddress,ThreadIsIoPending,<span style="color:#ff0000;"> ThreadHideFromDebugger // 17 (0x11)</span>} THREAD_INFORMATION_CLASS, *PTHREAD_INFORMATION_CLASS;typedef NTSTATUS (WINAPI* ZWSETINFORMATIONTHREAD)(HANDLE ThreadHandle,THREAD_INFORMATION_CLASS ThreadInformationClass,PVOID ThreadInformation,ULONG ThreadInformationLength);ZWSETINFORMATIONTHREAD pZwSetInformationThread = NULL;pZwSetInformationThread = (ZWSETINFORMATIONTHREAD)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "ZwSetInformationThread");pZwSetInformationThread(GetCurrentThread(), ThreadHideFromDebugger, NULL, 0);printf("ZwSetInformationThread() -> Debugger detached!!!\n\n"); }int _tmain(int argc, TCHAR* argv[]) {DetachDebugger();printf("\npress any key to quit...\n");_gettch();return 0; }利用TLS回調函數(詳情通過以下鏈接查看)
https://blog.csdn.net/CSNN2019/article/details/113094488
ETC
判斷當前系統是否為逆向分析系統(非常規系統),若是,則直接停止程序。這些技術都能從系統中輕松獲取各種信息(進程,文件,窗口,注冊表,主機名,計算機名,用戶名,環境變量等)。這些都可以借助Win32API獲取系統信息來實現,舉幾個例子:
破解之法
要想讓FindWindow()失效,只需要在調用FindWindow()把棧中0xC7F668這個名稱字符串用NULL來覆蓋即可,那么FindWindow()API將無法探測到相應的調試器
修改后:
接下來要讓GetWindowText() API失效,調用GetWindowText() API的代碼在0xDA192D處。若想正常調用GetWindowText(),就不能執行0xDA1912地址處的條件跳轉指令。要實現這點,可以直接操作條件跳轉語句,也可以將其上GetDesktopWindow()和GetWindow()API的返回值修改為NULL
總之呢,見招拆招,加油
調試程序代碼:
#include "stdio.h" #include "windows.h" #include "tchar.h"void FindDebuggerWindow() {BOOL bDebugging = FALSE;// using ClassNameif( FindWindow(L"OllyDbg", NULL) || // OllyDbgFindWindow(L"TIdaWindow", NULL) || // IDA ProFindWindow(L"WinDbgFrameClass", NULL) ) // WindbgbDebugging = TRUE;printf("FindWindow()\n");if( bDebugging ) printf(" => Found a debugger window!!!\n\n");else printf(" => Not found a debugger window...\n\n");// using WindowNamebDebugging = FALSE;TCHAR szWindow[MAX_PATH] = {0,};HWND hWnd = GetDesktopWindow();hWnd = GetWindow(hWnd, GW_CHILD);hWnd = GetWindow(hWnd, GW_HWNDFIRST);while( hWnd ){if( GetWindowText(hWnd, szWindow, MAX_PATH) ){if( _tcsstr(szWindow, L"IDA") ||_tcsstr(szWindow, L"OllyDbg") ||_tcsstr(szWindow, L"WinDbg") ){bDebugging = TRUE;break;}}hWnd = GetWindow(hWnd, GW_HWNDNEXT);}printf("GetWindowText()\n");if( bDebugging ) printf(" => Found a debugger window!!!\n\n");else printf(" => Not found a debugger window...\n\n"); }int _tmain(int argc, TCHAR* argv[]) {FindDebuggerWindow();printf("\npress any key to quit...\n");_gettch();return 0; }篇章大總結:
1.PEB結構中有幾個重要的成員標示了進程是否處于被調試狀態。(以下以32位為例)
+0x002 BeingDebugged : UChar
+0x00c Ldr : _PEB_LDR_DATA
+0x018 ProcessHeap : Ptr32 Void
+0x068 NtGlobalFlag : Uint4B
BeingDebugged成員在被調試狀態會顯示1,正常情況下為0。解決方法:更改該值為0。
Ldr:進程在被調試狀態時堆內存區域會出現一些特殊的標志,未使用的堆內存區域全部填充著0xFEEEFEEE,而Ldr正好在堆內存中被創建(只在XP系統中有,Vista之后的系統沒有這種標志)。解決方法:將該區域覆蓋為NULL即可。
ProcessHeap:ProcessHeap.Flags(+0x00c)在正常情況下值為0x2,ProcessHeap.ForceFlags成員(+0x10)的值為0x0,當調試時,該值會改變。(只在XP中有效)。解決辦法:只需將值改回去即可。
NtGlobalFalg:PEB.NtGlobalFlag會在調試情況下顯示0x70,該值是以下Flags值or運算的結果:(附加到進程無效,只有啟動調試有效)
FLG_HEAP_ENABLE_TAIL_CHECK (0x10)
FLG_HEAP_ENABLE_FREE_CHECK (0x20)
FLG_HEAP_VALIDATE_PARAMETERS (0x40)
解決方法:重置0即可
2.NtQueryInformationProcess()可以查詢ProcessDebugPort(0x7),ProcessDebugObjectHandle(0x1E)ProcessDebugFlags(0x1F)
當進程處于調試狀態時,系統會給它分配一個調試端口(Debug Port),正常狀態dwDebugPort為,調試狀態為0xFFFFFFFF
當進程處于調試狀態時,ProcessDebugObjectHandle一個句柄值,正常狀態為NULL
當進程處于調試狀態時,ProcessDebugFlags為0,正常為1
3.NtQueryObject()函數可以枚舉系統所有對象,通過觀察系統是否有調試對象句柄,就可以知道是否有進程在被調試。(wcscmp(L"DebugObject",pObjectTypeInfo->TypeName.Buffer)==0),解決方法,改變該函數參數
4.ZwSetInformationThread()該函數顧名思義是給線程設置信息的。該函數有兩個參數,第一個參數ThreadHandle為線程句柄,第二參數ThreadInformationClass表示線程信息類型,其值設置為ThreadHideFromDebugger(0x11),調用該函數后,調試進程將會與調試器分離開來,使調試器終止調試,同時終止自身進程。該函數對正常運行程序沒有影響。
6.TLS(線程局部存儲)TLS函數代碼會先于main()函數執行,于是我們可以在這里進行對程序是否被調試的判斷,例如判斷是否被下了int3斷點,PEB中的BeingDebugged是否為1等。
7.ETC利用API獲得進程窗口,進程,計算機名稱,虛擬機是否在運行狀態等判斷運行環境是否安全。
反調試技術系列:
靜態反調試技術(1)https://blog.csdn.net/CSNN2019/article/details/113105292
靜態反調試技術(2)https://blog.csdn.net/CSNN2019/article/details/113147820
靜態反調試技術(3)https://blog.csdn.net/CSNN2019/article/details/113178232
動態反調試技術 https://blog.csdn.net/CSNN2019/article/details/113181558
高級反調試技術 https://blog.csdn.net/CSNN2019/article/details/113263215
總結
以上是生活随笔為你收集整理的静态反调试技术(3)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: TLS回调函数(1)
- 下一篇: 动态反调试技术