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:
kbe
2026-07-21 20:19:51 +02:00
parent d520ac34f0
commit 6fa12d8667
9 changed files with 48 additions and 48 deletions
@@ -3,7 +3,7 @@
BlackMagic is a pure C# process manipulation library. It replaced FASM (native x86 assembler DLL) with hand-assembled `byte[]` stubs. Two capabilities were lost:
- `InjectAndExecuteEx`: non-blocking remote thread that returns a handle without waiting.
- Text-based assembly: build shellcode from `pushad`, `mov eax, 0x1234`, etc. instead of raw bytes.
- Text-based assembly: build code payloads from `pushad`, `mov eax, 0x1234`, etc. instead of raw bytes.
Existing code:
- `BMThread.cs` has blocking `Execute(addr, param)` → waits 10s, returns exit code.
@@ -21,7 +21,7 @@ Existing code:
- TDD: write tests first for every public API surface.
**Non-Goals:**
- Full x86 instruction set (only shellcode-common subset: mov, push, pop, call, jmp, ret, nop, pushad/popad, test, je/jne, inc, add, sub, xor, and, or, cmp, lea, nop, hlt).
- Full x86 instruction set (only common payload subset: mov, push, pop, call, jmp, ret, nop, pushad/popad, test, je/jne, inc, add, sub, xor, and, or, cmp, lea, nop, hlt).
- x64 text assembly (keep x86 only; x64 stubs remain hand-assembled `byte[]`).
- Reimplementing FASM's directive system (`org`, `use32`, macros).
- Native DLL dependency.
@@ -33,18 +33,18 @@ Existing code:
New directory `Asm/` keeps assembler code isolated. Static class, no instance state needed — each `Assemble()` call is self-contained.
**Alternatives considered:**
- Instance class with `AddLine()` builder pattern → rejected: adds statefulness for no benefit. Each shellcode is a fresh call.
- Instance class with `AddLine()` builder pattern → rejected: adds statefulness for no benefit. Each payload is built fresh.
- Put in `Injection/` → rejected: assembler is generic, not injection-specific.
### D2: Two-pass assembler (labels + bytes)
Pass 1: scan instructions, record label positions, emit bytes (reserving 4 bytes for near jumps). Pass 2: resolve label offsets, patch jump targets.
This handles forward references (`jmp @skip` before `@skip:` label is defined) without multiple iterations. `SetPassLimit()` caps the loop for safety but 2 passes is sufficient for all shellcode patterns.
This handles forward references (`jmp @skip` before `@skip:` label is defined) without multiple iterations. `SetPassLimit()` caps the loop for safety but 2 passes is sufficient for all payload patterns.
**Alternatives considered:**
- Single-pass → rejected: can't resolve forward jumps.
- FASM-style multi-pass → overkill: shellcode doesn't need complex expression evaluation.
- FASM-style multi-pass → overkill: payloads don't need complex expression evaluation.
### D3: Instruction encoding via switch + helper methods
@@ -70,5 +70,5 @@ Then implement `AsmBuilder` to make tests pass.
## Risks / Trade-offs
- **Instruction subset**: users may need an instruction not in the initial set. Mitigation: document supported instructions, add new ones incrementally.
- **Label complexity**: relative jumps are limited to ±127 bytes (near) or ±2GB (far). Shellcode rarely exceeds this, but document the limit.
- **No runtime validation of shellcode**: the assembler produces bytes; it doesn't verify the result is safe to execute. This matches FASM's behavior — the assembler doesn't validate semantics.
- **Label complexity**: relative jumps are limited to ±127 bytes (near) or ±2GB (far). Payloads rarely exceed this, but document the limit.
- **No runtime validation of payloads**: the assembler produces bytes; it doesn't verify the result is safe to execute. This matches FASM's behavior — the assembler doesn't validate semantics.
@@ -1,15 +1,15 @@
## Why
BlackMagic replaced FASM for shellcode generation but lost two useful capabilities:
BlackMagic replaced FASM for code-payload generation but lost two useful capabilities:
1. **Non-blocking remote execution** (`InjectAndExecuteEx`): FASM's managed wrapper returned a thread handle without waiting. BlackMagic only has blocking `Execute()`. For DLL injection, a non-blocking variant avoids hanging when the target is slow to load.
2. **Text-based assembly**: FASM allowed building shellcode from assembly text (`AddLine("pushad")`). BlackMagic requires hand-assembled `byte[]`. For prototyping, debugging, and one-off shellcode, text assembly is faster to write and easier to review. A managed assembler eliminates the native FASM DLL dependency while keeping the ergonomic benefit.
2. **Text-based assembly**: FASM allowed building code payloads from assembly text (`AddLine("pushad")`). BlackMagic requires hand-assembled `byte[]`. For prototyping, debugging, and one-off code payloads, text assembly is faster to write and easier to review. A managed assembler eliminates the native FASM DLL dependency while keeping the ergonomic benefit.
## What Changes
- Add `InjectAndExecuteEx()` to `BlackMagic` and `BMThread`: inject code then create a remote thread without waiting, returning the thread handle.
- Add `AsmBuilder` class: pure C# x86 text assembler that converts instruction text to `byte[]` machine code. Supports common shellcode instructions (mov, push, pop, call, jmp, ret, nop, pushad/popad, test, je, jne, inc, add, sub, xor, etc.).
- Add `AsmBuilder` class: pure C# x86 text assembler that converts instruction text to `byte[]` machine code. Supports common payload instructions (mov, push, pop, call, jmp, ret, nop, pushad/popad, test, je, jne, inc, add, sub, xor, etc.).
- Add `InjectAndExecute(string asm)` and `InjectAndExecuteEx(string asm)` overloads that accept assembly text, assemble via `AsmBuilder`, then inject+execute.
- Add `SetPassLimit()` to `AsmBuilder` for label resolution iteration control.