> Windows Syscalls
ntoskrnl.exeT1497T1106

NtQueryBootOptions

Lit le blob d'options de démarrage BCD du système — drapeaux debug, options de chargement OS, hyperviseur, test signing.

Prototype

NTSTATUS NtQueryBootOptions(
  PBOOT_OPTIONS BootOptions,
  PULONG        BootOptionsLength
);

Arguments

NameTypeDirDescription
BootOptionsPBOOT_OPTIONSoutStructure BOOT_OPTIONS allouée par l'appelant (longueur variable) recevant les options de boot actuelles.
BootOptionsLengthPULONGin/outEn entrée : capacité en octets. En sortie : octets écrits ; STATUS_BUFFER_TOO_SMALL retourne la taille requise.

IDs de syscalls par version de Windows

Version de WindowsID de syscallBuild
Win10 15070x129win10-1507
Win10 16070x12Fwin10-1607
Win10 17030x134win10-1703
Win10 17090x136win10-1709
Win10 18030x138win10-1803
Win10 18090x139win10-1809
Win10 19030x13Awin10-1903
Win10 19090x13Awin10-1909
Win10 20040x140win10-2004
Win10 20H20x140win10-20h2
Win10 21H10x140win10-21h1
Win10 21H20x141win10-21h2
Win10 22H20x141win10-22h2
Win11 21H20x147win11-21h2
Win11 22H20x149win11-22h2
Win11 23H20x149win11-23h2
Win11 24H20x14Bwin11-24h2
Server 20160x12Fwinserver-2016
Server 20190x139winserver-2019
Server 20220x146winserver-2022
Server 20250x14Bwinserver-2025

Module noyau

ntoskrnl.exeNtQueryBootOptions

APIs liées

NtSetBootOptionsNtQueryBootEntryOrderNtEnumerateBootEntriesbcdedit /enum {current}

Stub du syscall

4C 8B D1            mov r10, rcx
B8 4B 01 00 00      mov eax, 0x14B
F6 04 25 08 03 FE 7F 01   test byte ptr [0x7FFE0308], 1
75 03               jne short +3
0F 05               syscall
C3                  ret
CD 2E               int 2Eh
C3                  ret

Notes non documentées

Retourne le blob BOOT_OPTIONS capturé par le chargeur d'OS et exposé dans le noyau en cours d'exécution. La structure inclut Version, Length, Timeout, CurrentBootEntryId, NextBootEntryId, et un HeaderId suivi de la région des chaînes d'options. Exemples de chaînes présentes : `DEBUG`, `TESTSIGNING`, `HYPERVISORLAUNCHTYPE=AUTO`, `BOOTLOG`, `WINPE`, `NOEXECUTE=OPTIN`. Nécessite SeSystemEnvironmentPrivilege. Principalement utilisé par l'outillage de recovery / setup et par certains produits défensifs voulant détecter si l'hôte tourne en mode boot favorable au développeur.

Usage courant par les malwares

Faible signal offensif. Certains malwares (notamment les routines anti-analyse dans les loaders de masse) appellent cela pour détecter des états de boot favorables au debugger (`DEBUG`, `TESTSIGNING`, `BOOTLOG`) et abandonner ou modifier leur comportement pour échapper aux environnements sandbox / labo. C'est le schéma d'abus dominant — environmental keying plutôt que compromission directe. Lire les options de boot n'élève pas en soi le privilège ni ne persiste.

Opportunités de détection

Le volume d'appels légitimes est modéré (outillage de recovery, agents diagnostic OEM, certains produits de protection endpoint). L'ETW Microsoft-Windows-Kernel-General journalise l'accès. Le signal intéressant est la *corrélation* : un binaire qui vient d'élever, d'activer SeSystemEnvironmentPrivilege, puis a lu BootOptions juste avant de décider de déployer la suite du payload est la forme anti-analyse classique. Les éditeurs de sandbox répondent généralement en falsifiant le blob retourné pour rendre `DEBUG`/`TESTSIGNING` invisibles.

Exemples de syscalls directs

asmx64 direct stub (Win11 24H2)

; Direct syscall stub for NtQueryBootOptions (SSN 0x14B, Win11 24H2)
NtQueryBootOptions PROC
    mov  r10, rcx
    mov  eax, 14Bh
    syscall
    ret
NtQueryBootOptions ENDP

cAnti-analysis: refuse to run under DEBUG/TESTSIGNING boot

// Demonstrative environmental-keying check used by commodity loaders.
// In production the loader fingerprints additional artefacts before deciding.
#pragma pack(push,4)
typedef struct _BOOT_OPTIONS {
    ULONG  Version;
    ULONG  Length;
    ULONG  Timeout;
    ULONG  CurrentBootEntryId;
    ULONG  NextBootEntryId;
    WCHAR  HeaderId[1]; // variable
} BOOT_OPTIONS, *PBOOT_OPTIONS;
#pragma pack(pop)

BOOLEAN was;
RtlAdjustPrivilege(SE_SYSTEM_ENVIRONMENT_PRIVILEGE, TRUE, FALSE, &was);

UCHAR buf[1024];
ULONG len = sizeof(buf);
NTSTATUS s = NtQueryBootOptions((PBOOT_OPTIONS)buf, &len);
if (NT_SUCCESS(s)) {
    // Naive substring scan of the trailing options region.
    PCWSTR opts = (PCWSTR)(buf + sizeof(BOOT_OPTIONS));
    if (wcsstr(opts, L"DEBUG") || wcsstr(opts, L"TESTSIGNING")) {
        ExitProcess(0); // bail — looks like an analyst's machine
    }
}

Mappings MITRE ATT&CK

Last verified: 2026-05-20