Skip to content

CyberSnakeH/snakeengine-driver

Repository files navigation

SnakeEngine Driver (Linux)

CI Platform Kernel License

Hardened memory-access and hardware-breakpoint driver for Linux, inspired by Cheat Engine's DBK on Windows. Kernel module + modern C++ userland API with dlopen injection, ImGui overlay support, and VMA stealth. Research and educational use only.

Highlights

  • Kernel driver (kernel/): /dev/snakedrv, process attach/detach, forced read/write, memory region enumeration, hardware breakpoints, debug event queue, physical memory access, and VMA unlinking for stealth.
  • Userland library (userland/): typed C/C++ API (snakedrv.h, libsnakedrv.hpp) plus ELF mapping/injection helpers and remote symbol resolution.
  • Memory scanner (libsnakedrv_scanner): Cheat Engine-style scans (exact/range/changed/pattern/float/string) with bloom filter acceleration and parallel scanning.
  • dlopen injection: inject any .so into a running process via dlopen — full C++ runtime, TLS, exception handling, and OpenGL support out of the box.
  • ImGui overlay: inject a Dear ImGui window into SDL2/OpenGL games (e.g. AssaultCube) with DYNAPI hook.
  • VMA stealth: hide injected .so from /proc/pid/maps via maple tree VMA unlinking.
  • Automation (deploy.sh): deps, build, install, load/unload, test, inject, SELinux policy, DKMS integration.
  • Security (security/): udev rules, AppArmor profile, SELinux policy (v2.0 with kernel thread + unconfined_t support), Secure Boot signing.

Requirements

  • Linux kernel 6.1+ on x86_64 (VMA unlinking relies on Maple Tree)
  • Kernel headers matching the running kernel
  • gcc, g++, make, cmake
  • SDL2-devel, mesa-libGL-devel (for ImGui payload)
  • DKMS recommended for kernel upgrades
  • Secure Boot (optional): mokutil and sign-module.sh

Quick start

# Build everything (driver + library + tests + ImGui payload)
./deploy.sh build

# Install (kernel module, library, tools, SELinux policy)
sudo ./deploy.sh install

# Load the module
sudo ./deploy.sh load

# Check status
./deploy.sh status

Injection (dlopen method)

The recommended injection method uses dlopen for full runtime support:

# Inject a .so into a running process
sudo dlopen_inject <pid> /path/to/payload.so

# Or via deploy.sh
sudo ./deploy.sh inject <pid> /path/to/payload.so

The payload must export a ManualMapEntry(void*) function. Manual-map stealth is intentionally disabled for now: hiding the VMA before the payload has faulted all pages can crash the target on later page faults.

ImGui overlay example

# Build the ImGui payload
./deploy.sh payload

# Launch a game and inject
assaultcube &
sleep 5
sudo dlopen_inject $(pgrep assaultcube) libpayload_dlopen.so

This injects a Dear ImGui overlay window into the game via SDL2 DYNAPI hook.

C++ API usage

#include "libsnakedrv.hpp"

int main() {
    snake::Driver drv;
    drv.open();
    drv.attach(target_pid);

    // Read/write memory
    uint32_t hp = drv.read<uint32_t>(health_addr);
    drv.write(health_addr, 9999);

    // Hardware breakpoint
    auto bp = drv.setBreakpoint(addr,
        snake::BreakpointType::ReadWrite,
        snake::BreakpointLength::Byte4);

    // Poll debug events
    for (const auto& ev : drv.pollEvents(16))
        printf("Hit at 0x%lx\n", ev.address);

    drv.clearBreakpoint(*bp);
    drv.detach();
}

SELinux policy

The driver ships a SELinux policy that allows operation under enforcing mode.

Install via deploy.sh

sudo ./deploy.sh install    # installs policy automatically

Install manually

cd security/
sudo dnf install selinux-policy-devel    # Fedora
sudo make -f /usr/share/selinux/devel/Makefile snakeengine.pp
sudo semodule -i snakeengine.pp
sudo restorecon -Rv /dev/snakedrv

Verify

getenforce                    # should show "Enforcing"
sudo ./deploy.sh status       # should work without setenforce 0

