Files
whitemagic/openspec/changes/whitemagic-foundation/tasks.md
T
2026-07-21 22:30:10 +02:00

8.1 KiB

1. Project Setup

  • 1.1 Create WhiteMagic/WhiteMagic.csproj targeting net8.0-windows, AllowUnsafeBlocks=true, nullable enabled, TreatWarningsAsErrors, Platforms=x86;x64;AnyCPU
  • 1.2 Create WhiteMagicTest/WhiteMagicTest.csproj (xUnit, net8.0-windows) referencing WhiteMagic
  • 1.3 Create WhiteMagic.slnx (SDK 10 default solution format) and add both projects. (Built on SDK 10; net8.0-windows targeting pack auto-restored.)
  • 1.4 Add WhiteMagic/Native/ P/Invoke surface (LibraryImport): OpenProcess, Read/WriteProcessMemory, VirtualAllocEx/FreeEx/ProtectEx, CreateRemoteThread, Wow64Get/SetThreadContext, Get/SetThreadContext, LoadLibrary, GetProcAddress; add SafeMemoryHandle
  • 1.5 Verify empty projects build: dotnet build WhiteMagic.slnx — zero errors, zero warnings

2. Core Memory Access (spec: memory-access)

  • 2.1 Add tests for MarshalCache<T>: blittable size, marshal-required flag, IsIntPtr, computed-once behavior
  • 2.2 Implement WhiteMagic/MarshalCache.cs to pass 2.1
  • 2.3 Add tests for MemoryBase abstract contract + ExternalReader round-trip (Read<T>/Write<T>, arrays) using the current process as target
  • 2.4 Implement WhiteMagic/MemoryBase.cs (abstract) and WhiteMagic/ExternalReader.cs to pass 2.3
  • 2.5 Add tests for string read/write with encoding, null-terminator stop, and max length
  • 2.6 Implement ReadString/WriteString on MemoryBase to pass 2.5
  • 2.7 Add tests for relative/absolute addressing (GetAbsolute/GetRelative, isRelative flag)
  • 2.8 Implement addressing helpers to pass 2.7
  • 2.9 Add tests + implementation for InProcessReader (RPM/WPM on a self-handle — see D1 deviation note; direct deref rejected because .NET cannot catch AccessViolationException); verify shared MemoryBase API works for both readers
  • 2.10 Follow-up (found in review): ReadString scans for the null terminator byte-by-byte, so for UTF-16/UTF-32 it can match a misaligned multi-byte null across a char boundary (e.g. "A"+U+4200 = 41 00 00 42 matches {00,00} at offset 1) and can miss a terminator split across the 64-byte chunk boundary. Harmless for ASCII/UTF-8 (single-byte encodings). Fix: align the scan to the encoding's code-unit width and carry the last (nullLen-1) bytes across chunks. Add a UTF-16 test.

3. Managed Assembler (spec: managed-assembler)

  • 3.1 Add tests for EmitU8/EmitU32/EmitU64 little-endian primitives
  • 3.2 Implement WhiteMagic/Assembly/StubAssembler.cs emitters + IAssembler interface to pass 3.1
  • 3.3 Add tests for x86 cdecl stub encoding (reverse push, call, add esp, N*4, ret) with known byte expectations
  • 3.4 Implement x86 cdecl stub to pass 3.3
  • 3.5 Add tests for stdcall (no caller cleanup), thiscall (ecx = this), fastcall (ecx/edx) x86 stubs
  • 3.6 Implement x86 stdcall/thiscall/fastcall stubs to pass 3.5
  • 3.7 Add tests for x64 stub argument-register placement and call
  • 3.8 Implement x64 stub to pass 3.7
  • 3.9 Confirm no FASM/ManagedFasm reference exists in WhiteMagic output (assert via a test that scans loaded references)

