> Windows Syscalls
ntoskrnl.exeT1497T1106

NtQueryBootOptions

Lee el blob de opciones de arranque BCD del sistema — flags debug, opciones de carga del SO, hypervisor, test signing.

Prototipo

NTSTATUS NtQueryBootOptions(
  PBOOT_OPTIONS BootOptions,
  PULONG        BootOptionsLength
);

Argumentos

NameTypeDirDescription
BootOptionsPBOOT_OPTIONSoutEstructura BOOT_OPTIONS asignada por el llamador (longitud variable) que recibe las opciones de arranque actuales.
BootOptionsLengthPULONGin/outEn entrada: capacidad en bytes. En salida: bytes escritos; STATUS_BUFFER_TOO_SMALL devuelve el tamaño requerido.

IDs de syscalls por versión de Windows

Versión 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

Módulo del kernel

ntoskrnl.exeNtQueryBootOptions

APIs relacionadas

NtSetBootOptionsNtQueryBootEntryOrderNtEnumerateBootEntriesbcdedit /enum {current}

Stub del 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

Notas no documentadas

Devuelve el blob BOOT_OPTIONS capturado por el cargador de SO y expuesto al kernel en ejecución. La estructura incluye Version, Length, Timeout, CurrentBootEntryId, NextBootEntryId y un HeaderId seguido de la región de cadenas de opciones. Ejemplos de cadenas presentes: `DEBUG`, `TESTSIGNING`, `HYPERVISORLAUNCHTYPE=AUTO`, `BOOTLOG`, `WINPE`, `NOEXECUTE=OPTIN`. Requiere SeSystemEnvironmentPrivilege. Mayormente usada por herramientas de recovery / setup y por algunos productos defensivos que quieren detectar si el host corre en modo arranque amigable al desarrollador.

Uso común por malware

Señal ofensiva baja. Algunos malwares (notablemente rutinas anti-análisis en loaders commodity) llaman a esto para detectar estados de arranque amistosos al debugger (`DEBUG`, `TESTSIGNING`, `BOOTLOG`) y abortar o modificar comportamiento para evadir entornos sandbox / lab. Ese es el patrón de abuso dominante — environmental keying en lugar de compromiso directo. Leer opciones de arranque no escala privilegios por sí mismo ni persiste.

Oportunidades de detección

El volumen de llamadas legítimas es moderado (herramientas de recovery, agentes de diagnóstico OEM, algunos productos de protección endpoint). ETW Microsoft-Windows-Kernel-General registra el acceso. La señal interesante es la *correlación*: un binario que acaba de elevar, habilitar SeSystemEnvironmentPrivilege y luego leyó BootOptions justo antes de decidir desplegar más payload es la forma anti-análisis de libro de texto. Los proveedores de sandbox normalmente responden falsificando el blob devuelto para hacer `DEBUG`/`TESTSIGNING` invisibles.

Ejemplos de syscalls directos

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
    }
}

Mapeos MITRE ATT&CK

Last verified: 2026-05-20