From 4d66b61f00ab3f3b9d4f7c1ebe172a97f052658c Mon Sep 17 00:00:00 2001 From: Alessandro Bellia Date: Mon, 1 Dec 2025 16:43:19 +0100 Subject: [PATCH] Improve README clarity and references --- README.md | 118 +++++++++++++++++------------------------------------- 1 file changed, 36 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index dd08d5c..5469390 100644 --- a/README.md +++ b/README.md @@ -1,88 +1,42 @@ # OAC -Open Anti-Cheat. A kernel-mode anticheat just for fun. [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/lauralex/OAC) - -## Features - -OAC implements several advanced detection vectors, each designed to uncover a different class of malicious activity. - -### 1. Anti-Hypervisor CR3 Thrashing - -This routine is designed to detect and crash poorly implemented hypervisors or virtualization-based cheats by manipulating memory management in a way that is valid on bare metal but often unhandled in a virtualized environment. - -The detection works through the following sequence: -1. **Minimalist Page Table Creation:** The driver constructs its own set of page tables in memory. These tables only map the absolute minimum required for the routine to function: a small portion of the driver's code, the custom Page Fault ISR, the Interrupt Stack, the IDT, and a variable to store the original `CR3`. -2. **Context Swap:** In a critical, interrupt-disabled section, the driver saves the original `CR3` and swaps the Interrupt Descriptor Table Register (`IDTR`) to point to its own custom IDT. -3. **CR3 Thrash:** The driver then overwrites the live `CR3` register with the physical address of its own minimalist PML4 table. -4. **Deliberate Page Fault:** A page fault is intentionally triggered by accessing an unmapped address. A legitimate system will vector this fault through our custom ISR. Many simple hypervisors, however, will fail to properly handle the nested page fault during the `CR3` write VM-exit, leading to a system crash (triple fault). -5. **Recovery:** Our custom Page Fault ISR immediately restores the original `CR3` value and resumes execution. The driver then restores the original `IDTR`, cleans up, and returns the system to a stable state. - -### 2. NMI-Based System Integrity Scans - -To perform analysis from a high-privilege, "out-of-band" context that is difficult for malware to intercept, OAC uses Non-Maskable Interrupts (NMIs). An NMI is sent to every logical processor, triggering a series of deferred checks that run at a lower, safer IRQL. - -#### a. Kernel Stack Unwinding & NMI Blocking Check -When the NMI callback is invoked, it first locates the `KTRAP_FRAME` to get the state of the interrupted code. It then performs a safe stack walk to gather the instruction pointers (`RIP`) from the call stack of the code that was executing on each core. The safe unwinding is ensured by temporarily installing a custom Page Fault handler to gracefully handle potential memory access violations during the process. A failure to process all sent NMIs within a timeout period indicates that an NMI might have been blocked or dropped, a highly suspicious event. - -#### b. Kernel Module Digital Signature Verification -The instruction pointers gathered during the NMI stack walk are enqueued for deferred analysis. A worker thread processes each `RIP` to verify that it resides within a legitimately signed kernel module. This is accomplished by using the undocumented `CiValidateFileObject` function, effectively checking the digital signature of the driver file on disk that corresponds to the code running in memory. An invalid signature is a strong indicator of an unsigned or maliciously patched driver. - -#### c. CR3 Validation -The `CR3` register, which holds the physical address of the current process's page tables, is captured during the NMI. In the deferred worker thread, this captured `CR3` is validated against a list of `CR3` values from all active processes on the system (derived from `PsActiveProcessHead`). A `CR3` value that does not belong to any known process is a hallmark of a stealthy rootkit or hypervisor attempting to hide its own execution by using its own private memory space. - -#### d. Suspicious Page Table Mapping Detection -This is a robust memory forensics routine that scans for fundamental security boundary violations within a process's memory layout. -- **Threat Model:** Detects if a user-mode process has page table entries (PTEs) that grant it direct access (Read, Write, or Execute) to canonical kernel-space virtual addresses (`0xFFFF800000000000` and higher). Such a mapping is a critical security flaw and a common technique used in privilege escalation exploits. -- **Methodology:** The routine performs a full, recursive walk of the page table hierarchy (PML4 -> PDPT -> PD -> PT) for each active user-mode process. -- **Validation Logic:** For a virtual address to be accessible from user mode, the `User/Supervisor` bit must be set to `User` at **every single level** of the translation chain. This routine validates this condition and flags any kernel address that is accessible to user mode, also reporting on large page (2MB) mappings. - -### 3. WFP-Based Shellcode Detection -This feature leverages the Windows Filtering Platform (WFP) to monitor outbound network connections and perform deep, heuristic-based analysis on the originating thread to detect in-memory shellcode, such as reverse shells. - -- **Threat Model:** Detects cheats or malware that inject raw shellcode into a process and then execute it to establish a network connection. A common pattern for this is creating a memory region with Read-Write-Execute (RWX) permissions. -- **Methodology:** The detection process is triggered for every new outbound connection: - 1. **WFP Callout:** The driver registers a callout at the `ALE_AUTH_CONNECT` layer, intercepting TCP/IP connection attempts before they are established. - 2. **Thread Context Acquisition:** Upon interception, the driver identifies the originating process and thread. It then locates the thread's kernel trap frame (`KTRAP_FRAME`) to access the user-mode register state (like `RIP` and `RSP`) at the exact moment of the system call that initiated the connection. - 3. **Heuristic Stack Unwinding:** A custom stack walker, built using the Zydis disassembler, unwinds the user-mode call stack of the originating thread. To ensure accuracy and avoid bad data, the stack walker validates each potential return address using several heuristics: - * The address must be a valid user-mode address. - * The memory page containing the address must have execute permissions. - * The address must be the target of a preceding `CALL` instruction, confirming a legitimate function call. - 4. **RWX and Signature Scanning:** For each validated instruction pointer on the call stack, the driver performs two final checks: - * It queries the memory protection of the page. If the page is marked as `PAGE_EXECUTE_READWRITE` (RWX), it is flagged as highly suspicious, as legitimate code rarely resides in writable and executable memory. - * It scans the memory at the address for known shellcode byte patterns. - 5. **Blocking Action:** If a return address points to an RWX memory region and contains a shellcode signature, the driver concludes that the connection is malicious. It then instructs WFP to block the connection, preventing the shellcode from communicating. - -## IOCTL Interface - -The driver is controlled from a user-mode client via the following IOCTLs: - -| Control Code | Hex Value | Description | -| -------------------------------- | --------- | ------------------------------------------------------------------------------------------------------- | -| `IOCTL_TEST_COMMUNICATION` | `0x800` | A simple test command to verify that the client and driver can communicate. | -| `IOCTL_TRIGGER_CR3_THRASH` | `0x801` | Executes the anti-hypervisor CR3 thrashing routine. | -| `IOCTL_UNLOAD_DRIVER` | `0x802` | Unloads the kernel driver. | -| `IOCTL_TRIGGER_NMI_STACKWALK` | `0x803` | Triggers the NMI-based system integrity scans (stackwalk, signature check, CR3 validation, etc.). | -| `IOCTL_INITIALIZE_WFP_MONITOR` | `0x804` | Registers the WFP callouts to begin monitoring outbound network connections. | -| `IOCTL_DEINITIALIZE_WFP_MONITOR` | `0x805` | De-registers the WFP callouts and cleans up all related filters, stopping network monitoring. | - - -## Build [![Build Windows Kernel Driver](https://github.com/lauralex/OAC/actions/workflows/msbuild.yml/badge.svg)](https://github.com/lauralex/OAC/actions/workflows/msbuild.yml) -### Requirements -- Visual Studio (2022 preferably) -- Windows Software Development Kit ([SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/)) -- Windows Driver Kit ([WDK](https://learn.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk)) +Open Anti-Cheat (OAC) is an educational Windows kernel-mode driver that exposes several anti-cheat detection routines and a thin user-mode client. + +## Architecture at a glance +- **Driver entry & IOCTL dispatcher** — `DriverEntry` and `DriverInitialize` wire up the device, symbolic link, and IRP handlers in [`OAC/main.c`](OAC/main.c). The IOCTL switch fans out to each feature and cleanly tears down on `IOCTL_UNLOAD_DRIVER`. +- **CR3 manipulation pipeline** — low-level paging utilities live in [`OAC/mm.c`](OAC/mm.c) with the crash-oriented thrashing routine in [`OAC/cr3_thrasher.c`](OAC/cr3_thrasher.c) and validation helpers in [`OAC/cr3_validation.c`](OAC/cr3_validation.c). +- **NMI stack walker** — Non-Maskable Interrupt setup, safe unwinding, and deferred analysis are grouped in [`OAC/stackwalk.c`](OAC/stackwalk.c) and helpers like [`OAC/zyan_stackwalker.c`](OAC/zyan_stackwalker.c). +- **WFP network monitor** — callout registration and connection inspection live in [`OAC/wfp_monitor.c`](OAC/wfp_monitor.c) with shellcode heuristics in [`OAC/shellcode_analyzer.c`](OAC/shellcode_analyzer.c). +- **Support code** — signature checks via [`OAC/ci.c`](OAC/ci.c), module and serial logging utilities in [`OAC/module.c`](OAC/module.c) and [`OAC/serial_logger.c`](OAC/serial_logger.c), and interrupt stubs in [`OAC/isr.asm`](OAC/isr.asm). + +## Features (with code pointers) +- **Anti-hypervisor CR3 thrash** — builds minimalist page tables, swaps CR3/IDT, triggers a deliberate fault, and restores state to expose fragile hypervisors. See `TriggerCr3Thrash` in [`OAC/cr3_thrasher.c`](OAC/cr3_thrasher.c) and the IOCTL hook in [`OAC/main.c`](OAC/main.c#L236-L249). +- **NMI-based integrity sweeps** — broadcasts NMIs, safely unwinds stacks, verifies module signatures (`CiValidateFileObject`), and checks captured CR3 values against active processes. Entry point `TriggerNmiStackwalk` in [`OAC/stackwalk.c`](OAC/stackwalk.c) and deferred analysis helpers in [`OAC/ci.c`](OAC/ci.c) / [`OAC/cr3_validation.c`](OAC/cr3_validation.c). +- **Suspicious page-table mapping scan** — recursively walks user process PTEs to detect kernel mappings reachable from user mode. Implemented in [`OAC/pt_analyzer.c`](OAC/pt_analyzer.c). +- **WFP shellcode detection** — intercepts outbound connects, reconstructs user-mode call stacks with Zydis, flags RWX frames, and blocks matching shellcode signatures. Callout setup in [`OAC/wfp_monitor.c`](OAC/wfp_monitor.c) with stack validation in [`OAC/shellcode_analyzer.c`](OAC/shellcode_analyzer.c). + +## IOCTL surface +```c +// OAC/main.c +#define IOCTL_TEST_COMMUNICATION CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_TRIGGER_CR3_THRASH CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_UNLOAD_DRIVER CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_TRIGGER_NMI_STACKWALK CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_INITIALIZE_WFP_MONITOR CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_DEINITIALIZE_WFP_MONITOR CTL_CODE(FILE_DEVICE_UNKNOWN, 0x805, METHOD_BUFFERED, FILE_ANY_ACCESS) +``` +Use `IrpDeviceIoCtlHandler` in [`OAC/main.c`](OAC/main.c#L230-L304) to map each control code to the routines above. + +## Build +- Requires Visual Studio 2022, Windows SDK, and WDK. The solution file is [`OAC.sln`](OAC.sln) and the driver project lives in [`OAC/OAC.vcxproj`](OAC/OAC.vcxproj). +- GitHub Actions build uses [`msbuild.yml`](https://github.com/lauralex/OAC/actions/workflows/msbuild.yml). ## Usage +> **⚠️ Kernel-mode warning:** Running the driver can destabilize or crash the system. Only run on isolated test or virtual machines. -> **:warning: WARNING:** This is a kernel-mode driver. Running this code can lead to system instability or Blue Screen of Death (BSOD) errors. It requires disabling fundamental Windows security features. **Use this exclusively on a test machine or in a virtual machine.** - -### External tools (optional, but suggested) -- **Kernel Driver Mapper:** A tool is required to map the driver into the kernel. [KDMapper](https://github.com/TheCruZ/kdmapper) is recommended. - -### Running the Anti-Cheat -1. **Disable VDBL (Vulnerable Driver BlockList):** This security feature must be disabled as it may prevent `kdmapper`'s vulnerable driver from loading. [Instructions here](https://www.elevenforum.com/t/enable-or-disable-microsoft-vulnerable-driver-blocklist-in-windows-11.10031/). -2. **Map the driver:** Open an administrator command prompt and run `kdmapper_Release.exe OAC.sys`. -3. **Run the client:** Execute `OAC-Client.exe` to interact with the driver and trigger its features via the IOCTL interface. +1. (Optional) Disable the Vulnerable Driver Blocklist if using `kdmapper` to load the driver. +2. Map `OAC.sys` with your loader (e.g., `kdmapper_Release.exe OAC.sys`). +3. Run the user client `OAC-Client.exe` to issue IOCTLs for CR3 thrash, NMI stackwalk, or WFP monitoring. ## Credits -- [ia32-doc](https://github.com/ia32-doc/ia32-doc): for invaluable Intel architecture documentation and structures. -- [zydis](https://github.com/zyantific/zydis): for the powerful Zydis disassembler library. +- [ia32-doc](https://github.com/ia32-doc/ia32-doc) — Intel architecture documentation and structures. +- [Zydis](https://github.com/zyantific/zydis) — disassembler used for stack reconstruction.