- 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.
246 lines
7.7 KiB
Markdown
246 lines
7.7 KiB
Markdown
# 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
|
|
|
|
1. Open `WhiteMagic.slnx` in Visual Studio
|
|
2. Set `WhiteMagic.Examples` as the startup project
|
|
3. Press F5 to run
|
|
|
|
### From Command Line
|
|
|
|
```bash
|
|
# 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 `RemotePointer` for 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.Memory` API
|
|
- Use `RemotePointer` for 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**: `CreateRemoteThread` for 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`/`PatchManager` are 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 a `RemoteModule`
|
|
- `module["FunctionName"]` returns a `RemoteFunction`
|
|
- All high-level operations are built on top of the core memory API
|
|
|
|
## Common Patterns
|
|
|
|
### Reading a Nested Structure
|
|
|
|
```csharp
|
|
// 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
|
|
|
|
```csharp
|
|
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
|
|
|
|
```csharp
|
|
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
|
|
|
|
```csharp
|
|
// 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](../README.md) - Overview and quick start
|
|
- [Architecture Documentation](../docs/architecture.md) - System design and layer structure
|
|
- [Execution Models](../docs/execution-models.md) - Deep dive on execution strategies
|
|
- [Function Hooking](../docs/hooking.md) - DetourManager and PatchManager internals
|
|
- [Memory Access](../docs/memory-access.md) - MemoryBase and MarshalCache
|
|
- [Troubleshooting Guide](../docs/troubleshooting.md) - Common issues and solutions
|
|
|
|
## Safety Reminders
|
|
|
|
⚠️ **CRITICAL WARNINGS**:
|
|
|
|
1. **Execution Model Choice**:
|
|
- `RemoteThreadExecutor`: ONLY for thread-agnostic functions
|
|
- `MainThreadPump`: For state-sensitive calls (crash-safe)
|
|
- `InProcessInvoker`: Only after DLL injection
|
|
- **Using the wrong model crashes the target application!**
|
|
|
|
2. **Detours vs Patches**:
|
|
- Detours ONLY work in-process (requires injection)
|
|
- Patches work externally (no injection required)
|
|
|
|
3. **Thread Safety**:
|
|
- `DetourManager`/`PatchManager` are NOT thread-safe
|
|
- Synchronize concurrent modifications
|
|
|
|
4. **Handle Management**:
|
|
- Always use `using` statements or dispose `Magic` properly
|
|
- Leaked handles can cause resource exhaustion
|
|
|
|
5. **Anti-Cheat Detection**:
|
|
- Some operations (e.g., `CreateRemoteThread`) are easily detected
|
|
- Use `MainThreadPump` for stealthier operation
|
|
|
|
## 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.
|