72 lines
2.5 KiB
C#
72 lines
2.5 KiB
C#
using System.Runtime.InteropServices;
|
|
using static LightlessSync.Utils.PtrGuardMemory;
|
|
|
|
namespace LightlessSync.Utils
|
|
{
|
|
public static partial class PtrGuard
|
|
{
|
|
private static readonly nuint _hardMinWindows =
|
|
(nuint)(IntPtr.Size == 8 ? 0x0000000100000000UL : 0x0000000000010000UL);
|
|
private static readonly nuint _hardMaxWindows =
|
|
(nuint)(IntPtr.Size == 8 ? 0x00007FFFFFFFFFFFUL : 0x7FFFFFFFUL);
|
|
private const nuint _alignmentPtr = 0x7;
|
|
|
|
private static readonly (nuint min, nuint max) _sysRange = GetSysRange();
|
|
|
|
private static (nuint min, nuint max) GetSysRange()
|
|
{
|
|
GetSystemInfo(out var si);
|
|
return ((nuint)si.lpMinimumApplicationAddress, (nuint)si.lpMaximumApplicationAddress);
|
|
}
|
|
|
|
private static nuint GetMinAppAddr(bool isWine) => isWine ? _sysRange.min : _hardMinWindows;
|
|
private static nuint GetMaxAppAddr(bool isWine) => isWine ? _sysRange.max : _hardMaxWindows;
|
|
|
|
public static bool LooksLikePtr(nint p, bool isWine = false)
|
|
{
|
|
if (p == 0) return false;
|
|
nuint u = (nuint)p;
|
|
|
|
if (u < GetMinAppAddr(isWine)) return false;
|
|
if (u > GetMaxAppAddr(isWine)) return false;
|
|
if ((u & _alignmentPtr) != 0) return false;
|
|
if ((uint)u == 0x12345679u) return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
public static bool TryReadIntPtr(nint addr, bool isWine, out nint value)
|
|
{
|
|
value = 0;
|
|
|
|
if (!LooksLikePtr(addr, isWine))
|
|
return false;
|
|
|
|
return ReadProcessMemory(GetCurrentProcess(), addr, out value, (nuint)IntPtr.Size, out nuint bytesRead)
|
|
&& bytesRead == (nuint)IntPtr.Size;
|
|
}
|
|
|
|
public static bool IsReadable(nint addr, nuint size)
|
|
{
|
|
if (addr == 0 || size == 0) return false;
|
|
|
|
if (VirtualQuery(addr, out var mbi, (nuint)Marshal.SizeOf<MemoryBasicInformation>()) == 0)
|
|
return false;
|
|
|
|
const uint Commit = 0x1000;
|
|
const uint NoAccess = 0x01;
|
|
const uint PageGuard = 0x100;
|
|
|
|
if (mbi.State != Commit) return false;
|
|
if ((mbi.Protect & PageGuard) != 0) return false;
|
|
if (mbi.Protect == NoAccess) return false;
|
|
|
|
ulong start = (ulong)addr;
|
|
ulong end = start + size - 1;
|
|
ulong r0 = (ulong)mbi.BaseAddress;
|
|
ulong r1 = r0 + mbi.RegionSize - 1;
|
|
|
|
return start >= r0 && end <= r1;
|
|
}
|
|
}
|
|
} |