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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

3.调试事件的处理

發布時間:2025/3/20 编程问答 12 豆豆
生活随笔 收集整理的這篇文章主要介紹了 3.调试事件的处理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

調試器會有一個循環一直判斷EventList有沒有調試事件有就取出來處理。

調試器創建形式

  • 關聯調試器與被調試器進程
  • 調試循環
  • 每一種收集調試事件API都不一樣,是因為它要收集調試事件的類型是不一樣的。

    這是異常要收集的調試事件 typedef struct _EXCEPTION_DEBUG_INFO {EXCEPTION_RECORD ExceptionRecord;DWORD dwFirstChance; } EXCEPTION_DEBUG_INFO, *LPEXCEPTION_DEBUG_INFO;這是創建線程要收集的調試事件 typedef struct _CREATE_THREAD_DEBUG_INFO {HANDLE hThread;LPVOID lpThreadLocalBase;LPTHREAD_START_ROUTINE lpStartAddress; } CREATE_THREAD_DEBUG_INFO, *LPCREATE_THREAD_DEBUG_INFO; ..... .....

    下面代碼就類似拖拽程序到OD的框架。(W10記得以管理員身份運行VS)

    #define dbgProcessName L"C:\\Users\\Administrator\\Desktop\\012.exe"int main() {BOOL nIsConinue = TRUE;DEBUG_EVENT debugEvent = { 0 };//1.創建調試進程STARTUPINFO startupInfo = { 0 };PROCESS_INFORMATION pInfo = {0};GetStartupInfo(&startupInfo);BOOL bRet = CreateProcess(dbgProcessName,NULL,NULL,NULL,TRUE,DEBUG_PROCESS||DEBUG_ONLY_THIS_PROCESS,NULL,NULL,&startupInfo,&pInfo);if (bRet == FALSE){printf("CreateProcess error:%d\n", GetLastError());return 0;}//調試循環while (nIsConinue){bRet = WaitForDebugEvent(&debugEvent, INFINITE);//取DEBUG_EVENTif (!bRet){printf("WaitForDebugEvent error:%d\n", GetLastError());return 0;}switch (debugEvent.dwDebugEventCode){case EXCEPTION_DEBUG_EVENT:printf("異常:發生異常的地址:%X \n",debugEvent.u.Exception.ExceptionRecord.ExceptionAddress);break;case CREATE_THREAD_DEBUG_EVENT:printf("創建線程\n");break;case CREATE_PROCESS_DEBUG_EVENT:printf("創建進程\n");break;case EXIT_THREAD_DEBUG_EVENT:printf("退出線程\n");break;case EXIT_PROCESS_DEBUG_EVENT:printf("退出進程\n");break;case LOAD_DLL_DEBUG_EVENT:printf("加載DLL\n");break;case UNLOAD_DLL_DEBUG_EVENT:printf("卸載DLL\n");break;default:break;}//DBG_CONTINUE 表示調試器已處理該異常//DBG_EXCEPTION_NOT_HANDLED 表示調試器沒有處理該異常,轉回到用戶態中執行,尋找可以處理該異常的異常處理器bRet = ContinueDebugEvent(debugEvent.dwProcessId,debugEvent.dwThreadId,DBG_CONTINUE);//ContinueDebugEvent 告訴被調試程序讓被調試程序繼續執行}}

    運行會發現有一個異常我們取這個地址看看

    異常來自ntdll 的int 3,它為什么會在來個int 3呢?

    進程創建過程:

    <1>任何進程都是別的進程創建的: CreateProcess()
    <2>進程的創建過程

    1、映射EXE文件 2、創建內核對象_EPROCESS 3、映射系統DLL(ntdll.dll) 4、創建線程內核對象_ETHREAD 5、系統啟動線程映射DLL(ntdll.LdrInitalizeThunk())線程開始執行

    ntdll 比較特殊它在內核的時候就已經創建好了。

    LdrInitalizeThunk()
    判斷這個進程是不是這個進程的第一條線程,如果是先調用 LdrpInitializeProcess 初始化進程,再將這個進程用到的其他DLL映射進來。


    追上去

    如果被用戶模式調試器附加了就會call DbgBreakPoint() ,如果沒有調試器附加就不會調用這個int 3。

    調試器附加

    int main() {BOOL nIsConinue = TRUE;DEBUG_EVENT debugEvent = { 0 };PROCESS_INFORMATION pInfo = {0};//1.附加進程if (!DebugActiveProcess(14148)){return 0;}//調試循環while (nIsConinue){BOOL bRet = WaitForDebugEvent(&debugEvent, INFINITE);//取DEBUG_EVENTif (!bRet){printf("WaitForDebugEvent error:%d\n", GetLastError());return 0;}switch (debugEvent.dwDebugEventCode){case EXCEPTION_DEBUG_EVENT:printf("異常:發生異常的地址:%X \n",debugEvent.u.Exception.ExceptionRecord.ExceptionAddress);break;case CREATE_THREAD_DEBUG_EVENT:printf("創建線程\n");break;case CREATE_PROCESS_DEBUG_EVENT:printf("創建進程\n");break;case EXIT_THREAD_DEBUG_EVENT:printf("退出線程\n");break;case EXIT_PROCESS_DEBUG_EVENT:printf("退出進程\n");break;case LOAD_DLL_DEBUG_EVENT:printf("加載DLL\n");break;case UNLOAD_DLL_DEBUG_EVENT:printf("卸載DLL\n");break;default:break;}//DBG_CONTINUE 表示調試器已處理該異常//DBG_EXCEPTION_NOT_HANDLED 表示調試器沒有處理該異常,轉回到用戶態中執行,尋找可以處理該異常的異常處理器bRet = ContinueDebugEvent(debugEvent.dwProcessId,debugEvent.dwThreadId,DBG_CONTINUE);//ContinueDebugEvent 告訴被調試程序讓被調試程序繼續執行}}


    我們通過創建的形式能捕獲到他的創建信息,但現在我通過附加,這些信息都已經執行完了,為什么也能捕獲到這些信息呢?

    杜撰的調試消息

    當我們附加了一個進程后,有人給我們發送了假的消息。
    DebugActiveProcess 最終到內核會調用 NtDebugActiveProcess 。


    它為什么要發送這些假的消息?

    調試器都能看到所屬進程的DLL,是因為每個模塊加載的時候都能收集到調試事件,這個API在它的路上加了這些假消息就是希望給調試器提供一些必要的信息。

    但這些假信息并不靠譜,比如這個模塊別人有意隱藏,PEB+0xc的位置Ldr 0xc到0x1c也有模塊的信息 ,成員如下。
    但OD它是通過搜索內存來查找你的模塊的,具體看《內存管理》的章節

    要點
    <1>事件
    <2>系統斷點

    LdrinitializeThunkLdrpInitializeProcess開頭位置找到text:7C9415F1 mov ebx, [eax+30h] DbgBreakPoint()找到LdrpInitializeProcess引用的地址DbgBreakPoint()就是int 3

    <3> ContinueDebugEvent 函數

    總結

    以上是生活随笔為你收集整理的3.调试事件的处理的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。