Task 7.2: export resolution + module/function facade. - PeHeaderParser.GetExportAddress walks the PE32/PE32+ export directory and follows export forwarders (e.g. kernel32!HeapAlloc -> NTDLL.RtlAllocateHeap) into other loaded modules; ordinal and unresolvable API-set forwarders throw NotSupportedException. - RemoteModule resolves a module base via Process.Modules (name match tolerant of .dll/case); RemoteFunction executes via RemoteThreadExecutor by default, exposes Address for pump routing and CreateDelegate<T> for in-process. - Magic gains a string indexer: magic["user32"]["MessageBoxA"]. Task 3.8: add the missing live-execution ABI test - an SSE callee whose aligned movaps #GPs unless the stub delivers a 16-byte-aligned stack, combined with a 5th stack argument. Runtime-proves shadow space, alignment, and arg placement. Tests: 214 passing, 4 skipped. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
67 lines
2.2 KiB
C#
67 lines
2.2 KiB
C#
using System.Diagnostics;
|
|
using Process = System.Diagnostics.Process;
|
|
using WhiteMagic.Execution;
|
|
using WhiteMagic.Hooking;
|
|
|
|
namespace WhiteMagic;
|
|
|
|
/// <summary>
|
|
/// High-level entry point for a WhiteMagic session. Opens a process, exposes the
|
|
/// memory reader, execution tiers, hooking managers, and the <see cref="RemotePointer"/>
|
|
/// indexer.
|
|
/// </summary>
|
|
public sealed class Magic : IDisposable
|
|
{
|
|
/// <summary>The underlying memory reader for this session.</summary>
|
|
public MemoryBase Memory { get; }
|
|
|
|
/// <summary>Out-of-process execution via <c>CreateRemoteThread</c>.</summary>
|
|
public RemoteThreadExecutor RemoteThread { get; }
|
|
|
|
/// <summary>Named byte-patch manager.</summary>
|
|
public PatchManager PatchManager => Memory.PatchManager;
|
|
|
|
/// <summary>Inline-detour manager (in-process only).</summary>
|
|
public DetourManager DetourManager => Memory.DetourManager;
|
|
|
|
private Magic(MemoryBase memory)
|
|
{
|
|
Memory = memory;
|
|
RemoteThread = new RemoteThreadExecutor(memory);
|
|
}
|
|
|
|
/// <summary>Opens an external process for reading, writing, and execution.</summary>
|
|
public static Magic Open(System.Diagnostics.Process process)
|
|
{
|
|
return new Magic(new ExternalReader(process));
|
|
}
|
|
|
|
/// <summary>Creates an in-process session for the current process.</summary>
|
|
public static Magic OpenInProcess()
|
|
{
|
|
return new Magic(new InProcessReader());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a main-thread pump that hooks the per-frame function at
|
|
/// <paramref name="frameAddress"/>.
|
|
/// </summary>
|
|
public MainThreadPump CreateMainThreadPump(IntPtr frameAddress)
|
|
{
|
|
return new MainThreadPump(DetourManager, frameAddress);
|
|
}
|
|
|
|
/// <summary>Returns a <see cref="RemotePointer"/> at <paramref name="address"/>.</summary>
|
|
public RemotePointer this[IntPtr address] => new RemotePointer(Memory, address);
|
|
|
|
/// <summary>Returns the loaded <see cref="RemoteModule"/> named <paramref name="moduleName"/>
|
|
/// (e.g. <c>magic["user32"]["MessageBoxA"]</c>).</summary>
|
|
public RemoteModule this[string moduleName] => new RemoteModule(this, moduleName);
|
|
|
|
/// <inheritdoc />
|
|
public void Dispose()
|
|
{
|
|
Memory.Dispose();
|
|
}
|
|
}
|