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 許可協議。轉載請註明出處!