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:
@@ -1,4 +1,5 @@
|
||||
using System.Diagnostics;
|
||||
using Process = System.Diagnostics.Process;
|
||||
using System.Runtime.InteropServices;
|
||||
using WhiteMagic.Native;
|
||||
|
||||
@@ -13,6 +14,8 @@ public sealed class ExternalReader : MemoryBase
|
||||
{
|
||||
private readonly SafeMemoryHandle _handle;
|
||||
private readonly IntPtr _imageBase;
|
||||
private readonly bool _is64Bit;
|
||||
private readonly int _processId;
|
||||
private bool _disposed;
|
||||
|
||||
/// <summary>
|
||||
@@ -31,16 +34,27 @@ public sealed class ExternalReader : MemoryBase
|
||||
/// <param name="process">The target process.</param>
|
||||
/// <param name="desiredAccess">The access rights to request. Defaults to
|
||||
/// <see cref="DefaultAccess"/>.</param>
|
||||
public ExternalReader(Process process, ProcessAccess desiredAccess = DefaultAccess)
|
||||
public ExternalReader(System.Diagnostics.Process process, ProcessAccess desiredAccess = DefaultAccess)
|
||||
{
|
||||
_handle = NativeMethods.OpenProcess(desiredAccess, false, process.Id);
|
||||
_processId = process.Id;
|
||||
_handle = NativeMethods.OpenProcess(desiredAccess, false, _processId);
|
||||
if (_handle.IsInvalid)
|
||||
{
|
||||
int error = Marshal.GetLastPInvokeError();
|
||||
throw new InvalidOperationException(
|
||||
$"OpenProcess failed for PID {process.Id}: error {error}");
|
||||
$"OpenProcess failed for PID {_processId}: error {error}");
|
||||
}
|
||||
|
||||
// Derive target bitness. A 64-bit host sees a 32-bit target as WOW64.
|
||||
// A 32-bit host can only open 32-bit targets. If the API fails, fall
|
||||
// back to the current process bitness (self-open path).
|
||||
if (!NativeMethods.IsWow64Process(_handle, out bool wow64))
|
||||
{
|
||||
wow64 = false;
|
||||
}
|
||||
|
||||
_is64Bit = Environment.Is64BitProcess && !wow64;
|
||||
|
||||
// Process.MainModule throws Win32Exception for a bitness-mismatched or protected
|
||||
// target. A missing image base must not sink the whole reader — callers can still
|
||||
// use absolute addresses when ImageBase is unknown.
|
||||
@@ -60,6 +74,12 @@ public sealed class ExternalReader : MemoryBase
|
||||
/// <inheritdoc />
|
||||
public override SafeMemoryHandle Handle => _handle;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Is64Bit => _is64Bit;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override int ProcessId => _processId;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override byte[] ReadBytes(IntPtr address, int count, bool isRelative = false)
|
||||
{
|
||||
@@ -84,7 +104,7 @@ public sealed class ExternalReader : MemoryBase
|
||||
if (!_disposed)
|
||||
{
|
||||
_disposed = true;
|
||||
_handle.Dispose();
|
||||
base.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user