> Windows Syscalls
ntoskrnl.exeT1542.001T1106

NtQuerySystemEnvironmentValueEx

Lee una variable UEFI identificada por un par (nombre, GUID de proveedor) y devuelve sus datos y atributos.

Prototipo

NTSTATUS NtQuerySystemEnvironmentValueEx(
  PUNICODE_STRING VariableName,
  LPGUID          VendorGuid,
  PVOID           Value,
  PULONG          ValueLength,
  PULONG          Attributes
);

Argumentos

NameTypeDirDescription
VariableNamePUNICODE_STRINGinNombre de la variable UEFI, p. ej. L"BootOrder", L"dbx", L"PK", L"SecureBoot".
VendorGuidLPGUIDinEspacio GUID de proveedor. EFI_GLOBAL_VARIABLE para configuración de arranque, EFI_IMAGE_SECURITY_DATABASE_GUID para claves Secure Boot.
ValuePVOIDoutBúfer asignado por el llamador que recibe los datos crudos de la variable (binarios).
ValueLengthPULONGin/outEn entrada: capacidad del búfer. En salida: número de bytes efectivamente devueltos.
AttributesPULONGoutRecibe banderas de atributo EFI (NON_VOLATILE, BOOTSERVICE_ACCESS, RUNTIME_ACCESS, AUTHENTICATED_WRITE_ACCESS, ...).

IDs de syscalls por versión de Windows

Versión de WindowsID de syscallBuild
Win10 15070x146win10-1507
Win10 16070x14Dwin10-1607
Win10 17030x153win10-1703
Win10 17090x156win10-1709
Win10 18030x158win10-1803
Win10 18090x159win10-1809
Win10 19030x15Awin10-1903
Win10 19090x15Awin10-1909
Win10 20040x160win10-2004
Win10 20H20x160win10-20h2
Win10 21H10x160win10-21h1
Win10 21H20x161win10-21h2
Win10 22H20x161win10-22h2
Win11 21H20x168win11-21h2
Win11 22H20x16Bwin11-22h2
Win11 23H20x16Bwin11-23h2
Win11 24H20x16Dwin11-24h2
Server 20160x14Dwinserver-2016
Server 20190x159winserver-2019
Server 20220x166winserver-2022
Server 20250x16Dwinserver-2025

Módulo del kernel

ntoskrnl.exeNtQuerySystemEnvironmentValueEx

APIs relacionadas

GetFirmwareEnvironmentVariableExWGetFirmwareEnvironmentVariableWNtSetSystemEnvironmentValueExNtQuerySystemEnvironmentValueRtlAdjustPrivilege

Stub del syscall

4C 8B D1            mov r10, rcx
B8 6D 01 00 00      mov eax, 0x16D
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

La interfaz moderna de lectura de variables UEFI. Identifica una variable por (nombre, GUID de proveedor) — el nombre solo es ambiguo porque Secure Boot, BCD, utilidades de firmware de proveedor y gestión OEM reutilizan nombres cortos comunes bajo espacios GUID distintos. Devuelve los bytes crudos de la variable más su máscara de atributos EFI, permitiendo a los llamadores ver si la variable es no volátil, accesible en tiempo de ejecución o de escritura autenticada. Requiere SeSystemEnvironmentPrivilege. La superficie Win32 es GetFirmwareEnvironmentVariableExW.

Uso común por malware

Llamada de reconocimiento principal para actores conscientes del firmware. Leer `SecureBoot`, `SetupMode`, `PK`, `KEK`, `db`, `dbx` y `BootOrder` revela si Secure Boot está aplicándose, qué claves están enroladas, y qué cargador se ejecuta primero. TrickBoot (el módulo UEFI de TrickBot) utilizó el wrapper Win32 correspondiente para identificar firmware vulnerable. MoonBounce de APT41 y LoJax de Sednit/APT28 sondearon el estado UEFI por esta vía antes de decidir intentar persistencia vía el *setter* Ex. La lectura por sí sola es de bajo impacto; el valor está en seleccionar víctimas y evitar máquinas con firmware firmado.

Oportunidades de detección

Microsoft-Windows-Kernel-General ETW emite eventos de lectura de firmware incluyendo el nombre de variable y GUID. Los defensores deben hacer baseline de qué procesos leen legítimamente el estado de Secure Boot (System, mountvol, manage-bde, agentes de proveedor) y tratar a cualquier otro lector — especialmente malware en modo usuario que recién elevó y habilitó SeSystemEnvironmentPrivilege — como señal sospechosa de alta fidelidad. CrowdStrike y Microsoft Defender for Endpoint exponen llamadas directas mediante su sensor EDR; los wrappers Win32 también están comúnmente hookeados.

Ejemplos de syscalls directos

asmx64 direct stub (Win11 24H2)

; Direct syscall stub for NtQuerySystemEnvironmentValueEx (SSN 0x16D, Win11 24H2)
NtQuerySystemEnvironmentValueEx PROC
    mov  r10, rcx
    mov  eax, 16Dh
    syscall
    ret
NtQuerySystemEnvironmentValueEx ENDP

cRead SecureBoot state via Win32

// GUID for EFI_GLOBAL_VARIABLE: {8BE4DF61-93CA-11D2-AA0D-00E098032B8C}
// Win32 string-form is required by GetFirmwareEnvironmentVariableExW.
static const wchar_t* kGlobal = L"{8BE4DF61-93CA-11D2-AA0D-00E098032B8C}";
BOOLEAN was;
RtlAdjustPrivilege(SE_SYSTEM_ENVIRONMENT_PRIVILEGE, TRUE, FALSE, &was);

BYTE secureBoot = 0;
DWORD attrs = 0;
DWORD n = GetFirmwareEnvironmentVariableExW(
    L"SecureBoot", kGlobal, &secureBoot, sizeof(secureBoot), &attrs);
if (n == 1 && secureBoot == 1) {
    // Secure Boot is active. Variable attribute mask is in `attrs`.
}

rustDirect syscall query of BootOrder

// windows-sys = "0.59" — naked stub omitted for brevity (see x64 stub above).
// Demonstrates the call shape — privilege gating must be performed beforehand.
#[repr(C)]
struct UnicodeString { length: u16, max: u16, buf: *const u16 }

extern "system" {
    fn NtQuerySystemEnvironmentValueEx(
        name: *const UnicodeString,
        guid: *const windows_sys::core::GUID,
        value: *mut u8,
        value_len: *mut u32,
        attributes: *mut u32,
    ) -> i32;
}

const EFI_GLOBAL_VARIABLE: windows_sys::core::GUID = windows_sys::core::GUID {
    data1: 0x8BE4DF61, data2: 0x93CA, data3: 0x11D2,
    data4: [0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C],
};

Mapeos MITRE ATT&CK

Last verified: 2026-05-20