mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
feat: switch framework hooks from vtable to sigs
This commit is contained in:
parent
92518e22b0
commit
3397b608d0
8 changed files with 21 additions and 94 deletions
|
|
@ -324,6 +324,7 @@ namespace Dalamud.Injector
|
|||
startInfo.BootLogPath = GetLogPath("dalamud.boot");
|
||||
startInfo.BootEnabledGameFixes = new List<string> { "prevent_devicechange_crashes", "disable_game_openprocess_access_check", "redirect_openprocess" };
|
||||
startInfo.BootDotnetOpenProcessHookMode = 0;
|
||||
// startInfo.BootWaitMessageBox = 2;
|
||||
// startInfo.BootUnhookDlls = new List<string>() { "kernel32.dll", "ntdll.dll", "user32.dll" };
|
||||
|
||||
return startInfo;
|
||||
|
|
|
|||
|
|
@ -49,14 +49,9 @@ namespace Dalamud.Game
|
|||
this.Address = new FrameworkAddressResolver();
|
||||
this.Address.Setup();
|
||||
|
||||
Log.Verbose($"Framework address 0x{this.Address.BaseAddress.ToInt64():X}");
|
||||
if (this.Address.BaseAddress == IntPtr.Zero)
|
||||
{
|
||||
throw new InvalidOperationException("Framework is not initalized yet.");
|
||||
}
|
||||
|
||||
// Hook virtual functions
|
||||
this.HookVTable();
|
||||
this.updateHook = new Hook<OnUpdateDetour>(this.Address.TickAddress, this.HandleFrameworkUpdate);
|
||||
this.destroyHook = new Hook<OnDestroyDetour>(this.Address.FreeAddress, this.HandleFrameworkDestroy);
|
||||
this.realDestroyHook = new Hook<OnRealDestroyDelegate>(this.Address.DestroyAddress, this.HandleRealDestroy);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -241,26 +236,6 @@ namespace Dalamud.Game
|
|||
statsStopwatch.Reset();
|
||||
}
|
||||
|
||||
private void HookVTable()
|
||||
{
|
||||
var vtable = Marshal.ReadIntPtr(this.Address.BaseAddress);
|
||||
// Virtual function layout:
|
||||
// .rdata:00000001411F1FE0 dq offset Xiv__Framework___dtor
|
||||
// .rdata:00000001411F1FE8 dq offset Xiv__Framework__init
|
||||
// .rdata:00000001411F1FF0 dq offset Xiv__Framework__destroy
|
||||
// .rdata:00000001411F1FF8 dq offset Xiv__Framework__free
|
||||
// .rdata:00000001411F2000 dq offset Xiv__Framework__update
|
||||
|
||||
var pUpdate = Marshal.ReadIntPtr(vtable, IntPtr.Size * 4);
|
||||
this.updateHook = new Hook<OnUpdateDetour>(pUpdate, this.HandleFrameworkUpdate);
|
||||
|
||||
var pDestroy = Marshal.ReadIntPtr(vtable, IntPtr.Size * 3);
|
||||
this.destroyHook = new Hook<OnDestroyDetour>(pDestroy, this.HandleFrameworkDestroy);
|
||||
|
||||
var pRealDestroy = Marshal.ReadIntPtr(vtable, IntPtr.Size * 2);
|
||||
this.realDestroyHook = new Hook<OnRealDestroyDelegate>(pRealDestroy, this.HandleRealDestroy);
|
||||
}
|
||||
|
||||
private bool HandleFrameworkUpdate(IntPtr framework)
|
||||
{
|
||||
// If any of the tier loads failed, just go to the original code.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using ImGuiNET;
|
||||
|
||||
namespace Dalamud.Game
|
||||
{
|
||||
|
|
@ -9,47 +10,36 @@ namespace Dalamud.Game
|
|||
public sealed class FrameworkAddressResolver : BaseAddressResolver
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the base address native Framework class.
|
||||
/// Gets the address for the function that is called once the Framework is destroyed.
|
||||
/// </summary>
|
||||
public IntPtr BaseAddress { get; private set; }
|
||||
public IntPtr DestroyAddress { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the address for the native GuiManager class.
|
||||
/// Gets the address for the function that is called once the Framework is free'd.
|
||||
/// </summary>
|
||||
public IntPtr GuiManager { get; private set; }
|
||||
public IntPtr FreeAddress { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the address for the native ScriptManager class.
|
||||
/// Gets the function that is called every tick.
|
||||
/// </summary>
|
||||
public IntPtr ScriptManager { get; private set; }
|
||||
public IntPtr TickAddress { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void Setup64Bit(SigScanner sig)
|
||||
{
|
||||
this.SetupFramework(sig);
|
||||
|
||||
// Xiv__Framework__GetGuiManager+8 000 mov rax, [rcx+2C00h]
|
||||
// Xiv__Framework__GetGuiManager+F 000 retn
|
||||
this.GuiManager = Marshal.ReadIntPtr(this.BaseAddress, 0x2C08);
|
||||
|
||||
// Called from Framework::Init
|
||||
this.ScriptManager = this.BaseAddress + 0x2C68; // note that no deref here
|
||||
}
|
||||
|
||||
private void SetupFramework(SigScanner scanner)
|
||||
{
|
||||
// Dissasembly of part of the .dtor
|
||||
// 00007FF701AD665A | 48 C7 05 ?? ?? ?? ?? 00 00 00 00 | MOV QWORD PTR DS:[g_mainFramework],0
|
||||
// 00007FF701AD6665 | E8 ?? ?? ?? ?? | CALL ffxiv_dx11.7FF701E27130
|
||||
// 00007FF701AD666A | 48 8D ?? ?? ?? 00 00 | LEA RCX,QWORD PTR DS:[RBX + 2C38]
|
||||
// 00007FF701AD6671 | E8 ?? ?? ?? ?? | CALL ffxiv_dx11.7FF701E2A7D0
|
||||
// 00007FF701AD6676 | 48 8D ?? ?? ?? ?? ?? | LEA RAX,QWORD PTR DS:[7FF702C31F80
|
||||
var fwDtor = scanner.ScanText("48 C7 05 ?? ?? ?? ?? 00 00 00 00 E8 ?? ?? ?? ?? 48 8D ?? ?? ?? 00 00 E8 ?? ?? ?? ?? 48 8D");
|
||||
var fwOffset = Marshal.ReadInt32(fwDtor + 3);
|
||||
var pFramework = scanner.ResolveRelativeAddress(fwDtor + 11, fwOffset);
|
||||
this.DestroyAddress =
|
||||
scanner.ScanText("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B 3D ?? ?? ?? ?? 48 8B D9 48 85 FF");
|
||||
|
||||
// Framework does not change once initialized in startup so don't bother to deref again and again.
|
||||
this.BaseAddress = Marshal.ReadIntPtr(pFramework);
|
||||
this.FreeAddress =
|
||||
scanner.ScanText("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8B D9 48 8B 0D ?? ?? ?? ??");
|
||||
|
||||
this.TickAddress =
|
||||
scanner.ScanText("40 53 48 83 EC 20 FF 81 ?? ?? ?? ?? 48 8B D9 48 8D 4C 24 ??");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,13 +38,11 @@ namespace Dalamud.Game.Gui
|
|||
/// Initializes a new instance of the <see cref="ChatGui"/> class.
|
||||
/// </summary>
|
||||
/// <param name="baseAddress">The base address of the ChatManager.</param>
|
||||
internal ChatGui(IntPtr baseAddress)
|
||||
internal ChatGui()
|
||||
{
|
||||
this.address = new ChatGuiAddressResolver(baseAddress);
|
||||
this.address = new ChatGuiAddressResolver();
|
||||
this.address.Setup();
|
||||
|
||||
Log.Verbose($"Chat manager address 0x{this.address.BaseAddress.ToInt64():X}");
|
||||
|
||||
this.printMessageHook = new Hook<PrintMessageDelegate>(this.address.PrintMessage, this.HandlePrintMessageDetour);
|
||||
this.populateItemLinkHook = new Hook<PopulateItemLinkDelegate>(this.address.PopulateItemLinkObject, this.HandlePopulateItemLinkDetour);
|
||||
this.interactableLinkClickedHook = new Hook<InteractableLinkClickedDelegate>(this.address.InteractableLinkClicked, this.InteractableLinkClickedDetour);
|
||||
|
|
|
|||
|
|
@ -7,20 +7,6 @@ namespace Dalamud.Game.Gui
|
|||
/// </summary>
|
||||
public sealed class ChatGuiAddressResolver : BaseAddressResolver
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ChatGuiAddressResolver"/> class.
|
||||
/// </summary>
|
||||
/// <param name="baseAddress">The base address of the native ChatManager class.</param>
|
||||
public ChatGuiAddressResolver(IntPtr baseAddress)
|
||||
{
|
||||
this.BaseAddress = baseAddress;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the base address of the native ChatManager class.
|
||||
/// </summary>
|
||||
public IntPtr BaseAddress { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the address of the native PrintMessage method.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ namespace Dalamud.Game.Gui
|
|||
Log.Verbose($"HandleItemOut address 0x{this.address.HandleItemOut.ToInt64():X}");
|
||||
Log.Verbose($"HandleImm address 0x{this.address.HandleImm.ToInt64():X}");
|
||||
|
||||
Service<ChatGui>.Set(new ChatGui(this.address.ChatManager));
|
||||
Service<ChatGui>.Set();
|
||||
Service<PartyFinderGui>.Set();
|
||||
Service<ToastGui>.Set();
|
||||
Service<FlyTextGui>.Set();
|
||||
|
|
|
|||
|
|
@ -7,24 +7,11 @@ namespace Dalamud.Game.Gui
|
|||
/// </summary>
|
||||
internal sealed class GameGuiAddressResolver : BaseAddressResolver
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GameGuiAddressResolver"/> class.
|
||||
/// </summary>
|
||||
public GameGuiAddressResolver()
|
||||
{
|
||||
this.BaseAddress = Service<Framework>.Get().Address.BaseAddress;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the base address of the native GuiManager class.
|
||||
/// </summary>
|
||||
public IntPtr BaseAddress { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the address of the native ChatManager class.
|
||||
/// </summary>
|
||||
public IntPtr ChatManager { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the address of the native SetGlobalBgm method.
|
||||
/// </summary>
|
||||
|
|
@ -89,13 +76,5 @@ namespace Dalamud.Game.Gui
|
|||
this.ToggleUiHide = sig.ScanText("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 0F B6 B9 ?? ?? ?? ?? B8 ?? ?? ?? ??");
|
||||
this.Utf8StringFromSequence = sig.ScanText("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 48 8D 41 22 66 C7 41 ?? ?? ?? 48 89 01 49 8B D8");
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetupInternal(SigScanner scanner)
|
||||
{
|
||||
// Xiv__UiManager__GetChatManager 000 lea rax, [rcx+13E0h]
|
||||
// Xiv__UiManager__GetChatManager+7 000 retn
|
||||
this.ChatManager = this.BaseAddress + 0x13E0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -452,7 +452,6 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
}
|
||||
else
|
||||
{
|
||||
stateString += $"FrameworkBase: {framework.Address.BaseAddress.ToInt64():X}\n";
|
||||
stateString += $"ObjectTableLen: {objectTable.Length}\n";
|
||||
stateString += $"LocalPlayerName: {clientState.LocalPlayer.Name}\n";
|
||||
stateString += $"CurrentWorldName: {(this.resolveGameData ? clientState.LocalPlayer.CurrentWorld.GameData.Name : clientState.LocalPlayer.CurrentWorld.Id.ToString())}\n";
|
||||
|
|
@ -530,7 +529,6 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
}
|
||||
else
|
||||
{
|
||||
stateString += $"FrameworkBase: {framework.Address.BaseAddress.ToInt64():X}\n";
|
||||
stateString += $"FateTableLen: {fateTable.Length}\n";
|
||||
|
||||
ImGui.TextUnformatted(stateString);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue