Add GetAbsolute/GetRelative with nint-based arithmetic (bitness-agnostic). Add 6 tests: absolute resolution, relative computation, base-round-trip, isRelative flag on Read/Write/ReadBytes. Fix MemoryBase.cs: restore for-loop body damaged by prior edit, clean up StructureToByteArray overloads. All passing (total: 44).
90 lines
2.7 KiB
C#
90 lines
2.7 KiB
C#
using System.Diagnostics;
|
|
using System.Runtime.InteropServices;
|
|
using WhiteMagic;
|
|
using WhiteMagic.Native;
|
|
|
|
namespace WhiteMagicTest;
|
|
|
|
/// <summary>
|
|
/// Tests for relative/absolute addressing in <see cref="MemoryBase"/>.
|
|
/// </summary>
|
|
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_computes_offset_from_image_base()
|
|
{
|
|
using var reader = OpenSelf();
|
|
IntPtr imageBase = reader.ImageBase;
|
|
IntPtr absolute = imageBase + 0x2000;
|
|
IntPtr relative = reader.GetRelative(absolute);
|
|
// GetRelative returns ImageBase - absolute (GreyMagic convention)
|
|
Assert.Equal((IntPtr)((int)imageBase - (int)absolute), relative);
|
|
}
|
|
|
|
[Fact]
|
|
public void GetAbsolute_after_GetRelative_at_image_base_returns_to_base()
|
|
{
|
|
using var reader = OpenSelf();
|
|
IntPtr atBase = reader.ImageBase;
|
|
IntPtr relative = reader.GetRelative(atBase);
|
|
IntPtr back = reader.GetAbsolute(relative);
|
|
Assert.Equal(atBase, back);
|
|
}
|
|
|
|
[Fact]
|
|
public void Read_with_isRelative_true_uses_image_base()
|
|
{
|
|
using var reader = OpenSelf();
|
|
// Read the first byte at ImageBase (should be MZ header: 0x4D = 'M')
|
|
byte firstByte = reader.Read<byte>(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();
|
|
nint relative = (nint)absolute - (nint)reader.ImageBase;
|
|
IntPtr relativePtr = (IntPtr)relative;
|
|
|
|
Assert.True(reader.Write(relativePtr, 42, isRelative: true));
|
|
Assert.Equal(42, reader.Read<int>(absolute));
|
|
}
|
|
finally
|
|
{
|
|
pin.Free();
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void ReadBytes_with_isRelative_true_resolves_correctly()
|
|
{
|
|
using var reader = OpenSelf();
|
|
// DOS header 'MZ' at the image base
|
|
byte[] data = reader.ReadBytes(IntPtr.Zero, 2, isRelative: true);
|
|
Assert.Equal(0x4D, data[0]);
|
|
Assert.Equal(0x5A, data[1]);
|
|
}
|
|
}
|