Skip to content
Anti-Analysisintermediate

Heap Flags

Malware inspects the Flags and ForceFlags fields of the process heap header (via PEB.ProcessHeap) to detect debugger-modified heap metadata.

Windows modifies the heap header of a debugged process to enable extra validation. Two fields in the first heap block, reachable through PEB.ProcessHeap, reveal this: Flags and ForceFlags.

Under normal execution:

  • Flags = HEAP_GROWABLE (0x00000002)
  • ForceFlags = 0x00000000

When a process is created under a debugger (on Vista and later) the loader ORs in several checking bits:

Added flagValue
HEAP_TAIL_CHECKING_ENABLED0x00000020
HEAP_FREE_CHECKING_ENABLED0x00000040
HEAP_VALIDATE_PARAMETERS_ENABLED0x40000000

ForceFlags additionally carries 0x40000060. Checking for ForceFlags != 0 is the most portable test.

How it works

Offsets for the Flags and ForceFlags fields vary by bitness and Windows version. On 64-bit Vista+:

  • Heap Flags → heap base + 0x14
  • Heap ForceFlags → heap base + 0x18
c
#include <windows.h>

BOOL HeapFlagsDebugged(void)
{
#ifdef _WIN64
    PPEB pPeb = (PPEB)__readgsqword(0x60);
    PVOID heap  = *(PVOID *)((BYTE *)pPeb + 0x30); // PEB.ProcessHeap
    DWORD flags      = *(DWORD *)((BYTE *)heap + 0x14);
    DWORD forceflags = *(DWORD *)((BYTE *)heap + 0x18);
#else
    PPEB pPeb = (PPEB)__readfsdword(0x30);
    PVOID heap  = *(PVOID *)((BYTE *)pPeb + 0x18);
    DWORD flags      = *(DWORD *)((BYTE *)heap + 0x0C);
    DWORD forceflags = *(DWORD *)((BYTE *)heap + 0x10);
#endif
    // ForceFlags should always be 0 without a debugger
    if (forceflags != 0) return TRUE;
    // Flags should only have HEAP_GROWABLE set
    if (flags & ~0x00000002) return TRUE;
    return FALSE;
}

Detection & bypass

During debugging:

  • ScyllaHide patches heap flags automatically — ensure the "Heap Flags" option is ticked in its configuration.
  • Manual fix: locate PEB.ProcessHeap in the dump, set Flags = 0x00000002 and ForceFlags = 0x00000000.
  • NOP out or redirect the conditional jump following the comparison.

Static / automated detection:

  • YARA: pattern-match on the byte offsets 0x14 / 0x0C combined with PEB access.
  • Emulators and sandboxes should initialise heap flags to their non-debug values to avoid false-positive evasion.
  • Unprotect technique ID: U0112 / CAPA rule B0001.021.
Votes

Comments(0)