Policy details

The v2.0 policy covers:

  • unconfined_t (sudo processes) access to /dev/snakedrv ioctls
  • kernel_t threads (snake_injector, snake_shadow) with execmem for vm_mmap(PROT_EXEC)
  • CAP_SYS_PTRACE and CAP_SYS_ADMIN capability checks
  • udev device node creation
  • Boolean snakeengine_can_trace_all (default: on)

Project layout

kernel/          Kernel driver (snakedrv.ko)
  snakedrv_main.c          Core driver, IOCTLs, capability checks
  snakedrv_scanner.c       Memory scanner with bloom filter
  snakedrv_backend_process.c  Process memory backend
  snakedrv_injector.c      Injection: alloc, stealth, thread hijack, shadow memory
  snakedrv_backend.h       Backend abstraction (VFS-style vtable)
  snakedrv_optimize.h      Cache prefetch, huge page support
  snakedrv_bloom.h         Bloom filter for scan rescans
  snakedrv_memory.h        Slab caches, buffer pooling
  snakedrv_benchmark.h     Performance counters

userland/        C/C++ headers and library
  include/snakedrv.h       IOCTL definitions and ABI
  include/libsnakedrv.hpp  C++ driver API
  include/snakedrv_elf.hpp ELF parser and relocation engine
  src/libsnakedrv.cpp      Driver implementation
  src/snakedrv_injector.cpp  Manual mapper + dlopen injector

security/        Security policies
  snakeengine.te           SELinux type enforcement (v2.0)
  snakeengine.fc           SELinux file contexts
  snakeengine.apparmor     AppArmor profile
  99-snakedrv.rules        udev rules

dkms/            DKMS configuration
deploy.sh        Build, install, test, inject automation
sign-module.sh   Secure Boot module signing (MOK)

Security notes

  • Runtime access requires membership in the snakeengine group: sudo usermod -aG snakeengine $USER
  • All sensitive ioctls require CAP_SYS_PTRACE; physical memory and injection require CAP_SYS_ADMIN
  • SELinux policy v2.0 supports enforcing mode out of the box
  • Keep debug_level low in production; increase only for debugging
  • If Secure Boot blocks loading, sign the module with ./sign-module.sh

Changelog

2.0.2 (2026-06-04)

Driver update and source-install pipeline:

  • Added a production source-release flow for snakedrv-updater: GitHub tags now publish snakeengine-driver-X.Y.Z.tar.gz plus a matching .sigstore bundle, checksum files, and a standalone sigstore-verify binary.
  • Switched release signing to cosign's protobuf bundle format (--new-bundle-format) so the bundled sigstore-verify can parse and verify release signatures.
  • Hardened snakedrv-updater into a fail-closed updater: network timeouts, bounded Sigstore verification, fatal modprobe failures, loaded-module verification, ABI verification, /dev/snakedrv verification, and clear error messages.
  • Fixed update ordering: the kernel module is now built, installed, loaded, and validated before replacing libsnakedrv.so and headers, preventing mixed libsnakedrv/snakedrv.ko ABI states.
  • DKMS updates now remove stale snakedrv versions and /usr/src trees before registering the new version, avoiding stale source trees breaking later updates.
  • Added the source-install templates required by updater/deploy installs: packaging/dkms/dkms.conf.in, packaging/pkgconfig/snakedrv.pc.in, and packaging/cmake/SnakeDrvConfigVersion.cmake.in.
  • Added a package-free release workflow: no nfpm, no .deb, no .rpm; releases publish only the signed source tarball and verifier assets.

Install and deployment tooling:

  • deploy.sh install now installs the updater and verifier under /usr/lib/snakeengine/.
  • deploy.sh status reports update-tool installation state, loaded driver version/ABI, DKMS state, device state, and recent kernel logs.
  • deploy.sh load now treats an already-loaded module as a state to validate instead of blindly running insmod and failing with File exists.
  • deploy.sh build/install no longer requires the local tests/ or tests/payload_imgui/ directories. They are optional developer assets; production source installs build the driver, userland library, and verifier without them.
  • Fixed the advertised deploy.sh build-kernel command so it is accepted by the command parser and can be used for VM/kernel-only validation.
  • deploy.sh now builds tools/sigstore-verify with -buildvcs=false, making Go builds deterministic in source archives and temporary worktrees without reliable Git metadata.
  • The udev rule is now installed as a minimal root-owned 0644 rule for /dev/snakedrv with group snakeengine.

