內存斷點與硬件斷點


Windows內核分析索引目錄:https://www.cnblogs.com/onetrainee/p/11675224.html

內存斷點與硬件斷點

一、內存斷點

  內存斷點的本質是修改頁屬性,觸發頁異常,走0E號中斷

  1. 設置內存斷點:

    頁屬性如下:

    #define PAGE_NOACCESS           0x01    
    #define PAGE_READONLY           0x02    
    #define PAGE_READWRITE          0x04    
    #define PAGE_WRITECOPY          0x08    
    #define PAGE_EXECUTE            0x10    
    #define PAGE_EXECUTE_READ       0x20    
    #define PAGE_EXECUTE_READWRITE  0x40    
    #define PAGE_EXECUTE_WRITECOPY  0x80

    我們調用 VirutalProtectEx 函數來修改頁屬性。

    比如,當我們設置內存訪問斷點,我們將相應的地址所在的頁設置為 PAGE_NOACCESS。

       VirtualProtectEx(handle, (PVOID)debugAddress, 1, PAGE_NOACCESS, &oldProtote) 

    之后,程序訪問該地址會觸發 ACCESS_VIOLATION(c0000005)錯誤,會走0E號中斷,然后包裝加入到 DEBUG_OBJECT.EventLink,通知調試器有事件需要處理。

  2. 設置內存斷點案例:

1     DWORD debugAddress = _ttoi(debugStrAddress);
2 
3     if (VirtualProtectEx(handle, (PVOID)debugAddress, 1, PAGE_NOACCESS, &oldProtote))
4     {
5         setText(this->m_edlog, L"內存訪問斷點\r\n");
6     }

  3. 內存斷點恢復案例

 1 DWORD memoryHandler(CdebugToolsDlg *pdlg, DEBUG_EVENT dbgEvent)
 2 {
 3     
 4     //恢復內存斷點
 5     HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, TRUE, dbgEvent.dwProcessId);
 6     if (handle == NULL)
 7     {
 8         return -1;
 9     }
10 
11     auto er = dbgEvent.u.Exception.ExceptionRecord;
12     if (er.ExceptionInformation[0] == 0)
13     {
14         CString str;
15         str.Format(L"讀斷點被觸發%X,er.ExceptionAddress = %X", er.ExceptionInformation[1], er.ExceptionAddress);
16         setText(pdlg->m_edlog, str);
17     }
18 
19     DWORD dwProtect =0;
20     BOOLEAN isCommand = 0;
21 
22     isCommand = VirtualProtectEx(handle, (PVOID)er.ExceptionInformation[1], 1, oldProtote, &dwProtect);
23     
24     handleInt3 = TRUE;
25     while (isCommand && handleInt3)
26     {
27         Sleep(1);
28     }
29     
30     handleInt3 = FALSE;
31     return 0;
32 }

  4. 注意事項

    1)我們是對一個地址(字節,字或雙字)下斷點,但實際上操作的是一個頁。因此,如果我們要詳細處理,將觸發頁異常時,我們必須判斷是否是我們的目標地址,如果不是,則從調試器角度自然放行,不通知使用者。

    2)在修復好頁異常之后,我們在重新設置頁異常,以便於下一次斷下。

 

二、硬件斷點

  硬件斷點是基於寄存器 Dr0~Dr7 實現的。

  Dr寄存器在三環沒有讀取和修改權限(mov eax,dr3),只能通過CONTEXT來讀取,或填寫CONTEXT然后傳遞到零環來修改。

  關於硬件斷點,詳情可以查看 在Intel手冊 Volume3 Chapter 17.2 Debug Registers

  1. DR寄存器的基本布局

    如下圖:Dr0~3寄存器存儲四個硬件斷點的地址,Dr4~5為保留寄存器,Dr6 狀態寄存器,Dr7 控制寄存器。

    我們如果使用DR1作為硬件斷點,必須在Dr7設置好相應的標志,否則無法使用。

    

      1)DR6寄存器介紹

        

 

       2)DR7寄存器介紹

        

 

    2. 硬件斷點的設置

 1     DWORD debugAddress = _ttoi(debugStrAddress);
 2 
 3     
 4     HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, TRUE, hThreadId);
 5     if (hThread == NULL)
 6     {
 7         return;
 8     }
 9     
10     SuspendThread(hThread);
11 
12     CONTEXT context = {0};
13     context.ContextFlags = CONTEXT_ALL;
14     GetThreadContext(hThread, &context);
15     
16     context.Dr0 = debugAddress;
17     context.Dr7 |= 0x3fff1;
18     SetThreadContext(hThread, &context);
19     
20     ResumeThread(hThread);
21 
22     setText(this->m_edlog, L"硬件訪問斷點\r\n");

    3. 硬件斷點的恢復

1     BOOLEAN isHard = context.Dr6 & 0xf;
2     if (isHard)
3     {
4         //下次在斷下
5         context.Dr7 |= 1;
6         CString str;
7         str.Format(L"硬件中斷被觸發%X,er.ExceptionAddress = %X", er.ExceptionInformation[1], er.ExceptionAddress);
8         setText(pdlg->m_edlog, str);
9     }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM