Merge pull request #1073 from Ottermandias/SigScanner

This commit is contained in:
goat 2023-01-13 18:14:17 +01:00 committed by GitHub
commit 235137ccef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -9,6 +9,7 @@ using System.Runtime.InteropServices;
using Dalamud.IoC; using Dalamud.IoC;
using Dalamud.IoC.Internal; using Dalamud.IoC.Internal;
using Iced.Intel;
using Newtonsoft.Json; using Newtonsoft.Json;
using Serilog; using Serilog;
@ -173,26 +174,36 @@ public class SigScanner : IDisposable, IServiceType
/// Scan for a .data address using a .text function. /// Scan for a .data address using a .text function.
/// This is intended to be used with IDA sigs. /// This is intended to be used with IDA sigs.
/// Place your cursor on the line calling a static address, and create and IDA sig. /// 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> /// </summary>
/// <param name="signature">The signature of the function using the data.</param> /// <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> /// <param name="offset">The offset from function start of the instruction using the data.</param>
/// <returns>An IntPtr to the static memory location.</returns> /// <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); var instructionAddress = (byte*)this.ScanText(signature);
instrAddr = IntPtr.Add(instrAddr, offset); instructionAddress += offset;
var bAddr = (long)this.Module.BaseAddress;
long num;
do try
{ {
instrAddr = IntPtr.Add(instrAddr, 1); var reader = new UnsafeCodeReader(instructionAddress, signature.Length + 8);
num = Marshal.ReadInt32(instrAddr) + (long)instrAddr + 4 - bAddr; 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> /// <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> /// <summary>
/// Helper for ScanText to get the correct address for IDA sigs that mark the first JMP or CALL location. /// Helper for ScanText to get the correct address for IDA sigs that mark the first JMP or CALL location.
/// </summary> /// </summary>