Compare commits
2 Commits
ptr-crash
...
ptr-guard-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
20dd95c75c | ||
|
|
0808dae4f1 |
@@ -127,7 +127,7 @@ public class PlayerDataFactory
|
||||
{
|
||||
nint basePtr = playerPointer;
|
||||
|
||||
if (!PtrGuard.LooksLikePtr(basePtr))
|
||||
if (!PtrGuard.LooksLikePtr(basePtr, _dalamudUtil.IsWine))
|
||||
return true;
|
||||
|
||||
nint drawObjAddr = basePtr + _drawObjectOffset;
|
||||
@@ -135,10 +135,10 @@ public class PlayerDataFactory
|
||||
if (!PtrGuard.IsReadable(drawObjAddr, (nuint)IntPtr.Size))
|
||||
return true;
|
||||
|
||||
if (!PtrGuard.TryReadIntPtr(drawObjAddr, out var drawObj))
|
||||
if (!PtrGuard.TryReadIntPtr(drawObjAddr, _dalamudUtil.IsWine, out var drawObj))
|
||||
return true;
|
||||
|
||||
if (drawObj != 0 && !PtrGuard.LooksLikePtr(drawObj))
|
||||
if (drawObj != 0 && !PtrGuard.LooksLikePtr(drawObj, _dalamudUtil.IsWine))
|
||||
return true;
|
||||
|
||||
return drawObj == 0;
|
||||
|
||||
@@ -174,85 +174,65 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase, IHighP
|
||||
|
||||
private unsafe void CheckAndUpdateObject(bool allowPublish)
|
||||
{
|
||||
try
|
||||
var prevAddr = Address;
|
||||
var prevDrawObj = DrawObjectAddress;
|
||||
string? nameString = null;
|
||||
|
||||
var nextAddr = _getAddress();
|
||||
|
||||
if (nextAddr != IntPtr.Zero && !PtrGuard.LooksLikePtr(nextAddr, _dalamudUtil.IsWine))
|
||||
{
|
||||
var prevAddr = Address;
|
||||
var prevDrawObj = DrawObjectAddress;
|
||||
string? nameString = null;
|
||||
nextAddr = IntPtr.Zero;
|
||||
}
|
||||
|
||||
var nextAddr = _getAddress();
|
||||
if (nextAddr != IntPtr.Zero &&
|
||||
!PtrGuard.IsReadable(nextAddr, (nuint)sizeof(FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject)))
|
||||
{
|
||||
nextAddr = IntPtr.Zero;
|
||||
}
|
||||
|
||||
if (nextAddr != IntPtr.Zero && !PtrGuard.LooksLikePtr(nextAddr))
|
||||
Address = nextAddr;
|
||||
|
||||
if (Address != IntPtr.Zero)
|
||||
{
|
||||
var gameObject = (FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)Address;
|
||||
|
||||
var draw = (nint)gameObject->DrawObject;
|
||||
|
||||
if (!PtrGuard.LooksLikePtr(draw, _dalamudUtil.IsWine) || !PtrGuard.IsReadable(draw, (nuint)sizeof(DrawObject)))
|
||||
draw = 0;
|
||||
|
||||
DrawObjectAddress = draw;
|
||||
EntityId = gameObject->EntityId;
|
||||
|
||||
if (PtrGuard.IsReadable(Address, (nuint)sizeof(Character)))
|
||||
{
|
||||
nextAddr = IntPtr.Zero;
|
||||
var chara = (Character*)Address;
|
||||
nameString = chara->GameObject.NameString;
|
||||
|
||||
if (!string.IsNullOrEmpty(nameString) && !string.Equals(nameString, Name, StringComparison.Ordinal))
|
||||
Name = nameString;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawObjectAddress = IntPtr.Zero;
|
||||
EntityId = uint.MaxValue;
|
||||
}
|
||||
|
||||
if (nextAddr != IntPtr.Zero &&
|
||||
!PtrGuard.IsReadable(nextAddr, (nuint)sizeof(FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject)))
|
||||
{
|
||||
nextAddr = IntPtr.Zero;
|
||||
}
|
||||
CurrentDrawCondition = (Address != IntPtr.Zero && DrawObjectAddress != IntPtr.Zero)
|
||||
? IsBeingDrawnUnsafe()
|
||||
: DrawCondition.DrawObjectZero;
|
||||
|
||||
Address = nextAddr;
|
||||
if (_haltProcessing || !allowPublish) return;
|
||||
|
||||
if (Address != IntPtr.Zero)
|
||||
{
|
||||
var gameObject = (FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)Address;
|
||||
|
||||
var draw = (nint)gameObject->DrawObject;
|
||||
|
||||
if (!PtrGuard.LooksLikePtr(draw) || !PtrGuard.IsReadable(draw, (nuint)sizeof(DrawObject)))
|
||||
draw = 0;
|
||||
|
||||
DrawObjectAddress = draw;
|
||||
EntityId = gameObject->EntityId;
|
||||
|
||||
if (PtrGuard.IsReadable(Address, (nuint)sizeof(Character)))
|
||||
{
|
||||
var chara = (Character*)Address;
|
||||
nameString = chara->GameObject.NameString;
|
||||
|
||||
if (!string.IsNullOrEmpty(nameString) && !string.Equals(nameString, Name, StringComparison.Ordinal))
|
||||
Name = nameString;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DrawObjectAddress = IntPtr.Zero;
|
||||
EntityId = uint.MaxValue;
|
||||
}
|
||||
|
||||
CurrentDrawCondition = (Address != IntPtr.Zero && DrawObjectAddress != IntPtr.Zero)
|
||||
? IsBeingDrawnUnsafe()
|
||||
: DrawCondition.DrawObjectZero;
|
||||
|
||||
if (_haltProcessing || !allowPublish) return;
|
||||
|
||||
bool drawObjDiff = DrawObjectAddress != prevDrawObj;
|
||||
bool addrDiff = Address != prevAddr;
|
||||
|
||||
if (Address == IntPtr.Zero || DrawObjectAddress == IntPtr.Zero)
|
||||
{
|
||||
if (addrDiff || drawObjDiff)
|
||||
{
|
||||
CurrentDrawCondition = DrawCondition.DrawObjectZero;
|
||||
Logger.LogTrace("[{this}] Changed", this);
|
||||
if (_isOwnedObject && ObjectKind != ObjectKind.Player)
|
||||
Mediator.Publish(new ClearCacheForObjectMessage(this));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!PtrGuard.IsReadable(Address, (nuint)sizeof(Character)) ||
|
||||
!PtrGuard.IsReadable(DrawObjectAddress, (nuint)sizeof(DrawObject)))
|
||||
{
|
||||
Logger.LogTrace("[{this}] Pointers became invalid during update", this);
|
||||
Address = IntPtr.Zero;
|
||||
DrawObjectAddress = IntPtr.Zero;
|
||||
CurrentDrawCondition = DrawCondition.DrawObjectZero;
|
||||
return;
|
||||
}
|
||||
bool drawObjDiff = DrawObjectAddress != prevDrawObj;
|
||||
bool addrDiff = Address != prevAddr;
|
||||
|
||||
if (Address != IntPtr.Zero && DrawObjectAddress != IntPtr.Zero
|
||||
&& PtrGuard.IsReadable(Address, (nuint)sizeof(Character))
|
||||
&& PtrGuard.IsReadable(DrawObjectAddress, (nuint)sizeof(DrawObject)))
|
||||
{
|
||||
var chara = (Character*)Address;
|
||||
var drawObj = (DrawObject*)DrawObjectAddress;
|
||||
|
||||
@@ -335,11 +315,12 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase, IHighP
|
||||
Mediator.Publish(new CreateCacheForObjectMessage(this));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
else if (addrDiff || drawObjDiff)
|
||||
{
|
||||
Address = IntPtr.Zero;
|
||||
DrawObjectAddress = IntPtr.Zero;
|
||||
CurrentDrawCondition = DrawCondition.DrawObjectZero;
|
||||
Logger.LogTrace("[{this}] Changed", this);
|
||||
if (_isOwnedObject && ObjectKind != ObjectKind.Player)
|
||||
Mediator.Publish(new ClearCacheForObjectMessage(this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,7 +361,7 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase, IHighP
|
||||
private unsafe bool CompareAndUpdateMainHand(Weapon* weapon)
|
||||
{
|
||||
var p = (nint)weapon;
|
||||
if (!PtrGuard.LooksLikePtr(p) || !PtrGuard.IsReadable(p, (nuint)sizeof(Weapon)))
|
||||
if (!PtrGuard.LooksLikePtr(p, _dalamudUtil.IsWine) || !PtrGuard.IsReadable(p, (nuint)sizeof(Weapon)))
|
||||
return false;
|
||||
|
||||
bool hasChanges = false;
|
||||
@@ -396,7 +377,7 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase, IHighP
|
||||
private unsafe bool CompareAndUpdateOffHand(Weapon* weapon)
|
||||
{
|
||||
var p = (nint)weapon;
|
||||
if (!PtrGuard.LooksLikePtr(p) || !PtrGuard.IsReadable(p, (nuint)sizeof(Weapon)))
|
||||
if (!PtrGuard.LooksLikePtr(p, _dalamudUtil.IsWine) || !PtrGuard.IsReadable(p, (nuint)sizeof(Weapon)))
|
||||
return false;
|
||||
|
||||
bool hasChanges = false;
|
||||
@@ -462,18 +443,11 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase, IHighP
|
||||
{
|
||||
if (Address == IntPtr.Zero) return DrawCondition.ObjectZero;
|
||||
if (DrawObjectAddress == IntPtr.Zero) return DrawCondition.DrawObjectZero;
|
||||
|
||||
if (!PtrGuard.IsReadable(Address, (nuint)sizeof(FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject)))
|
||||
return DrawCondition.ObjectZero;
|
||||
|
||||
var visibilityFlags = ((FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)Address)->RenderFlags;
|
||||
if (visibilityFlags != VisibilityFlags.None) return DrawCondition.RenderFlags;
|
||||
|
||||
if (ObjectKind == ObjectKind.Player)
|
||||
{
|
||||
if (!PtrGuard.IsReadable(DrawObjectAddress, (nuint)sizeof(CharacterBase)))
|
||||
return DrawCondition.DrawObjectZero;
|
||||
|
||||
var modelInSlotLoaded = (((CharacterBase*)DrawObjectAddress)->HasModelInSlotLoaded != 0);
|
||||
if (modelInSlotLoaded) return DrawCondition.ModelInSlotLoaded;
|
||||
var modelFilesInSlotLoaded = (((CharacterBase*)DrawObjectAddress)->HasModelFilesInSlotLoaded != 0);
|
||||
|
||||
@@ -5,40 +5,41 @@ namespace LightlessSync.Utils
|
||||
{
|
||||
public static partial class PtrGuard
|
||||
{
|
||||
private const ulong _aligmentPtr = 0x7UL;
|
||||
private static readonly nuint _minAppAddr = (nuint)GetMinAppAddr();
|
||||
private static readonly nuint _maxAppAddr = (nuint)GetMaxAppAddr();
|
||||
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 nint GetMinAppAddr()
|
||||
private static readonly (nuint min, nuint max) _sysRange = GetSysRange();
|
||||
|
||||
private static (nuint min, nuint max) GetSysRange()
|
||||
{
|
||||
GetSystemInfo(out var si);
|
||||
return si.lpMinimumApplicationAddress;
|
||||
return ((nuint)si.lpMinimumApplicationAddress, (nuint)si.lpMaximumApplicationAddress);
|
||||
}
|
||||
|
||||
private static nint GetMaxAppAddr()
|
||||
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)
|
||||
{
|
||||
GetSystemInfo(out var si);
|
||||
return si.lpMaximumApplicationAddress;
|
||||
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 LooksLikePtr(nint p)
|
||||
{
|
||||
if (p == 0) return false;
|
||||
nuint u = (nuint)p;
|
||||
|
||||
if (u < _minAppAddr) return false;
|
||||
if (u > _maxAppAddr) return false;
|
||||
if ((u & _aligmentPtr) != 0) return false;
|
||||
if ((uint)u == 0x12345679u) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool TryReadIntPtr(nint addr, out nint value)
|
||||
public static bool TryReadIntPtr(nint addr, bool isWine, out nint value)
|
||||
{
|
||||
value = 0;
|
||||
|
||||
if (!LooksLikePtr(addr))
|
||||
if (!LooksLikePtr(addr, isWine))
|
||||
return false;
|
||||
|
||||
return ReadProcessMemory(GetCurrentProcess(), addr, out value, (nuint)IntPtr.Size, out nuint bytesRead)
|
||||
@@ -49,7 +50,7 @@ namespace LightlessSync.Utils
|
||||
{
|
||||
if (addr == 0 || size == 0) return false;
|
||||
|
||||
if (VirtualQuery(addr, out var mbi, (nuint)Marshal.SizeOf<MEMORY_BASIC_INFORMATION>()) == 0)
|
||||
if (VirtualQuery(addr, out var mbi, (nuint)Marshal.SizeOf<MemoryBasicInformation>()) == 0)
|
||||
return false;
|
||||
|
||||
const uint Commit = 0x1000;
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace LightlessSync.Utils
|
||||
internal static class PtrGuardMemory
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct MEMORY_BASIC_INFORMATION
|
||||
internal struct MemoryBasicInformation
|
||||
{
|
||||
public nint BaseAddress;
|
||||
public nint AllocationBase;
|
||||
@@ -19,7 +19,7 @@ namespace LightlessSync.Utils
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
internal static extern nuint VirtualQuery(
|
||||
nint lpAddress,
|
||||
out MEMORY_BASIC_INFORMATION lpBuffer,
|
||||
out MemoryBasicInformation lpBuffer,
|
||||
nuint dwLength);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
@@ -34,10 +34,10 @@ namespace LightlessSync.Utils
|
||||
internal static extern nint GetCurrentProcess();
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
internal static extern void GetSystemInfo(out SYSTEM_INFO lpSystemInfo);
|
||||
internal static extern void GetSystemInfo(out SystemInfo lpSystemInfo);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct SYSTEM_INFO
|
||||
internal struct SystemInfo
|
||||
{
|
||||
public ushort wProcessorArchitecture;
|
||||
public ushort wReserved;
|
||||
|
||||
Reference in New Issue
Block a user