PDA

Просмотр полной версии : [Руководство] Find Pattern (C#)


крайслер
10.11.2013, 19:15
Класс довольно известный и распространенный, но тем не менее мало кто о нем знает или умеет использовать.Работает без перебоев и отклонений.
sigScan C# Implementation - Written by atom0s [aka Wiccaan]

Необходимые "ссылки"
using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;

Сам класс:
public class SigScan
{

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool ReadProcessMemory(IntPtr hProcess,IntPtr lpBaseAddress,[Out()] byte[] lpBuffer,int dwSize,out int lpNumberOfBytesRead);

/// m_vDumpedRegion
private byte[] m_vDumpedRegion;
/// m_vProcess
private Process m_vProcess;
private IntPtr m_vAddress;
/// m_vSize
private Int32 m_vSize;


#region "sigScan Class Construction"
/// SigScan
public SigScan()
{
this.m_vProcess = null;
this.m_vAddress = IntPtr.Zero;
this.m_vSize = 0;
this.m_vDumpedRegion = null;
}

/// SigScan
/// <param name="proc">The process to dump the memory from.</param>
/// <param name="addr">The started address to begin the dump.</param>
/// <param name="size">The size of the dump.</param>

public SigScan(Process proc, IntPtr addr, int size)
{
this.m_vProcess = proc;
this.m_vAddress = addr;
this.m_vSize = size;
}
#endregion
#region "sigScan Class Private Methods"

/// DumpMemory
/// <returns>Boolean based on RPM results and valid properties.</returns>
private bool DumpMemory()
{
try
{
// Checks to ensure we have valid data.
if (this.m_vProcess == null) return false;
if (this.m_vProcess.HasExited == true) return false;

if (this.m_vAddress == IntPtr.Zero) return false;
if (this.m_vSize == 0) return false;
// Create the region space to dump into.
this.m_vDumpedRegion = new byte[this.m_vSize];
bool bReturn = false;
int nBytesRead = 0;
// Dump the memory.
bReturn = ReadProcessMemory( this.m_vProcess.Handle, this.m_vAddress, this.m_vDumpedRegion, this.m_vSize, out nBytesRead);
// Validation checks.
if (bReturn == false || nBytesRead != this.m_vSize)return false;
return true;
}
catch (Exception ex)
{
return false;
}
}
/// MaskCheck
/// <param name="nOffset">Offset in the dump to start at.</param>
/// <param name="btPattern">Pattern to scan for.</param>
/// <param name="strMask">Mask to compare against.</param>
/// <returns>Boolean depending on if the pattern was found.</returns>
private bool MaskCheck(int nOffset, byte[] btPattern, string strMask)
{
// Loop the pattern and compare to the mask and dump.
for (int x = 0; x < btPattern.Length; x++)
{
// If the mask char is a wildcard, just continue.
if (strMask[x] == '?')
continue;
// If the mask char is not a wildcard, ensure a match is made in the pattern.
if ((strMask[x] == 'x') && (btPattern[x] != this.m_vDumpedRegion[nOffset + x]))
return false;
}
// The loop was successful so we found the pattern.
return true;
}
#endregion
#region "sigScan Class Public Methods"
/// FindPattern
/// <param name="btPattern">Byte pattern to look for in the dumped region.</param>
/// <param name="strMask">The mask string to compare against.</param>
/// <param name="nOffset">The offset added to the result address.</param>
/// <returns>IntPtr - zero if not found, address if found.</returns>
public IntPtr FindPattern(byte[] btPattern, string strMask, int nOffset)
{
try
{
// Dump the memory region if we have not dumped it yet.
if (this.m_vDumpedRegion == null || this.m_vDumpedRegion.Length == 0)
{
if (!this.DumpMemory())return IntPtr.Zero;
}
// Ensure the mask and pattern lengths match.
if (strMask.Length != btPattern.Length) return IntPtr.Zero;

for (int x = 0; x < this.m_vDumpedRegion.Length; x++)
{
if (this.MaskCheck(x, btPattern, strMask))
{
// The pattern was found, return it.
return new IntPtr((int)this.m_vAddress + (x + nOffset));
}
}
// Pattern was not found.
return IntPtr.Zero;
}
catch (Exception ex)
{
return IntPtr.Zero;
}
}
public void ResetRegion()
{
this.m_vDumpedRegion = null;
}
#endregion
#region "sigScan Class Properties"

public Process Process
{
get { return this.m_vProcess; }
set { this.m_vProcess = value; }
}
public IntPtr Address
{
get { return this.m_vAddress; }
set { this.m_vAddress = value; }
}
public Int32 Size
{
get { return this.m_vSize; }
set { this.m_vSize = value; }
}
#endregion



}

Способов использования два:
SigScan _sigScan = new SigScan();
_sigScan.Process = someProc;
_sigScan.Address = new IntPtr(0x123456);
_sigScan.Size = 0x1000;
IntPtr pAddr = _sigScan.FindPattern(new byte[]{ 0xFF, 0xFF, 0xFF, 0xFF, 0x51, 0x55, 0xFC, 0x11 }, "xxxx?xx?", 12);
и
SigScan _sigScan = new SigScan(someProc, new IntPtr(0x123456), 0x1000);
IntPtr pAddr = _sigScan.FindPattern(new byte[]{ 0xFF, 0xFF, 0xFF, 0xFF, 0x51, 0x55, 0xFC, 0x11 }, "xxxx?xx?", 12);


Как это использовать:
Нам нужено получить хендл процесса и найти сигнатуру(гайд я писал ранее ([Ссылки могут видеть только зарегистрированные и активированные пользователи]))

Process someProc = Process.GetProcessesByName("crimsonland")[0];
SigScan _sigScan = new SigScan(someProc, new IntPtr(0x401000), 0x6e000);
byte[] buff = new byte[] { 0xD9, 0x9F, 0x00, 0x00, 0x00, 0x00, 0xD9, 0x87, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x1D, 0x00, 0x00, 0x00, 0x00, 0xDF, 0xE0, 0xF6, 0xC4, 0x01, 0x0F, 0x84, 0x00, 0x00, 0x00, 0x00 };
IntPtr pAddr = _sigScan.FindPattern(buff, "xx????xx????xx????xxxxxxx????", 0);

Для наглядности\проверки адресс можно вывести так:
label.Text = string.Format("0x{0:X6}", pAddr.ToInt32());

[Ссылки могут видеть только зарегистрированные и активированные пользователи]



PS: последний параметр у функции FindPattern
FindPattern(buff, "xx????xx????xx????xxxxxxx????", 0);
это не количество байт в массиве, а смещение относительно искомого адресса.