NtGlobalFlag 是一个Windows
内核全局标记,在Windows
调试方案中经常用到。这个标记定义了一组系统的调试参数,包括启用或禁用调试技术的开关、造成崩溃的错误代码和处理方式等等。通过改变这个标记,可以在运行时设置和禁用不同的调试技术和错误处理方式,比如调试器只能访问当前进程、只允许用户模式调试、启用特定的错误处理方式等等。但由于NtGlobalFlag
标记是内核全局标记,其改变会影响整个系统的行为,需要谨慎处理。
利用该标记反调试,首先定位dt -rv ntdll!_TEB
找到TEB
结构并通过TEB
找到PEB
结构,然后找到+0x068 NtGlobalFlag
,这个位置的NtGlobalFlag
类似于BeingDebugged
,如果是调试状态NtGlobalFlag
的值会是0x70
,所以可以判断这个标志是否为0x70
来判断程序是否被调试了,首先我们来使用汇编代码解决。
#include
#include
// 返回调试状态
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
#include
#include
// 声明该函数
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;
}