日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

静态反调试技术(3)

發(fā)布時間:2025/3/21 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 静态反调试技术(3) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • ZwSetInformationThread
    • 破解方法
    • **調(diào)試程序代碼**:
  • 利用TLS回調(diào)函數(shù)(詳情通過以下鏈接查看)
  • ETC
    • 破解之法
    • **調(diào)試程序代碼**:
  • 篇章大總結(jié):
  • 反調(diào)試技術(shù)系列:

ZwSetInformationThread

強制分離(Detach)被調(diào)試者和調(diào)試器的技術(shù)。利用ZwSetInformationThread()API,被調(diào)試者可將自身從調(diào)試器中分離出來

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()函數(shù)是一個系統(tǒng)原生API(System Native API),它是用來為線程設(shè)置信息的。該函數(shù)有2個參數(shù),第一個參數(shù)ThreadHandle用來接收當前線程的句柄,第二個參數(shù)ThreadInformationClass表示線程信息類型,若其值設(shè)置為ThreadHideFromDebugger(0x11),調(diào)用該函數(shù)后,調(diào)試進程就會被分離出來。ZwSetInformationThread() API不會對正常的程序(非調(diào)試運行)產(chǎn)生任何影響,但若運行的是調(diào)試程序,調(diào)用該API將使調(diào)試器終止運行,同時終止自身進程。




破解方法

簡單的破解思路就是:調(diào)用0x00DA1823 地址處的ntdll.ZwSetInformationThreadAPI前,查找存儲在棧中的第二個參數(shù)ThreadInformationClass值,若值為ThreadHideFromDebugger(0x11),則修改為0后繼續(xù)運行即可

當然也可以勾取ZwSetInformationThread()API,并以同樣的方式操作函數(shù)的參數(shù)。

提示:
利用ZwSetInformationThread()進行反調(diào)試的工作原理是:將線程隱藏起來,調(diào)試器就接受不到信息,從而無法調(diào)試。另外,Windows XP 以后新增了 DebugActiveProcessStop()API

BOOL WINAPI DebugActiveProcessStop( __in DWORD dwProcessId );

DebugActiveProcessStop()API用來分離調(diào)試器和被調(diào)試進程從而停止調(diào)試。而前面介紹的ZwSetInformationThread()API則是用來隱藏當前線程,使調(diào)試器無法再接收到該線程的調(diào)試事件,最終停止調(diào)試。

調(diào)試程序代碼

#include "stdio.h" #include "windows.h" #include "tchar.h"void DetachDebugger() {//強制分離被調(diào)試者和調(diào)試器的技術(shù)。調(diào)試器與被調(diào)試進程同時終止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回調(diào)函數(shù)(詳情通過以下鏈接查看)

https://blog.csdn.net/CSNN2019/article/details/113094488

ETC

