Files
kbe 3f0bea6bd4 Implement core diagnostic memory layer, execution helpers, and high-level facade slices
Implemented:
- Core: UTF-16 ReadString boundary/alignment fix, target bitness and process id on MemoryBase
- function interception: PatchManager, DetourManager, InstructionAnalyzer, MainThreadDispatcher
- Execution: BackgroundTaskExecutor, InProcessInvoker
- High-level: Magic facade, RemotePointer, async wrappers
- Discovery/external code loading/Window groundwork (PEB/TEB, pattern scanning, raw allocations, DLL external code loading, window/input)

Tests: 180 passing, 4 integration/interactive tests skipped.
2026-07-21 23:43:14 +02:00

85 lines
2.4 KiB
C#

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;
/// <summary>
/// Tests for the high-level facade (<see cref="Magic"/>) and <see cref="RemotePointer"/>.
/// </summary>
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<InProcessReader>(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<int>(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<int>(payload, CallConvention.Cdecl, 10, 32);
Assert.Equal(42, result);
}
finally
{
NativeMethods.VirtualFreeEx(magic.Memory.Handle, payload, 0, MemoryFreeType.Release);
}
}
}