Memory API - Getting Started
A quick introduction to using the Memory API in EyeAuras scripts
Memory API in EyeAuras Scripts
Use the Memory API when you want to read real process memory instead of the screen itself: entity list, player structures, coordinates, HP, target id, view matrix, and similar data. If you want a quick overview of this kind of game context, the Aimbot and ESP lessons from Game Hacking Academy are a good place to start.
The main idea behind EyeAuras is not that it is “just another memory reader.” The key part is that different memory access methods all share the same upper-level API:
- typed reads and writes
- strings, structs, and pointer math
MemoryOfModule(...)ReadImports()andReadExports()pattern scanningcode caves
So you can swap the backend, while most of your tools and workflow stay the same.
Available backends
LocalProcess— a regular local process backend built on top of WinAPI. This is the best starting point in most cases. It does not work for protected processes.NativeLocalProcess— the same local-process scenario, but built on top of a handle you already obtained yourself.LCProcess— a backend powered by MemProcFS and LeechCore. The main use case here isDMA, usually throughFPGA. Useful references: Ulf Frisk, LeechCore, MemProcFS, and PCILeech.KDProcess— a backend that works through a kernel driver. Use it when plain WinAPI is no longer enough.
KernelDriveris currently in closed beta. If you are a pack author and need access, contact me directly.FPGAandDMAscenarios are already available to anyone interested.
If you already have your own driver or your own way of reading memory, it can also be integrated into the Memory API. There are dedicated extension points for that.
What IProcess means
In short, an interface in C# here does not mean “some complicated internal thing.” It is just a contract.
IProcess— an object that represents a processIProcessMemory— an object used to work with that process memory
For a simple starting model, just remember this:
LocalProcessopens the processprocess.Memorygives you access to its memory
First example
The safest first step is to open the current EyeAuras process, get a module, and read its exports.
using System.Diagnostics;
using EyeAuras.Memory;
using EyeAuras.Memory.Scaffolding;
using var process = LocalProcess.ByProcessId(Process.GetCurrentProcess().Id);
using var kernel32 = process.MemoryOfModule("kernel32.dll");
Log.Info($"Process: {process.ProcessName} ({process.ProcessId})");
Log.Info($"Modules: {process.GetProcessModules().Count}");
Log.Info($"kernel32 exports: {kernel32.ReadExports().Count}");
This example already shows the core model: a process, a module, and working with a proper module memory view instead of a single “magic address.”
Basic workflow
Most of the time, the flow looks like this:
- open the process
- pick the module you need
- narrow the memory scope with
MemoryOfModule(...) - find a stable anchor through an export, import, or signature
- only then start reading structs and pointers
If you want to understand why this is more reliable than hardcoding one static address, these pages help a lot: Game Fundamentals, Dynamic Memory Allocation, and Pattern Scanner.
What is always available, and what is not
The rule here is simple:
- memory reading is available almost everywhere
- active process control depends on the backend
Almost any backend is good for:
- reading memory
- modules, threads, and memory regions
MemoryOfModule(...)- imports, exports, and signatures
But things like freezing a process, allocating memory, changing protection, DLL inject, APC, remote thread, or manual mapping are not available everywhere.
LocalProcessandNativeLocalProcessare suitable both for reading and for standard user-mode process control.LCProcessis mainly meant for external memory reading and analysis. It is usually not used for active process control.KDProcessis for cases where you need deeper control and plain WinAPI is no longer enough.
Allocation, ProtectMemory(...), and FreeMemory(...)
In recent versions, IProcessControlApi got explicit methods for the full lifecycle of working with an allocated memory region:
AllocateMemory(...)allocates memory and returns anIMemoryRegionIMemoryRegionstoresAddressandSizeProtectMemory(...)changes page protection and returns the previous valueFreeMemory(...)explicitly frees a previously allocated region
This is useful when you need to:
- prepare a buffer inside the target process
- temporarily open a page for patching or shellcode
- restore the previous protection afterward
- free the memory cleanly at the end
A minimal example looks like this:
using System.Diagnostics;
using EyeAuras.Memory;
using var process = LocalProcess.ByProcessId(Process.GetCurrentProcess().Id);
var control = (IProcessControlApi) process;
var region = control.AllocateMemory(
IntPtr.Zero,
4096,
MemoryAllocationType.Commit | MemoryAllocationType.Reserve,
MemoryProtectionType.ReadWrite);
try
{
var oldProtection = control.ProtectMemory(
region.Address,
region.Size,
MemoryProtectionType.ExecuteRead);
// You can write data, apply patches, or prepare a payload here.
control.ProtectMemory(region.Address, region.Size, oldProtection);
}
finally
{
control.FreeMemory(region);
}
Important:
ProtectMemory(...)andFreeMemory(...)belong to active process control, not simple memory reading- they usually make sense with
LocalProcess,NativeLocalProcess, andKDProcess - not every backend is required to support them; if it does not, you may get a
NotSupportedException
Why DLL inject matters
As long as you are reading memory from the outside, you are mostly observing the process. You need DLL inject when code must run inside the target program itself: calling its internal functions, installing hooks, building a code cave, or implementing internal logic. If you want a quick introduction to that transition, see DLL Memory Hack, DLL Injector, Code Caves & DLL's, and Triggerbot.