<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    初探Windows調試原理和反附加手段

    VSole2021-09-06 17:59:00

    最近粗淺的研究了一下Windows應用層相關調試API和對應調試原理,以達到實現反附加的功能。本文內容主要參考《軟件調試》和網絡上相關優秀文章,并且主要側重在應用層調試附加方面,關于內核層面因為水平有限本文沒有詳細展現。

    用戶態調試基本流程

    首先我們先用調試API編寫一個最簡單的附加調試器:

    int main(int argc,TCHAR *argv[])
    {
        DWORD dwPID;
           BOOL waitEvent = TRUE;
        if (argc > 1) {
            dwPID = atoi(argv[1]);
        }
        else {
            printf("usage: MyDebugger.exe dwPID");
            exit(0);
        }
        DebugActiveProcess(dwPID);
        while (waitEvent)
        {
            DEBUG_EVENT MyDebugInfo;
            waitEvent = WaitForDebugEvent(&MyDebugInfo, INFINITE); // Waiting
            switch (MyDebugInfo.dwDebugEventCode)
            {
                case EXIT_PROCESS_DEBUG_EVENT:
                    waitEvent = FALSE
                    break;
            }
            if (waitEvent) {
                ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);
            }
        }
        return 0;
    }
    

    上文主要用到的就是 DebugActiveProcess 這個調試API對目標PID進程進行調試附加操作,如果我們要在程序創建的時候就對程序進行調試可以在Debugger中執行CreateProcess并將第6個參數傳入DEBUG_ONLY_THIS_PROCESS,這樣設置之后,子進程發生的調試事件會通知給父進程處理。

    CreateProcess(path, // 可執行模塊路徑
        NULL, // 命令行
        NULL, // 安全描述符
        NULL, // 線程屬性是否可繼承
        FALSE, // 否從調用進程處繼承了句柄
        DEBUG_ONLY_THIS_PROCESS, // 以“只”調試的方式啟動
        NULL, // 新進程的環境塊
        NULL, // 新進程的當前工作路徑(當前目錄)
        &stcStartupInfo, // 指定進程的主窗口特性
        &stcProcInfo)) // 接收新進程的識別信息
    

    DEBUG_EVENT中的dwDebugEventCode表示調試信息的種類,對于DEBUG_EVENT詳細的介紹可以查看MSDN,簡單來說就是用共用體來存儲具體的數據。

    typedef struct _DEBUG_EVENT {
        DWORD dwDebugEventCode;
        DWORD dwProcessId;
        DWORD dwThreadId;
        union {
            EXCEPTION_DEBUG_INFO Exception;
            CREATE_THREAD_DEBUG_INFO CreateThread;
            CREATE_PROCESS_DEBUG_INFO        
            CreateProcessInfo;
            EXIT_THREAD_DEBUG_INFO ExitThread;
            EXIT_PROCESS_DEBUG_INFO ExitProcess;
            LOAD_DLL_DEBUG_INFO LoadDll;
            UNLOAD_DLL_DEBUG_INFO UnloadDll;
            OUTPUT_DEBUG_STRING_INFO DebugString;
            RIP_INFO RipInfo;
        } u;
    } DEBUG_EVENT, *LPDEBUG_EVENT;
    

    用戶態 DebugActiveProcess 實現

    我們通過查找NT5的源碼可以看到DebugActiveProcess 具體實現代碼,主要就是調用了DbgUiConnectToDbg ,ProcessIdToHandle和DbgUiDebugActiveProcess這三個函數。

    DbgUiConnectToDbg

    首先判斷TEB->DbgSsReserved[1]是否保存著調試對象的句柄,如果存在則直接返回函數如果不存在就進行初始化并調用NtCreateDebugObject創建調試對象。

    ProcessIdToHandle

    如果是偽句柄則調用CsrGetProcessId獲取csrss.exe的PID,然后調用NtOpenProcess獲得對應進程句柄,給后續調用做準備。

    DbgUiDebugActiveProcess

    此函數首先傳入進程和調試對象的句柄進入內核,然后調用DbgUiIssueRemoteBreakin函數創建線程開始地址為DbgUiRemoteBreakin的遠程線程讓被調試進程斷下來,如果遠程線程設置失敗則調用DbgUiStopDebugging停止調試。

    這個地方創建了遠程線程是在將來反附加檢測的主要檢測點。

    調試子系統

    Windows的調試子系統使用調試事件驅動,這個和窗體的消息驅動是很類似的。在調試子系統中使用WaitForDebugEvent在用戶態等待調試事件,當調試器處理調試事件時,被調試進程會被掛起,所以調試器處理完畢后要調用ContinueDebugEvent使被掛起的被調試進程繼續運行。

    下圖是張銀奎老師在軟件調試縱橫談中的調試模型,在用戶空間部分就是我們此前通過源碼分析的用戶態附加調試API DebugActiveProcess 的基本流程,在系統空間維護著一個DebugObject的鏈表并且通過Dbgk*例程采集和傳遞調試事件。

    反附加手段

    根據此前內容知道,當調試器附加一個進程的時候是調用DebugActiveProcess函數,該函數內部調用了DbgUiDebugActiveProcess,此函數內部會調用DbgUiIssueRemoteBreakin函數,最后內部則會通過RtlCreateUserThread在被調試進程內創建一個線程,線程的起始地址是DbgUiRemoteBreakin。

    在被調試進程內DbgUiRemoteBreakin會判斷PEB中的BeingDebugged標志位,如果在調試則調用DbgBreakPoint函數,調試器附加后被調試進程就中斷在DbgBreakPoint函數內。

    根據上述流程我們可以知道在被調試進程(我們的程序)會創建新線程,線程起始函數是DbgUiRemoteBreakin。所以我們可以Hook DbgUiRemoteBreakin 直接調用 ExitProcess 結束我們的程序。

    反反附加插件

    本文以ScyllaHide為例子,因為ScyllaHide是開源項目可以直接分析源碼,插件加載后我們此前設置的HOOK會被還原。

     

    對于SharpOD,他會在插件加載的時候Hook調試器的DebugActiveProcess和CreateProcessInternalW,在DebugActiveProcessDetour 會在被調試進程中添加ShellCode,并HOOK LdrInitializeThunk 跳轉到ShellCode中斷,并在附加進程的調試事件到達后還原LdrInitializeThunk 。

    x64dbg的Titan Engine

    對于新版x64dbg會內嵌Titan Engine(2020年11月12日版本后添加),所以SharpOD插件對于反反附加對新版本x64dbg起不到作用。在Titan Engine內部自己實現了DebugActiveProcess一套流程。

    并且沒有調用DbgUiIssueRemoteBreakin讓程序被調試器附加的時候斷下。

    總結

    本文初步學習了Windows用戶層基本的調試原理和模型,并給出了一個簡單的反附加方案,同時分析了目前常見的反反附加插件。不過同時存在不知道如何繞過SharpOD的反反附加檢測等問題,還需要進一步學習研究。因為本人水平有限,如果存在錯誤還望各位前輩指正。

    程序調試線程
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    某視頻app的學習記錄
    2022-01-03 16:58:52
    這個看見有人說有個版本開始不能截了,我這邊一直都是換證書的,沒感覺有影響,估計我下的是盜版,碰到再看了。先新建一個自己的測試app,接著的工作就是搬代碼了,直接導出所有的反編譯代碼
    Web安全常見漏洞修復建議
    安卓工具總結
    2021-10-14 08:39:34
    JRE:Java Runtime Environment是Java運行時環境,包含了java虛擬機,java基礎類庫安裝過程:1)雙擊啟動安裝程序2)默認安裝路徑3)jre路徑選擇4)配置環境變量JAVA_HOME. 這里介紹幾款不錯的安卓模擬器。
    Windows安全工具錦集
    2023-01-07 11:03:54
    解決了OD對64位應用程序調試上的缺陷:下載地址:https://x64dbg.com/#startdnSpy一款針對.NET程序的開源逆向程序的工具。還能設置斷點,修改請求和響應的數據,模擬弱網絡環境。支持插件擴展:下載地址:https://www.telerik.com/download/fiddlerMicrosoftNetwork Monitor只支持Windows平臺的網絡數據分析工具,提供了一個專業的網路實時流量圖形界面,擁有識別和監控超過300種網絡協議的能力:下載地址:https://www.microsoft.com/en-us/download/details.aspx?
    一. 應用層隧道技術1. ssh隧道建立雙向安全隧道將其他TCP端口的通信通過SSH連接轉發用SSH作為傳輸層協議,對流量自動加解密突破防火墻訪問規則的限制SSH本地端口轉發本機偵聽端口
    截住 APP 重打包就一定程度上防止了病毒的傳播。如果 PermissionGroup 的屬性為空,會導致權限定義無效,且其他 APP 無法使用該權限。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类