fix: try to copy .text and .data of TargetModule to avoid conflicts(WIP, needs testing)

This commit is contained in:
goat 2020-01-26 17:25:11 +09:00
parent 3ae9705e8d
commit e2f9773e33
5 changed files with 67 additions and 20 deletions

View file

@ -14,10 +14,10 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Label="Feature"> <PropertyGroup Label="Feature">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<AssemblyVersion>4.7.0.0</AssemblyVersion> <AssemblyVersion>4.7.2.0</AssemblyVersion>
<FileVersion>4.7.0.0</FileVersion> <FileVersion>4.7.2.0</FileVersion>
<Description>XIVLauncher addon injection</Description> <Description>XIVLauncher addon injection</Description>
<Version>4.7.0.0</Version> <Version>4.7.2.0</Version>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DocumentationFile></DocumentationFile> <DocumentationFile></DocumentationFile>

View file

@ -28,9 +28,9 @@ namespace Dalamud {
private readonly ManualResetEvent unloadSignal; private readonly ManualResetEvent unloadSignal;
public readonly ProcessModule TargetModule; private readonly ProcessModule targetModule;
private readonly SigScanner sigScanner; public readonly SigScanner SigScanner;
public Framework Framework { get; } public Framework Framework { get; }
@ -48,7 +48,7 @@ namespace Dalamud {
public readonly DalamudConfiguration Configuration; public readonly DalamudConfiguration Configuration;
internal readonly WinSockHandlers WinSock2; private readonly WinSockHandlers WinSock2;
public readonly InterfaceManager InterfaceManager; public readonly InterfaceManager InterfaceManager;
@ -63,11 +63,11 @@ namespace Dalamud {
this.unloadSignal = new ManualResetEvent(false); this.unloadSignal = new ManualResetEvent(false);
// Initialize the process information. // Initialize the process information.
this.TargetModule = Process.GetCurrentProcess().MainModule; this.targetModule = Process.GetCurrentProcess().MainModule;
this.sigScanner = new SigScanner(this.TargetModule); SigScanner = new SigScanner(this.targetModule, true);
// Initialize game subsystem // Initialize game subsystem
Framework = new Framework(this.sigScanner, this); Framework = new Framework(this.SigScanner, this);
// Initialize managers. Basically handlers for the logic // Initialize managers. Basically handlers for the logic
CommandManager = new CommandManager(this, info.Language); CommandManager = new CommandManager(this, info.Language);
@ -76,7 +76,7 @@ namespace Dalamud {
ChatHandlers = new ChatHandlers(this); ChatHandlers = new ChatHandlers(this);
NetworkHandlers = new NetworkHandlers(this, this.Configuration.OptOutMbCollection); NetworkHandlers = new NetworkHandlers(this, this.Configuration.OptOutMbCollection);
this.ClientState = new ClientState(this, info, this.sigScanner, this.TargetModule); this.ClientState = new ClientState(this, info, this.SigScanner, this.targetModule);
this.BotManager = new DiscordBotManager(this, this.Configuration.DiscordFeatureConfig); this.BotManager = new DiscordBotManager(this, this.Configuration.DiscordFeatureConfig);
@ -84,7 +84,7 @@ namespace Dalamud {
this.WinSock2 = new WinSockHandlers(); this.WinSock2 = new WinSockHandlers();
this.InterfaceManager = new InterfaceManager(this, this.sigScanner); this.InterfaceManager = new InterfaceManager(this, this.SigScanner);
this.InterfaceManager.OnDraw += BuildDalamudUi; this.InterfaceManager.OnDraw += BuildDalamudUi;
this.InterfaceManager.Enable(); this.InterfaceManager.Enable();
} }
@ -135,6 +135,8 @@ namespace Dalamud {
this.unloadSignal.Dispose(); this.unloadSignal.Dispose();
this.WinSock2.Dispose(); this.WinSock2.Dispose();
this.SigScanner.Dispose();
} }
#region Interface #region Interface

View file

@ -14,9 +14,9 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Label="Feature"> <PropertyGroup Label="Feature">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<AssemblyVersion>4.7.0.0</AssemblyVersion> <AssemblyVersion>4.7.2.0</AssemblyVersion>
<Version>4.7.0.0</Version> <Version>4.7.2.0</Version>
<FileVersion>4.7.0.0</FileVersion> <FileVersion>4.7.2.0</FileVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup Label="Resources"> <ItemGroup Label="Resources">
<None Include="$(SolutionDir)/Resources/**/*" CopyToOutputDirectory="PreserveNewest" Visible="false" /> <None Include="$(SolutionDir)/Resources/**/*" CopyToOutputDirectory="PreserveNewest" Visible="false" />

View file

@ -7,18 +7,24 @@ using System.Runtime.InteropServices;
using Serilog; using Serilog;
namespace Dalamud.Game { namespace Dalamud.Game {
public sealed class SigScanner { public sealed class SigScanner : IDisposable {
public SigScanner(ProcessModule module) { public SigScanner(ProcessModule module, bool doCopy = false) {
Module = module; Module = module;
Is32BitProcess = !Environment.Is64BitProcess; Is32BitProcess = !Environment.Is64BitProcess;
IsCopy = doCopy;
// Limit the search space to .text section. // Limit the search space to .text section.
SetupSearchSpace(module); SetupSearchSpace(module);
if (IsCopy)
SetupCopiedSegments();
Log.Verbose("Module base: {Address}", TextSectionBase); Log.Verbose("Module base: {Address}", TextSectionBase);
Log.Verbose("Moudle size: {Size}", TextSectionSize); Log.Verbose("Module size: {Size}", TextSectionSize);
} }
public bool IsCopy { get; private set; }
public bool Is32BitProcess { get; } public bool Is32BitProcess { get; }
public IntPtr TextSectionBase { get; private set; } public IntPtr TextSectionBase { get; private set; }
@ -72,19 +78,58 @@ namespace Dalamud.Game {
} }
} }
private IntPtr textCopyPtr;
private IntPtr dataCopyPtr;
private unsafe void SetupCopiedSegments() {
Log.Verbose("text copy START");
// .text
this.textCopyPtr = Marshal.AllocHGlobal(TextSectionSize);
Log.Verbose($"Alloc: {this.textCopyPtr.ToInt64():x}");
Buffer.MemoryCopy(TextSectionBase.ToPointer(), this.textCopyPtr.ToPointer(), TextSectionSize,
TextSectionSize);
Log.Verbose("data copy START");
// .data
this.dataCopyPtr = Marshal.AllocHGlobal(DataSectionSize);
Buffer.MemoryCopy(DataSectionBase.ToPointer(), this.dataCopyPtr.ToPointer(), DataSectionSize,
DataSectionSize);
Log.Verbose("copy OK!");
}
public void Dispose() {
Marshal.FreeHGlobal(this.textCopyPtr);
Marshal.FreeHGlobal(this.dataCopyPtr);
}
public IntPtr ScanText(string signature) { public IntPtr ScanText(string signature) {
return Scan(TextSectionBase, TextSectionSize, signature); var mBase = IsCopy ? this.textCopyPtr : TextSectionBase;
var scanRet = Scan(mBase, TextSectionSize, signature);
return IsCopy
? (new IntPtr(scanRet.ToInt64() - (this.textCopyPtr.ToInt64() - TextSectionBase.ToInt64())))
: scanRet;
} }
public IntPtr ScanData(string signature) { public IntPtr ScanData(string signature) {
return Scan(DataSectionBase, DataSectionSize, signature); var mBase = IsCopy ? this.dataCopyPtr : DataSectionBase;
var scanRet = Scan(DataSectionBase, DataSectionSize, signature);
return IsCopy
? (new IntPtr(scanRet.ToInt64() - (this.textCopyPtr.ToInt64() - TextSectionBase.ToInt64())))
: scanRet;
} }
public IntPtr ScanModule(string signature) { public IntPtr ScanModule(string signature) {
// TODO: This does not respect the copy flag.
return Scan(Module.BaseAddress, Module.ModuleMemorySize, signature); return Scan(Module.BaseAddress, Module.ModuleMemorySize, signature);
} }
public IntPtr Scan(IntPtr baseAddress, int size, string signature) { public IntPtr Scan(IntPtr baseAddress, int size, string signature) {
Log.Verbose($"Scan at {baseAddress.ToInt64():x} with {size:x} for {signature}");
var needle = SigToNeedle(signature); var needle = SigToNeedle(signature);
unsafe { unsafe {

View file

@ -55,7 +55,7 @@ namespace Dalamud.Plugin
this.Framework = dalamud.Framework; this.Framework = dalamud.Framework;
this.ClientState = dalamud.ClientState; this.ClientState = dalamud.ClientState;
this.UiBuilder = new UiBuilder(dalamud.InterfaceManager, pluginName); this.UiBuilder = new UiBuilder(dalamud.InterfaceManager, pluginName);
this.TargetModuleScanner = new SigScanner(dalamud.TargetModule); this.TargetModuleScanner = dalamud.SigScanner;
this.dalamud = dalamud; this.dalamud = dalamud;
this.pluginName = pluginName; this.pluginName = pluginName;