Skip to content
Anti-Analysisintermediate

NtGlobalFlag

Malware reads the NtGlobalFlag field of the PEB (offset 0x68/0xBC) to detect if the process was launched under a debugger via the 0x70 heap flag combination.

When a process is created by a debugger, the Windows loader sets three heap-validation flags in the NtGlobalFlag field of the Process Environment Block (PEB):

FlagValue
FLG_HEAP_ENABLE_TAIL_CHECK0x10
FLG_HEAP_ENABLE_FREE_CHECK0x20
FLG_HEAP_VALIDATE_PARAMETERS0x40

The combined value of 0x70 is therefore a reliable debugger indicator. The field sits at PEB offset 0x68 on 32-bit Windows and 0xBC on 64-bit Windows. It is not modified when a debugger attaches to an already-running process, so this check specifically targets processes spawned inside a debugger.

How it works

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

BOOL NtGlobalFlagDebugged(void)
{
#ifdef _WIN64
    PPEB pPeb = (PPEB)__readgsqword(0x60);
    DWORD ntgf = *(DWORD *)((BYTE *)pPeb + 0xBC);
#else
    PPEB pPeb = (PPEB)__readfsdword(0x30);
    DWORD ntgf = *(DWORD *)((BYTE *)pPeb + 0x68);
#endif
    return (ntgf & 0x70) != 0;
}

Alternatively, malware uses NtQueryInformationProcess to retrieve the PEB pointer indirectly before reading the field, hiding the API name behind dynamic resolution.

In assembly (x86):

asm
mov  eax, fs:[30h]       ; PEB pointer
mov  eax, [eax + 68h]    ; NtGlobalFlag
and  eax, 70h
jnz  debugger_detected

Detection & bypass

During debugging:

  • Use a debugger plugin (ScyllaHide, TitanHide) that patches NtGlobalFlag to 0 before the check executes.
  • Manually zero the field: in x64dbg open the dump at gs:[60h]+0xBC and write 00 00 00 00.
  • If the process must start under the debugger, patch the check with a NOP sled or force the branch to the non-detected path.

Static / automated detection:

  • YARA: search for the string "NtGlobalFlag" or the byte sequence 68h / BCh combined with PEB access patterns.
  • CAPA rule U0111 flags reads at peb+0x68 / peb+0xBC followed by a bitwise AND against 0x70.
  • Frida/dynamic instrumentation: hook reads of those PEB offsets and return 0.
Votes

Comments(0)