Commit Graph
7 Commits
Author SHA1 Message Date
kbeandClaude Opus 4.8 b06a034072 Guard BuildCallStub against argument-count overflow
The x64 frame math (0x20 + 8*stackArgs) and x86 arg buffer size grow with the
argument count. An absurdly large count could overflow int and produce a bogus
or negative frame. Add a MaxArguments (256) bound checked at the public entry —
far above any real calling convention — so the arithmetic stays in range. Add a
test asserting the cap is inclusive and count+1 throws.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 22:10:33 +02:00
kbeandClaude Opus 4.8 cb437ef9b5 Fix x64 stub ABI and marshal-path sizing; dedupe RPM readers
x64 call stub was ABI-broken: fixed 0x20 frame left rsp misaligned at the
inner call (callee entry rsp ≡ 0, ABI requires ≡ 8) and, for 5+ args, wrote
stack args over the return address. Compute frame K ≡ 8 (mod 16), K ≥
0x20 + 8*stackArgs, so the callee sees a 16-aligned stack and stack args land
above the shadow window. Load register args as full 64-bit imm64 (was imm32,
which truncated pointers > 4 GiB). BuildCallStub now takes nuint[]; x86 range-
checks each arg against uint.MaxValue instead of silently truncating.

MarshalCache conflated managed and unmanaged width in one Size field: the
blittable path needs Unsafe.SizeOf<T> (bool = 1) while the marshal path needs
Marshal.SizeOf<T> (inline ByValTStr/ByValArray expand past the managed
pointer). Add MarshalSize; MemoryBase picks per TypeRequiresMarshal at all four
IO sites. Prevents PtrToStructure/StructureToPtr from over-reading/overwriting
the pinned scratch buffer (heap corruption on write).

Extract shared RPM/WPM into RpmHelper: honor partial reads (dead Array.Resize
removed), consistent write-return semantics; InProcessReader now guards
MainModule like ExternalReader.

Tests: x64 frame-alignment property + inline-marshal round-trip added (both
fail against the pre-fix code); existing x64 byte-expectation tests updated to
the new frame. Build clean, 100/100 pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 21:53:22 +02:00
kbe 6fa12d8667 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.
2026-07-21 20:19:51 +02:00
kbe 2ecdd147a7 review fixes: rename CallingConvention→CallConvention, seal, edge cases
HIGH: rename CallingConvention to CallConvention to avoid BCL collision
 with System.Runtime.InteropServices.CallingConvention.

FIXES:
- checked(uint) casts for x86 pointer truncation (ArgumentOverflow)
- checked distance for E8 rel32 range (>2 GiB → throw)
- add esp, imm32 (81 /0 id) when cleanup > 127 bytes
- pointerSize validation (throw on != 4 and != 8)
- switch default: throw on unknown convention
- track argIndex instead of args[1..] slicing
- EmitMovRegImm32 helper (avoids manual ip tracking bugs)
- seal StubAssembler
- IAssembler doc: note BuildCallStub is StubAssembler-specific
- thiscall 0-args throws test; fastcall 0-args is valid
- update remote-execution spec example to CallConvention.Cdecl

All passing (total: 93).
2026-07-21 19:59:48 +02:00
kbe f39ecf820d Phase 3 complete: managed assembler
task 3.5-3.6: x86 stdcall/thiscall/fastcall stubs (8 tests)
task 3.7-3.8: x64 stub with RCX/RDX/R8/R9 register args + stack push (4 tests)
task 3.9: no-FASM reference assertion test

All passing (total: 87).
2026-07-21 19:52:04 +02:00
kbe f7236eea9b task 3.3-3.4: x86 cdecl stub encoding + CallingConvention enum
Add CallingConvention enum (Cdecl, Stdcall, Thiscall, Fastcall).
Implement BuildCallStub on StubAssembler with x86 cdecl support:
reverse arg push, call rel32, add esp (caller cleanup), ret.
x64 stub is a placeholder (task 3.7-3.8).

3 new tests: 0-arg (call+ret), 1-arg (push+call+cleanup+ret),
2-args (reverse push+call+cleanup+ret). Known byte expectations.
All passing (total: 67).
2026-07-21 19:37:20 +02:00
kbe 855595837f task 3.1-3.2: IAssembler interface + StubAssembler emit primitives
Add IAssembler seam (Assemble(text, origin)) with StubAssembler default
backend. StubAssembler provides EmitU8/EmitU32/EmitU64 little-endian
byte emitters (zero dep, no FASM). Assemble throws NotSupportedException
on StubAssembler (text assembly deferred to IcedAssembler, Phase 8).

7 new tests: EmitU8, EmitU32 x2, EmitU64 x2, IS-A check,
Assemble throws. All passing (total: 64).
2026-07-21 19:35:11 +02:00