Kernel driver ABI and runtime validation:

  • Introduced SNAKEDRV_ABI_VERSION and exposed the loaded ABI through driver info/module parameters so userland can reject unsupported kernels instead of failing later with mismatched IOCTL layouts.
  • Added runtime scanner ABI coverage for backend selection, scan options, first scan, next scan, result-set info, result retrieval, perf stats, reset, free, and detach paths.
  • Fixed the scanner IOCTL header duplication issue by consolidating SNAKEDRV_IOCTL_MAGIC usage between core and scanner headers.
  • Added safer kernel scanner/result-set plumbing and ABI checks for the process backend.

Kernel safety fixes:

  • Fixed the injector_shadow_alloc error path so partially created shadow mappings are unmapped if later allocation steps fail.
  • Added validation for breakpoint target addresses before programming hardware breakpoints, avoiding arbitrary kernel-address breakpoints.
  • Kept VMA stealth explicit and bounded; deferred VMA hiding remains disabled unless the target mapping can be handled safely.

Userland library and manual mapping:

  • Hardened ELF symbol and relocation parsing in userland/src/snakedrv_injector.cpp with stricter bounds checks.
  • Added local selftests for IOCTL ABI validation and manual-map ELF entry discovery.
  • manualMapLibrary() now has a concrete test path using a payload that exports ManualMapEntry.
  • Added installable pkg-config and CMake metadata for downstream driver consumers, with ABI checks in the generated CMake config.
  • Installed headers now live under include/snakedrv/, matching the installed library and generated metadata.

2.0.1 (2026-04-10)

Cross-distro kernel build fixes (tested on Ubuntu 24.04 / kernel 6.17.0-20-generic in a VM, still working on Fedora 43 / kernel 6.19):

  • page->flags type fix: the previous LINUX_VERSION_CODE >= 6.10 guard around page->flags.f was wrong in both directions. The memdesc_flags_t struct wrapper landed later than 6.10 in mainline and distros cherry-pick it independently of the version bump. Replaced the #if with a version-independent *(unsigned long *)&page->flags — identical layout in both cases because memdesc_flags_t wraps a single unsigned long. Fixes error: request for member 'f' in something not a structure or union on Ubuntu 6.17 and similar distros without the backport.

  • Retpoline thunk flags propagated to out-of-tree builds: Ubuntu kernels with CONFIG_MITIGATION_RETPOLINE=y sometimes fail to pass -mindirect-branch=thunk-extern -mindirect-branch-register to external modules (especially when building from a shared folder on a VM), causing objtool: indirect call found in MITIGATION_RETPOLINE build errors on every function pointer call in the scanner and main driver. kernel/Makefile now -includes the target kernel's include/config/auto.conf and re-adds the retpoline flags explicitly when CONFIG_MITIGATION_RETPOLINE (or legacy CONFIG_RETPOLINE) is set, so gcc emits __x86_indirect_thunk_rax calls instead of raw indirect calls.

  • deploy.sh build-kernel target: new command that builds only the kernel module (skipping userland library, tests, and the ImGui payload). Useful for cross-testing the driver in a VM where the userland components aren't needed.

2.0.0 (2026-04-07)

Kernel driver security hardening:

  • Added CAP_SYS_PTRACE gate on all debug/memory ioctls
  • Added CAP_SYS_ADMIN gate on physical memory, injection, and shadow memory ioctls
  • Fixed use-after-free in process detach: proper atomic_dec_and_test refcounting with kfree on zero
  • Fixed integer overflow in do_query_regions: check_mul_overflow before kvzalloc
  • Fixed page->flags type for kernel 6.10+ (memdesc_flags_t struct wrapper)
  • Increased d_path buffer from 256 to PATH_MAX (4096 bytes)
  • Added forward declaration for cleanup_breakpoints to fix implicit function error

