Skip to content

Commit

Permalink
Change memory reading to 64bit
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
FelixArbeithuber committed Apr 16, 2023
1 parent 6868788 commit f4cf078
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 48 deletions.
7 changes: 6 additions & 1 deletion LeagueBroadcast.Common/Utils/ByteUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
32 changes: 14 additions & 18 deletions LeagueBroadcast.Farsight/FarsightController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LeagueBroadcast.Farsight
{
Expand Down Expand Up @@ -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<int>(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<int> toVisit = new();
HashSet<int> visited = new();
toVisit.Enqueue(buff.ToInt(GameOffsets.MapRoot));
Queue<IntPtr> toVisit = new();
HashSet<IntPtr> 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);
Expand All @@ -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;
Expand All @@ -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;
Expand Down
36 changes: 18 additions & 18 deletions LeagueBroadcast.Farsight/Memory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
Expand All @@ -50,45 +50,45 @@ public static IntPtr GetModuleAddress(string ModuleName)
return new IntPtr(-1);
}

public static T ReadMemory<T>(int Address) where T : struct
public static T ReadMemory<T>(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<T>(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<T>(int Address, int MatrixSize) where T : struct
public static float[] ReadMatrix<T>(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<T>(int Address, object Value)
public static void WriteMemory<T>(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<T>(int Address, char[] Value)
public static void WriteMemory<T>(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
Expand Down Expand Up @@ -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

Expand All @@ -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
Expand Down
34 changes: 26 additions & 8 deletions LeagueBroadcast.Farsight/Object/GameObject.cs
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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())
Expand All @@ -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}");
}

Expand Down Expand Up @@ -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;
}
}

Expand Down
2 changes: 0 additions & 2 deletions LeagueBroadcast.Farsight/Snapshot.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using LeagueBroadcast.Farsight.Object;
using System;
using System.Collections.Generic;
using System.Text;

namespace LeagueBroadcast.Farsight
{
Expand Down
2 changes: 1 addition & 1 deletion Offsets/Offsets-13.7.1.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@
"Name": "0x38a0",
"NameLength": "0x38b0"
},
"FileVersion": "1.0"
"FileVersion": "2.0"
}

0 comments on commit f4cf078

Please sign in to comment.