using System.Diagnostics; using System.Runtime.InteropServices; using WhiteMagic; using WhiteMagic.Native; namespace WhiteMagicTest; /// /// Tests for relative/absolute addressing in . /// GetAbsolute(relative) = ImageBase + relative. /// GetRelative(absolute) = absolute - ImageBase (inverse of GetAbsolute). /// public class AddressingTests { private static ExternalReader OpenSelf() { return new ExternalReader( Process.GetCurrentProcess(), ProcessAccess.VmRead | ProcessAccess.VmWrite | ProcessAccess.VmOperation | ProcessAccess.QueryInformation); } [Fact] public void GetAbsolute_resolves_relative_offset() { using var reader = OpenSelf(); IntPtr imageBase = reader.ImageBase; IntPtr result = reader.GetAbsolute((IntPtr)0x1000); Assert.Equal(imageBase + 0x1000, result); } [Fact] public void GetRelative_returns_absolute_minus_image_base() { using var reader = OpenSelf(); IntPtr imageBase = reader.ImageBase; IntPtr absolute = imageBase + 0x2000; IntPtr relative = reader.GetRelative(absolute); Assert.Equal((IntPtr)((nint)absolute - (nint)imageBase), relative); } [Fact] public void GetAbsolute_and_GetRelative_are_inverses() { using var reader = OpenSelf(); IntPtr offset = (IntPtr)0x3000; // Round-trip: offset -> absolute -> back to offset IntPtr absolute = reader.GetAbsolute(offset); IntPtr back = reader.GetRelative(absolute); Assert.Equal(offset, back); // Reverse round-trip: absolute -> offset -> back to absolute IntPtr relative = reader.GetRelative(absolute); IntPtr absoluteAgain = reader.GetAbsolute(relative); Assert.Equal(absolute, absoluteAgain); } [Fact] public void GetRelative_on_ImageBase_returns_zero() { using var reader = OpenSelf(); IntPtr relative = reader.GetRelative(reader.ImageBase); Assert.Equal(IntPtr.Zero, relative); } [Fact] public void Read_with_isRelative_true_uses_image_base() { using var reader = OpenSelf(); // DOS header 'MZ' at the image base byte firstByte = reader.Read(IntPtr.Zero, isRelative: true); Assert.Equal(0x4D, firstByte); } [Fact] public void Write_with_isRelative_true_resolves_correctly() { using var reader = OpenSelf(); int slot = 0; GCHandle pin = GCHandle.Alloc(slot, GCHandleType.Pinned); try { IntPtr absolute = pin.AddrOfPinnedObject(); IntPtr relative = reader.GetRelative(absolute); Assert.True(reader.Write(relative, 42, isRelative: true)); Assert.Equal(42, reader.Read(absolute)); } finally { pin.Free(); } } [Fact] public void ReadBytes_with_isRelative_true_resolves_correctly() { using var reader = OpenSelf(); byte[] data = reader.ReadBytes(IntPtr.Zero, 2, isRelative: true); Assert.Equal(0x4D, data[0]); Assert.Equal(0x5A, data[1]); } }