調試子系統採集調試事件的方法和過程(1)

来源:http://www.cnblogs.com/weikanzong/archive/2016/03/08/5253664.html
-Advertisement-
Play Games

軟體調試的應用場景一般是: 查找程式的BUG 逆向破解 本篇文章是本人在閱讀張銀奎老師的 <軟體調試>做的筆記. 主要闡述調試器獲取到的調試事件是何時產生,如何收集的. 閱讀目錄 進程創建和線程創建事件的採集過程 進程和線程退出事件的採集過程 模塊映射和反映射事件的採集過程 異常事件的採集 能夠採集


軟體調試的應用場景一般是:

  1. 查找程式的BUG
  2. 逆向破解

本篇文章是本人在閱讀張銀奎老師的 <軟體調試>做的筆記.

主要闡述調試器獲取到的調試事件是何時產生,如何收集的.

 

    閱讀目錄

 

 

 

 

 

 

 能夠採集到的調試事件(消息)有:    


1
typedef enum _DBGKM_APINUMBER 2 { 3 DbgKmExceptionApi=0, // 異常事件 4 DbgKmCreateThreadApi,//創建線程事件 5 DbgKmCreateProcessApi,//創建進程事件 6 DbgKmExitThreadApi,// 線程退出事件 7 DbgKmExitProcessApi,// 進程退出事件 8 DbgKmLoadDllApi, // 載入Dll事件 9 DbgKmUnLoadDllApi, // 卸載Dll事件 10 DbgKmErrorReportApi,// 內部錯誤事件 11 DbgKmMaxApiNumber, // 這組常量的最大值 12 }

    PS:DbgKmErrorReportApi 是用來報告調試子系統內部的錯誤 ,目前已經不再使用
    


    - 進程創建和線程創建事件的採集過程

        創建新的進程和線程 ,進程的通信,終止進程和線程,資源分配回收這些任務通常稱為進程管理,完成這些功能的是ntoskrnl.exe中有Ps或Psp開頭的系列函數. 這寫系列函數被泛稱為進程管理器.進程管理器創建新的用戶態Windows線程時,有如下工作
        -    為該線程建立必要的內核對象和數據結構
        -    分配棧空間
        -    掛起該線程
        -    通知環境子系統(子系統會作必要的設置和登記)
        -    調用 PspUserThreadStartup,準備啟動線程(函數總是會調用 調試子系統的內核函數 DbgkCreateThread.)
                - 調試子系統的內核函數 DbgkCreateThread()函數會檢查新創建線程所在的進程是否正在被調試(根據 DebugPort 是否為NULL),如果為NULL,便立即返回(返回到 PspUserThreadStartup()函數),如果不是NULL,則會繼續檢查該進程的用戶態時間(UserTime)是否為0,目的是判斷該線程是否是進程中的第一個線程 ,如果是第一個線程,則通過DbgkpQueueMessage()函數向調試埠(DebugPort)發送DbgKmCreateProcessApi消息. 如果不是第一個線程,則發送DbgkmCreateTheadApi消息.            

      具體流程如下:
            
                  建立內核對象和數據結構
                            ||
                            \/
                        分配棧空間
                            ||
                            \/
                         掛起線程
                            ||
                            \/
                      通知環境子系統
                            ||     |--> 必要的設置和登記
                            \/
            ----->>>PspUserThreadStartup()
            ||           |--> DbgkCreateThread()/*在函數內部調用*/
            ||                   ||
    返回到上層函數          \/
            ||<--是<<- [DebugPort==NULL]
                              ||
                             不是
                              ||
                              \/                            --------------------------------
                         [UserTime==0]--是-->>|通過DbgkpQueueMessage()函數   |
                              ||                           |發送DbgKmCreateProcessApi消息 |
                             不是                         --------------------------------
                              ||       
                              \/       
                -------------------------------
                | 通過DbgkpQueueMessage()函數 |      
                | 發送DbgkmCreateTheadApi消息 |
                -------------------------------    
                
    -    進程和線程退出事件的採集過程         

         進程管理器的PspExitThread函數負責線程的退出和清除.在函數銷毀線程的結構和資源之前 , 該函數會調用調試子系統的函數讓調試器(如果有)得到處理機會.如果退出的是一個進程中的最後一個線程,PspExitThread會調用DbgkExitProcess函數 , 否則調用DbgkExitThread函數.DbgExitThread函數被調用後,會檢查進程的DebugPort是否位0,如果不為0,則會先將該進程掛起,然後通過 DbgkpQueueMessage函數向DebugPort發送DbgKmExitThreadApi消息.並且會等待DbgKmExitThreadApi函數返回才將掛起的線程恢復運行.DbgExitProcess函數執行過程和DbgExitThread函數非常類似,只不過發送的是DbgKmExitProcessApi消息.且沒必要執行掛起和恢復動作,因為進程管理器已經對該線程做了刪除標記(??)

 

 


            
    -    模塊映射和反映射事件的採集過程
            當系統要dll時,會首先判斷該dll是否被載入過(判斷條件是什麼?)如果是,則不會重覆載入,只將該dll對應的記憶體頁面映射到目標進程的記憶體空間(如何得知要已載入的dll在記憶體中的位置和大小),並把該dll的引用次數加1. 當一個進程退出或調用FreeLibrary函數卸載一個Dll時 , 系統會從該進程的虛擬記憶體空間中把該Dll的映射刪除(如何得知映射到了進程的虛擬記憶體空間的哪個地址) , 並遞減該Dll的引用次數, 如果引用次數為0,那麼該Dll會被徹底移出記憶體(從哪移出)系統內核中的記憶體管理器(Memory Manager)便是負責DLl的映射和發映射. 記憶體管理器使用Section對象來表示一塊可被多個進程共用的記憶體區域. 並設計了一系列的內核服務和函數來實現各種映射和反映射任務. NtMapViewOfSection函數就是用來映射模塊的內核服務,NtUnmapViewOfSection是用來反映射的.當NtMapViewOfSection在把一個模塊映像成功映射到指定進程空間中時,(主要是使用MmMapViewOfSection映射),NtMapViewOfSection函數會調用調試子系統的DbgkMapViewOfSection函數通知調試子系統.           
            模塊映射過程如下:
                - 遞歸遍歷模塊的輸入表(LdrpWalkImportDescriptor)
                - 載入輸入表依賴的模塊(LdrpLoadImportModule)
                - 將模塊映射到進程的虛擬空間(用戶態函數:ZwMapViewOfSection)
                   - 將模塊映射到進程的虛擬空間(內核態函數:NtMapViewOfSection)
                - 通知調試子系統(DbgkMapViewOfSection)
                    - 檢查DebugPort欄位是否為空
                        - 如果為空則發送調試信息到調試埠(DbgkpQueueMessage)
            
            MnUnmapViewOfSection函數的執行過程也類似 , 該函數會調用調試子系統
            的DbgkUnmapViewOfSection函數,
            DbgkUnmapViewOfSection函數內部會檢測DebugPort不為空後,會發送
            DbgKmUnLoadDllAPi消息
    
    -    異常事件的採集
        KiDispatchException函數:異常分發的樞紐,它會給每個異常安排最多兩輪被處理的機會,對於每一輪處理機會, 它都會調用調試子系統的DbgkForwardException函數來通知調試子系統. DbgkForwardException函數可以向進程的異常埠發消息,也可以向調試埠發消息,具體決定給哪一個發消息 , 是由KiDispatchException函數在調用它時通過傳遞一個布爾類型的形參給這個函數傳參決定的.如果DbgkForwardException決定了給異常埠發消息, 那麼DbgkForwardException函數會判斷進程的DebugPort欄位是否為空,如果不為空,則通過DbgkpQueueMessage函數發送DbgKmExceptionApi消息.
        
        
        
    
       


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • --寫在開始-- 玩Linux,不同的版本會有一些細微區別; so,經常需要查看伺服器版本號; --正文-- 有以下命令可以查看linux伺服器版本號:# lsb_release -a LSB Version: :base-4.0-amd64:base-4.0-noarch:core-4.0-amd
  • 開始---->運行---->cmd,或者是window+R組合鍵,調出命令視窗 輸入命令:netstat -ano,列出所有埠的情況。在列表中我們觀察被占用的埠,比如是49157,首先找到它。 查看被占用埠對應的PID,輸入命令:netstat -aon|findstr "49157",回車,
  • whereis命令只能用於程式名的搜索,而且只搜索二進位文件(參數-b)、man說明文件(參數-m)和源代碼文件(參數-s)。如果省略參數,則返回所有信息。 和find相比,whereis查找的速度非常快,這是因為linux系統會將 系統內的所有文件都記錄在一個資料庫文件中,當使用whereis和下
  • crontab定時任務格式 1 * * * * * command 2 第1列表示分鐘1~59 每分鐘用*或者 */1表示 3 第2列表示小時1~23(0表示0點) 4 第3列表示日期1~31 5 第4列表示月份1~12 6 第5列標識號星期0~6(0表示星期天) 7 第6列要運行的命令 cront
  • 四、進程優先順序前臺後臺01.進程式控制制#find /name aaa &#ps aux | grep find#updatedb & #ps aux | grep updatedbroot 5871 52.8 0.2 2204 700 pts\2 R(低優先順序) 08:43 0:02 updatedb
  • Mbps=Mbit/s即兆比特每秒。Million bits per second的縮寫 傳輸速率是指設備的的數據交換能力,也叫“帶寬”,單位是Mbps(兆位/秒),目前主流的集線器帶寬主要有10Mbps、54Mbps/100Mbps自適應型、100Mbps和150Mbps四種。 中文名兆位每秒外文
  • 1、建議使用dubbo-2.3.3以上版本的使用zookeeper註冊中心客戶端(官網這樣說的) 2、Zookeeper是Apache Hadoop的子項目,強度相對較好,建議生產環境使用該註冊中心 3、Dubbo未對Zookeeper伺服器端做任何侵入修改,只需安裝原生的Zookeeper服務...
  • 假設區域網中有多台主機,只能開通ssh服務(埠22),如果發現其他服務打開,則全部關閉。通過運行一個shell腳本,完成以上功能。在實際運維中,可以通過puppet等工具更快更好的完成這個功能,所以本案例僅僅用來練手,為了熟悉sed, awk, grep等常見的shell命令而已。 1、通過nma
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...