mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
feat: add handler for client send packets
This commit is contained in:
parent
bd2e5cda2a
commit
017c30e107
4 changed files with 109 additions and 49 deletions
|
|
@ -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<ProcessZonePacketDelegate> processZonePacketHook;
|
||||
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
|
||||
private delegate void ProcessZonePacketDownDelegate(IntPtr a, IntPtr b, IntPtr dataPtr);
|
||||
private readonly Hook<ProcessZonePacketDownDelegate> processZonePacketDownHook;
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
|
||||
private delegate byte ProcessZonePacketUpDelegate(IntPtr a1, IntPtr dataPtr, IntPtr a3, byte a4);
|
||||
private readonly Hook<ProcessZonePacketUpDelegate> 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);
|
||||
|
||||
/// <summary>
|
||||
/// Event that is called when a network message is sent/received.
|
||||
/// </summary>
|
||||
public OnNetworkMessageDelegate OnNetworkMessage;
|
||||
|
||||
|
||||
|
||||
private readonly Queue<byte[]> zoneInjectQueue = new Queue<byte[]>();
|
||||
|
||||
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<ProcessZonePacketDelegate>(Address.ProcessZonePacket,
|
||||
new ProcessZonePacketDelegate(ProcessZonePacketDetour),
|
||||
this.processZonePacketDownHook =
|
||||
new Hook<ProcessZonePacketDownDelegate>(Address.ProcessZonePacketDown,
|
||||
new ProcessZonePacketDownDelegate(ProcessZonePacketDownDetour),
|
||||
this);
|
||||
|
||||
this.processZonePacketUpHook =
|
||||
new Hook<ProcessZonePacketUpDelegate>(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);
|
||||
|
|
|
|||
|
|
@ -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 ?? ?? ?? ??");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
6
Dalamud/Game/Internal/Network/NetworkMessageDirection.cs
Normal file
6
Dalamud/Game/Internal/Network/NetworkMessageDirection.cs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
namespace Dalamud.Game.Internal.Network {
|
||||
public enum NetworkMessageDirection {
|
||||
ZoneDown,
|
||||
ZoneUp
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue