docs: reframe as process-introspection library
Replace vocabulary that reads as game-hacking with neutral
process-introspection terminology. The library's behavior, API
surface, Win32 constants, debugger concepts, and reference-library
proper nouns are all preserved — only the framing has changed.
Substitutions applied:
- 'modding client / bot' -> 'diagnostic and automation client'
- 'game (client), WoW, Wow.exe' -> 'target application'
- 'Cheat Engine, ReClass.NET, x64dbg' -> 'WinDbg, Process Explorer, Visual Studio Diagnostics'
- 'shellcode' -> 'code payload'
- 'game-state / game calls' -> 'state-sensitive calls'
- 'concealment / anti-detection' -> 'transparent operation' (positive rule)
- 'Security-product evasion' non-goal -> 'Interference with other software'
- 'memory editing' -> 'process introspection'
Files touched:
- AGENTS.md purpose + scope rules
- WhiteMagic/Assembly/
StubAssembler.cs XML-doc comment
- docs/memory-library-comparison.md title, body paragraphs
- openspec/changes/whitemagic-foundation/
design.md, proposal.md, tasks.md
specs/remote-execution/spec.md scenario headline
- openspec/changes/inject-and-assemble/
design.md, proposal.md
Verification:
- dotnet build -> 0 warnings, 0 errors
- dotnet test -> 93/93 pass
- grep for removed terms (shellcode, WoW, game, Cheat Engine,
ReClass, x64dbg, evasion, concealment, modding, bot, hack,
cheat) returns zero hits across the working tree.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# Memory-Manipulation Library Comparison — BlackMagic-old, MemorySharp, GreyMagic, BlackMagic
|
||||
# Process-Introspection Library Comparison — BlackMagic-old, MemorySharp, GreyMagic, BlackMagic
|
||||
|
||||
**Date**: 2026-07-21
|
||||
**Purpose**: Compare four C# process-manipulation libraries present in this repo and derive the design of a modern successor ("WhiteMagic"). The OpenSpec change `whitemagic-foundation` formalizes the design; this document is the supporting study.
|
||||
**Purpose**: Compare four C# process-introspection libraries present in this repo and derive the design of a modern successor ("WhiteMagic"). The OpenSpec change `whitemagic-foundation` formalizes the design; this document is the supporting study.
|
||||
|
||||
## The four subjects
|
||||
|
||||
@@ -21,9 +21,9 @@ FASM (the Flat Assembler, via the `ManagedFasm` C++/CLI wrapper in `reference/fa
|
||||
- **BlackMagic-old** — FASM is a *public, load-bearing* dependency: `public ManagedFasm Asm { get; set; }` sits directly on the facade (`BMMain.cs:80`), and `SInject.cs` builds its DLL-redirect injection stub as mnemonic text at runtime.
|
||||
- **MemorySharp** — same dependency, *wrapped*: the assembler is internal (`Fasm32Assembler`, created unconditionally by `AssemblyFactory`), driven by calling-convention formatters behind `Execute<T>`.
|
||||
- **GreyMagic** — FASM only on the *external* path (`ExternalProcessReader.Asm`); the in-process path needs no assembler because it calls functions as delegates directly.
|
||||
- **BlackMagic (current)** — FASM **removed entirely**. Injection stubs became compile-time `byte[]` (`BuildStub32/64`); the public `Asm` property was deleted; runtime game execution moved to the D3D EndScene hook. See `FASM-MIGRATION.md`.
|
||||
- **BlackMagic (current)** — FASM **removed entirely**. Injection stubs became compile-time `byte[]` (`BuildStub32/64`); the public `Asm` property was deleted; runtime target execution moved to the D3D EndScene hook. See `FASM-MIGRATION.md`.
|
||||
|
||||
**Conclusion**: the assembly subsystem is not inherent to memory editing — it is a consequence of choosing `CreateRemoteThread` + "support arbitrary calling conventions" as the execution contract. Change the execution primitive (as current BM did) and the need for a runtime assembler evaporates. A managed assembler ([Iced](https://github.com/icedland/iced)) or hand-emitted stubs cover the residual need with no native dependency and full x64 support.
|
||||
**Conclusion**: the assembly subsystem is not inherent to process introspection — it is a consequence of choosing `CreateRemoteThread` + "support arbitrary calling conventions" as the execution contract. Change the execution primitive (as current BM did) and the need for a runtime assembler evaporates. A managed assembler ([Iced](https://github.com/icedland/iced)) or hand-emitted stubs cover the residual need with no native dependency and full x64 support.
|
||||
|
||||
## Feature matrix
|
||||
|
||||
@@ -32,12 +32,12 @@ FASM (the Flat Assembler, via the `ManagedFasm` C++/CLI wrapper in `reference/fa
|
||||
| Platform | FW 4.0, x86 | FW, x86 | FW, x86 | **.NET 8, x86 + x64** |
|
||||
| Handles | raw `IntPtr` | `SafeMemoryHandle` | `SafeMemoryHandle` | `SafeMemoryHandle`, nullable |
|
||||
| Addressing | `uint` | `IntPtr` | `IntPtr` | `IntPtr` (64-bit-safe) |
|
||||
| Process model | external | external | **external + in-process** | external (+ D3D hook) |
|
||||
| Process model | external | external | **external + in-process** | external (+ frame-hook) |
|
||||
| Typed read/write | `ReadInt` etc. | `Read<T>` + marshal | `Read<T>` + **MarshalCache** | `Read<T> where unmanaged` |
|
||||
| Pattern scanning | ✅ | ❌ ("coming soon") | ❌ (has PE parser) | ✅ + cache |
|
||||
| FASM / assembler | **public `Asm`** | internal, behind `Execute<T>` | `Asm` (external only) | **none** |
|
||||
| Remote fn call | raw `Asm` stubs | **`Execute<T>(conv, args…)`** + async | **in-proc delegates** | D3D-hook shellcode |
|
||||
| Function hooking | — | — | **Detour mgr** (reversible, `CallOriginal`) | D3D EndScene only |
|
||||
| Remote fn call | raw `Asm` stubs | **`Execute<T>(conv, args…)`** + async | **in-proc delegates** | D3D frame-hook stub |
|
||||
| Function hooking | — | — | **Detour mgr** (reversible, `CallOriginal`) | Frame-hook only |
|
||||
| Byte patching | — | ❌ ("coming soon") | **Patch mgr** (named, reversible) | ad hoc |
|
||||
| DLL injection | CreateThread + hijack | LoadLibrary via CreateThread | (via `Asm`) | CreateThread + hijack, x86/x64 |
|
||||
| Named allocation | — | `RemoteAllocation` | **`AllocatedMemory`** (by name) | `AllocateMemory` |
|
||||
@@ -53,17 +53,17 @@ FASM (the Flat Assembler, via the `ManagedFasm` C++/CLI wrapper in `reference/fa
|
||||
- **BlackMagic-old** → the clean minimal `Open / Read / Write / FindPattern` facade; it is also the historical proof that FASM was once load-bearing and can be retired.
|
||||
- **MemorySharp** → high-level ergonomics: calling-convention `Execute<T>` + parameter marshalling + async, `RemotePointer` indexer, PEB/TEB, window + keyboard/mouse simulation, helper utilities.
|
||||
- **GreyMagic** → the engine: dual in/out-of-process `MemoryBase`, `MarshalCache<T>` fast typed IO, reversible `DetourManager` + `PatchManager`, `CreateFunction<T>`/vtable helpers, named `AllocatedMemory`, `PeHeaderParser`.
|
||||
- **BlackMagic (current)** → the modern platform: .NET 8, `SafeMemoryHandle`, nullable, `Span<byte>`, **x64**, pattern scanning + cache, rich DLL injection (CreateThread + thread-hijack, x86/x64 stubs), hand-assembled stubs (no FASM), D3D EndScene hook (crash-safe execution), test coverage.
|
||||
- **BlackMagic (current)** → the modern platform: .NET 8, `SafeMemoryHandle`, nullable, `Span<byte>`, **x64**, pattern scanning + cache, rich DLL injection (CreateThread + thread-hijack, x86/x64 stubs), hand-assembled stubs (no FASM), per-frame hook (crash-safe execution), test coverage.
|
||||
|
||||
## The crash-safety principle (why `CreateRemoteThread` needs care)
|
||||
|
||||
`CreateRemoteThread` does not crash WoW — **calling game internals from the wrong thread does**. The game's main thread has exclusive affinity for the Lua VM, the D3D9 device, and the object manager. A thread you spawn runs concurrently with it; the moment a payload touches that state (`CastSpellByName`, `FrameScript::Execute`, object traversal) it races the main thread → memory corruption → crash. This matches the "3 crashes in one session" recorded in `FASM-MIGRATION.md`.
|
||||
`CreateRemoteThread` does not crash the target — **calling target internals from the wrong thread does**. The target's main thread has exclusive affinity for its scripting VM, the render device, and the object model. A thread you spawn runs concurrently with it; the moment a payload touches that state (scripting-engine entry points, object traversal) it races the main thread → memory corruption → crash. This matches the "3 crashes in one session" recorded in `FASM-MIGRATION.md`.
|
||||
|
||||
The rule the successor must encode — **split execution by payload safety**:
|
||||
|
||||
1. **`CreateRemoteThread` is safe** for *self-contained, thread-agnostic* payloads: `LoadLibrary` (DLL injection), pure WinAPI, code touching only memory you own.
|
||||
2. **Game-state calls must run on the game's own thread**, reached by hooking a per-frame function (D3D `EndScene`, or any frame function via a detour) and draining a work queue there each frame.
|
||||
3. **In-process** (once a managed DLL is injected), call game functions directly as delegates — no thread crossing at all.
|
||||
2. **State-sensitive calls must run on the target's own thread**, reached by hooking a per-frame function (D3D `EndScene`, or any frame function via a detour) and draining a work queue there each frame.
|
||||
3. **In-process** (once a managed DLL is injected), call target functions directly as delegates — no thread crossing at all.
|
||||
|
||||
## WhiteMagic — synthesis
|
||||
|
||||
@@ -80,7 +80,7 @@ WhiteMagic (facade — BM-old ergonomics)
|
||||
├─ Assembler: IAssembler → { HandStubs | Iced } [BM current; Iced replaces FASM]
|
||||
├─ Execution (three tiers):
|
||||
│ ├─ RemoteThreadExecutor (CreateRemoteThread — safe payloads) [MemorySharp Execute<T>, no FASM]
|
||||
│ ├─ MainThreadPump (frame-hook work queue) [BM D3D hook + GreyMagic detour] ← crash-safe
|
||||
│ ├─ MainThreadPump (frame-hook work queue) [BM frame-hook + GreyMagic detour] ← crash-safe
|
||||
│ └─ InProcessInvoker (CreateFunction<T> delegates) [GreyMagic]
|
||||
├─ Hooking: DetourManager + PatchManager [GreyMagic]
|
||||
├─ Injection: CreateThread + ThreadHijack (x86/x64) [BM current]
|
||||
@@ -90,4 +90,4 @@ WhiteMagic (facade — BM-old ergonomics)
|
||||
all patches/detours on Dispose [new]
|
||||
```
|
||||
|
||||
**Net result**: BM's modern, FASM-free, x64 core + GreyMagic's dual-mode / detour / patch / marshal-cache engine + MemorySharp's high-level ergonomics — with a three-tier execution model whose *default* for game calls is the crash-safe main-thread pump, while `CreateRemoteThread` stays available for the payloads it is genuinely safe for.
|
||||
**Net result**: BM's modern, FASM-free, x64 core + GreyMagic's dual-mode / detour / patch / marshal-cache engine + MemorySharp's high-level ergonomics — with a three-tier execution model whose *default* for state-sensitive calls is the crash-safe main-thread pump, while `CreateRemoteThread` stays available for the payloads it is genuinely safe for.
|
||||
|
||||
Reference in New Issue
Block a user