4. Crash-Safe Execution Slice (spec: remote-execution, function-hooking)

  • 4.1 Add tests for PatchManager/Patch: apply writes bytes, remove restores original, IsApplied reflects state
  • 4.2 Implement WhiteMagic/Hooking/PatchManager.cs + Patch.cs to pass 4.1
  • 4.3 Add tests for DetourManager/Detour in-process: apply redirects, CallOriginal, remove restores, named lookup
  • 4.4 Implement WhiteMagic/Hooking/DetourManager.cs + Detour.cs (inline jmp, x86/x64 form) to pass 4.3
  • 4.5 Add tests for instruction-boundary validation (aligned splice permitted, misaligned rejected when boundary info available)
  • 4.6 Implement minimal prologue length-decoder in Detour.Apply to pass 4.5. Default StubAssembler covers ONLY the common x86/x64 prologue shapes — enumerate the covered opcodes in code + XML doc (e.g. push reg 0x50-0x57, mov edi,edi 8B FF, push ebp/mov ebp,esp 55 8B EC, sub esp,imm 83 EC / 81 EC, REX-prefixed forms). On any opcode outside the set, refuse the splice (do not guess). Full arbitrary-prologue validation is gated on the optional Iced backend (task 8.3) — document that slices 2-5 ship partial boundary safety.
  • 4.7 Add tests for auto-restore: disposing a MemoryBase reverts all active patches and detours
  • 4.8 Wire manager registration + MemoryBase.Dispose restore to pass 4.7
  • 4.9 Add tests for MainThreadPump queue semantics: item runs on hooked thread, result returned, throwing item surfaces exception and pump survives, dispose uninstalls hook (use a self-hosted frame-loop harness in-process)
  • 4.10 Implement WhiteMagic/Execution/MainThreadPump.cs (frame-function detour + thread-safe work queue + completion handles) to pass 4.9
  • 4.11 Add tests for RemoteThreadExecutor.Execute<T> (convention stub + wait + typed exit; no-process failure is deterministic)
  • 4.12 Implement WhiteMagic/Execution/RemoteThreadExecutor.cs and parameter marshalling (string/struct → remote alloc → free) to pass 4.11

5. Injection & Discovery (spec: dll-injection, memory-discovery)

  • 5.1 Add tests for pattern scanning: found (range/module/all-modules), wildcard mask, not-found returns Zero
  • 5.2 Implement WhiteMagic/Discovery/PatternScanner.cs to pass 5.1
  • 5.3 Add tests + implement scan result cache (repeat served from cache, clear rescans)
  • 5.4 Add tests + implement WhiteMagic/Discovery/PeHeaderParser.cs (sections, entry point)
  • 5.5 Add tests + implement WhiteMagic/Memory/AllocatedMemory.cs (named regions, typed read/write by name, address by name, free on dispose)
  • 5.6 Add tests + implement raw code injection (InjectCode at address and into fresh allocation)
  • 5.7 Add tests + implement DLL injection via remote thread (LoadLibrary), including bitness-mismatch and missing-file failures
  • 5.8 Add tests + implement DLL injection via thread-hijack (save/redirect/restore context) with x86 and x64 stubs

6. In-Process Tier (spec: remote-execution)

  • 6.1 Add tests for InProcessInvoker.CreateFunction<TDelegate> calling a known in-process function directly
  • 6.2 Implement WhiteMagic/Execution/InProcessInvoker.cs (Marshal.GetDelegateForFunctionPointer) + vtable-entry helper to pass 6.1
  • 6.3 Document that the CLR-host managed loader (injecting InProcessReader into a foreign process) is a separate follow-up change

7. High-Level Ergonomics (spec: high-level-api)

  • 7.1 Add tests + implement RemotePointer indexer (sharp[addr].Read/Write/Execute relative to base)
  • 7.2 Add tests + implement RemoteModule/RemoteFunction (sharp["mod"]["fn"]) resolving export addresses and executing via a chosen strategy
  • 7.3 Add tests + implement ManagedPeb/ManagedTeb field reads
  • 7.4 Add tests + implement WindowFactory/RemoteWindow (enumerate, move/resize/title/activate/flash, query by class)
  • 7.5 Add tests + implement keyboard/mouse simulation (PostMessage + SendInput) to a target window
  • 7.6 Add tests + implement Task-based async execution wrappers over the executors and pump
  • 7.7 Add minimal facade (WhiteMagic entry type) exposing Open, readers, executors, managers, and the indexer

8. Optional Iced Backend (spec: managed-assembler)

  • 8.1 Add Iced package reference behind an IcedAssembler : IAssembler in a way that keeps the default StubAssembler dependency-free
  • 8.2 Add tests + implement IcedAssembler.Assemble(text, origin) for arbitrary mnemonics and origin-relative encoding
  • 8.3 Add tests + wire full prologue instruction-boundary validation (D5) using the Iced disassembler when present

9. Verification

  • 9.1 Run full test suite: dotnet test WhiteMagicTest/WhiteMagicTest.csproj — all pass
  • 9.2 Run full build (dotnet build WhiteMagic.slnx) — zero errors, zero new warnings in WhiteMagic
  • 9.3 Confirm existing BlackMagic/its tests are unchanged and still green
  • 9.4 Update docs/memory-library-comparison.md "WhiteMagic — synthesis" section with any deviations discovered during implementation