From 017c30e107b84314ff5346f4664f19554e2f58a4 Mon Sep 17 00:00:00 2001 From: goat <16760685+goaaats@users.noreply.github.com> Date: Tue, 28 Apr 2020 01:48:36 +0200 Subject: [PATCH] feat: add handler for client send packets --- Dalamud/Game/Internal/Network/GameNetwork.cs | 97 +++++++++++++++---- .../Network/GameNetworkAddressResolver.cs | 9 +- .../Network/NetworkMessageDirection.cs | 6 ++ Dalamud/Util.cs | 46 ++++----- 4 files changed, 109 insertions(+), 49 deletions(-) create mode 100644 Dalamud/Game/Internal/Network/NetworkMessageDirection.cs diff --git a/Dalamud/Game/Internal/Network/GameNetwork.cs b/Dalamud/Game/Internal/Network/GameNetwork.cs index eb59ce2a5..384d80315 100644 --- a/Dalamud/Game/Internal/Network/GameNetwork.cs +++ b/Dalamud/Game/Internal/Network/GameNetwork.cs @@ -4,55 +4,79 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Dalamud.Hooking; using Serilog; +using SharpDX.DXGI; namespace Dalamud.Game.Internal.Network { public sealed class GameNetwork : IDisposable { - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - private delegate void ProcessZonePacketDelegate(IntPtr a, IntPtr b, IntPtr dataPtr); + #region Hooks - private readonly Hook processZonePacketHook; + [UnmanagedFunctionPointer(CallingConvention.ThisCall)] + private delegate void ProcessZonePacketDownDelegate(IntPtr a, IntPtr b, IntPtr dataPtr); + private readonly Hook processZonePacketDownHook; + + [UnmanagedFunctionPointer(CallingConvention.ThisCall)] + private delegate byte ProcessZonePacketUpDelegate(IntPtr a1, IntPtr dataPtr, IntPtr a3, byte a4); + private readonly Hook processZonePacketUpHook; + + #endregion private GameNetworkAddressResolver Address { get; } private IntPtr baseAddress; public delegate void OnZonePacketDelegate(IntPtr dataPtr); + [Obsolete("Please use OnNetworkMessage instead. For modifications, it will take precedence.")] public OnZonePacketDelegate OnZonePacket; - private readonly Dalamud dalamud; + public delegate void OnNetworkMessageDelegate(IntPtr dataPtr, NetworkMessageDirection direction); + + /// + /// Event that is called when a network message is sent/received. + /// + public OnNetworkMessageDelegate OnNetworkMessage; + + private readonly Queue zoneInjectQueue = new Queue(); - public GameNetwork(Dalamud dalamud, SigScanner scanner) { - this.dalamud = dalamud; + public GameNetwork(SigScanner scanner) { Address = new GameNetworkAddressResolver(); Address.Setup(scanner); Log.Verbose("===== G A M E N E T W O R K ====="); - Log.Verbose("ProcessZonePacket address {ProcessZonePacket}", Address.ProcessZonePacket); + Log.Verbose("ProcessZonePacketDown address {ProcessZonePacketDown}", Address.ProcessZonePacketDown); + Log.Verbose("ProcessZonePacketUp address {ProcessZonePacketUp}", Address.ProcessZonePacketUp); - this.processZonePacketHook = - new Hook(Address.ProcessZonePacket, - new ProcessZonePacketDelegate(ProcessZonePacketDetour), + this.processZonePacketDownHook = + new Hook(Address.ProcessZonePacketDown, + new ProcessZonePacketDownDelegate(ProcessZonePacketDownDetour), this); + + this.processZonePacketUpHook = + new Hook(Address.ProcessZonePacketUp, + new ProcessZonePacketUpDelegate(ProcessZonePacketUpDetour), + this); } public void Enable() { - this.processZonePacketHook.Enable(); + this.processZonePacketDownHook.Enable(); + this.processZonePacketUpHook.Enable(); } public void Dispose() { - this.processZonePacketHook.Dispose(); + this.processZonePacketDownHook.Dispose(); + this.processZonePacketUpHook.Dispose(); } - private void ProcessZonePacketDetour(IntPtr a, IntPtr b, IntPtr dataPtr) { + private void ProcessZonePacketDownDetour(IntPtr a, IntPtr b, IntPtr dataPtr) { this.baseAddress = a; - // Call events - this.OnZonePacket?.Invoke(dataPtr); - try { - this.processZonePacketHook.Original(a, b, dataPtr); + // Call events + this.OnZonePacket?.Invoke(dataPtr); + this.OnNetworkMessage?.Invoke(dataPtr, NetworkMessageDirection.ZoneDown); + + this.processZonePacketDownHook.Original(a, b, dataPtr); } catch (Exception ex) { string header; try { @@ -63,12 +87,45 @@ namespace Dalamud.Game.Internal.Network { header = "failed"; } - Log.Error(ex, "Exception on ProcessZonePacket hook. Header: " + header); + Log.Error(ex, "Exception on ProcessZonePacketDown hook. Header: " + header); - this.processZonePacketHook.Original(a, b, dataPtr); + this.processZonePacketDownHook.Original(a, b, dataPtr); } } + private byte ProcessZonePacketUpDetour(IntPtr a1, IntPtr dataPtr, IntPtr a3, byte a4) { + + try + { + // Call events + this.OnNetworkMessage?.Invoke(dataPtr, NetworkMessageDirection.ZoneUp); + + var op = Marshal.ReadInt16(dataPtr); + var length = Marshal.ReadInt16(dataPtr, 8); + + Log.Verbose("[ZONEUP] op: {0} len: {1}", op.ToString("X"), length); + Util.DumpMemory(dataPtr + 0x20, length); + } + catch (Exception ex) + { + string header; + try + { + var data = new byte[32]; + Marshal.Copy(dataPtr, data, 0, 32); + header = BitConverter.ToString(data); + } + catch (Exception) + { + header = "failed"; + } + + Log.Error(ex, "Exception on ProcessZonePacketUp hook. Header: " + header); + } + + return this.processZonePacketUpHook.Original(a1, dataPtr, a3, a4); + } + #if DEBUG public void InjectZoneProtoPacket(byte[] data) { this.zoneInjectQueue.Enqueue(data); @@ -102,7 +159,7 @@ namespace Dalamud.Game.Internal.Network { Marshal.Copy(packetData, 0, unmanagedPacketData, packetData.Length); if (this.baseAddress != IntPtr.Zero) { - this.processZonePacketHook.Original(this.baseAddress, IntPtr.Zero, unmanagedPacketData); + this.processZonePacketDownHook.Original(this.baseAddress, IntPtr.Zero, unmanagedPacketData); } Marshal.FreeHGlobal(unmanagedPacketData); diff --git a/Dalamud/Game/Internal/Network/GameNetworkAddressResolver.cs b/Dalamud/Game/Internal/Network/GameNetworkAddressResolver.cs index 09ad99ebb..dd78ea2d4 100644 --- a/Dalamud/Game/Internal/Network/GameNetworkAddressResolver.cs +++ b/Dalamud/Game/Internal/Network/GameNetworkAddressResolver.cs @@ -2,12 +2,15 @@ using System; namespace Dalamud.Game.Internal.Network { public sealed class GameNetworkAddressResolver : BaseAddressResolver { - public IntPtr ProcessZonePacket { get; private set; } - + public IntPtr ProcessZonePacketDown { get; private set; } + public IntPtr ProcessZonePacketUp { get; private set; } + protected override void Setup64Bit(SigScanner sig) { //ProcessZonePacket = sig.ScanText("48 89 74 24 18 57 48 83 EC 50 8B F2 49 8B F8 41 0F B7 50 02 8B CE E8 ?? ?? 7A FF 0F B7 57 02 8D 42 89 3D 5F 02 00 00 0F 87 60 01 00 00 4C 8D 05"); //ProcessZonePacket = sig.ScanText("48 89 74 24 18 57 48 83 EC 50 8B F2 49 8B F8 41 0F B7 50 02 8B CE E8 ?? ?? 73 FF 0F B7 57 02 8D 42 ?? 3D ?? ?? 00 00 0F 87 60 01 00 00 4C 8D 05"); - ProcessZonePacket = sig.ScanText("48 89 74 24 ?? 57 48 83 EC 50 8B FA 49 8B F0"); + ProcessZonePacketDown = sig.ScanText("48 89 74 24 ?? 57 48 83 EC 50 8B FA 49 8B F0"); + ProcessZonePacketUp = + sig.ScanText("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 56 41 57 48 83 EC 70 8B 81 ?? ?? ?? ??"); } } } diff --git a/Dalamud/Game/Internal/Network/NetworkMessageDirection.cs b/Dalamud/Game/Internal/Network/NetworkMessageDirection.cs new file mode 100644 index 000000000..0074a24de --- /dev/null +++ b/Dalamud/Game/Internal/Network/NetworkMessageDirection.cs @@ -0,0 +1,6 @@ +namespace Dalamud.Game.Internal.Network { + public enum NetworkMessageDirection { + ZoneDown, + ZoneUp + } +} diff --git a/Dalamud/Util.cs b/Dalamud/Util.cs index 8c1642c0f..36fbd92b6 100644 --- a/Dalamud/Util.cs +++ b/Dalamud/Util.cs @@ -1,19 +1,21 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; +using Serilog; -namespace Dalamud -{ - static class Util - { - public static string ByteArrayToHex(byte[] bytes, int offset = 0, int bytesPerLine = 16) - { - if (bytes == null) - { - return String.Empty; - } +namespace Dalamud { + internal static class Util { + public static void DumpMemory(IntPtr offset, int len = 512) { + var data = new byte[len]; + Marshal.Copy(offset, data, 0, len); + Log.Information(ByteArrayToHex(data)); + } + + public static string ByteArrayToHex(byte[] bytes, int offset = 0, int bytesPerLine = 16) { + if (bytes == null) return string.Empty; var hexChars = "0123456789ABCDEF".ToCharArray(); @@ -26,8 +28,7 @@ namespace Dalamud var sb = new StringBuilder(numLines * lineLength); - for (var i = 0; i < bytes.Length; i += bytesPerLine) - { + for (var i = 0; i < bytes.Length; i += bytesPerLine) { var h = i + offset; line[0] = hexChars[(h >> 28) & 0xF]; @@ -42,25 +43,18 @@ namespace Dalamud var hexColumn = offsetBlock; var charColumn = byteBlock; - for (var j = 0; j < bytesPerLine; j++) - { - if (j > 0 && (j & 7) == 0) - { - hexColumn++; - } + for (var j = 0; j < bytesPerLine; j++) { + if (j > 0 && (j & 7) == 0) hexColumn++; - if (i + j >= bytes.Length) - { + if (i + j >= bytes.Length) { line[hexColumn] = ' '; line[hexColumn + 1] = ' '; line[charColumn] = ' '; - } - else - { + } else { var by = bytes[i + j]; - line[hexColumn] = hexChars[(@by >> 4) & 0xF]; - line[hexColumn + 1] = hexChars[@by & 0xF]; - line[charColumn] = @by < 32 ? '.' : (char)@by; + line[hexColumn] = hexChars[(by >> 4) & 0xF]; + line[hexColumn + 1] = hexChars[by & 0xF]; + line[charColumn] = by < 32 ? '.' : (char) by; } hexColumn += 3;