Use when designing, writing, reviewing, debugging, or hardening Windows WDM/KMDF drivers, IRP and IOCTL paths, PnP/power lifecycles, queues, cancellation, kernel memory, callbacks, or version-pinned ring-0 research. Covers WDK, HVCI, Driver Verifier, KD triage, manual mapping, APC/VAD/DKOM research, and safe teardown; route BYOVD to byovd and user-mode exploitation to exploit-dev.
Use when the task involves kernel-mode driver development, kernel shellcode,
manual mapping, injection, rootkit techniques, or any ring-0 code.
Project scaffolding
Default stack: C or C++ with the WDK. Prefer KMDF for new PnP device and queue work; use WDM when a required contract is genuinely below the framework. Keep private-layout research isolated from the supported driver path.
Link documented WDK imports normally. Use MmGetSystemRoutineAddress only for optional exported APIs with an explicit OS-version fallback; pattern-scanned or unexported routines are unsupported, version-pinned research dependencies.
Give every allocation a unique, searchable POOL_TAG; never reuse another driver's tag to disguise ownership.
Compile out DbgPrint in release builds, but retain WPP/IFR diagnostics suitable for crash correlation.
Prefer ExAllocatePool2 with NX POOL_FLAG_NON_PAGED or POOL_FLAG_PAGED; executable pool requires a documented design reason and a compatible HVCI policy.
Annotate IRQL and ownership with SAL (_IRQL_requires_max_, _Must_inspect_result_, _Post_writable_byte_size_) and build with /W4 /WX plus Code Analysis for Drivers.
Teardown every queue, callback registration, work item, timer, allocation, interface, symbolic link, and handle through the same ownership path that created it.
Correctness before stealth
A supported driver must survive malformed requests, concurrent removal, low-resource injection, Driver Verifier, and HVCI before any version-pinned research technique is considered. Prefer KMDF for new device/queue code; choose WDM only when the required contract is not represented by the framework.
IOCTL boundary contract
Define access deliberately; FILE_ANY_ACCESS is not a harmless default:
Secure the device with an INF security descriptor, IoCreateDeviceSecure, or WdfDeviceInitAssignSDDLString. Validate the caller's granted handle access as well as request contents.
Transfer method
Buffer source
Required handling
METHOD_BUFFERED
Irp->AssociatedIrp.SystemBuffer
Check both stack lengths, initialize every output byte, set IoStatus.Information to bytes actually written.
METHOD_IN_DIRECT / METHOD_OUT_DIRECT
Small input in SystemBuffer, second buffer described by Irp->MdlAddress
Validate direction and length; map with MmGetSystemAddressForMdlSafe(..., NormalPagePriority | MdlMappingNoExecute) and handle NULL.
METHOD_NEITHER
Type3InputBuffer / Irp->UserBuffer
Only probe inside __try/__except in the original requestor context at allowed IRQL, copy into owned kernel memory immediately, and never queue raw user pointers.
In KMDF use WdfRequestRetrieveInputBuffer, WdfRequestRetrieveOutputBuffer, and WdfRequestCompleteWithInformation; the framework still does not validate semantic fields, integer arithmetic, nested offsets, or versioned request headers. Gate lengths before pointer addition and use checked arithmetic such as RtlULongLongAdd.
allocation, complex parsing, waits, or request completion policy
Pair every reference with a release in the same state machine: ObReferenceObject/ObDereferenceObject, MDL lock/unlock/free, remove-lock acquire/release, WDF object parentage, rundown acquire/release, and IRP ownership. Use EX_RUNDOWN_REF for callbacks that race teardown and IO_REMOVE_LOCK in WDM PnP paths. Use work items for PASSIVE-only work; a DPC is not a generic worker thread.
Driver lifecycle
WDM path
DriverEntry initializes immutable state, dispatch entries (IRP_MJ_CREATE, IRP_MJ_CLOSE, IRP_MJ_CLEANUP, IRP_MJ_DEVICE_CONTROL, IRP_MJ_PNP, and IRP_MJ_POWER), DriverUnload where legal, and AddDevice for PnP drivers.
AddDevice creates the FDO, attaches with IoAttachDeviceToDeviceStackSafe, initializes IO_REMOVE_LOCK, clears DO_DEVICE_INITIALIZING, and unwinds every partial failure in reverse order.
IRP_MN_START_DEVICE acquires translated resources only after the lower stack completes. Do not accept I/O until start succeeds.
Every dispatch validates IO_STACK_LOCATION, acquires the remove lock, sets a cancel-safe ownership state, forwards or completes the IRP exactly once, and releases the lock on the matching completion path.
Use IoCsqInitialize or a framework queue for cancellable IRPs. The cancel routine, worker, timeout, and cleanup path must have one atomic winner; fixed sleeps are not synchronization.
Handle query-stop/remove, stop, surprise-removal, and remove distinctly. On remove, reject new I/O, drain with IoReleaseRemoveLockAndWait, detach, delete links/interfaces, then delete the device.
Forward power/PnP IRPs according to the WDK contract; never complete an IRP both locally and in a completion routine.
KMDF path
DriverEntry -> WdfDriverCreate -> EvtDriverDeviceAdd -> WdfDeviceCreate -> WdfIoQueueCreate. Put hardware transitions in EvtDevicePrepareHardware/EvtDeviceReleaseHardware, power transitions in D0 callbacks, request work in typed EvtIo* callbacks, cancellation in EvtRequestCancel, and per-object teardown in EvtCleanupCallback/EvtDestroyCallback. Once a request is forwarded or completed, the driver no longer owns it unless the documented API returns ownership.
Run only in a disposable KD-enabled VM. Include checked/debug versus release, x64 versus ARM64 when supported, HVCI off/on, normal versus low-resource/special-pool verifier, start/stop/remove/surprise-remove, malformed IOCTL corpus, cancellation at each ownership edge, and repeated load/unload. Test-signing is a lab boot-policy choice; it is not production signing.
On a crash preserve the dump, exact SYS/PDB identity, verifier settings, and these KD views before changing code:
These topics preserve the skill's ring-0 research coverage, but they are not supported driver architecture. Pin the exact Windows build, module hashes, PDB identity, offsets, VBS/HVCI state, and rollback snapshot. Treat every unexported routine, pattern-derived address, or internal layout as invalid after an update until re-proven.
APC delivery and thread context
MmAllocateContiguousMemory returns kernel virtual memory backed by contiguous physical pages; it does not allocate target-process user memory.
A documented ZwAllocateVirtualMemory path requires a process handle with the right access and strict requestor/context handling. Prefer a cooperative user-mode component for legitimate instrumentation; never retain an attach across waits or calls into unknown code.
PsSuspendThread, PsGetContextThread, and PsResumeThread are not a supported WDK thread-hijack contract. A lab that studies them must resolve and validate each build independently, account for WOW64/CET state, restore context on every exit, and cannot ship this path as production code.
Internal KAPC layout and queue behavior are version-sensitive. Prove target-thread lifetime, APC environment, delivery conditions, cancellation, and allocation ownership before claiming a result.
VAD, callbacks, DKOM, and SSDT
MMVAD, EPROCESS, ETHREAD, token fast references, callback storage, and service tables are private layouts. Direct edits can violate reference counts, locks, PatchGuard, HVCI, and concurrent enumerators even when one debugger observation looks correct.
A driver unregisters only registrations it owns, using the matching cookie/handle and documented API: PsSetCreateProcessNotifyRoutineEx(..., TRUE), ObUnRegisterCallbacks, CmUnRegisterCallback, FltUnregisterFilter, and corresponding thread/image APIs. Do not clear callback arrays or unlink filter globals.
DKOM unlinking and token replacement are forensic experiments, not lifecycle mechanisms. Record every invariant broken and restore the original list links/fast-reference semantics from a snapshot rather than trusting unload.
SSDT pointer edits, CR0.WP manipulation, and NXE changes are unsupported on x64 and conflict with PatchGuard/HVCI. Use documented filter/callback interfaces for drivers; route a genuine VMM/EPT experiment to hypervisor-dev or hyper-v-offensive.
Dynamic resolution
UNICODE_STRING name = RTL_CONSTANT_STRING(L"ExAllocatePool2");
PVOID optional = MmGetSystemRoutineAddress(&name);
Use this only for an exported API with a documented older-build fallback. Pattern scanning an unexported function requires static uniqueness, runtime boundary checks, fail-closed behavior, and a build-specific test matrix.
Routing
Batch A: bof-coff-development, windows-rpc-com-attack, windows-telemetry-etw, and hyper-v-offensive.
Batch B: linux-kernel-exploitation, c2-implant-engineering, ebpf-offensive, and linux-host-post-exploitation.
Use windows-internals for build-specific object/I/O context, driver-comm for IOCTL protocol design, kernel-callbacks for callback ownership, and windows-driver-0day for a confirmed driver vulnerability.
Use byovd for third-party vulnerable-driver operations, exploit-dev for a proved primitive, and hypervisor-dev for a custom VMM boundary.
Verification checklist
Documented versus unexported/version-pinned dependencies are explicit
Device ACL and every IOCTL method/access/length contract are tested
PnP, power, cancellation, removal, and partial-failure unwind paths are covered
IRQL, request, reference, MDL, allocation, and callback ownership are balanced
NX pool, SAL, /W4 /WX, Code Analysis, signing, and HVCI results are recorded
Driver Verifier passes malformed-I/O and repeated lifecycle tests
KD crash triage and exact SYS/PDB/build evidence are preserved
1---2name: kernel-dev3description: Use when designing, writing, reviewing, debugging, or hardening Windows WDM/KMDF drivers, IRP and IOCTL paths, PnP/power lifecycles, queues, cancellation, kernel memory, callbacks, or version-pinned ring-0 research. Covers WDK, HVCI, Driver Verifier, KD triage, manual mapping, APC/VAD/DKOM research, and safe teardown; route BYOVD to byovd and user-mode exploitation to exploit-dev.4---56# Kernel development workflow78## Activation910Use when the task involves kernel-mode driver development, kernel shellcode,11manual mapping, injection, rootkit techniques, or any ring-0 code.1213## Project scaffolding1415Default stack: C or C++ with the WDK. Prefer KMDF for new PnP device and queue work; use WDM when a required contract is genuinely below the framework. Keep private-layout research isolated from the supported driver path.1617```18<project>/19├── src/20│ ├── driver.c # DriverEntry / EvtDriverDeviceAdd21│ ├── device.c # device creation, ACL, interfaces22│ ├── queue.c # dispatch, cancellation, completion23│ ├── ioctl.c # versioned boundary validation24│ ├── pnp-power.c # start/stop/remove and D-state ownership25│ ├── trace.c # WPP/IFR diagnostics26│ └── util.c # checked arithmetic and owned helpers27├── include/ # public request ABI + internal contracts28├── tests/ # malformed IOCTL and lifecycle harnesses29├── research/ # optional, build-pinned private-layout work30├── package/ # INF, catalog, signing inputs31├── <project>.vcxproj32└── README.md # support matrix and teardown contract33```3435## Coding conventions3637- Link documented WDK imports normally. Use `MmGetSystemRoutineAddress` only for optional exported APIs with an explicit OS-version fallback; pattern-scanned or unexported routines are unsupported, version-pinned research dependencies.38- Give every allocation a unique, searchable `POOL_TAG`; never reuse another driver's tag to disguise ownership.39- Compile out `DbgPrint` in release builds, but retain WPP/IFR diagnostics suitable for crash correlation.40- Prefer `ExAllocatePool2` with NX `POOL_FLAG_NON_PAGED` or `POOL_FLAG_PAGED`; executable pool requires a documented design reason and a compatible HVCI policy.41- Annotate IRQL and ownership with SAL (`_IRQL_requires_max_`, `_Must_inspect_result_`, `_Post_writable_byte_size_`) and build with `/W4 /WX` plus Code Analysis for Drivers.42- Teardown every queue, callback registration, work item, timer, allocation, interface, symbolic link, and handle through the same ownership path that created it.4344## Correctness before stealth4546A supported driver must survive malformed requests, concurrent removal, low-resource injection, Driver Verifier, and HVCI before any version-pinned research technique is considered. Prefer KMDF for new device/queue code; choose WDM only when the required contract is not represented by the framework.4748### IOCTL boundary contract4950Define access deliberately; `FILE_ANY_ACCESS` is not a harmless default:5152```c53#define IOCTL_LAB_QUERY CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, \54 METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)55```5657Secure the device with an INF security descriptor, `IoCreateDeviceSecure`, or `WdfDeviceInitAssignSDDLString`. Validate the caller's granted handle access as well as request contents.5859| Transfer method | Buffer source | Required handling |60|---|---|---|61| `METHOD_BUFFERED` | `Irp->AssociatedIrp.SystemBuffer` | Check both stack lengths, initialize every output byte, set `IoStatus.Information` to bytes actually written. |62| `METHOD_IN_DIRECT` / `METHOD_OUT_DIRECT` | Small input in `SystemBuffer`, second buffer described by `Irp->MdlAddress` | Validate direction and length; map with `MmGetSystemAddressForMdlSafe(..., NormalPagePriority \| MdlMappingNoExecute)` and handle NULL. |63| `METHOD_NEITHER` | `Type3InputBuffer` / `Irp->UserBuffer` | Only probe inside `__try/__except` in the original requestor context at allowed IRQL, copy into owned kernel memory immediately, and never queue raw user pointers. |6465In KMDF use `WdfRequestRetrieveInputBuffer`, `WdfRequestRetrieveOutputBuffer`, and `WdfRequestCompleteWithInformation`; the framework still does not validate semantic fields, integer arithmetic, nested offsets, or versioned request headers. Gate lengths before pointer addition and use checked arithmetic such as `RtlULongLongAdd`.6667### IRQL and resource ownership6869| Context | Allowed work | Forbidden shortcuts |70|---|---|---|71| `PASSIVE_LEVEL` | pageable code, registry/file Zw calls, waits, device setup/teardown | holding spin locks across calls or attaching indefinitely |72| `APC_LEVEL` or below | documented memory-manager operations that state this limit | touching pageable user buffers after context changes |73| `DISPATCH_LEVEL` | DPC-safe nonpaged state, spin locks, completion enqueue | blocking, pageable code/data, registry/file I/O, user probing |74| ISR/DIRQL | acknowledge hardware, capture minimal state, queue DPC | allocation, complex parsing, waits, or request completion policy |7576Pair every reference with a release in the same state machine: `ObReferenceObject`/`ObDereferenceObject`, MDL lock/unlock/free, remove-lock acquire/release, WDF object parentage, rundown acquire/release, and IRP ownership. Use `EX_RUNDOWN_REF` for callbacks that race teardown and `IO_REMOVE_LOCK` in WDM PnP paths. Use work items for PASSIVE-only work; a DPC is not a generic worker thread.7778## Driver lifecycle7980### WDM path81821. `DriverEntry` initializes immutable state, dispatch entries (`IRP_MJ_CREATE`, `IRP_MJ_CLOSE`, `IRP_MJ_CLEANUP`, `IRP_MJ_DEVICE_CONTROL`, `IRP_MJ_PNP`, and `IRP_MJ_POWER`), `DriverUnload` where legal, and `AddDevice` for PnP drivers.832. `AddDevice` creates the FDO, attaches with `IoAttachDeviceToDeviceStackSafe`, initializes `IO_REMOVE_LOCK`, clears `DO_DEVICE_INITIALIZING`, and unwinds every partial failure in reverse order.843. `IRP_MN_START_DEVICE` acquires translated resources only after the lower stack completes. Do not accept I/O until start succeeds.854. Every dispatch validates `IO_STACK_LOCATION`, acquires the remove lock, sets a cancel-safe ownership state, forwards or completes the IRP exactly once, and releases the lock on the matching completion path.865. Use `IoCsqInitialize` or a framework queue for cancellable IRPs. The cancel routine, worker, timeout, and cleanup path must have one atomic winner; fixed sleeps are not synchronization.876. Handle query-stop/remove, stop, surprise-removal, and remove distinctly. On remove, reject new I/O, drain with `IoReleaseRemoveLockAndWait`, detach, delete links/interfaces, then delete the device.887. Forward power/PnP IRPs according to the WDK contract; never complete an IRP both locally and in a completion routine.8990### KMDF path9192`DriverEntry -> WdfDriverCreate -> EvtDriverDeviceAdd -> WdfDeviceCreate -> WdfIoQueueCreate`. Put hardware transitions in `EvtDevicePrepareHardware`/`EvtDeviceReleaseHardware`, power transitions in D0 callbacks, request work in typed `EvtIo*` callbacks, cancellation in `EvtRequestCancel`, and per-object teardown in `EvtCleanupCallback`/`EvtDestroyCallback`. Once a request is forwarded or completed, the driver no longer owns it unless the documented API returns ownership.9394### Build, signing, and test matrix9596```powershell97msbuild .\driver.sln /m /p:Configuration=Release /p:Platform=x6498InfVerif.exe /w .\package\driver.inf99signtool.exe verify /kp /v .\package\driver.sys100pnputil.exe /add-driver .\package\driver.inf /install101verifier.exe /standard /driver driver.sys102verifier.exe /querysettings103```104105Run only in a disposable KD-enabled VM. Include checked/debug versus release, x64 versus ARM64 when supported, HVCI off/on, normal versus low-resource/special-pool verifier, start/stop/remove/surprise-remove, malformed IOCTL corpus, cancellation at each ownership edge, and repeated load/unload. Test-signing is a lab boot-policy choice; it is not production signing.106107On a crash preserve the dump, exact SYS/PDB identity, verifier settings, and these KD views before changing code:108109```text110!analyze -v111!verifier 3 driver.sys112!irp <address>113!locks114!pool <address>115!wdfkd.wdfdevicequeues <WDFDEVICE>116```117118## Version-pinned research techniques119120### Research classification121122These topics preserve the skill's ring-0 research coverage, but they are not supported driver architecture. Pin the exact Windows build, module hashes, PDB identity, offsets, VBS/HVCI state, and rollback snapshot. Treat every unexported routine, pattern-derived address, or internal layout as invalid after an update until re-proven.123124### APC delivery and thread context125126- `MmAllocateContiguousMemory` returns kernel virtual memory backed by contiguous physical pages; it does **not** allocate target-process user memory.127- A documented `ZwAllocateVirtualMemory` path requires a process handle with the right access and strict requestor/context handling. Prefer a cooperative user-mode component for legitimate instrumentation; never retain an attach across waits or calls into unknown code.128- `PsSuspendThread`, `PsGetContextThread`, and `PsResumeThread` are not a supported WDK thread-hijack contract. A lab that studies them must resolve and validate each build independently, account for WOW64/CET state, restore context on every exit, and cannot ship this path as production code.129- Internal `KAPC` layout and queue behavior are version-sensitive. Prove target-thread lifetime, APC environment, delivery conditions, cancellation, and allocation ownership before claiming a result.130131### VAD, callbacks, DKOM, and SSDT132133- `MMVAD`, `EPROCESS`, `ETHREAD`, token fast references, callback storage, and service tables are private layouts. Direct edits can violate reference counts, locks, PatchGuard, HVCI, and concurrent enumerators even when one debugger observation looks correct.134- A driver unregisters only registrations it owns, using the matching cookie/handle and documented API: `PsSetCreateProcessNotifyRoutineEx(..., TRUE)`, `ObUnRegisterCallbacks`, `CmUnRegisterCallback`, `FltUnregisterFilter`, and corresponding thread/image APIs. Do not clear callback arrays or unlink filter globals.135- DKOM unlinking and token replacement are forensic experiments, not lifecycle mechanisms. Record every invariant broken and restore the original list links/fast-reference semantics from a snapshot rather than trusting unload.136- SSDT pointer edits, `CR0.WP` manipulation, and NXE changes are unsupported on x64 and conflict with PatchGuard/HVCI. Use documented filter/callback interfaces for drivers; route a genuine VMM/EPT experiment to `hypervisor-dev` or `hyper-v-offensive`.137138### Dynamic resolution139140```c141UNICODE_STRING name = RTL_CONSTANT_STRING(L"ExAllocatePool2");142PVOID optional = MmGetSystemRoutineAddress(&name);143```144145Use this only for an exported API with a documented older-build fallback. Pattern scanning an unexported function requires static uniqueness, runtime boundary checks, fail-closed behavior, and a build-specific test matrix.146147## Routing148149- Batch A: `bof-coff-development`, `windows-rpc-com-attack`, `windows-telemetry-etw`, and `hyper-v-offensive`.150- Batch B: `linux-kernel-exploitation`, `c2-implant-engineering`, `ebpf-offensive`, and `linux-host-post-exploitation`.151- Use `windows-internals` for build-specific object/I/O context, `driver-comm` for IOCTL protocol design, `kernel-callbacks` for callback ownership, and `windows-driver-0day` for a confirmed driver vulnerability.152- Use `byovd` for third-party vulnerable-driver operations, `exploit-dev` for a proved primitive, and `hypervisor-dev` for a custom VMM boundary.153154## Verification checklist155156- [ ] Documented versus unexported/version-pinned dependencies are explicit157- [ ] Device ACL and every IOCTL method/access/length contract are tested158- [ ] PnP, power, cancellation, removal, and partial-failure unwind paths are covered159- [ ] IRQL, request, reference, MDL, allocation, and callback ownership are balanced160- [ ] NX pool, SAL, `/W4 /WX`, Code Analysis, signing, and HVCI results are recorded161- [ ] Driver Verifier passes malformed-I/O and repeated lifecycle tests162- [ ] KD crash triage and exact SYS/PDB/build evidence are preserved
Run npx skillmds@latest add netvar1337/kernel-dev in your terminal (requires Node.js), paste this page's agent-chat prompt into Claude, Cursor, or any MCP-connected agent, or download the SKILL.md file and copy it into your agent's skills directory.
Use when designing, writing, reviewing, debugging, or hardening Windows WDM/KMDF drivers, IRP and IOCTL paths, PnP/power lifecycles, queues, cancellation, kernel memory, callbacks, or version-pinned ring-0 research. Covers WDK, HVCI, Driver Verifier, KD triage, manual mapping, APC/VAD/DKOM research, and safe teardown; route BYOVD to byovd and user-mode exploitation to exploit-dev. It is listed under Security, Productivity on SkillMD.
This skill has not completed SkillMD's automated safety review yet. SkillMD never runs a skill's scripts for you; review the SKILL.md before installing.
This skill is tagged as working with Claude Code, Claude.ai, OpenAI Codex. SKILL.md is an open format, so most agents that read a skills directory can load it too.
Yes. Installing skills from SkillMD is free, and the skill stays under its author's original license.
netvar1337 (@netvar1337) published this skill. Their other Agent Skills are listed on their SkillMD profile.