Ergonomic Win32 process and memory management API for Cheatron, powered by Bun and Koffi.
Important
64-bit Windows only. This project exclusively targets 64-bit Windows environments.
- Process Management: Open processes by PID, access the current process, and query memory information.
- Memory Operations: Read and write memory buffers from/to target processes.
- Thread Management: Create local/remote threads (supports
CREATE_SUSPENDEDflags), get/set thread context, suspend/resume, and track exit codes. - Module Helper: Easy access to loaded modules, complete
MODULEINFOretrieval, module dimension sizing, and function addresses. - High-Performance Async Pattern Scanning: Memory scanning powered by
async *generators and an assembly-injectedmemmem. Supports full process scan viaVirtualQuery, module-scoped scan, or arbitrary range scan. (Wildcards are no longer supported for performance reasons). - Assembly Generation: Test x86 assembly scripts and integrate safely with
@cheatron/keystone. - Low-level FFI: Direct access to
Kernel32Impl,psapi, andMsvcrtImpl(includesmemcmpandmemmem) for advanced Win32 API calls. - Safe Handles: Automatic handle cleanup using
FinalizationRegistry. - Integrated Logging: Centralized, shared static logging powered by
@cheatron/log.
bun add @cheatron/nativeimport { Process, currentProcess, NativePointer } from '@cheatron/native';
// Open a process by ID
const proc = Process.open(1234);
// Read memory
const buffer = proc.memory.read(new NativePointer(0x10000000n), 1024);
console.log(buffer.toString('hex'));
// Write memory
proc.memory.write(
new NativePointer(0x20000000n),
Buffer.from([0x90, 0x90, 0x90]),
);
// Create a thread in the target process
const thread = proc.createThread(new NativePointer(0x30000000n));
thread.wait();
console.log(`Thread exited with: ${thread.getExitCode()}`);
proc.close();The Process class provides methods for interacting with Windows processes. Use Process.open(pid) or Process.current() to get an instance. All address parameters accept any IPointer — wrap raw bigint values with new NativePointer(addr).
memory.read(address: IPointer, size: number): Buffermemory.write(address: IPointer, buffer: Buffer): voidcreateThread(startAddress: IPointer, ...): Threadmemory.query(address: IPointer): MemoryBasicInformationmemory.alloc(size, address?: IPointer | null, ...): NativePointermemory.free(address: IPointer): booleanmemory.protect(address: IPointer, size, newProtect): number | null
Manage execution flow within processes.
suspend() / resume(): numbergetContext(flags?: number): ThreadContextsetContext(ctx: ThreadContext): voidgetExitCode(): numberwait(timeoutMs?: number): WaitReturn
Enumerate and interact with loaded DLLs.
Module.get(name: string): ModuleModule.kernel32 / Module.crt / Module.ntdll / Module.kernelbase: Pre-defined lazy-cached instances.getProcAddress(name: string): NativePointerfindPattern(pattern: Pattern): ScanResult— scan within this module's memory range.Module.scan(pattern: Pattern, moduleNames?): ScanResult— scan across multiple modules (default: all static modules).- All results are returned via
ScanResultwhich is anAsyncIterable.
High-performance memory pattern matching using an assembly-injected memmem (faster than any JS-side byte loop). Wildcards are not supported. Scanning is an async * generator-based process so it yields immediately on first match and prevents blocking the event loop.
new Pattern("55 8B EC 56")— Create signatures (hex strings or byte arrays).process.findPattern(pattern: Pattern)— Full process scan viaVirtualQuery(all committed readable regions).Module.scan(pattern: Pattern, ['kernel32.dll'])— Module-scoped scan (static method onModule).process.findPatternInRange(pattern: Pattern, memory: NativeMemory)— Arbitrary range scan.ScanResultis anAsyncIterable: Usefor await (const entry of result), orawait result.first(),await result.all().- Access properties via async methods:
await result.getLength(),await result.getAddresses(), etc.
For tasks not covered by the ergonomic API, you can use the raw implementations directly:
import { Kernel32Impl, MsvcrtImpl } from '@cheatron/native';
const hProcess = Kernel32Impl.GetCurrentProcess();
const ptr = MsvcrtImpl.malloc(1024);
MsvcrtImpl.free(ptr);This project uses Bun. To run tests on Linux, you need wine.
# Install dependencies
bun install
# Run tests (runs natively or via wine depending on environment)
bun test
# Build the project
bun run buildMIT