Files
LightlessClient/LightlessSync/Utils/PtrGuard.cs
2026-01-22 02:46:49 +01:00

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;
}
}
}