8.3 NtGlobalFlag

NtGlobalFlag 是一個Windows內核全局標記,在Windows調試方案中經常用到。這個標記定義了一組系統的調試參數,包括啓用或禁用調試技術的開關、造成崩潰的錯誤代碼和處理方式等等。通過改變這個標記,可以在運行時設置和禁用不同的調試技術和錯誤處理方式,比如調試器只能訪問當前進程、只允許用戶模式調試、啓用特定的錯誤處理方式等等。但由於NtGlobalFlag標記是內核全局標記,其改變會影響整個系統的行爲,需要謹慎處理。

利用該標記反調試,首先定位dt -rv ntdll!_TEB找到TEB結構並通過TEB找到PEB結構,然後找到+0x068 NtGlobalFlag,這個位置的NtGlobalFlag類似於BeingDebugged,如果是調試狀態NtGlobalFlag的值會是0x70,所以可以判斷這個標誌是否爲0x70來判斷程序是否被調試了,首先我們來使用匯編代碼解決。

#include <stdio.h>
#include <windows.h>

// 返回調試狀態
BOOL IsDebug()
{
    DWORD Debug = 0;
    __asm
    {
        mov eax, fs:[0x18]       // TEB基地址
        mov eax, [eax + 0x30]    // 找到PEB
        mov eax, [eax + 0x68]    // 找打 NtGlobalFlag
        mov Debug, eax           // 取出值
    }

    if (Debug == 112)
    {
        return TRUE;
    }

    return FALSE;
}

int main(int argc, char * argv[])
{

    if (IsDebug)
    {
        printf("[-] 程序正在被調試 \n");
    }
    else
    {
        printf("[*] 程序正常 \n");
    }

    system("pause");
    return 0;
}

當然除了使用純彙編實現反調試外,我們也可以使用NativeAPI中的ZwQueryInformationProcess()這個函數來讀取到程序中的PET數據,然後判斷PebBase+0x68是否等於70,由於這個函數並沒有公開,所以在使用時應該自行聲明一下結構類型。

#include <stdio.h>
#include <windows.h>
#include <winternl.h>

// 聲明該函數
typedef NTSTATUS(NTAPI *typedef_ZwQueryInformationProcess)(
    IN HANDLE ProcessHandle,
    IN PROCESSINFOCLASS ProcessInformationClass,
    OUT PVOID ProcessInformation,
    IN ULONG ProcessInformationLength,
    OUT PULONG ReturnLength OPTIONAL
    );

// 調試狀態檢測
BOOL IsDebug()
{
    HANDLE hProcess = NULL;
    DWORD ProcessId = 0;
    PROCESS_BASIC_INFORMATION Pbi;
    typedef_ZwQueryInformationProcess pZwQueryInformationProcess = NULL;
    ProcessId = GetCurrentProcessId();
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId);

    if (hProcess != NULL)
    {
        HMODULE hModule = LoadLibrary("ntdll.dll");
        pZwQueryInformationProcess = (typedef_ZwQueryInformationProcess)GetProcAddress(hModule, "ZwQueryInformationProcess");

        NTSTATUS Status = pZwQueryInformationProcess(hProcess, ProcessBasicInformation, &Pbi,sizeof(PROCESS_BASIC_INFORMATION), NULL);
        if (NT_SUCCESS(Status))
        {
            DWORD ByteRead = 0;
            WORD NtGlobalFlag = 0;
            ULONG PebBase = (ULONG)Pbi.PebBaseAddress;

            // 讀取調試標誌並判斷
            if (ReadProcessMemory(hProcess, (LPCVOID)(PebBase + 0x68), &NtGlobalFlag, 2, &ByteRead) && ByteRead == 2)
            {
                if (NtGlobalFlag == 0x70)
                {
                    return TRUE;
                }
            }
        }
        CloseHandle(hProcess);
    }

    return FALSE;
}

int main(int argc, char * argv[])
{
    if (IsDebug() == TRUE)
    {
        printf("[-] 進程正在被調試 \n");
    }
    else
    {
        printf("[*] 程序正常 \n");
    }

    system("pause");
    return 0;
}

本文作者: 王瑞
本文鏈接: https://www.lyshark.com/post/e45d84be.html
版權聲明: 本博客所有文章除特別聲明外,均採用 BY-NC-SA 許可協議。轉載請註明出處!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章