mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 10:17:22 +01:00
* Add IInternal/PublicDisposableService Plugins are exposed interfaces that are not inherited from `IDisposable`, but services implementing plugin interfaces often implement `IDisposable`. Some plugins may try to call `IDisposable.Dispose` on everything provided, and it also is possible to use `using` clause too eagerly while working on Dalamud itself, such as writing `using var smth = await Service<SomeService>.GetAsync();`. Such behaviors often lead to a difficult-to-debug errors, and making those services either not an `IDisposable` or making `IDisposable.Dispose` do nothing if the object has been loaded would prevent such errors. As `ServiceManager` must be the only class dealing with construction and disposal of services, `IInternalDisposableService` has been added to limit who can dispose the object. `IPublicDisposableService` also has been added to classes that can be constructed and accessed directly by plugins; for those, `Dispose` will be ignored if the instance is a service instance, and only `DisposeService` will respond. In addition, `DalamudPluginInterface` and `UiBuilder` also have been changed so that their `IDisposable.Dispose` no longer respond, and instead, internal functions have been added to only allow disposal from Dalamud. * Cleanup * Postmerge fixes * More explanation on RunOnFrameworkThread(ClearHooks) * Mark ReliableFileStorage public ctor obsolete --------- Co-authored-by: goat <16760685+goaaats@users.noreply.github.com>
100 lines
2.8 KiB
C#
100 lines
2.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
|
|
#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 = new byte[] { 0x31, 0xC0, 0x90, 0x90, 0x90, 0x90 };
|
|
private byte[] original;
|
|
private IntPtr debugCheckAddress;
|
|
|
|
[ServiceManager.ServiceConstructor]
|
|
private AntiDebug(TargetSigScanner sigScanner)
|
|
{
|
|
try
|
|
{
|
|
this.debugCheckAddress = sigScanner.ScanText("FF 15 ?? ?? ?? ?? 85 C0 74 11 41");
|
|
}
|
|
catch (KeyNotFoundException)
|
|
{
|
|
this.debugCheckAddress = IntPtr.Zero;
|
|
}
|
|
|
|
Log.Verbose($"Debug check address 0x{this.debugCheckAddress.ToInt64():X}");
|
|
|
|
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() => this.Disable();
|
|
|
|
/// <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 0x{this.debugCheckAddress.ToInt64():X}");
|
|
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 0x{this.debugCheckAddress.ToInt64():X}");
|
|
SafeMemory.WriteBytes(this.debugCheckAddress, this.original);
|
|
}
|
|
else
|
|
{
|
|
Log.Information("Debug check was not overwritten?");
|
|
}
|
|
|
|
this.IsEnabled = false;
|
|
}
|
|
}
|