From f4cf07861d1e81b06bb379376e431ea773f9cdcf Mon Sep 17 00:00:00 2001 From: FX Date: Sun, 16 Apr 2023 14:49:52 +0200 Subject: [PATCH] Change memory reading to 64bit Changed pointers to IntPtr to fit 64bit. The offsets stay as Int32 because because all of the offsets still fit in Int32 and you can add Int32 to IntPtr easier than Int64. Also added offsets file for patch 13.7.1. There are new "Level" and "NameLength" offsets. The GameObject.Name is now also a packed String but it doesn't exist for some GameObjects (handled by special NameLength check that defaults to an empty name). Since the biggest offset is now "Level" instead of "EXP" the GameObject buffer size had to be adjusted to "Level" + sizeof(int). --- LeagueBroadcast.Common/Utils/ByteUtils.cs | 7 +++- .../FarsightController.cs | 32 ++++++++--------- LeagueBroadcast.Farsight/Memory.cs | 36 +++++++++---------- LeagueBroadcast.Farsight/Object/GameObject.cs | 34 +++++++++++++----- LeagueBroadcast.Farsight/Snapshot.cs | 2 -- Offsets/Offsets-13.7.1.json | 2 +- 6 files changed, 65 insertions(+), 48 deletions(-) diff --git a/LeagueBroadcast.Common/Utils/ByteUtils.cs b/LeagueBroadcast.Common/Utils/ByteUtils.cs index 3e0fd31..3f520f9 100644 --- a/LeagueBroadcast.Common/Utils/ByteUtils.cs +++ b/LeagueBroadcast.Common/Utils/ByteUtils.cs @@ -13,7 +13,12 @@ public static byte[] GetSubArray(this byte[] source, int offset, int size) return res; } - public static int ToInt(this byte[] source, int offset = 0) + public static IntPtr ToIntPtr(this byte[] source, int offset = 0) + { + return new IntPtr(BitConverter.ToInt64(source, offset)); + } + + public static int ToInt(this byte[] source, int offset = 0) { return BitConverter.ToInt32(source, offset); } diff --git a/LeagueBroadcast.Farsight/FarsightController.cs b/LeagueBroadcast.Farsight/FarsightController.cs index 19fe623..a696e16 100644 --- a/LeagueBroadcast.Farsight/FarsightController.cs +++ b/LeagueBroadcast.Farsight/FarsightController.cs @@ -7,8 +7,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace LeagueBroadcast.Farsight { @@ -69,37 +67,35 @@ public Snapshot CreateSnapshot(double gameTime = 0) private void ReadObjects(Snapshot snap) { int maxObjects = 500; - int[] pointers = new int[maxObjects]; + IntPtr[] pointers = new IntPtr[maxObjects]; byte[] buff = new byte[500]; - int objectManager = Memory.ReadMemory(Memory.m_baseAddress + GameOffsets.Manager); + IntPtr objectManager = Memory.ReadMemory(Memory.m_baseAddress + GameOffsets.Manager, 8).ToIntPtr(); Array.Copy(Memory.ReadMemory(objectManager, 100), 0, buff, 0, 100); - Queue toVisit = new(); - HashSet visited = new(); - toVisit.Enqueue(buff.ToInt(GameOffsets.MapRoot)); + Queue toVisit = new(); + HashSet visited = new(); + toVisit.Enqueue(buff.ToIntPtr(GameOffsets.MapRoot)); int objNr = 0; int read = 0; - int child1, child2, child3, node; + IntPtr child1, child2, child3, node; while(read < maxObjects && toVisit.Count > 0) { node = toVisit.Dequeue(); if(visited.Contains(node)) - { continue; - } read++; visited.Add(node); - buff.Write(Memory.ReadMemory(node, 0x30)); - child1 = buff.ToInt(0); - child2 = buff.ToInt(4); - child3 = buff.ToInt(8); + buff.Write(Memory.ReadMemory(node, 0x50)); + child1 = buff.ToIntPtr(0); + child2 = buff.ToIntPtr(8); + child3 = buff.ToIntPtr(16); toVisit.Enqueue(child1); toVisit.Enqueue(child2); @@ -110,8 +106,8 @@ private void ReadObjects(Snapshot snap) if (netID - 0x40000000 > 0x100000) continue; - int addr = buff.ToInt(GameOffsets.MapNodeObject); - if (addr == 0) + IntPtr addr = buff.ToIntPtr(GameOffsets.MapNodeObject); + if (addr == IntPtr.Zero) continue; pointers[objNr++] = addr; @@ -127,12 +123,12 @@ private void ReadObjects(Snapshot snap) if(!snap.ObjectMap.ContainsKey(netID)) { obj = new(); - obj.LoadFromMemory(pointers[i], ObjectOffsets.EXP + 0x4); + obj.LoadFromMemory(pointers[i], ObjectOffsets.Level + 0x4); snap.ObjectMap.Add(netID, obj); } else { obj = snap.ObjectMap[netID]; - obj.LoadFromMemory(pointers[i], ObjectOffsets.EXP + 0x4); + obj.LoadFromMemory(pointers[i], ObjectOffsets.Level + 0x4); if (netID != obj.NetworkID) snap.ObjectMap[obj.NetworkID] = obj; diff --git a/LeagueBroadcast.Farsight/Memory.cs b/LeagueBroadcast.Farsight/Memory.cs index c6b8da7..7048481 100644 --- a/LeagueBroadcast.Farsight/Memory.cs +++ b/LeagueBroadcast.Farsight/Memory.cs @@ -15,7 +15,7 @@ public class Memory public static int m_iNumberOfBytesRead = 0; public static int m_iNumberOfBytesWritten = 0; - public static int m_baseAddress = 0; + public static IntPtr m_baseAddress = IntPtr.Zero; public static bool IsConnected => m_pProcessHandle != (IntPtr)0; @@ -26,7 +26,7 @@ public static bool Initialize(Process p ) m_pProcessHandle = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, false, m_Process.Id); // Sets Our ProcessHandle m_Process.Exited += (s, e) => { m_Process = null; m_pProcessHandle = (IntPtr)0; m_iNumberOfBytesRead = 0; m_iNumberOfBytesWritten = 0; }; - m_baseAddress = m_Process.MainModule.BaseAddress.ToInt32(); + m_baseAddress = m_Process.MainModule.BaseAddress; Log.Verbose("Attached to League Process"); return true; @@ -50,45 +50,45 @@ public static IntPtr GetModuleAddress(string ModuleName) return new IntPtr(-1); } - public static T ReadMemory(int Address) where T : struct + public static T ReadMemory(IntPtr Address) where T : struct { int ByteSize = Marshal.SizeOf(typeof(T)); // Get ByteSize Of DataType byte[] buffer = new byte[ByteSize]; // Create A Buffer With Size Of ByteSize - ReadProcessMemory((int)m_pProcessHandle, Address, buffer, buffer.Length, ref m_iNumberOfBytesRead); // Read Value From Memory + ReadProcessMemory(m_pProcessHandle, Address, buffer, buffer.Length, ref m_iNumberOfBytesRead); // Read Value From Memory return ByteArrayToStructure(buffer); // Transform the ByteArray to The Desired DataType } - public static byte[] ReadMemory(int Address, int size) + public static byte[] ReadMemory(IntPtr Address, int size) { var buffer = new byte[size]; - ReadProcessMemory((int)m_pProcessHandle, Address, buffer, size, ref m_iNumberOfBytesRead); + ReadProcessMemory(m_pProcessHandle, Address, buffer, size, ref m_iNumberOfBytesRead); return buffer; } - public static float[] ReadMatrix(int Address, int MatrixSize) where T : struct + public static float[] ReadMatrix(IntPtr Address, int MatrixSize) where T : struct { int ByteSize = Marshal.SizeOf(typeof(T)); byte[] buffer = new byte[ByteSize * MatrixSize]; // Create A Buffer With Size Of ByteSize * MatrixSize - ReadProcessMemory((int)m_pProcessHandle, Address, buffer, buffer.Length, ref m_iNumberOfBytesRead); + ReadProcessMemory(m_pProcessHandle, Address, buffer, buffer.Length, ref m_iNumberOfBytesRead); return ConvertToFloatArray(buffer); // Transform the ByteArray to A Float Array (PseudoMatrix ;P) } - public static void WriteMemory(int Address, object Value) + public static void WriteMemory(IntPtr Address, object Value) { byte[] buffer = StructureToByteArray(Value); // Transform Data To ByteArray - WriteProcessMemory((int)m_pProcessHandle, Address, buffer, buffer.Length, out m_iNumberOfBytesWritten); + WriteProcessMemory(m_pProcessHandle, Address, buffer, buffer.Length, out m_iNumberOfBytesWritten); } - public static void WriteMemory(int Address, char[] Value) + public static void WriteMemory(IntPtr Address, char[] Value) { byte[] buffer = Encoding.UTF8.GetBytes(Value); - WriteProcessMemory((int)m_pProcessHandle, Address, buffer, buffer.Length, out m_iNumberOfBytesWritten); + WriteProcessMemory(m_pProcessHandle, Address, buffer, buffer.Length, out m_iNumberOfBytesWritten); } #region Transformation @@ -133,12 +133,12 @@ private static byte[] StructureToByteArray(object obj) return arr; } - public static int GetChampionObjectSize(int Address) + public static int GetChampionObjectSize(IntPtr Address) { var res = new MEMORY_BASIC_INFORMATION(); - VirtualQueryEx((int)m_pProcessHandle, Address, out res, Convert.ToUInt32(Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION)))); + VirtualQueryEx(m_pProcessHandle, Address, out res, Convert.ToUInt32(Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION)))); Log.Verbose("Champ region size:" + res.RegionSize); - return res.RegionSize > 0? res.RegionSize : 0x3A00; + return res.RegionSize > 0 ? res.RegionSize : 0x3A00; } #endregion @@ -148,13 +148,13 @@ public static int GetChampionObjectSize(int Address) private static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); [DllImport("kernel32.dll")] - private static extern bool ReadProcessMemory(int hProcess, int lpBaseAddress, byte[] buffer, int size, ref int lpNumberOfBytesRead); + private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] buffer, int size, ref int lpNumberOfBytesRead); [DllImport("kernel32.dll")] - private static extern bool WriteProcessMemory(int hProcess, int lpBaseAddress, byte[] buffer, int size, out int lpNumberOfBytesWritten); + private static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] buffer, int size, out int lpNumberOfBytesWritten); [DllImport("kernel32.dll")] - static extern int VirtualQueryEx(int hProcess, int lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, uint dwLength); + static extern int VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, uint dwLength); #endregion #region Constants diff --git a/LeagueBroadcast.Farsight/Object/GameObject.cs b/LeagueBroadcast.Farsight/Object/GameObject.cs index 7cf7a0d..835c87e 100644 --- a/LeagueBroadcast.Farsight/Object/GameObject.cs +++ b/LeagueBroadcast.Farsight/Object/GameObject.cs @@ -1,10 +1,7 @@ using LeagueBroadcast.Common; -using LeagueBroadcast.Common.Data.DTO; -using LeagueBroadcast.Common.Data.RIOT; using LeagueBroadcast.Common.Utils; using Newtonsoft.Json; using System; -using System.Linq; using System.Numerics; using System.Text; @@ -31,7 +28,7 @@ public class GameObject public float EXP; public int Level; - public void LoadFromMemory(int baseAdr, int buffSize = 0x3600) + public void LoadFromMemory(IntPtr baseAdr, int buffSize = 0x4100) { //TODO Make VirtualQueryEx functional, currently always returns 0. If buff size every becomes a problem again, actually fix this if (buffSize == 0x0) @@ -45,13 +42,28 @@ public void LoadFromMemory(int baseAdr, int buffSize = 0x3600) mem.ToFloat(FarsightController.ObjectOffsets.Pos), mem.ToFloat(FarsightController.ObjectOffsets.Pos + 4), mem.ToFloat(FarsightController.ObjectOffsets.Pos + 8) - ); + ); Health = BitConverter.ToSingle(mem, FarsightController.ObjectOffsets.Health); MaxHealth = mem.ToFloat(FarsightController.ObjectOffsets.MaxHealth); Mana = mem.ToFloat(FarsightController.ObjectOffsets.Mana); MaxMana = mem.ToFloat(FarsightController.ObjectOffsets.MaxMana); NetworkID = mem.ToInt(FarsightController.ObjectOffsets.NetworkID); - Name = Memory.ReadMemory(Memory.ReadMemory(baseAdr + FarsightController.ObjectOffsets.Name, 4).ToInt(), 50).DecodeAscii(); + + //Name = Memory.ReadMemory(Memory.ReadMemory(baseAdr + FarsightController.ObjectOffsets.Name, 8).ToIntPtr(), 50).DecodeAscii(); + + int nameLength = mem.ToInt(FarsightController.ObjectOffsets.NameLength); + if (nameLength <= 0 || nameLength > 100) + { + Name = ""; + } + else if (nameLength < 16) + { + Name = Encoding.UTF8.GetString(mem.SubArray(FarsightController.ObjectOffsets.Name, nameLength)); + } + else if (nameLength > 0) + { + Name = Encoding.UTF8.GetString(Memory.ReadMemory(mem.ToIntPtr(FarsightController.ObjectOffsets.Name), nameLength)); + } int displayNameLength = mem.ToInt(FarsightController.ObjectOffsets.DisplayNameLength); if (displayNameLength < 16) @@ -60,7 +72,7 @@ public void LoadFromMemory(int baseAdr, int buffSize = 0x3600) } else { - DisplayName = Encoding.UTF8.GetString(Memory.ReadMemory(mem.ToInt(FarsightController.ObjectOffsets.DisplayName), displayNameLength)); + DisplayName = Encoding.UTF8.GetString(Memory.ReadMemory(mem.ToIntPtr(FarsightController.ObjectOffsets.DisplayName), displayNameLength)); } if (IsChampion()) @@ -74,7 +86,7 @@ public void LoadChampFromMemory(byte[] source) CurrentGold = source.ToFloat(FarsightController.ObjectOffsets.CurrentGold); GoldTotal = source.ToFloat(FarsightController.ObjectOffsets.GoldTotal); EXP = source.ToFloat(FarsightController.ObjectOffsets.EXP); - Level = ChampionLevel.EXPToLevel(EXP); + Level = source.ToInt(FarsightController.ObjectOffsets.Level); Log.Verbose($"{Name} Gold: {CurrentGold}/{GoldTotal}, Exp:{EXP}/{Level}"); } @@ -143,8 +155,14 @@ public class Offsets [JsonConverter(typeof(HexStringJsonConverter))] public int EXP; + [JsonConverter(typeof(HexStringJsonConverter))] + public int Level; + [JsonConverter(typeof(HexStringJsonConverter))] public int Name; + + [JsonConverter(typeof(HexStringJsonConverter))] + public int NameLength; } } diff --git a/LeagueBroadcast.Farsight/Snapshot.cs b/LeagueBroadcast.Farsight/Snapshot.cs index 0bfb15e..07b25cc 100644 --- a/LeagueBroadcast.Farsight/Snapshot.cs +++ b/LeagueBroadcast.Farsight/Snapshot.cs @@ -1,7 +1,5 @@ using LeagueBroadcast.Farsight.Object; -using System; using System.Collections.Generic; -using System.Text; namespace LeagueBroadcast.Farsight { diff --git a/Offsets/Offsets-13.7.1.json b/Offsets/Offsets-13.7.1.json index e2f14fb..8c02907 100644 --- a/Offsets/Offsets-13.7.1.json +++ b/Offsets/Offsets-13.7.1.json @@ -25,5 +25,5 @@ "Name": "0x38a0", "NameLength": "0x38b0" }, - "FileVersion": "1.0" + "FileVersion": "2.0" }