mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
Merge pull request #1073 from Ottermandias/SigScanner
This commit is contained in:
commit
235137ccef
1 changed files with 42 additions and 11 deletions
|
|
@ -9,6 +9,7 @@ using System.Runtime.InteropServices;
|
|||
|
||||
using Dalamud.IoC;
|
||||
using Dalamud.IoC.Internal;
|
||||
using Iced.Intel;
|
||||
using Newtonsoft.Json;
|
||||
using Serilog;
|
||||
|
||||
|
|
@ -173,26 +174,36 @@ public class SigScanner : IDisposable, IServiceType
|
|||
/// Scan for a .data address using a .text function.
|
||||
/// This is intended to be used with IDA sigs.
|
||||
/// Place your cursor on the line calling a static address, and create and IDA sig.
|
||||
/// The signature and offset should not break through instruction boundaries.
|
||||
/// </summary>
|
||||
/// <param name="signature">The signature of the function using the data.</param>
|
||||
/// <param name="offset">The offset from function start of the instruction using the data.</param>
|
||||
/// <returns>An IntPtr to the static memory location.</returns>
|
||||
public IntPtr GetStaticAddressFromSig(string signature, int offset = 0)
|
||||
public unsafe IntPtr GetStaticAddressFromSig(string signature, int offset = 0)
|
||||
{
|
||||
var instrAddr = this.ScanText(signature);
|
||||
instrAddr = IntPtr.Add(instrAddr, offset);
|
||||
var bAddr = (long)this.Module.BaseAddress;
|
||||
long num;
|
||||
var instructionAddress = (byte*)this.ScanText(signature);
|
||||
instructionAddress += offset;
|
||||
|
||||
do
|
||||
try
|
||||
{
|
||||
instrAddr = IntPtr.Add(instrAddr, 1);
|
||||
num = Marshal.ReadInt32(instrAddr) + (long)instrAddr + 4 - bAddr;
|
||||
var reader = new UnsafeCodeReader(instructionAddress, signature.Length + 8);
|
||||
var decoder = Decoder.Create(64, reader, (ulong)instructionAddress, DecoderOptions.AMD);
|
||||
while (reader.CanReadByte)
|
||||
{
|
||||
var instruction = decoder.Decode();
|
||||
if (instruction.IsInvalid) continue;
|
||||
if (instruction.Op0Kind is OpKind.Memory || instruction.Op1Kind is OpKind.Memory)
|
||||
{
|
||||
return (IntPtr)instruction.MemoryDisplacement64;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
while (!(num >= this.DataSectionOffset && num <= this.DataSectionOffset + this.DataSectionSize)
|
||||
&& !(num >= this.RDataSectionOffset && num <= this.RDataSectionOffset + this.RDataSectionSize));
|
||||
|
||||
return IntPtr.Add(instrAddr, Marshal.ReadInt32(instrAddr) + 4);
|
||||
throw new KeyNotFoundException($"Can't find any referenced address in the given signature {signature}.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -384,6 +395,26 @@ public class SigScanner : IDisposable, IServiceType
|
|||
}
|
||||
}
|
||||
|
||||
private unsafe class UnsafeCodeReader : CodeReader
|
||||
{
|
||||
private readonly int length;
|
||||
private readonly byte* address;
|
||||
private int pos;
|
||||
public UnsafeCodeReader(byte* address, int length)
|
||||
{
|
||||
this.length = length;
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
public bool CanReadByte => this.pos < this.length;
|
||||
|
||||
public override int ReadByte()
|
||||
{
|
||||
if (this.pos >= this.length) return -1;
|
||||
return *(this.address + this.pos++);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper for ScanText to get the correct address for IDA sigs that mark the first JMP or CALL location.
|
||||
/// </summary>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue