MonMon.MemoryToolkit
1.0.0-preview.1
dotnet add package MonMon.MemoryToolkit --version 1.0.0-preview.1
NuGet\Install-Package MonMon.MemoryToolkit -Version 1.0.0-preview.1
<PackageReference Include="MonMon.MemoryToolkit" Version="1.0.0-preview.1" />
<PackageVersion Include="MonMon.MemoryToolkit" Version="1.0.0-preview.1" />
<PackageReference Include="MonMon.MemoryToolkit" />
paket add MonMon.MemoryToolkit --version 1.0.0-preview.1
#r "nuget: MonMon.MemoryToolkit, 1.0.0-preview.1"
#:package MonMon.MemoryToolkit@1.0.0-preview.1
#addin nuget:?package=MonMon.MemoryToolkit&version=1.0.0-preview.1&prerelease
#tool nuget:?package=MonMon.MemoryToolkit&version=1.0.0-preview.1&prerelease
MemoryToolkit
A modern, span-first .NET library for reading, writing, scanning and freezing the memory of a target
Windows process. It is a clean-room rewrite of the classic Memory.dll game-trainer library — same
capabilities, redesigned for net10.0, with CsWin32-generated
P/Invoke instead of hand-written [DllImport]s.
Intended for authorized use: game trainers on software you own, debugging, reverse-engineering research, and security testing. Reading and writing another process's memory requires appropriate privileges.
Highlights
- Span-first I/O — every read/write is built on
Span<byte>/ReadOnlySpan<byte>; allocating helpers sit on top. - Explicit, endian-correct serialization — primitives go through
BinaryPrimitives(little-endian); custom structs opt in viaIBinaryReadable<T>/IBinaryWritable<T>(the generic-mathIBinaryInteger<T>pattern). No blindMemoryMarshalreinterpret, no host-endian assumptions. - One unified pointer walk —
PointerPath+AddressExpressionreplace the old duplicated 32/64-bit resolvers. Addresses arenuint, so the legacy 64-bit truncation bug is gone. - 32-bit and 64-bit targets — the x64 host drives both; per-target pointer size is detected at
runtime (
IsWow64Process2). - AoB scanning with nibble wildcards (
48 8B ?? A? ?A), vectorized via aSearchValuesanchor and parallelized across regions. - Async freezing via
PeriodicTimer; dispose the handle to unfreeze. - Diagnostics — thread/process suspend-resume, thread start addresses, raw region dumps and full minidumps.
SafeHandle-backed,IDisposable, structuredILoggerlogging (no-op by default).
Requirements
- Windows 10 1809+ (x64). The package targets
net10.0-windows10.0.17763.0, built x64.
Install
dotnet add package MonMon.MemoryToolkit
Quick start
using MemoryToolkit;
using MemoryToolkit.Scanning;
using TargetProcess game = TargetProcess.Open("game.exe");
// Read / write primitives (little-endian).
int health = game.ReadInt32(game.Resolve("game.exe+0x1F4,0x10"));
game.WriteInt32(game.Resolve("game.exe+0x1F4,0x10"), 999);
// Typed pointer paths.
PointerPath ammo = PointerPath.Module("game.exe", 0x2A4).Then(0x8);
game.WriteSingle(game.Resolve(ammo), 100f);
// Freeze a value until disposed.
using IValueFreeze frozen = game.FreezeInt32(game.Resolve(ammo), 999);
// Array-of-bytes scan.
AobScanner scanner = new(game);
AobPattern pattern = AobPattern.Parse("48 8B 05 ?? ?? ?? ?? 89 01");
nuint? hit = await scanner.FindFirstAsync(pattern);
Custom structs
Implement the two interfaces to read/write a domain type without reinterpreting raw bytes:
public readonly record struct Vec3(float X, float Y, float Z)
: IBinaryReadable<Vec3>, IBinaryWritable<Vec3>
{
public static int SerializedSize => 12;
public static Vec3 ReadLittleEndian(ReadOnlySpan<byte> s) => new(
BinaryPrimitives.ReadSingleLittleEndian(s),
BinaryPrimitives.ReadSingleLittleEndian(s[4..]),
BinaryPrimitives.ReadSingleLittleEndian(s[8..]));
public void WriteLittleEndian(Span<byte> d)
{
BinaryPrimitives.WriteSingleLittleEndian(d, X);
BinaryPrimitives.WriteSingleLittleEndian(d[4..], Y);
BinaryPrimitives.WriteSingleLittleEndian(d[8..], Z);
}
}
Vec3 position = game.Read<Vec3>(game.Resolve(ammo));
Building
dotnet restore MemoryToolkit.slnx
dotnet build MemoryToolkit.slnx -c Release
dotnet test MemoryToolkit.slnx -c Release
The test suite covers the pure layer (AoB matcher, address parser, serialization, bitfields) plus
integration tests that exercise real ReadProcessMemory/WriteProcessMemory/VirtualQueryEx against
the test process's own pinned buffers — so they run on CI without a separate target.
Versioning
Versions come from git tags via MinVer with a v tag prefix
(e.g. tag v1.2.3 → package 1.2.3). Off-tag builds get a -nightly prerelease suffix. Pushing a v*
tag triggers the release workflow, which packs a single x64 NuGet package (MonMon.MemoryToolkit) and
publishes it to nuget.org using the NUGET_API_KEY secret.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0-windows10.0.17763 is compatible. |
-
net10.0-windows10.0.17763
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.9)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|
See https://github.com/berndt-simon/MemoryToolkit/releases for release notes.