判斷當前系統(tǒng)是否為逆向分析系統(tǒng)(非常規(guī)系統(tǒng)),若是,則直接停止程序。這些技術(shù)都能從系統(tǒng)中輕松獲取各種信息(進程,文件,窗口,注冊表,主機名,計算機名,用戶名,環(huán)境變量等)。這些都可以借助Win32API獲取系統(tǒng)信息來實現(xiàn),舉幾個例子:

  • 檢測OllyDbg窗口----->FindWindow()
  • 檢測OllyDbg進程------>CreatToolhelp32Snapshot()
  • 檢查計算機名稱是否為“TEST”,“ANALYSIS”等------->GetComputerName()
  • 檢查程序運行路徑是否存在“TEST”,“SAMPLE”等名稱------->GetCommandLine()
  • 檢測虛擬機是否處于運行狀態(tài)(查看虛擬機特有的進程名稱---->VMWareService.exe,VMWareTray.exe,VMWareUser.exe等)
  • 破解之法


    要想讓FindWindow()失效,只需要在調(diào)用FindWindow()把棧中0xC7F668這個名稱字符串用NULL來覆蓋即可,那么FindWindow()API將無法探測到相應(yīng)的調(diào)試器
    修改后:

    接下來要讓GetWindowText() API失效,調(diào)用GetWindowText() API的代碼在0xDA192D處。若想正常調(diào)用GetWindowText(),就不能執(zhí)行0xDA1912地址處的條件跳轉(zhuǎn)指令。要實現(xiàn)這點,可以直接操作條件跳轉(zhuǎn)語句,也可以將其上GetDesktopWindow()和GetWindow()API的返回值修改為NULL


    總之呢,見招拆招,加油

    調(diào)試程序代碼

    #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; }

    篇章大總結(jié):

    1.PEB結(jié)構(gòu)中有幾個重要的成員標示了進程是否處于被調(diào)試狀態(tài)。(以下以32位為例)
    +0x002 BeingDebugged : UChar
    +0x00c Ldr : _PEB_LDR_DATA
    +0x018 ProcessHeap : Ptr32 Void
    +0x068 NtGlobalFlag : Uint4B

    BeingDebugged成員在被調(diào)試狀態(tài)會顯示1,正常情況下為0。解決方法:更改該值為0。
    Ldr:進程在被調(diào)試狀態(tài)時堆內(nèi)存區(qū)域會出現(xiàn)一些特殊的標志,未使用的堆內(nèi)存區(qū)域全部填充著0xFEEEFEEE,而Ldr正好在堆內(nèi)存中被創(chuàng)建(只在XP系統(tǒng)中有,Vista之后的系統(tǒng)沒有這種標志)。解決方法:將該區(qū)域覆蓋為NULL即可。
    ProcessHeap:ProcessHeap.Flags(+0x00c)在正常情況下值為0x2,ProcessHeap.ForceFlags成員(+0x10)的值為0x0,當調(diào)試時,該值會改變。(只在XP中有效)。解決辦法:只需將值改回去即可。
    NtGlobalFalg:PEB.NtGlobalFlag會在調(diào)試情況下顯示0x70,該值是以下Flags值or運算的結(jié)果:(附加到進程無效,只有啟動調(diào)試有效)
    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)
    當進程處于調(diào)試狀態(tài)時,系統(tǒng)會給它分配一個調(diào)試端口(Debug Port),正常狀態(tài)dwDebugPort為,調(diào)試狀態(tài)為0xFFFFFFFF
    當進程處于調(diào)試狀態(tài)時,ProcessDebugObjectHandle一個句柄值,正常狀態(tài)為NULL
    當進程處于調(diào)試狀態(tài)時,ProcessDebugFlags為0,正常為1
    3.NtQueryObject()函數(shù)可以枚舉系統(tǒng)所有對象,通過觀察系統(tǒng)是否有調(diào)試對象句柄,就可以知道是否有進程在被調(diào)試。(wcscmp(L"DebugObject",pObjectTypeInfo->TypeName.Buffer)==0),解決方法,改變該函數(shù)參數(shù)
    4.ZwSetInformationThread()該函數(shù)顧名思義是給線程設(shè)置信息的。該函數(shù)有兩個參數(shù),第一個參數(shù)ThreadHandle為線程句柄,第二參數(shù)ThreadInformationClass表示線程信息類型,其值設(shè)置為ThreadHideFromDebugger(0x11),調(diào)用該函數(shù)后,調(diào)試進程將會與調(diào)試器分離開來,使調(diào)試器終止調(diào)試,同時終止自身進程。該函數(shù)對正常運行程序沒有影響。
    6.TLS(線程局部存儲)TLS函數(shù)代碼會先于main()函數(shù)執(zhí)行,于是我們可以在這里進行對程序是否被調(diào)試的判斷,例如判斷是否被下了int3斷點,PEB中的BeingDebugged是否為1等。
    7.ETC利用API獲得進程窗口,進程,計算機名稱,虛擬機是否在運行狀態(tài)等判斷運行環(huán)境是否安全。

    反調(diào)試技術(shù)系列:

    靜態(tài)反調(diào)試技術(shù)(1)https://blog.csdn.net/CSNN2019/article/details/113105292
    靜態(tài)反調(diào)試技術(shù)(2)https://blog.csdn.net/CSNN2019/article/details/113147820
    靜態(tài)反調(diào)試技術(shù)(3)https://blog.csdn.net/CSNN2019/article/details/113178232
    動態(tài)反調(diào)試技術(shù) https://blog.csdn.net/CSNN2019/article/details/113181558
    高級反調(diào)試技術(shù) https://blog.csdn.net/CSNN2019/article/details/113263215

    總結(jié)

    以上是生活随笔為你收集整理的静态反调试技术(3)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。