> Windows Syscalls
ntoskrnl.exeT1542.003T1542T1106

NtSetBootEntryOrder

Schreibt die Boot-Reihenfolge der Firmware — das Array der BOOT_ENTRY-IDs, das die Plattform der Reihe nach versucht.

Prototyp

NTSTATUS NtSetBootEntryOrder(
  PULONG Ids,
  ULONG  Count
);

Argumente

NameTypeDirDescription
IdsPULONGinArray von BOOT_ENTRY-Kennungen in der gewünschten Versuchsreihenfolge. Index 0 wird zuerst versucht.
CountULONGinAnzahl der Einträge in Ids. Muss jeder aktuell registrierten ID entsprechen — Teilreihenfolgen werden abgelehnt.

Syscall-IDs pro Windows-Version

Windows-VersionSyscall-IDBuild
Win10 15070x16Cwin10-1507
Win10 16070x174win10-1607
Win10 17030x17Awin10-1703
Win10 17090x17Dwin10-1709
Win10 18030x17Fwin10-1803
Win10 18090x180win10-1809
Win10 19030x181win10-1903
Win10 19090x181win10-1909
Win10 20040x187win10-2004
Win10 20H20x187win10-20h2
Win10 21H10x187win10-21h1
Win10 21H20x189win10-21h2
Win10 22H20x189win10-22h2
Win11 21H20x191win11-21h2
Win11 22H20x194win11-22h2
Win11 23H20x194win11-23h2
Win11 24H20x196win11-24h2
Server 20160x174winserver-2016
Server 20190x180winserver-2019
Server 20220x18Fwinserver-2022
Server 20250x196winserver-2025

Kernel-Modul

ntoskrnl.exeNtSetBootEntryOrder

Verwandte APIs

SetFirmwareEnvironmentVariableW (BootOrder)bcdedit.exe /defaultbcdedit.exe /bootsequenceBcdSetElementData (Boot Order GUID)NtQueryBootEntryOrderNtAddBootEntry

Syscall-Stub

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

Undokumentierte Hinweise

Das Schreib-Gegenstück zu NtQueryBootEntryOrder. Auf UEFI ruft der Kernel letztlich `EFI_SET_VARIABLE` gegen die globale `BootOrder`-Variable auf (Vendor-GUID `{8BE4DF61-93CA-11d2-AA0D-00E098032B8C}`) mit `EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS`. SeSystemEnvironmentPrivilege ist Pflicht und der Aufruf scheitert mit STATUS_INVALID_PARAMETER, wenn eine übergebene ID nicht existiert.

Häufige Malware-Nutzung

Der Schlussstein der BCD-basierten Bootkit-Installation: nachdem ein bösartiges `Boot####` per NtAddBootEntry registriert wurde, ist dies der Aufruf, der dem Angreifer den nächsten Reboot **sichert**, indem er diese ID an Position 0 hebt. Ohne diesen Schritt bleibt der Angreifer-Eintrag inaktiv — UEFI probiert den vorhandenen Windows Boot Manager zuerst und erreicht ihn nie. Die Umsortierung macht das Implant erst aktiv. BlackLotus, ESPecter und das TrickBoot-Modul beenden ihren Installationspfad jeweils mit dieser Primitive.

Erkennungs­möglichkeiten

**Hochpräzisester BCD-Indikator der Familie.** Jede Änderung an `BootOrder`, die einen nicht-Microsoft-, nicht-OEM-Recovery-Eintrag auf Slot 0 hebt, ist im Wesentlichen diagnostisch für einen Bootkit-Versuch. Überwachen: ETW Microsoft-Windows-Kernel-Boot-Reihenfolgeänderungs-Events, Sysmon-Registry-Events auf BCD-Schreibvorgängen und die EFI-`BootOrder`-Variable via periodischem CHIPSEC- oder Eclypsium-Scan. Verteidiger sollten Endpoints zusätzlich in **Measured Boot + Remote Attestation** einschreiben — die PCR[4]-Messungen (Hash des Boot-Manager-Image) und PCR[7] (Secure-Boot-Policy + Signaturen-DB-Hash) weichen bereits beim allerersten kompromittierten Boot von der erwarteten Baseline ab, bevor der Nutzer überhaupt angemeldet ist.

Direkte Syscall-Beispiele

asmx64 direct stub (Win11 24H2, SSN 0x196)

NtSetBootEntryOrder PROC
    mov  r10, rcx          ; PULONG Ids
    mov  eax, 0196h        ; Win11 24H2
    syscall
    ret
NtSetBootEntryOrder ENDP

cPromote attacker ID to slot 0 (PoC)

// PoC: read order, move our_id to the front, write back.
extern NTSTATUS NTAPI NtQueryBootEntryOrder(PULONG, PULONG);
extern NTSTATUS NTAPI NtSetBootEntryOrder(PULONG, ULONG);

NTSTATUS promote(ULONG our_id) {
    ULONG count = 0;
    NtQueryBootEntryOrder(NULL, &count);
    PULONG ids = (PULONG)HeapAlloc(GetProcessHeap(), 0, count * sizeof(ULONG));
    NtQueryBootEntryOrder(ids, &count);
    // find our_id, swap to front
    for (ULONG i = 0; i < count; ++i) {
        if (ids[i] == our_id) {
            memmove(&ids[1], &ids[0], i * sizeof(ULONG));
            ids[0] = our_id;
            break;
        }
    }
    NTSTATUS s = NtSetBootEntryOrder(ids, count);
    HeapFree(GetProcessHeap(), 0, ids);
    return s;
}

rustNaked stub

use std::arch::asm;

#[unsafe(naked)]
unsafe extern "system" fn nt_set_boot_entry_order(_ids: *const u32, _count: u32) -> i32 {
    asm!(
        "mov r10, rcx",
        "mov eax, 0x196",  // Win11 24H2
        "syscall",
        "ret",
        options(noreturn),
    );
}

MITRE ATT&CK-Mappings

Last verified: 2026-05-20