using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading.Tasks; using WhiteMagic; using WhiteMagic.Assembly; using WhiteMagic.Native; using Xunit; namespace WhiteMagicTest; /// /// Tests for the high-level facade () and . /// public class HighLevelTests { private static readonly byte[] AddPayload = [0x89, 0xC8, 0x01, 0xD0, 0xC3]; [Fact] public void OpenExternal_returns_session_for_current_process() { using var magic = Magic.Open(Process.GetCurrentProcess()); Assert.NotNull(magic.Memory); Assert.False(magic.Memory.Handle.IsInvalid); Assert.Same(magic.Memory.PatchManager, magic.PatchManager); Assert.Same(magic.Memory.DetourManager, magic.DetourManager); } [Fact] public void OpenInProcess_returns_session_for_self() { using var magic = Magic.OpenInProcess(); Assert.IsType(magic.Memory); Assert.False(magic.Memory.Handle.IsInvalid); } [Fact] public void Indexer_returns_remote_pointer_that_reads_and_writes_relative() { using var magic = Magic.OpenInProcess(); byte[] slot = new byte[16]; GCHandle pin = GCHandle.Alloc(slot, GCHandleType.Pinned); try { IntPtr baseAddr = pin.AddrOfPinnedObject(); magic[baseAddr + 4].Write(0x12345678); Assert.Equal(0x12345678, magic[baseAddr].Read(4)); } finally { pin.Free(); } } [Fact] public async Task RemoteThread_ExecuteAsync_runs_payload_and_returns_result() { if (!Environment.Is64BitProcess) { return; } using var magic = Magic.OpenInProcess(); IntPtr payload = NativeMethods.VirtualAllocEx( magic.Memory.Handle, IntPtr.Zero, 4096, MemoryAllocationType.Commit | MemoryAllocationType.Reserve, MemoryProtectionType.ExecuteReadWrite); Assert.NotEqual(IntPtr.Zero, payload); try { magic.Memory.WriteBytes(payload, AddPayload); int result = await magic.RemoteThread.ExecuteAsync(payload, CallConvention.Cdecl, 10, 32); Assert.Equal(42, result); } finally { NativeMethods.VirtualFreeEx(magic.Memory.Handle, payload, 0, MemoryFreeType.Release); } } }