Debugger Detection Using NtGlobalFlag

This is another simple anti-reversing trick used to detect a debugger. As I have shown earlier in my post about the TEB structure and the PEB structure, NtGlobalFlag is located in the PEB Structure at offset PEB+104.

When the process is being debugged the NtGlobalFlag is set to 0x70.

If we examine the API in a debugger we can see that it uses FS[30] segment register which is the linear address of Process Environment Block (PEB) and then reach the offset 0x68 which is the NtGlobalFlag.

Here’s a simple implementation of this in FASM.

format pe gui 4.0
entry start
; »»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»»
; Title: Checking if the process is being debugged by a ring3 debugger
; using the PEB's NtGlobalFlag.
; Website:
; Author: Osanda Malith Jayathissa (@OsandaMalith)
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
include ''
section '.data' data readable writeable
Title db "Status",0
Found db "Debugger Found",0
NotFound db "Debuger Not Found",0
; =======================================
section '.text' code readable executable
mov eax, [fs:0x18] ; Pointer to TEB Structure
mov eax, [eax + 0x30] ; Pointer to PEB Structure
movzx eax, byte [eax + 68h]; BeingDebugged bit
cmp eax, 70h
je found
push 0x30
push Title
push NotFound
push 0
call [MessageBox]
jmp exit
push 0x10
push Title
push Found
push 0
call [MessageBox]
push 0
call [ExitProcess]
; ===============================================
section '.idata' import data readable
; ===============================================
library kernel32,'kernel32.dll',\
import kernel32,\
import User32,\

Here’s another way coded in C in which we first take the address of the PEB structure and then get the address to the NtGlobalFlag using “ZwQueryInformationProcess” kernel mode API.

#include <Winternl.h>
#include <Windows.h>
#include <tchar.h>
#include <stdio.h>
 * Author: Osanda Malith Jayathissa (@OsandaMalith)
 * Website:
 * Using ZwQueryInformationProcess we get the PEB Address and 
 * then we check the NtGlobalFlag to determine the process is being debugged or not.

int main() {
	typedef unsigned long(__stdcall *pfnZwQueryInformationProcess)
		IN  unsigned int, 
	pfnZwQueryInformationProcess ZwQueryInfoProcess = NULL;
	HMODULE hNtDll = LoadLibrary(_T("ntdll.dll"));
	if (hNtDll == NULL) { }

	ZwQueryInfoProcess = (pfnZwQueryInformationProcess) GetProcAddress(hNtDll,
	if (ZwQueryInfoProcess == NULL) { }
	unsigned long status;

	DWORD pid = GetCurrentProcessId();
	status = ZwQueryInfoProcess(hProcess,
	PPEB peb_addr = pbi.PebBaseAddress;
	DWORD ptr = pbi.PebBaseAddress;
	DWORD *temp = ptr;
	MessageBox(0, *temp ? "Debugger found" : "Debugger not found","Status",0x30);
	return 0;

You can check my github repository (will update soon with more):

In 64-bit systems the implementation would be as follow. Thanks to b3mb4m for mentioning in the comments.

The NtGlobalFlag is located at PEB+0xbc. When the process is being debugged the value is 0x70 as usual.

The assembly implementation would be like this.

Here’s an simple example using inline assembly.

#include <Windows.h>
 * Author: Osanda Malith Jayathissa (@OsandaMalith)
 * Website:
 * 64-bit implementation for NtGlobalFlag using inline asm.
int NtGlobalFlag64(){
  	".intel_syntax noprefix;"
  	"xor rax, rax;"
	"mov rbx, qword ptr gs:[0x60];"      
	"mov eax, dword ptr [rbx + 0xbc];"  

int main(){
	MessageBox(NULL, NtGlobalFlag64() ? "Debugger Detected!" : "No Debugger Found" , "Status", 0x30);

4 thoughts on “Debugger Detection Using NtGlobalFlag

  1. I did try same thing with inline assembly before, but there has little differents between 32bit and 64bit operation systems.

    “The NtGlobalFlag field exists at offset 0x68 in the Process Environment Block
    on the 32-bit versions of Windows, and at offset 0xBC on the 64-bit versions of
    Windows. The value in that field is zero by default.”(‘The “Ultimate” Anti-Debugging Referance’ by P.Ferrie’)

    My approach for this(for 32&64 bits),

    Good to see some raw assembly resources for it, regards 🙂

    • Yes thanks 🙂 I checked your code. But it seems to be wrong.

      “mov ebx,[fs:0x30];”
      “mov al, [eax+0x10bc];”

      You move the wrong segment register. In 64 bit it’s gs:[0x60] and it should be a qword, mov rbx, qword ptr gs:[0x60]. Also notice you move the value into ebx and then you move [eax+0x10bc] into al, actually it should be mov eax, dword ptr [rbx + 0xbc].

      The correct implementation would be:

      xor rax, rax
      mov rbx, qword ptr gs:[0x60]
      mov eax, dword ptr [rbx + 0xbc]

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s