> Windows Syscalls
ntoskrnl.exeT1055.012T1055T1106

NtResumeProcess

Decrements every thread's suspend count in a target process, resuming threads that reach zero.

Prototype

NTSTATUS NtResumeProcess(
  HANDLE ProcessHandle
);

Arguments

NameTypeDirDescription
ProcessHandleHANDLEinHandle to the process to resume. Requires PROCESS_SUSPEND_RESUME.

Syscall IDs by Windows version

Windows versionSyscall IDBuild
Win10 15070x161win10-1507
Win10 16070x168win10-1607
Win10 17030x16Ewin10-1703
Win10 17090x171win10-1709
Win10 18030x173win10-1803
Win10 18090x174win10-1809
Win10 19030x175win10-1903
Win10 19090x175win10-1909
Win10 20040x17Bwin10-2004
Win10 20H20x17Bwin10-20h2
Win10 21H10x17Bwin10-21h1
Win10 21H20x17Dwin10-21h2
Win10 22H20x17Dwin10-22h2
Win11 21H20x185win11-21h2
Win11 22H20x188win11-22h2
Win11 23H20x188win11-23h2
Win11 24H20x18Awin11-24h2
Server 20160x168winserver-2016
Server 20190x174winserver-2019
Server 20220x183winserver-2022
Server 20250x18Awinserver-2025

Kernel module

ntoskrnl.exeNtResumeProcess

Related APIs

DebugActiveProcessStopResumeThreadNtResumeThreadNtSuspendProcessNtOpenProcess

Syscall stub

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

NtResumeProcess mirrors NtSuspendProcess and is similarly undocumented. It iterates the EPROCESS ThreadListHead calling KeResumeThread on each entry; threads whose suspend count drops to zero return to the dispatcher's ready queue. Like its counterpart the SSN drifts almost every release (0x161 → 0x18A across the supported window), and like its counterpart it is the per-process counterpart to ResumeThread without requiring the caller to enumerate threads via Toolhelp / NtGetNextThread.

Common malware usage

Always appears paired with NtSuspendProcess. Its three main roles: (1) closing the **Fork & Run** loop — after injecting and executing post-exploitation logic in a sacrificial process, the implant calls NtResumeProcess on its own helper if it suspended itself between heartbeats, or on the BOF thread once setup is done; (2) finishing **process hollowing** by reviving the previously suspended target after the malicious image is in place and the thread context is patched; (3) thawing the database / EDR processes a ransomware suspended pre-encryption once the encryption pass completes and the operator wants the victim's services to come back up cleanly (a courtesy in double-extortion scenarios meant to make recovery dependent on the operator's good faith).

Detection opportunities

By itself NtResumeProcess is harmless — every debugger and the Windows runtime use it. The actionable telemetry is the *pair*: NtSuspendProcess → write/inject → NtResumeProcess from the same caller on the same target within a short window, especially when the target is a sacrificial-process candidate (rundll32.exe, notepad.exe, RuntimeBroker.exe) freshly spawned by the same caller. ETW `Microsoft-Windows-Kernel-Audit-API-Calls` exposes Resume invocations when the audit policy enables them; combine with Sysmon Event ID 10 (ProcessAccess) showing PROCESS_SUSPEND_RESUME being requested on a non-child process for a high-signal alert.

Direct syscall examples

asmx64 direct stub (Win11 24H2)

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

chollowing teardown

// Final step of a process-hollowing routine: after writing the malicious
// image, fixing the suspended thread's RIP and Rcx, we resume everything.
#include <windows.h>

typedef NTSTATUS (NTAPI *pNtResumeProcess)(HANDLE);

void FinishHollow(HANDLE hProcess, HANDLE hThread, CONTEXT *ctx) {
    SetThreadContext(hThread, ctx);

    pNtResumeProcess NtResumeProcess = (pNtResumeProcess)GetProcAddress(
        GetModuleHandleA("ntdll.dll"), "NtResumeProcess");
    NtResumeProcess(hProcess);
}

rustthaw frozen DBs

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

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

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

MITRE ATT&CK mappings

Last verified: 2026-05-20