Injector improvements:

  • Fixed unsafe vm_flags manipulation: uses vm_flags_set() on kernel 6.3+ instead of UB pointer cast
  • Fixed maple tree VMA unlinking: mas_set_range(vm_start, vm_end-1) for correct range coverage
  • Added wait_for_completion_timeout (5s) on all worker threads instead of unbounded waits
  • Fixed thread hijack x86-64 ABI: RSP alignment handled by compiler (-mincoming-stack-boundary=3)
  • Implemented shadow memory subsystem: pin-and-hide via get_user_pages_remote + VMA unlinking
  • Implemented SHADOW_ALLOC, SHADOW_WRITE, SHADOW_FREE ioctls (0x68-0x6A)
  • Shadow cleanup via MAP_FIXED + vm_munmap to restore mm consistency on free
  • Transparent shadow read interception in READ_MEMORY ioctl handler

Scanner improvements:

  • Hard cap on scanner_create_result_set: max 10M results (160 MB)
  • Fixed parallel scan worker: separate alloc_buf/scan_buf to prevent kvfree on aligned pointer
  • Added get_unaligned() for safe unaligned memory access in scan loops
  • Added linux/unaligned.h / asm/unaligned.h compatibility for kernel 6.5+

Userland library:

  • Fixed MemoryRegion::end() overflow: saturates to UINT64_MAX instead of wrapping
  • Added static_assert(is_trivially_copyable_v<T>) on read<T>/write<T> templates
  • Fixed readString bounds: clamp bytesRead to maxLength before null-terminator write
  • Fixed DebugEvent instruction length: clamp to sizeof(k.instruction) to prevent over-read
  • Added exception safety in event loop thread (try/catch around callback)
  • Fixed followPointerChain address overflow with __builtin_add_overflow
  • Made resolve_imports strict: returns false on unresolved symbols instead of silent continue
  • Added R_X86_64_64 relocation type support in relocate_base
  • Added .init_array discovery and execution via thread hijack
  • Implemented dlopen injection path in ManualMapper (replaces manual mapping as default)
  • Added SDL2 DYNAPI jump table hook for render loop interception

SELinux policy v2.0:

  • Added unconfined_t access to snakedrv_device_t (fixes EPERM for sudo operations)
  • Added kernel_t execmem for vm_mmap(PROT_EXEC) in injector kernel threads
  • Added sysadm_t and unconfined_service_t device access rules
  • Updated file contexts for dlopen_inject and libpayload_dlopen.so

Scripts:

  • deploy.sh v2.0: added set -o pipefail, trap cleanup, cd || die guards, umask 022
  • deploy.sh: new commands test, inject, payload; installs dlopen_inject and payload
  • deploy.sh: removed hardcoded SSH credentials, removed QEMU/VM references
  • deploy.sh: sanitized PREFIX variable, fixed unquoted expansions
  • sign-module.sh: RSA 4096-bit keys, AES-256 encrypted private key, chmod 700/600
  • sign-module.sh: cross-distro sign-file detection (Fedora + Debian/Ubuntu)

1.2 (2026-01-15)

  • Manual map injector pipeline (alloc, relocate, write); VMA stealth remains disabled until deferred page-fault-safe hiding is implemented
  • Improved remote symbol resolution and IFUNC handling for glibc
  • GitHub Actions CI build and release workflows
  • Documentation and wiki refresh

1.1 (2025-12-06)

  • Fixed AppArmor policy errors and improved profile compatibility
  • Resolved objtool compilation errors (RETPOLINE) on newer kernels
  • Added sign-module.sh for Secure Boot module signing (MOK workflow)

1.0 (2025-12-01)

  • Initial public release
  • Kernel module with privileged memory access and hardware breakpoints
  • Userland library (C++ API)
  • DKMS, udev, AppArmor, SELinux artifacts
  • Automation script deploy.sh

Contributing

Contributions are welcome. Please keep kernel changes minimal and auditable.

License

GPL-2.0

Disclaimer

This project is for educational and research use.

About

Production-ready Linux kernel driver with a modern C++ userland API for privileged memory access, region discovery, and hardware breakpoints- builts

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors