反調試——9——調試器原理


反調試——9——調試器原理

調試一個程序分兩種情況:

1 打開這個程序。

2:這個程序已經是一個運行狀態了,將其進程進行附加。

打開進程

通過打開運行進程方式來調試進程需要調用一個API:

BOOL CreateProcessA(
  LPCSTR                lpApplicationName,
  LPSTR                 lpCommandLine,
  LPSECURITY_ATTRIBUTES lpProcessAttributes,
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  BOOL                  bInheritHandles,
  DWORD                 dwCreationFlags,
  LPVOID                lpEnvironment,
  LPCSTR                lpCurrentDirectory,
  LPSTARTUPINFOA        lpStartupInfo,
  LPPROCESS_INFORMATION lpProcessInformation
);
//dwCreatetionFlags需要設置為DEBUG_PROCESS
//打開進程示例程序
    STARTUPINFOA sw{ 0 };
    PROCESS_INFORMATION pInfo{ 0 };
    auto retCP = CreateProcessA("F:\\Sublime Text 3\\sublime_text.exe",
        NULL,NULL,NULL,FALSE,
        DEBUG_PROCESS,NULL,NULL,&sw,&pInfo);
    if (retCP == 00)
    {
        cout << "打開進程失敗" << endl;
        return;
    }

 

 

附加進程

通過DebugActiveProcess這個API來附加到進程。

BOOL DebugActiveProcess(
  DWORD dwProcessId
);

 

細節

無論是通過打開進程還是附加進程來實現調試,都只是開始調用的方式不一樣,在調試器和操作系統之間的交互方式都是相同的。

創建了調試進程后接下來就是死循環等待調試事件

當調試進程時,被調試進程執行的一些操作事件將會被通知給調試器,比如dll的加載和卸載,thread的創建和銷毀,異常信息等等。當這些事件需要被發送到調試器時,Windows內核將首先掛起進程中的所有線程,然后把發生的事件通知給調試器,等待調試器的處理。

調試器通過WaitForDebugEvent API來等待調試事件,調試事件被封裝到了DEBUG_EVENT結構體中,調試器需要處理的就是循環接受調試事件然后處理DEBUG_EVENT結構體中傳遞過來的不同調試信息。

在發送事件event給調試器debugger時,被調試進程會被掛起,直到調試器調用了continueDebugEvent函數

利用調試器原理實現附加反調試

利用調試器的原理,我們可以通過創建一個調試模式下的進程,那么這個以調試模式創建的進程就不能被其它進程拿去調試了,因為它已經在被一個我們自己的進程以調試模式創建了。

#include<iostream>
#include<Windows.h>
using namespace std;
​
​
void TestDebugger()
{
    STARTUPINFOA sw{ 0 };
    PROCESS_INFORMATION pInfo{ 0 };
    auto retCP = CreateProcessA("E:\\test\\Debug\\02 CStaticText.exe",
        NULL, NULL, NULL, FALSE,
        DEBUG_PROCESS, NULL, NULL, &sw, &pInfo);
    if (retCP == 0)
    {
        cout << "打開進程失敗" << endl;
        return;
    }
    while (TRUE)
    {
        DEBUG_EVENT debugEvent{ 0 };
        auto rDebugEvent = WaitForDebugEvent(&debugEvent, -1);
        if (rDebugEvent)
        {
            cout << debugEvent.dwDebugEventCode << endl;
            //dwDebugEventCode是用來區分不同事件的事件碼,用來判斷事件
        }
        ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId,
            DBG_CONTINUE);//在發送事件event給調試器debugger時,被調試進程會被掛起,直到調試器調用了continueDebugEvent函數
    }
}
​
int main()
{
​
    TestDebugger();
    system("pause");
    return 0;
}

 

然后來測試一下,這樣啟動后,是否還能被調試器附加上:

 

 

這樣一來就不會被調試器附加上了。

 


免責聲明!

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



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