> Windows Syscalls
ntoskrnl.exeT1106

NtCreateProfile

Erzeugt ein Kernel-Mode-Sampling-Profiler-Objekt, das den Program Counter in ein Histogramm einsortiert.

Prototyp

NTSTATUS NtCreateProfile(
  PHANDLE        ProfileHandle,
  HANDLE         Process,
  PVOID          ProfileBase,
  SIZE_T         ProfileSize,
  ULONG          BucketSize,
  PULONG         Buffer,
  ULONG          BufferSize,
  KPROFILE_SOURCE ProfileSource,
  KAFFINITY      Affinity
);

Argumente

NameTypeDirDescription
ProfileHandlePHANDLEoutEmpfängt ein Handle auf das neu erzeugte Profil-Objekt.
ProcessHANDLEinHandle des zu profilierenden Prozesses oder NULL für das gesamte System.
ProfileBasePVOIDinStart des virtuellen Adressbereichs, dessen RIP-Samples gezählt werden.
ProfileSizeSIZE_TinLänge des profilierten Adressbereichs in Bytes.
BucketSizeULONGinlog2 der Bucket-Größe in Bytes, z. B. 2 für 4-Byte-Buckets.
BufferPULONGinVom Aufrufer bereitgestellter Buffer, der die Sample-Zähler pro Bucket aufnimmt.
BufferSizeULONGinGröße von Buffer in Bytes; muss ProfileSize >> BucketSize ULONG-Einträge fassen.
ProfileSourceKPROFILE_SOURCEinSampling-Quelle (ProfileTime, ProfileTotalIssues, ProfileBranchMispredictions usw.).
AffinityKAFFINITYinBitmaske der CPUs, auf die das Profil angewendet wird. 0 wählt alle verfügbaren CPUs.

Syscall-IDs pro Windows-Version

Windows-VersionSyscall-IDBuild
Win10 15070xAEwin10-1507
Win10 16070xB0win10-1607
Win10 17030xB3win10-1703
Win10 17090xB4win10-1709
Win10 18030xB5win10-1803
Win10 18090xB5win10-1809
Win10 19030xB6win10-1903
Win10 19090xB6win10-1909
Win10 20040xBAwin10-2004
Win10 20H20xBAwin10-20h2
Win10 21H10xBAwin10-21h1
Win10 21H20xBBwin10-21h2
Win10 22H20xBBwin10-22h2
Win11 21H20xBFwin11-21h2
Win11 22H20xC0win11-22h2
Win11 23H20xC0win11-23h2
Win11 24H20xC2win11-24h2
Server 20160xB0winserver-2016
Server 20190xB5winserver-2019
Server 20220xBEwinserver-2022
Server 20250xC2winserver-2025

Kernel-Modul

ntoskrnl.exeNtCreateProfile

Verwandte APIs

NtStartProfileNtStopProfileNtSetIntervalProfileNtQueryIntervalProfileNtCreateProfileEx

Syscall-Stub

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

NtCreateProfile treibt zusammen mit NtStartProfile / NtStopProfile / NtSetIntervalProfile / NtQueryIntervalProfile den klassischen Sampling-Profiler des Kernels — dasselbe Backend, das vor Jahrzehnten KernRate antrieb und das heute noch von einigen PerfView- und WPR-Szenarien genutzt wird. Der Profiler hängt sich an den High-Resolution-Timer (oder eine Hardware-PMU-Quelle auf unterstützten CPUs) und inkrementiert bei jedem Tick den Histogramm-Bucket, der dem unterbrochenen RIP entspricht, sofern RIP innerhalb von [ProfileBase, ProfileBase + ProfileSize) liegt. Der Buffer-Zeiger kommt aus dem User-Mode, der Kernel schreibt aber direkt aus dem ISR-Kontext hinein — daher muss der Buffer resident bleiben (praktisch sollte der Aufrufer ihn VirtualLocken). Erfordert SeSystemProfilePrivilege für systemweites Profiling.

Häufige Malware-Nutzung

Echt schwaches offensives Signal. Die historischen Missbräuche sind eng: (1) akademische Side-Channel-Arbeiten, die Sampling-Profiler nutzten, um Kernel-Scheduler-Verhalten zu fingerprinten und Geheimnisse aus Opfer-Threads auf geteilten Kernen abzuleiten; (2) Nischen-Timing-Attack-PoCs, die `ProfileTotalIssues` missbrauchten, um Retired Instructions in fremden Code-Pfaden zu zählen. Keines davon hat in Commodity-Malware Einzug gehalten — die SeSystemProfilePrivilege-Anforderung und der ungewöhnliche Syscall-Footprint machen es unrentabler als QueryPerformanceCounter fürs Timing oder PMU-MSR-Zugriffe für feinkörnige Seitenkanäle. Überwiegend defensives Tooling-Terrain.

Erkennungs­möglichkeiten

Sehr geringe Hintergrundnutzung in User-Mode-Malware. Ein Nicht-Systemprozess, der NtCreateProfile aufruft, besonders mit `Process == NULL` (systemweit) und `ProfileSource != ProfileTime`, ist im Grunde nie gutartig. `SeSystemProfilePrivilege`-Vergaben so auditieren wie SeDebugPrivilege. Das Profilobjekt selbst ist unter `\KernelObjects` sichtbar und benannte Profile-Handles lassen sich via NtQueryObject aufzählen. EDR-Abdeckung ist dürftig — es ist einer der seltenen nativen Syscalls, die fast nichts hookt, weil fast nichts ihn aufruft.

Direkte Syscall-Beispiele

cProfile the current process's main module

// Minimal NtCreateProfile + NtStartProfile sequence — defensive perf use.
#include <windows.h>
#include <winternl.h>

typedef NTSTATUS (NTAPI *PNTCREATEPROFILE)(PHANDLE, HANDLE, PVOID, SIZE_T, ULONG,
                                           PULONG, ULONG, ULONG, ULONG_PTR);
typedef NTSTATUS (NTAPI *PNTSTARTPROFILE)(HANDLE);

void profile_self(PVOID base, SIZE_T size) {
    ULONG bucketShift = 2;                 // 4-byte buckets
    ULONG entries     = (ULONG)(size >> bucketShift);
    ULONG *buf        = (ULONG*)VirtualAlloc(NULL, entries * sizeof(ULONG),
                                             MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    VirtualLock(buf, entries * sizeof(ULONG));

    HMODULE nt = GetModuleHandleA("ntdll.dll");
    PNTCREATEPROFILE pNtCreateProfile = (PNTCREATEPROFILE)GetProcAddress(nt, "NtCreateProfile");
    PNTSTARTPROFILE  pNtStartProfile  = (PNTSTARTPROFILE) GetProcAddress(nt, "NtStartProfile");

    HANDLE hProf = NULL;
    pNtCreateProfile(&hProf, GetCurrentProcess(), base, size, bucketShift,
                     buf, entries * sizeof(ULONG), 0 /* ProfileTime */, 0);
    pNtStartProfile(hProf);
}

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

NtCreateProfile PROC
    mov  r10, rcx
    mov  eax, 0C2h
    syscall
    ret
NtCreateProfile ENDP

MITRE ATT&CK-Mappings

Last verified: 2026-05-20