# Troubleshooting Guide This guide covers common issues, errors, and solutions when using WhiteMagic. ## Table of Contents - [Process Access Issues](#process-access-issues) - [Memory Operation Failures](#memory-operation-failures) - [Execution Errors](#execution-errors) - [Hooking Problems](#hooking-problems) - [Pattern Scanning Issues](#pattern-scanning-issues) - [Performance Problems](#performance-problems) - [Crash and Stability Issues](#crash-and-stability-issues) - [Build and Compilation Errors](#build-and-compilation-errors) --- ## Process Access Issues ### "Process is not open for read/write" **Symptom:** ``` System.InvalidOperationException: Process is not open for read/write. ``` **Causes:** 1. Process has exited 2. Process handle is closed 3. Insufficient permissions **Solutions:** ```csharp // Check process state if (magic.Memory.Handle.IsInvalid || magic.Memory.Handle.IsClosed) { Console.WriteLine("Process handle is invalid or closed"); } // Re-open the process using var magic = Magic.Open(process); ``` **Prevention:** - Keep `Process` object alive - Don't dispose `Magic` while using it - Use `using` statement for automatic cleanup ### "OpenProcess failed: Access Denied" **Symptom:** ``` Process.Open returns false, or Magic.Open throws Win32Exception ``` **Causes:** 1. Insufficient privileges (not running as administrator) 2. Target process is protected (anti-cheat, system process) 3. 32-bit/64-bit mismatch **Solutions:** ```csharp // Run as administrator // Right-click → Run as Administrator // Check process bitness matches host if (Environment.Is64BitProcess != Is64BitProcess(targetProcess)) { Console.WriteLine("Bitness mismatch between host and target"); } ``` **Prevention:** - Run with admin privileges - Check target process protection level - Ensure bitness compatibility --- ## Memory Operation Failures ### "Read returns default value" **Symptom:** ```csharp int value = magic.Memory.Read(address); // value is 0 (or default), but expected different value ``` **Causes:** 1. Address is invalid 2. Memory protection prevents reading 3. Fewer bytes read than expected 4. Process has exited **Solutions:** ```csharp // Verify address with debugger // Check if address is readable byte[] test = magic.Memory.ReadBytes(address, 4); if (test.Length < 4) { Console.WriteLine("Cannot read from address"); } // Validate handle if (magic.Memory.Handle.IsInvalid) { Console.WriteLine("Process handle is invalid"); } ``` ### "Write returns false" **Symptom:** ```csharp bool success = magic.Memory.Write(address, value); if (!success) { /* Write failed */ } ``` **Causes:** 1. Memory is read-only (e.g., `.text` section) 2. Address is invalid 3. Process has exited 4. Anti-cheat blocking writes **Solutions:** ```csharp // Retry with delay for (int i = 0; i < 3; i++) { if (magic.Memory.Write(address, value)) break; Thread.Sleep(50); } // Check if memory is protected // Use VirtualProtectEx if you have rights (advanced) ``` **For code patches, use `PatchManager` instead:** ```csharp var patch = magic.PatchManager.Create("Patch", address, bytes); patch.Apply(); // Handles VirtualProtect automatically ``` --- ## Execution Errors ### "CreateRemoteThread failed" **Symptom:** ``` Win32Exception: CreateRemoteThread failed ``` **Causes:** 1. Target process is protected 2. Insufficient permissions 3. Target process has exited **Solutions:** ```csharp // Ensure process is still running if (process.HasExited) { Console.WriteLine("Process has exited"); } // Check permissions // Run as administrator ``` ### "Crash when calling target function via RemoteThreadExecutor" **Symptom:** Target application crashes after `RemoteThreadExecutor.Execute` **Cause:** Calling single-threaded function from remote thread (thread-affinity violation) **Solution:** Use `MainThreadPump` instead: ```csharp // WRONG (crashes game): int health = magic.RemoteThread.Execute( readHealthFn, CallConvention.Cdecl ); // RIGHT (crash-safe): var pump = magic.CreateMainThreadPump(frameAddress); int health = await pump.Enqueue(() => magic.Memory.Read(healthAddress) ); ``` **Explanation:** Game state, scripting engines, and render contexts are often main-thread-only. Use `MainThreadPump` for these. ### "MainThreadPump work item wedged" **Symptom:** `Enqueue()` hangs or times out **Cause:** Work item threw exception or entered infinite loop **Solution:** ```csharp try { int result = await pump.Enqueue(() => { // Keep work items short! return magic.Memory.Read(address); }, TimeSpan.FromSeconds(1)); // Add timeout } catch (TimeoutException) { Console.WriteLine("Work item wedged (stuck the frame)"); } ``` **Prevention:** - Keep pump work items short (< 1ms) - Avoid blocking calls in work items - Use timeout on `Enqueue` --- ## Hooking Problems ### "Detour failed: prologue too short" **Symptom:** ``` InvalidOperationException: Prologue is too short for detour (minimum 5 bytes required) ``` **Cause:** Function prologue is shorter than minimum required for jmp instruction **Solutions:** ```csharp // Option 1: Hook a different function var detour = magic.DetourManager.Detour(alternativeAddress, hook); // Option 2: Patch deeper into function (after prologue) // (Advanced, risky) // Option 3: For WinAPI, use hot-patch area if (IsHotPatchPadded(functionAddress)) { // Can use 2-byte jmp at [address-2] } ``` ### "Patch failed: access violation" **Symptom:** ``` AccessViolationException when applying patch ``` **Cause:** Memory is protected or invalid **Solutions:** ```csharp // Verify address is valid byte[] test = magic.Memory.ReadBytes(address, 1); // Use PatchManager (handles VirtualProtect automatically) var patch = magic.PatchManager.Create("Patch", address, bytes); patch.Apply(); ``` ### "Hook not called" **Symptom:** Detour applied successfully, but hook delegate never executes **Causes:** 1. Wrong function address 2. Target already called function before hook installed 3. Target is using a different implementation (e.g., forwarded export) **Solutions:** ```csharp // Verify address with debugger // Install hook early (before target uses function) // Check for forwarded exports var fn = magic["module"]["function"]; Console.WriteLine($"Function address: {fn.Address}"); ``` --- ## Pattern Scanning Issues ### "FindPattern returns IntPtr.Zero" **Symptom:** Pattern scan finds no matches **Causes:** 1. Pattern is incorrect 2. Module not loaded 3. Memory layout changed (ASLR, update) 4. Pattern wildcards too broad **Solutions:** ```csharp // Verify pattern syntax // Use IDA-style: "48 8B ? ? ? ? ?" // ? = wildcard byte // Narrow search range // Scan only relevant module, not entire memory // Check if module is loaded var module = magic["moduleName"]; if (module.BaseAddress == IntPtr.Zero) { Console.WriteLine("Module not loaded"); } // Test with known pattern var test = magic.Memory.FindPattern("48 8B 05 ? ? ? ?", module.BaseAddress, 0x1000); ``` ### "Pattern scanner is slow" **Symptom:** `FindPattern` takes several seconds **Cause:** Scanning large memory regions without cache **Solution:** ```csharp // Use pattern cache (if available in your version) // Or cache results manually private static readonly Dictionary PatternCache = new(); IntPtr FindPatternCached(string pattern, IntPtr baseAddr, int size) { string key = $"{pattern}_{baseAddr}_{size}"; if (PatternCache.TryGetValue(key, out var cached)) return cached; IntPtr result = magic.Memory.FindPattern(pattern, baseAddr, size); PatternCache[key] = result; return result; } ``` --- ## Performance Problems ### "Memory reads are slow" **Symptom:** `Read` takes several milliseconds **Causes:** 1. Reading individual elements in a loop 2. Using marshalled types extensively 3. Target process is heavily loaded **Solutions:** ```csharp // WRONG: Slow loop for (int i = 0; i < 1000; i++) { values[i] = magic.Memory.Read(baseAddr + i * 4); } // RIGHT: Batch read values = magic.Memory.Read(baseAddr, 1000); // RIGHT: Use blittable types // Use int instead of bool where possible ``` ### "High CPU usage" **Symptom:** WhiteMagic causes high CPU in target process **Cause:** Polling loops, tight read loops in pump **Solutions:** ```csharp // WRONG: Tight loop in pump while (true) { int health = magic.Memory.Read(healthAddr); if (health == 0) break; } // RIGHT: Event-driven or throttled // Use MainThreadPump with delays // Or poll at reasonable interval (e.g., 60 Hz) ``` --- ## Crash and Stability Issues ### "Target crashes when attached" **Symptom:** Target application crashes shortly after `Magic.Open` **Cause:** Thread-affinity violation (calling function from wrong thread) **Solution:** Use `MainThreadPump` for state-sensitive calls: ```csharp // Identify the crash-safe execution model var pump = magic.CreateMainThreadPump(frameAddress); // All state-sensitive calls go through pump await pump.Enqueue(() => { /* safe code */ }); ``` ### "Random crashes during operation" **Symptom:** Intermittent crashes, hard to reproduce **Causes:** 1. Race conditions (concurrent memory access) 2. Anti-cheat interference 3. Memory protection changes mid-operation **Solutions:** ```csharp // Add synchronization lock (syncLock) { magic.Memory.Write(address, value); } // Handle access violations gracefully try { magic.Memory.Read(address); } catch (AccessViolationException) { // Retry or handle gracefully } // Check for anti-cheat // Some anti-cheat tools detect and block memory manipulation ``` --- ## Build and Compilation Errors ### "XML documentation errors" **Symptom:** Build fails with `CS1591` or `CS0419` errors **Cause:** Missing XML comments or ambiguous cref references **Solution:** ```xml $(NoWarn);CS1591 ``` Or add missing XML comments (see [Documentation Best Practices](../README.md#documentation)). ### "Type or namespace not found" **Symptom:** `WhiteMagic` namespace not found after adding reference **Cause:** Project not referencing `WhiteMagic.dll` **Solution:** ```bash dotnet add reference ../WhiteMagic/WhiteMagic.csproj # OR dotnet add package WhiteMagic ``` --- ## Debugging Tips ### Enable Detailed Logging ```csharp // Add diagnostic logging using System.Diagnostics; Debug.WriteLine($"Reading from 0x{address:X}"); int value = magic.Memory.Read(address); Debug.WriteLine($"Read result: {value}"); ``` ### Verify with External Tools - **Cheat Engine:** Verify memory addresses and values - **x64dbg/windbg:** Verify function addresses and disassembly - **Process Hacker:** Check process handles and permissions ### Common Pitfalls 1. ❌ **Forgetting `isRelative` for module-relative addresses** ```csharp // WRONG int value = magic.Memory.Read(0x1000); // RIGHT (if 0x1000 is module-relative) int value = magic.Memory.Read(0x1000, isRelative: true); ``` 2. ❌ **Using `RemoteThreadExecutor` for game state** ```csharp // WRONG (crashes) int health = magic.RemoteThread.Execute(fn, CallConvention.Cdecl); // RIGHT (crash-safe) int health = await pump.Enqueue(() => magic.Memory.Read(addr)); ``` 3. ❌ **Not disposing `Magic`** ```csharp // WRONG (leaks handles) var magic = Magic.Open(process); // ... use magic // Forgot to dispose! // RIGHT using (var magic = Magic.Open(process)) { // ... use magic } // Auto-disposes ``` --- ## Getting Help If you're still stuck: 1. **Check documentation:** - [Architecture](./architecture.md) - [Execution Models](./execution-models.md) - [Memory Access](./memory-access.md) - [Function Hooking](./hooking.md) 2. **Search issues:** Check existing GitHub issues 3. **Create minimal reproduction:** ```csharp // Minimal code that reproduces the issue using var magic = Magic.Open(process); int value = magic.Memory.Read(address); // What happens vs. what you expect ``` 4. **Include system info:** - WhiteMagic version - .NET version - Target process (if applicable) - Windows version - x86 or x64 --- ## Common Error Codes | Win32 Error | Meaning | Solution | |-------------|---------|----------| | `ERROR_ACCESS_DENIED` (5) | Insufficient permissions | Run as administrator | | `ERROR_INVALID_HANDLE` (6) | Handle is invalid/closed | Re-open process | | `ERROR_NOT_ENOUGH_MEMORY` (8) | Insufficient memory | Reduce buffer size | | `ERROR_NOACCESS` (998) | Invalid access | Check memory protection | | `ERROR_PARTIAL_COPY` (299) | Partial read/write | Retry or check address | --- *For more information, see the main [README](../README.md) and [architecture documentation](./architecture.md).*