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.
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user