> Windows Syscalls
ntoskrnl.exeT1542.003T1542T1106

NtModifyBootEntry

Remplace une BOOT_ENTRY existante dans la base BCD par un nouveau descripteur, identifié par son ID.

Prototype

NTSTATUS NtModifyBootEntry(
  PBOOT_ENTRY BootEntry
);

Arguments

NameTypeDirDescription
BootEntryPBOOT_ENTRYinPointeur vers une BOOT_ENTRY dont le champ `Id` sélectionne l'entrée existante à écraser. Le reste de la structure devient le nouveau contenu.

IDs de syscalls par version de Windows

Version de WindowsID de syscallBuild
Win10 15070x102win10-1507
Win10 16070x107win10-1607
Win10 17030x10Bwin10-1703
Win10 17090x10Cwin10-1709
Win10 18030x10Ewin10-1803
Win10 18090x10Fwin10-1809
Win10 19030x110win10-1903
Win10 19090x110win10-1909
Win10 20040x115win10-2004
Win10 20H20x115win10-20h2
Win10 21H10x115win10-21h1
Win10 21H20x116win10-21h2
Win10 22H20x116win10-22h2
Win11 21H20x11Cwin11-21h2
Win11 22H20x11Dwin11-22h2
Win11 23H20x11Dwin11-23h2
Win11 24H20x11Fwin11-24h2
Server 20160x107winserver-2016
Server 20190x10Fwinserver-2019
Server 20220x11Bwinserver-2022
Server 20250x11Fwinserver-2025

Module noyau

ntoskrnl.exeNtModifyBootEntry

APIs liées

BcdSetElementData (bcd.dll)bcdedit.exe /set {bootmgr} pathSetFirmwareEnvironmentVariableWNtAddBootEntryNtDeleteBootEntryNtEnumerateBootEntriesNtSetBootEntryOrder

Stub du syscall

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

Contrairement à NtAddBootEntry, NtModifyBootEntry n'a pas de paramètre `Id` en sortie — l'ID est la *clé primaire* embarquée dans la BOOT_ENTRY entrante. Le noyau localise l'entrée firmware correspondante (variable EFI `Boot####` sur UEFI, entrée dans la ruche BCD sur BIOS) et la réécrit atomiquement. SeSystemEnvironmentPrivilege requis. Le même blob opaque `OsOptionsLength` est honoré, ce qui permet de patcher en un coup n'importe quels éléments BCD (BcdLibraryDevice_ApplicationDevice, BcdOSLoaderString_KernelPath, etc.).

Usage courant par les malwares

La variante de persistance BCD la plus furtive : plutôt que d'*ajouter* une entrée suspecte que les défenseurs verraient dans `bcdedit /enum`, le malware **mute l'entrée Windows légitime `{current}`** pour que son élément `path` pointe sur un bootmgr malveillant ou un binaire EFI chaîné qui rebrousse ensuite vers le vrai loader. L'utilisateur ne voit aucun menu supplémentaire ; le système démarre simplement par le stage 0 de l'attaquant. C'est la technique attribuée à ESPecter (qui modifie l'objet BCD existant Windows Boot Manager) et à la reconnaissance `bcdedit /set {bootmgr} path` de TrickBoot. BlackLotus patche également l'entrée existante pour désactiver les vérifications d'intégrité BitLocker avant l'exécution de son bootkit.

Opportunités de détection

Les modifications BCD touchent la même télémétrie que les ajouts : ETW Microsoft-Windows-Kernel-Boot, deltas registre sur `HKLM\BCD00000000`, et événement d'audit 4673 pour SeSystemEnvironmentPrivilege. Différencier spécifiquement les éléments `path`, `device` et `nx` des objets `{current}` et `{bootmgr}` par rapport à une baseline de référence — tout changement hors fenêtre Patch Tuesday est suspect. Windows Defender Application Control (WDAC) ne peut pas empêcher l'appel, mais appliquer **Boot Integrity** via Measured Boot + un service d'attestation distante (Azure Attestation, santé des appareils Intune) détecte la dérive post-démarrage car les mesures TPM PCR[4]/PCR[7] divergeront de la politique attendue.

Exemples de syscalls directs

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

NtModifyBootEntry PROC
    mov  r10, rcx          ; PBOOT_ENTRY (Id baked into the struct)
    mov  eax, 11Fh         ; Win11 24H2
    syscall
    ret
NtModifyBootEntry ENDP

cHijack the existing Windows entry path

// Conceptual: rewrite the {current} Windows entry so its bootmgr path becomes our shim.
// Read the existing entry via NtEnumerateBootEntries, mutate the FilePath, write back.
NTSTATUS hijack_current(ULONG id, const wchar_t* shim_path) {
    BYTE buf[1024] = {0};
    PBOOT_ENTRY be = (PBOOT_ENTRY)buf;
    be->Version = 1;
    be->Length  = sizeof(buf);
    be->Id      = id;                 // ID returned by NtEnumerateBootEntries
    be->Attributes = BOOT_ENTRY_ATTRIBUTE_ACTIVE;
    be->BootFilePathOffset = FIELD_OFFSET(BOOT_ENTRY, OsOptions);
    // Build a FILE_PATH(\EFI\evil\shim.efi) here ...
    return NtModifyBootEntry(be);
}

rustNaked stub

use std::arch::asm;

#[unsafe(naked)]
unsafe extern "system" fn nt_modify_boot_entry(_entry: *mut u8) -> i32 {
    asm!(
        "mov r10, rcx",
        "mov eax, 0x11F",  // Win11 24H2
        "syscall",
        "ret",
        options(noreturn),
    );
}

Mappings MITRE ATT&CK

Last verified: 2026-05-20