Files
whitemagic/WhiteMagic/InProcessReader.cs
T
kbe 6eb78e7974 Phase 2: Core Memory Access complete
task 2.9: implement InProcessReader with tests

Add InProcessReader: direct pointer dereference (unsafe) against own
process via Buffer.MemoryCopy. Implements MemoryBase API for in-process
scenarios (injected managed DLL).

8 tests: ImageBase, Read/Write int, ReadBytes, WriteBytes, Read/Write
struct, dispose lifecycle.

All passing: 52 tests (7 Native + 12 MarshalCache + 11 MemoryBase +
8 String + 6 Addressing + 8 InProcessReader).
2026-07-21 17:09:36 +02:00

75 lines
2.0 KiB
C#

using System.Diagnostics;
using System.Runtime.InteropServices;
using WhiteMagic.Native;
namespace WhiteMagic;
/// <summary>
/// In-process memory reader that accesses the owning process's memory through
/// direct pointer dereference (<c>unsafe</c>). Use this reader from within a
/// managed DLL injected into the target process.
/// </summary>
public sealed class InProcessReader : MemoryBase
{
private readonly SafeMemoryHandle _handle;
private readonly IntPtr _imageBase;
private bool _disposed;
/// <summary>
/// Creates an in-process reader for the current process.
/// </summary>
public InProcessReader()
{
Process current = Process.GetCurrentProcess();
_handle = NativeMethods.OpenProcess(
ProcessAccess.VmRead | ProcessAccess.VmWrite | ProcessAccess.VmOperation | ProcessAccess.QueryInformation,
false,
current.Id);
_imageBase = current.MainModule?.BaseAddress ?? IntPtr.Zero;
}
/// <inheritdoc />
public override IntPtr ImageBase => _imageBase;
/// <inheritdoc />
public override SafeMemoryHandle Handle => _handle;
/// <inheritdoc />
public override unsafe byte[] ReadBytes(IntPtr address, int count, bool isRelative = false)
{
if (isRelative)
address = GetAbsolute(address);
byte[] buffer = new byte[count];
fixed (byte* ptr = buffer)
{
Buffer.MemoryCopy((void*)address, ptr, count, count);
}
return buffer;
}
/// <inheritdoc />
public override unsafe int WriteBytes(IntPtr address, ReadOnlySpan<byte> bytes, bool isRelative = false)
{
if (isRelative)
address = GetAbsolute(address);
fixed (byte* ptr = bytes)
{
Buffer.MemoryCopy(ptr, (void*)address, bytes.Length, bytes.Length);
}
return bytes.Length;
}
/// <inheritdoc />
public override void Dispose()
{
if (!_disposed)
{
_disposed = true;
_handle.Dispose();
}
}
}