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.
266 lines
9.0 KiB
C#
266 lines
9.0 KiB
C#
using System.Runtime.InteropServices;
|
|
|
|
namespace WhiteMagic.Native;
|
|
|
|
/// <summary>
|
|
/// The x87 and MMX state inside a 32-bit thread context.
|
|
/// </summary>
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
public unsafe struct FloatingSaveArea32
|
|
{
|
|
/// <summary>The x87 FPU control word.</summary>
|
|
public uint ControlWord;
|
|
/// <summary>The x87 FPU status word.</summary>
|
|
public uint StatusWord;
|
|
/// <summary>The x87 FPU tag word.</summary>
|
|
public uint TagWord;
|
|
/// <summary>The offset of the instruction that caused the last FPU exception.</summary>
|
|
public uint ErrorOffset;
|
|
/// <summary>The selector of the instruction that caused the last FPU exception.</summary>
|
|
public uint ErrorSelector;
|
|
/// <summary>The offset of the operand that caused the last FPU exception.</summary>
|
|
public uint DataOffset;
|
|
/// <summary>The selector of the operand that caused the last FPU exception.</summary>
|
|
public uint DataSelector;
|
|
/// <summary>The 80-byte register area.</summary>
|
|
public fixed byte RegisterArea[80];
|
|
/// <summary>The CR0 numeric-processor-extension state.</summary>
|
|
public uint Cr0NpxState;
|
|
}
|
|
|
|
/// <summary>
|
|
/// A 32-bit x86 thread context. Use it with <c>GetThreadContext</c> and
|
|
/// <c>SetThreadContext</c> from a 32-bit process targeting a 32-bit thread.
|
|
/// The total size is 716 bytes.
|
|
/// </summary>
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
public unsafe struct Context32
|
|
{
|
|
/// <summary>Selects which parts of the context are valid. See <see cref="ContextFlags"/>.</summary>
|
|
public uint ContextFlags;
|
|
|
|
/// <summary>Debug register 0.</summary>
|
|
public uint Dr0;
|
|
/// <summary>Debug register 1.</summary>
|
|
public uint Dr1;
|
|
/// <summary>Debug register 2.</summary>
|
|
public uint Dr2;
|
|
/// <summary>Debug register 3.</summary>
|
|
public uint Dr3;
|
|
/// <summary>Debug register 6.</summary>
|
|
public uint Dr6;
|
|
/// <summary>Debug register 7.</summary>
|
|
public uint Dr7;
|
|
|
|
/// <summary>The floating-point state.</summary>
|
|
public FloatingSaveArea32 FloatSave;
|
|
|
|
/// <summary>The GS segment.</summary>
|
|
public uint SegGs;
|
|
/// <summary>The FS segment.</summary>
|
|
public uint SegFs;
|
|
/// <summary>The ES segment.</summary>
|
|
public uint SegEs;
|
|
/// <summary>The DS segment.</summary>
|
|
public uint SegDs;
|
|
|
|
/// <summary>The EDI register.</summary>
|
|
public uint Edi;
|
|
/// <summary>The ESI register.</summary>
|
|
public uint Esi;
|
|
/// <summary>The EBX register.</summary>
|
|
public uint Ebx;
|
|
/// <summary>The EDX register.</summary>
|
|
public uint Edx;
|
|
/// <summary>The ECX register.</summary>
|
|
public uint Ecx;
|
|
/// <summary>The EAX register.</summary>
|
|
public uint Eax;
|
|
|
|
/// <summary>The base (frame) pointer.</summary>
|
|
public uint Ebp;
|
|
/// <summary>The instruction pointer.</summary>
|
|
public uint Eip;
|
|
/// <summary>The CS segment.</summary>
|
|
public uint SegCs;
|
|
/// <summary>The flags register.</summary>
|
|
public uint EFlags;
|
|
/// <summary>The stack pointer.</summary>
|
|
public uint Esp;
|
|
/// <summary>The SS segment.</summary>
|
|
public uint SegSs;
|
|
|
|
/// <summary>The extended (processor-specific) registers. The size is 512 bytes.</summary>
|
|
public fixed byte ExtendedRegisters[512];
|
|
}
|
|
|
|
/// <summary>
|
|
/// A 64-bit (AMD64) thread context. Use it with the native
|
|
/// <c>GetThreadContext</c> and <c>SetThreadContext</c> from a 64-bit process.
|
|
/// The structure needs 16-byte alignment. The total size is 1232 bytes.
|
|
/// </summary>
|
|
[StructLayout(LayoutKind.Sequential, Pack = 16)]
|
|
public unsafe struct Context64
|
|
{
|
|
/// <summary>Home storage for a register parameter.</summary>
|
|
public ulong P1Home;
|
|
/// <summary>Home storage for a register parameter.</summary>
|
|
public ulong P2Home;
|
|
/// <summary>Home storage for a register parameter.</summary>
|
|
public ulong P3Home;
|
|
/// <summary>Home storage for a register parameter.</summary>
|
|
public ulong P4Home;
|
|
/// <summary>Home storage for a register parameter.</summary>
|
|
public ulong P5Home;
|
|
/// <summary>Home storage for a register parameter.</summary>
|
|
public ulong P6Home;
|
|
|
|
/// <summary>Selects which parts of the context are valid. See <see cref="ContextFlags"/>.</summary>
|
|
public uint ContextFlags;
|
|
/// <summary>The MXCSR register.</summary>
|
|
public uint MxCsr;
|
|
|
|
/// <summary>The CS segment.</summary>
|
|
public ushort SegCs;
|
|
/// <summary>The DS segment.</summary>
|
|
public ushort SegDs;
|
|
/// <summary>The ES segment.</summary>
|
|
public ushort SegEs;
|
|
/// <summary>The FS segment.</summary>
|
|
public ushort SegFs;
|
|
/// <summary>The GS segment.</summary>
|
|
public ushort SegGs;
|
|
/// <summary>The SS segment.</summary>
|
|
public ushort SegSs;
|
|
|
|
/// <summary>The flags register.</summary>
|
|
public uint EFlags;
|
|
|
|
/// <summary>Debug register 0.</summary>
|
|
public ulong Dr0;
|
|
/// <summary>Debug register 1.</summary>
|
|
public ulong Dr1;
|
|
/// <summary>Debug register 2.</summary>
|
|
public ulong Dr2;
|
|
/// <summary>Debug register 3.</summary>
|
|
public ulong Dr3;
|
|
/// <summary>Debug register 6.</summary>
|
|
public ulong Dr6;
|
|
/// <summary>Debug register 7.</summary>
|
|
public ulong Dr7;
|
|
|
|
/// <summary>The RAX register.</summary>
|
|
public ulong Rax;
|
|
/// <summary>The RCX register.</summary>
|
|
public ulong Rcx;
|
|
/// <summary>The RDX register.</summary>
|
|
public ulong Rdx;
|
|
/// <summary>The RBX register.</summary>
|
|
public ulong Rbx;
|
|
/// <summary>The stack pointer.</summary>
|
|
public ulong Rsp;
|
|
/// <summary>The base (frame) pointer.</summary>
|
|
public ulong Rbp;
|
|
/// <summary>The RSI register.</summary>
|
|
public ulong Rsi;
|
|
/// <summary>The RDI register.</summary>
|
|
public ulong Rdi;
|
|
/// <summary>The R8 register.</summary>
|
|
public ulong R8;
|
|
/// <summary>The R9 register.</summary>
|
|
public ulong R9;
|
|
/// <summary>The R10 register.</summary>
|
|
public ulong R10;
|
|
/// <summary>The R11 register.</summary>
|
|
public ulong R11;
|
|
/// <summary>The R12 register.</summary>
|
|
public ulong R12;
|
|
/// <summary>The R13 register.</summary>
|
|
public ulong R13;
|
|
/// <summary>The R14 register.</summary>
|
|
public ulong R14;
|
|
/// <summary>The R15 register.</summary>
|
|
public ulong R15;
|
|
|
|
/// <summary>The instruction pointer.</summary>
|
|
public ulong Rip;
|
|
|
|
/// <summary>The XMM save area. The size is 512 bytes.</summary>
|
|
public fixed byte FltSave[512];
|
|
|
|
/// <summary>The vector registers (26 entries of 16 bytes, stored as 52 entries of 8 bytes).</summary>
|
|
public fixed ulong VectorRegister[52];
|
|
|
|
/// <summary>The vector control register.</summary>
|
|
public ulong VectorControl;
|
|
|
|
/// <summary>The debug-control MSR.</summary>
|
|
public ulong DebugControl;
|
|
/// <summary>The target RIP of the last branch.</summary>
|
|
public ulong LastBranchToRip;
|
|
/// <summary>The source RIP of the last branch.</summary>
|
|
public ulong LastBranchFromRip;
|
|
/// <summary>The target RIP of the last exception.</summary>
|
|
public ulong LastExceptionToRip;
|
|
/// <summary>The source RIP of the last exception.</summary>
|
|
public ulong LastExceptionFromRip;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Layout matches <c>MEMORY_BASIC_INFORMATION</c>. Uses pointer-sized fields so the
|
|
/// structure is 28 bytes on x86 and 48 bytes on x64, matching the layout the OS expects
|
|
/// from a caller of those bitnesses.
|
|
/// </summary>
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
internal struct MemoryBasicInformation
|
|
{
|
|
/// <summary>A pointer to the base address of the region of pages.</summary>
|
|
public nint BaseAddress;
|
|
|
|
/// <summary>A pointer to the base address of a range of pages allocated by the VirtualAllocEx function.</summary>
|
|
public nint AllocationBase;
|
|
|
|
/// <summary>The memory protection option when the region was initially allocated.</summary>
|
|
public uint AllocationProtect;
|
|
|
|
/// <summary>The size of the region beginning at the base address, in bytes.</summary>
|
|
public nuint RegionSize;
|
|
|
|
/// <summary>The state of the pages in the region.</summary>
|
|
public uint State;
|
|
|
|
/// <summary>The access protection of the pages in the region.</summary>
|
|
public uint Protect;
|
|
|
|
/// <summary>The type of pages in the region.</summary>
|
|
public uint Type;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Layout matches <c>THREADENTRY32</c> used by <c>Thread32First</c>/<c>Thread32Next</c>.
|
|
/// </summary>
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
internal struct ThreadEntry32
|
|
{
|
|
/// <summary>The size of the structure, in bytes.</summary>
|
|
public uint dwSize;
|
|
|
|
/// <summary>This member is no longer used and is always zero.</summary>
|
|
public uint cntUsage;
|
|
|
|
/// <summary>The thread identifier.</summary>
|
|
public uint th32ThreadID;
|
|
|
|
/// <summary>The identifier of the process that owns the thread.</summary>
|
|
public uint th32OwnerProcessID;
|
|
|
|
/// <summary>The kernel base priority level assigned to the thread.</summary>
|
|
public int tpBasePri;
|
|
|
|
/// <summary>This member is no longer used.</summary>
|
|
public int tpDeltaPri;
|
|
|
|
/// <summary>This member is reserved.</summary>
|
|
public uint dwFlags;
|
|
}
|