> Windows Syscalls
ntoskrnl.exeT1106T1553

NtCompareSigningLevels

Vergleicht zwei SE_SIGNING_LEVEL-Werte gemäß der Code-Integrity-Policy-Ordnung und liefert, ob der erste den zweiten dominiert.

Prototyp

NTSTATUS NtCompareSigningLevels(
  SE_SIGNING_LEVEL FirstSigningLevel,
  SE_SIGNING_LEVEL SecondSigningLevel
);

Argumente

NameTypeDirDescription
FirstSigningLevelSE_SIGNING_LEVELinErstes zu vergleichendes Signaturlevel (0 Unchecked, 4 Authenticode, 6 Store, 8 Antimalware, 12 Microsoft, 14 Windows).
SecondSigningLevelSE_SIGNING_LEVELinZweites Signaturlevel, das mit dem ersten verglichen wird.

Syscall-IDs pro Windows-Version

Windows-VersionSyscall-IDBuild
Win10 17030x98win10-1703
Win10 17090x99win10-1709
Win10 18030x9Awin10-1803
Win10 18090x9Awin10-1809
Win10 19030x9Awin10-1903
Win10 19090x9Awin10-1909
Win10 20040x9Cwin10-2004
Win10 20H20x9Cwin10-20h2
Win10 21H10x9Cwin10-21h1
Win10 21H20x9Cwin10-21h2
Win10 22H20x9Cwin10-22h2
Win11 21H20x9Ewin11-21h2
Win11 22H20x9Ewin11-22h2
Win11 23H20x9Ewin11-23h2
Win11 24H20xA0win11-24h2
Server 20190x9Awinserver-2019
Server 20220x9Ewinserver-2022
Server 20250xA0winserver-2025

Kernel-Modul

ntoskrnl.exeNtCompareSigningLevels

Verwandte APIs

NtGetCachedSigningLevelNtSetCachedSigningLevelWldpQueryDynamicCodeTrustCiCompareSigningLevels

Syscall-Stub

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

Ein reiner Vergleichs-Helper, der nur deshalb als Syscall exponiert ist, damit die Ordnungs-Policy von Code Integrity an *einem* Ort lebt — dem Kernel — statt in jedem User-Mode-Komponenten neu implementiert zu werden. Liefert `STATUS_SUCCESS` (0), wenn `FirstSigningLevel` im CI-Verband größer oder gleich `SecondSigningLevel` ist, sonst `STATUS_NOT_FOUND` (0xC0000225). Wichtig: die Ordnung ist *nicht* numerisch: obwohl die Konstanten zufällig monoton sind (`0 < 4 < 6 < 8 < 12 < 14`), läuft der Kernel über `CiCompareSigningLevels` in `ci.dll`, das policy-definierte Äquivalenzen anwendet (zum Beispiel können `SE_SIGNING_LEVEL_STORE` und `SE_SIGNING_LEVEL_ANTIMALWARE` unter bestimmten WHQL-Policy-Flags als äquivalent gelten). Daher der Syscall — um diese Policy zu zentralisieren. Eingeführt in Windows 10 1703 zusammen mit dem Rest der modernen Code-Integrity-API-Oberfläche; nicht vorhanden auf Windows 10 1507 / 1607.

Häufige Malware-Nutzung

Nahezu null offensiver Wert. Es ist eine *reine* Funktion (keine Seiteneffekte, keine Privilegien, kein Ressourcenzugriff), die zwei Integer nimmt und einen Status liefert — es gibt nichts zu missbrauchen. Der einzige reale Grund, warum ein Angreifer sie aufruft, ist Buchhaltung: Red-Team-Loader, die eine CIG-Bypass-Primitive gebaut haben, rufen sie vor dem Commit zur Injection auf, um sicherzustellen, dass das gefälschte Level das vom Ziel geforderte dominiert. Sonst ist keine Malware-Familie als Nutzerin dokumentiert, und EDRs ignorieren ihn.

Erkennungs­möglichkeiten

Kein sinnvoller Detection-Punkt. Die Funktion hat keinen beobachtbaren Seiteneffekt, ETW loggt keine Per-Call-Events, und das Volumen aus legitimer `ci.dll`-Selbstnutzung ist so hoch, dass ratio-basiertes Hunting unpraktisch ist. Detection-Aufwand ist besser bei den *Aufrufern* angelegt — jeder Aufruf von `NtCompareSigningLevels` außerhalb von `ci.dll`, `wldp.dll`, `lsass.exe` und einer Handvoll Defender-Komponenten ist ungewöhnlich, aber nicht zwangsläufig bösartig. Mit User-Mode-Syscall-Telemetrie ist das Verknüpfen von `NtCompareSigningLevels`-Aufrufen mit benachbarten `NtSetCachedSigningLevel`- / `NtGetCachedSigningLevel`-Aufrufen aus demselben Thread ein wesentlich stärkeres Signal als dieser Aufruf isoliert.

Direkte Syscall-Beispiele

cDoes the cached level satisfy the target's CIG requirement?

// Used internally by ci.dll and by some EDRs to short-circuit policy decisions.
// Returns STATUS_SUCCESS if `have` dominates `need`, STATUS_NOT_FOUND otherwise.
#include <windows.h>
#include <winternl.h>

typedef NTSTATUS (NTAPI* pNtCompareSigningLevels)(UCHAR, UCHAR);

BOOL satisfies(UCHAR have, UCHAR need) {
    pNtCompareSigningLevels f = (pNtCompareSigningLevels)GetProcAddress(
        GetModuleHandleA("ntdll.dll"), "NtCompareSigningLevels");
    return NT_SUCCESS(f(have, need));
}

// Example: do we meet ProcessSignaturePolicy.MicrosoftSignedOnly = 1?
// satisfies(SE_SIGNING_LEVEL_MICROSOFT, SE_SIGNING_LEVEL_MICROSOFT) == TRUE
// satisfies(SE_SIGNING_LEVEL_AUTHENTICODE, SE_SIGNING_LEVEL_MICROSOFT) == FALSE

asmx64 direct stub (Win11 24H2 / Server 2025, SSN 0xA0)

NtCompareSigningLevels PROC
    mov  r10, rcx
    mov  eax, 0A0h
    syscall
    ret
NtCompareSigningLevels ENDP

MITRE ATT&CK-Mappings

Last verified: 2026-05-20