- Example5: Fix format string bugs (alignment specifier placement, SafeMemoryHandle formatting) - Example4: Fix DetourManager.Detour() → Create() in all doc strings - Example3: Fix MemoryBase.CreateFunction() → InProcessInvoker.CreateFunction() in doc strings - Examples 1-5: Correct all runtime errors and API mismatches vs actual WhiteMagic API - README: Fix DetourManager.Detour() examples to use Create(); add missing code fence markers - Add WhiteMagic.Examples project with 5 comprehensive example files (40+ sub-examples) - Add docfx.json and toc.md for DocFX API reference generation - Add 5 conceptual guides: architecture, memory-access, execution-models, hooking, troubleshooting - Ensure zero errors, zero warnings across all projects (net8.0-windows) Doc strings now teach correct APIs; runtime format bugs eliminated; build succeeds.
7.7 KiB
WhiteMagic Examples
This directory contains comprehensive examples demonstrating all major features of the WhiteMagic library.
Prerequisites
- Target Process: Most examples use Notepad as the target. Launch Notepad before running the examples.
- Administrator Privileges: Some operations require elevated privileges. Run Visual Studio or terminal as Administrator.
- .NET 8.0 SDK: Ensure you have .NET 8.0 installed.
Running the Examples
From Visual Studio
- Open
WhiteMagic.slnxin Visual Studio - Set
WhiteMagic.Examplesas the startup project - Press F5 to run
From Command Line
# Navigate to the examples directory
cd WhiteMagic.Examples
# Run the examples
dotnet run
Example Categories
1. Basic Memory Operations (Example1_BasicMemoryOperations.cs)
Demonstrates:
- Reading and writing primitive types (int, float, double, bool)
- Reading and writing arrays
- Reading and writing strings (ANSI and Unicode)
- Reading and writing raw bytes
- Using
RemotePointerfor fluent pointer arithmetic - Relative addressing (module-relative offsets)
- Error handling for memory operations
- Working with custom structs
Key Takeaways:
- All memory operations go through the
Magic.MemoryAPI - Use
RemotePointerfor clean, fluent pointer arithmetic - Reads throw exceptions on failure; writes return
false - Prefer blittable types for best performance
2. Pattern Scanning (Example2_PatternScanning.cs)
Demonstrates:
- Simple pattern scans with wildcards
- Multiple pattern scans in one operation
- Region-specific scanning (e.g., .text section only)
- Finding function signatures
- Cached pattern scanning for performance
- Flexible wildcard patterns
- Signature-based scanning (code caves, NOPs, INT3s)
- Pattern validation
Key Takeaways:
- Use IDA-style patterns:
"48 8B ? ? ? ? ?"where?is a wildcard - Cache results for repeated scans
- Narrow search region when possible for better performance
3. Execution Models (Example3_ExecutionModels.cs)
Demonstrates:
- RemoteThreadExecutor:
CreateRemoteThreadfor thread-agnostic calls - MainThreadPump: Crash-safe execution for state-sensitive calls
- InProcessInvoker: Direct delegates for in-process calls
- Choosing the right execution model
- Combining execution models (inject then switch)
- Error handling for each model
Key Takeaways:
- CRITICAL: Use the right model for the payload:
RemoteThreadExecutor: Only for thread-agnostic functions (WinAPI, DLL injection)MainThreadPump: For state-sensitive calls (game state, scripting, UI)InProcessInvoker: Only after DLL injection
- Using the wrong model crashes the target application
4. Function Hooking (Example4_FunctionHooking.cs)
Demonstrates:
- Inline Detours: Function hooking with trampolines
- Detours with parameter modification
- Detours with return value modification
- Multiple detours (chain hooking)
- Byte Patching: Named byte patches
- NOP patching (removing instructions)
- Conditional patching (toggle on/off)
- Prologue validation and safety
- Automatic restoration on disposal
Key Takeaways:
- Detours ONLY work in-process (requires DLL injection)
- Patches work externally (no injection required)
DetourManager/PatchManagerare NOT thread-safe- All hooks and patches auto-restore on disposal
5. High-Level API (Example5_HighLevelAPI.cs)
Demonstrates:
- RemotePointer: Fluent pointer arithmetic with
[]indexing - RemoteModule: Module enumeration and export resolution
- RemoteFunction: Function resolution and execution
- ManagedPeb/ManagedTeb: Typed PEB/TEB access
- RemoteWindow: Window manipulation (move, resize, flash, activate)
- Memory allocation and freeing
- Module pattern scanning
- Export function iteration
- Chaining high-level operations
Key Takeaways:
- Use high-level APIs for cleaner, more readable code
magic["ModuleName"]returns aRemoteModulemodule["FunctionName"]returns aRemoteFunction- All high-level operations are built on top of the core memory API
Common Patterns
Reading a Nested Structure
// GameManager -> PlayerList -> Player[i] -> Health
IntPtr gameManagerPtr = magic.Memory.ImageBase + 0x1000;
IntPtr playerListPtr = magic.Memory.Read<IntPtr>(gameManagerPtr + 0x20);
IntPtr playerPtr = magic.Memory.Read<IntPtr>(playerListPtr + (playerIndex * 8));
int health = magic.Memory.Read<int>(playerPtr + 0x4);
Using RemotePointer for Cleaner Code
int health = magic[gameManagerPtr]
.Read<IntPtr>(0x20) // PlayerList
.Let(ptr => magic[ptr]
.Read<IntPtr>(playerIndex * 8)) // Player
.Let(ptr => magic[ptr]
.Read<int>(0x4)); // Health
Safe Retry Loop for Writes
for (int i = 0; i < 5; i++)
{
if (magic.Memory.Write(address, value))
break;
Thread.Sleep(100 * (1 << i)); // Exponential backoff
}
Crash-Safe State Access
// WRONG (crashes in most games)
int health = magic.RemoteThread.Execute<int>(fn, CallConvention.Cdecl);
// RIGHT (crash-safe)
var pump = magic.CreateMainThreadPump(frameAddress);
int health = await pump.Enqueue(() => magic.Memory.Read<int>(healthAddress));
Troubleshooting
"Process is not open for read/write"
Cause: Process has exited or handle is invalid
Solution: Ensure process is still running and handle is valid
"Read returns default value"
Cause: Address is invalid or memory is protected
Solution: Verify address with debugger; check memory protection
"Write returns false"
Cause: Memory is read-only or process has exited
Solution: Retry with delay; use PatchManager for code patches
"CreateRemoteThread failed"
Cause: Insufficient permissions or target is protected
Solution: Run as Administrator; check target process protection
"Crash when calling target function"
Cause: Calling single-threaded function from remote thread
Solution: Use MainThreadPump instead of RemoteThreadExecutor
"Detour failed: prologue too short"
Cause: Function prologue is shorter than minimum (5 bytes)
Solution: Hook different function; patch deeper into function
Further Reading
- Main README - Overview and quick start
- Architecture Documentation - System design and layer structure
- Execution Models - Deep dive on execution strategies
- Function Hooking - DetourManager and PatchManager internals
- Memory Access - MemoryBase and MarshalCache
- Troubleshooting Guide - Common issues and solutions
Safety Reminders
⚠️ CRITICAL WARNINGS:
-
Execution Model Choice:
RemoteThreadExecutor: ONLY for thread-agnostic functionsMainThreadPump: For state-sensitive calls (crash-safe)InProcessInvoker: Only after DLL injection- Using the wrong model crashes the target application!
-
Detours vs Patches:
- Detours ONLY work in-process (requires injection)
- Patches work externally (no injection required)
-
Thread Safety:
DetourManager/PatchManagerare NOT thread-safe- Synchronize concurrent modifications
-
Handle Management:
- Always use
usingstatements or disposeMagicproperly - Leaked handles can cause resource exhaustion
- Always use
-
Anti-Cheat Detection:
- Some operations (e.g.,
CreateRemoteThread) are easily detected - Use
MainThreadPumpfor stealthier operation
- Some operations (e.g.,
Contributing
Found a bug or have a suggestion? Please open an issue on GitHub.
License
These examples are part of the WhiteMagic project. See the main LICENSE file for details.