Implements VirtualQueryEx + MEMORY_BASIC_INFORMATION wrappers, the immutable MemoryRegion record, the ProtectionScope disposable helper, and MemoryBase.QueryRegion/EnumerateRegions/ChangeProtection. Closes section 1 of add-thread-region-finder.
219 lines
9.7 KiB
C#
219 lines
9.7 KiB
C#
using System.Runtime.InteropServices;
|
|
|
|
namespace WhiteMagic.Native;
|
|
|
|
/// <summary>
|
|
/// P/Invoke declarations for the Win32 process, memory, thread, and module
|
|
/// APIs that WhiteMagic uses. Every declaration uses <see cref="LibraryImportAttribute"/>
|
|
/// (source-generated interop). SetLastError is enabled on all calls that the
|
|
/// Win32 API documents as setting a thread-local last-error value.
|
|
/// </summary>
|
|
internal static partial class NativeMethods
|
|
{
|
|
// ── Process ──────────────────────────────────────────────────────────────
|
|
|
|
/// <summary>Opens an existing process and returns a handle to it.</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
internal static partial SafeMemoryHandle OpenProcess(
|
|
ProcessAccess desiredAccess,
|
|
[MarshalAs(UnmanagedType.Bool)] bool inheritHandle,
|
|
int processId);
|
|
|
|
/// <summary>Opens an existing thread and returns a handle to it.</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
internal static partial SafeMemoryHandle OpenThread(
|
|
ThreadAccess desiredAccess,
|
|
[MarshalAs(UnmanagedType.Bool)] bool inheritHandle,
|
|
int threadId);
|
|
|
|
/// <summary>Closes an open object handle.</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static partial bool CloseHandle(IntPtr handle);
|
|
|
|
/// <summary>Determines whether the specified process is running under WOW64.</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static partial bool IsWow64Process(
|
|
SafeMemoryHandle process,
|
|
[MarshalAs(UnmanagedType.Bool)] out bool wow64Process);
|
|
|
|
/// <summary>Retrieves the termination status of the specified thread.</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static partial bool GetExitCodeThread(
|
|
SafeMemoryHandle thread,
|
|
out uint exitCode);
|
|
|
|
// ── Memory ───────────────────────────────────────────────────────────────
|
|
|
|
/// <summary>Reads memory from a process.</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static partial bool ReadProcessMemory(
|
|
SafeMemoryHandle process,
|
|
IntPtr baseAddress,
|
|
Span<byte> buffer,
|
|
int size,
|
|
out nint bytesRead);
|
|
|
|
/// <summary>Writes memory to a process.</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static partial bool WriteProcessMemory(
|
|
SafeMemoryHandle process,
|
|
IntPtr baseAddress,
|
|
ReadOnlySpan<byte> buffer,
|
|
int size,
|
|
out nint bytesWritten);
|
|
|
|
/// <summary>Reserves or commits a region of memory in a process.</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
internal static partial IntPtr VirtualAllocEx(
|
|
SafeMemoryHandle process,
|
|
IntPtr address,
|
|
nint size,
|
|
MemoryAllocationType allocationType,
|
|
MemoryProtectionType protect);
|
|
|
|
/// <summary>Changes the protection on a committed region of memory.</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static partial bool VirtualProtectEx(
|
|
SafeMemoryHandle process,
|
|
IntPtr address,
|
|
nint size,
|
|
MemoryProtectionType newProtect,
|
|
out MemoryProtectionType oldProtect);
|
|
|
|
/// <summary>Releases or decommits a region of memory in a process.</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static partial bool VirtualFreeEx(
|
|
SafeMemoryHandle process,
|
|
IntPtr address,
|
|
nint size,
|
|
MemoryFreeType freeType);
|
|
|
|
// ── Threading ────────────────────────────────────────────────────────────
|
|
|
|
/// <summary>Creates a thread that runs in the virtual address space of a process.</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
internal static partial SafeMemoryHandle CreateRemoteThread(
|
|
SafeMemoryHandle process,
|
|
IntPtr threadAttributes,
|
|
nint stackSize,
|
|
IntPtr startAddress,
|
|
IntPtr parameter,
|
|
ThreadCreationFlags creationFlags,
|
|
out uint threadId);
|
|
|
|
/// <summary>Suspends the specified thread.</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
internal static partial uint SuspendThread(SafeMemoryHandle thread);
|
|
|
|
/// <summary>Resumes the specified thread.</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
internal static partial uint ResumeThread(SafeMemoryHandle thread);
|
|
|
|
/// <summary>Returns the thread identifier of the specified thread.</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
internal static partial uint GetThreadId(SafeMemoryHandle thread);
|
|
|
|
/// <summary>Returns the identifier of the calling thread.</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
internal static partial uint GetCurrentThreadId();
|
|
|
|
/// <summary>Sets a 64-bit thread context (AMD64).</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static partial bool SetThreadContext(
|
|
SafeMemoryHandle thread,
|
|
ref Context64 context);
|
|
|
|
/// <summary>Gets a 64-bit thread context (AMD64).</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static partial bool GetThreadContext(
|
|
SafeMemoryHandle thread,
|
|
ref Context64 context);
|
|
|
|
/// <summary>Sets a 32-bit thread context (x86 or WOW64).</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static partial bool SetThreadContext(
|
|
SafeMemoryHandle thread,
|
|
ref Context32 context);
|
|
|
|
/// <summary>Gets a 32-bit thread context (x86 or WOW64).</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static partial bool GetThreadContext(
|
|
SafeMemoryHandle thread,
|
|
ref Context32 context);
|
|
|
|
|
|
// ── Modules ──────────────────────────────────────────────────────────────
|
|
|
|
/// <summary>Loads a module into the calling process.</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true, EntryPoint = "LoadLibraryW")]
|
|
internal static partial IntPtr LoadLibrary(
|
|
[MarshalAs(UnmanagedType.LPWStr)] string lpFileName);
|
|
|
|
/// <summary>Returns the address of a function or variable from a loaded module.</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
internal static partial IntPtr GetProcAddress(
|
|
IntPtr hModule,
|
|
[MarshalAs(UnmanagedType.LPStr)] string lpProcName);
|
|
|
|
/// <summary>Waits until an object is signaled or the timeout elapses. Returns a
|
|
/// <c>WAIT_*</c> status (DWORD); <c>WAIT_FAILED</c> is <c>0xFFFFFFFF</c>.</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
internal static partial uint WaitForSingleObject(
|
|
SafeMemoryHandle handle,
|
|
uint milliseconds);
|
|
|
|
// ── Memory query ───────────────────────────────────────────────────────
|
|
|
|
/// <summary>Retrieves information about a range of pages in the virtual address space of a specified process.</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
internal static partial nuint VirtualQueryEx(
|
|
SafeMemoryHandle process,
|
|
IntPtr address,
|
|
out MemoryBasicInformation buffer,
|
|
nuint length);
|
|
|
|
// ── Thread enumeration ─────────────────────────────────────────────────
|
|
|
|
/// <summary>Takes a snapshot of the specified processes, as well as the heaps, modules, and threads used by these processes.</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
internal static partial SafeMemoryHandle CreateToolhelp32Snapshot(
|
|
SnapshotFlags dwFlags,
|
|
int th32ProcessID);
|
|
|
|
/// <summary>Retrieves information about the first thread of any process encountered in a system snapshot.</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static partial bool Thread32First(
|
|
SafeMemoryHandle hSnapshot,
|
|
ref ThreadEntry32 lpte);
|
|
|
|
/// <summary>Retrieves information about the next thread of any process encountered in a system snapshot.</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static partial bool Thread32Next(
|
|
SafeMemoryHandle hSnapshot,
|
|
ref ThreadEntry32 lpte);
|
|
|
|
/// <summary>Retrieves timing information for the specified thread.</summary>
|
|
[LibraryImport("kernel32.dll", SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
internal static partial bool GetThreadTimes(
|
|
SafeMemoryHandle thread,
|
|
out long creationTime,
|
|
out long exitTime,
|
|
out long kernelTime,
|
|
out long userTime);
|
|
|
|
}
|