Move AntiDebug to xivfixes (#2264)

* Move AntiDebug to xivfixes

* Update BootEnabledGameFixes

* Check BootEnabledGameFixes

* Apply suggestions from code review

Co-authored-by: KazWolfe <KazWolfe@users.noreply.github.com>

---------

Co-authored-by: KazWolfe <KazWolfe@users.noreply.github.com>
This commit is contained in:
Haselnussbomber 2025-05-09 22:53:44 +02:00 committed by GitHub
parent 4dce0c00e8
commit 33605e3ace
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 45 additions and 121 deletions

View file

@ -648,6 +648,48 @@ void xivfixes::symbol_load_patches(bool bApply) {
}
}
void xivfixes::disable_game_debugging_protection(bool bApply) {
static const char* LogTag = "[xivfixes:disable_game_debugging_protection]";
static const std::vector<uint8_t> patchBytes = {
0x31, 0xC0, // XOR EAX, EAX
0x90, // NOP
0x90, // NOP
0x90, // NOP
0x90 // NOP
};
if (!bApply)
return;
if (!g_startInfo.BootEnabledGameFixes.contains("disable_game_debugging_protection")) {
logging::I("{} Turned off via environment variable.", LogTag);
return;
}
// Find IsDebuggerPresent in Framework.Tick()
const char* matchPtr = utils::signature_finder()
.look_in(utils::loaded_module(g_hGameInstance), ".text")
.look_for_hex("FF 15 ?? ?? ?? ?? 85 C0 74 13 41")
.find_one()
.Match.data();
if (!matchPtr) {
logging::E("{} Failed to find signature.", LogTag);
return;
}
void* address = const_cast<void*>(static_cast<const void*>(matchPtr));
DWORD oldProtect;
if (VirtualProtect(address, patchBytes.size(), PAGE_EXECUTE_READWRITE, &oldProtect)) {
memcpy(address, patchBytes.data(), patchBytes.size());
VirtualProtect(address, patchBytes.size(), oldProtect, &oldProtect);
logging::I("{} Patch applied at address 0x{:X}.", LogTag, reinterpret_cast<uintptr_t>(address));
} else {
logging::E("{} Failed to change memory protection.", LogTag);
}
}
void xivfixes::apply_all(bool bApply) {
for (const auto& [taskName, taskFunction] : std::initializer_list<std::pair<const char*, void(*)(bool)>>
{
@ -658,6 +700,7 @@ void xivfixes::apply_all(bool bApply) {
{ "backup_userdata_save", &backup_userdata_save },
{ "prevent_icmphandle_crashes", &prevent_icmphandle_crashes },
{ "symbol_load_patches", &symbol_load_patches },
{ "disable_game_debugging_protection", &disable_game_debugging_protection },
}
) {
try {

View file

@ -8,6 +8,7 @@ namespace xivfixes {
void backup_userdata_save(bool bApply);
void prevent_icmphandle_crashes(bool bApply);
void symbol_load_patches(bool bApply);
void disable_game_debugging_protection(bool bApply);
void apply_all(bool bApply);
}

View file

@ -476,6 +476,7 @@ namespace Dalamud.Injector
"backup_userdata_save",
"prevent_icmphandle_crashes",
"symbol_load_patches",
"disable_game_debugging_protection",
};
startInfo.BootDotnetOpenProcessHookMode = 0;
startInfo.BootWaitMessageBox |= args.Contains("--msgbox1") ? 1 : 0;

View file

@ -284,11 +284,6 @@ internal sealed class DalamudConfiguration : IInternalDisposableService
/// </summary>
public bool IsFocusManagementEnabled { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating whether the anti-anti-debug check is enabled on startup.
/// </summary>
public bool IsAntiAntiDebugEnabled { get; set; } = false;
/// <summary>
/// Gets or sets a value indicating whether to resume game main thread after plugins load.
/// </summary>

View file

@ -1,102 +0,0 @@
using System.Collections.Generic;
using Dalamud.Utility;
#if !DEBUG
using Dalamud.Configuration.Internal;
#endif
using Serilog;
namespace Dalamud.Game.Internal;
/// <summary>
/// This class disables anti-debug functionality in the game client.
/// </summary>
[ServiceManager.EarlyLoadedService]
internal sealed class AntiDebug : IInternalDisposableService
{
private readonly byte[] nop = [0x31, 0xC0, 0x90, 0x90, 0x90, 0x90];
private byte[]? original;
private IntPtr debugCheckAddress;
[ServiceManager.ServiceConstructor]
private AntiDebug(TargetSigScanner sigScanner)
{
try
{
// This sig has to be the call site in Framework_Tick
this.debugCheckAddress = sigScanner.ScanText("FF 15 ?? ?? ?? ?? 85 C0 74 13 41");
}
catch (KeyNotFoundException)
{
this.debugCheckAddress = IntPtr.Zero;
}
Log.Verbose($"Debug check address {Util.DescribeAddress(this.debugCheckAddress)}");
if (!this.IsEnabled)
{
#if DEBUG
this.Enable();
#else
if (Service<DalamudConfiguration>.Get().IsAntiAntiDebugEnabled)
this.Enable();
#endif
}
}
/// <summary>Finalizes an instance of the <see cref="AntiDebug"/> class.</summary>
~AntiDebug() => ((IInternalDisposableService)this).DisposeService();
/// <summary>
/// Gets a value indicating whether the anti-debugging is enabled.
/// </summary>
public bool IsEnabled { get; private set; } = false;
/// <inheritdoc />
void IInternalDisposableService.DisposeService() => this.Disable();
/// <summary>
/// Enables the anti-debugging by overwriting code in memory.
/// </summary>
public void Enable()
{
if (this.IsEnabled)
return;
this.original = new byte[this.nop.Length];
if (this.debugCheckAddress != IntPtr.Zero && !this.IsEnabled)
{
Log.Information($"Overwriting debug check at {Util.DescribeAddress(this.debugCheckAddress)}");
SafeMemory.ReadBytes(this.debugCheckAddress, this.nop.Length, out this.original);
SafeMemory.WriteBytes(this.debugCheckAddress, this.nop);
}
else
{
Log.Information("Debug check already overwritten?");
}
this.IsEnabled = true;
}
/// <summary>
/// Disable the anti-debugging by reverting the overwritten code in memory.
/// </summary>
public void Disable()
{
if (!this.IsEnabled)
return;
if (this.debugCheckAddress != IntPtr.Zero && this.original != null)
{
Log.Information($"Reverting debug check at {Util.DescribeAddress(this.debugCheckAddress)}");
SafeMemory.WriteBytes(this.debugCheckAddress, this.original);
}
else
{
Log.Information("Debug check was not overwritten?");
}
this.IsEnabled = false;
}
}

View file

@ -14,7 +14,6 @@ using Dalamud.Game.ClientState;
using Dalamud.Game.ClientState.Conditions;
using Dalamud.Game.ClientState.Keys;
using Dalamud.Game.Gui;
using Dalamud.Game.Internal;
using Dalamud.Hooking;
using Dalamud.Interface.Animation.EasingFunctions;
using Dalamud.Interface.Colors;
@ -719,19 +718,6 @@ internal class DalamudInterface : IInternalDisposableService
this.dalamud.StartInfo.LogName);
}
var antiDebug = Service<AntiDebug>.Get();
if (ImGui.MenuItem("Disable Debugging Protections", null, antiDebug.IsEnabled))
{
var newEnabled = !antiDebug.IsEnabled;
if (newEnabled)
antiDebug.Enable();
else
antiDebug.Disable();
this.configuration.IsAntiAntiDebugEnabled = newEnabled;
this.configuration.QueueSave();
}
ImGui.Separator();
if (ImGui.MenuItem("Open Data window"))