Custom IProcess
How to connect your own driver or memory reading method to the Memory API
How to create a custom IProcess
If you already have your own driver, bridge, or another way to read memory, you almost never need to build “yet another Memory API”. In most cases, two layers are enough:
IMemoryBackendfor rawread/writeIProcess, which describes the process and exposesMemory
Once you have that, your backend immediately gets access to typed reads, MemoryOfModule(...), imports, exports, signatures, and code cave.
What to use as a reference in the codebase
NativeLocalProcess— a good example of a process wrapper built on top of an existing backendLCProcess— a good reference for a backend mostly focused on reading and analysisKDProcess— an example of a backend with a deeper control API
Minimal structure
IMemoryBackend stays very small:
public interface IMemoryBackend : IDisposable, IMemorySpan
{
bool IsValid { get; }
bool TryReadMemory(IntPtr address, Span<byte> target);
bool TryWriteMemory(IntPtr address, ReadOnlySpan<byte> source);
}
In most cases, this is where your driver call, IOCTL, RPC, or DMA bridge lives.
On top of that, you implement IProcess and expose MemoryAccessor right away:
public sealed class MyDriverProcess : DisposableReactiveObject, IProcess
{
public MyDriverProcess(MyDriverClient driver, int processId, string? processName = null)
{
ProcessId = processId;
ProcessName = processName;
var memoryBackend = new MyDriverMemoryBackend(driver, processId).AddTo(Anchors);
Memory = new MemoryAccessor(Log, memoryBackend).AddTo(Anchors);
}
public string? ProcessName { get; }
public int ProcessId { get; }
public IProcessMemory Memory { get; }
public IReadOnlyList<ProcessModuleInformation> GetProcessModules() => driver.GetModules(ProcessId);
public IReadOnlyList<ProcessThreadInformation> GetThreads() => driver.GetThreads(ProcessId);
public MemoryBasicInformation VirtualQuery(IntPtr address) => driver.VirtualQuery(ProcessId, address);
public IReadOnlyList<MemoryBasicInformation> GetMemoryRegions() => driver.GetMemoryRegions(ProcessId);
}
There is one key line here:
Memory = new MemoryAccessor(Log, memoryBackend);
That is what connects your backend to the full EyeAuras upper layer.
What you should implement right away
If you want the integration to be truly usable, do not stop at TryReadMemory(...). A practical minimum is:
MemoryGetProcessModules()GetThreads()VirtualQuery(...)GetMemoryRegions()
Without modules, you lose proper MemoryOfModule(...). Without regions and VirtualQuery(...), memory analysis becomes much less useful.
What you can add later
If your driver can do more, you can also expose extra capability interfaces on top of IProcess:
IProcessControlApi— suspend, allocate, protect,remote threadIProcessSupportsManualMappingIProcessSupportsUserApc
So the usual path looks like this:
- first, make reading stable and describe the process properly
- then add the control API
- only after that move on to
DLL injectandmanual mapping
Common mistakes
- Trying to implement PE parsing, signatures, and strings directly inside the driver class
- Exposing only raw read/write without modules or a memory map
- Mixing the low-level backend and the process wrapper into one large class
- Starting with injection before verifying normal reads, modules, and signatures
If a game uses a non-standard structure layout, that usually does not require a new backend. In most cases, the right solution is a separate mapper on top of an existing IProcess.