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 ] mov eax, [eax + 0x30 ] mov eax, [eax + 0x68 ] 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 ; }