Design Philosophy

CS2ExternDrv was designed to be the absolute minimum kernel driver needed to provide stealthy memory access for an external cheat. The key design decisions were driven by one goal: minimize detectable surface area.

Shared Memory Protocol

Traditional drivers create a device object and expose IOCTL codes. This driver creates only a named section that user-mode opens by name:

Kernel creates:  \BaseNamedObjects\CS2ExternShared
User-mode opens: Global\CS2ExternShared

Structure:
  Magic (4 bytes)      - 0x4B3A7F2E
  Status (4 bytes)     - PENDING/COMPLETED/ERROR
  Command (4 bytes)      - READ/WRITE/GET_BASE/SET_PID
  OperationCounter     - User increments to signal new command
  ProcessId (4 bytes)
  Address (8 bytes)
  Size (4 bytes)
  Data[4096]           - Payload buffer

Why No IOCTL?

IOCTL-based drivers have several detectable components:

By using shared memory only, the driver only creates a section object. This is significantly less visible and works well with manual mappers that may not properly set up device objects anyway.

The tradeoff: No interrupts means polling overhead. The driver spins on the OperationCounter field, sleeping briefly between checks. This is acceptable for a cheat that reads at human-like rates (60-120Hz).

Security Model

Process Whitelisting

The driver implements a write-once whitelist:

This prevents an attacker who compromises the user-mode component from using the driver to attack arbitrary processes.

Address Validation

Integration Flow

1. User loads driver via kdmapper
2. Driver creates shared section, starts polling thread
3. User-mode cheat opens section via OpenFileMapping
4. Cheat sets target PID (CS2 process)
5. For each memory read:
   - Write address/size to shared memory
   - Increment OperationCounter
   - Driver detects change, performs read
   - Driver writes data, sets COMPLETED status
   - User-mode reads data

Building and Loading

The driver is built with WDK as a standard kernel driver, but loaded via kdmapper rather than SCM:

What I Learned

This minimal approach taught me that drivers can be much smaller than typical examples suggest. The shared memory approach, while less efficient than IOCTL for high-throughput scenarios, is perfectly adequate for game cheating use cases where you're reading at display refresh rates.

The main challenge was synchronization: ensuring the polling thread doesn't miss commands while avoiding excessive CPU usage. The solution was exponential backoff with a cap (1ms to 50ms sleep based on activity).