using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Runtime.InteropServices;
using ReClassNET.Core;
using ReClassNET.Memory;
namespace ReClassNET.MemoryScanner
{
public class PatternScanner
{
///
/// Searchs for the in the specified .
///
/// The pattern to search.
/// The process to read from.
/// The module of the process.
/// The address of the pattern or if the pattern was not found.
public static IntPtr FindPattern(BytePattern pattern, RemoteProcess process, Module module)
{
Contract.Requires(pattern != null);
Contract.Requires(process != null);
Contract.Requires(module != null);
return FindPattern(pattern, process, module.Start, module.Size.ToInt32());
}
///
/// Searchs for the in the specified .
///
/// The pattern to search.
/// The process to read from.
/// The section of the process.
/// The address of the pattern or if the pattern was not found.
public static IntPtr FindPattern(BytePattern pattern, RemoteProcess process, Section section)
{
Contract.Requires(pattern != null);
Contract.Requires(process != null);
Contract.Requires(section != null);
return FindPattern(pattern, process, section.Start, section.Size.ToInt32());
}
///
/// Searchs for the in the specified address range.
///
/// The pattern to search.
/// The process to read from.
/// The start address.
/// The size of the address range.
/// The address of the pattern or if the pattern was not found.
public static IntPtr FindPattern(BytePattern pattern, RemoteProcess process, IntPtr start, int size)
{
Contract.Requires(pattern != null);
Contract.Requires(process != null);
var moduleBytes = process.ReadRemoteMemory(start, size);
var offset = FindPattern(pattern, moduleBytes);
if (offset == -1)
{
return IntPtr.Zero;
}
return start + offset;
}
///
/// Searchs for the in the specified data.
///
/// The pattern to search.
/// The data to scan.
/// The index in data where the pattern was found or -1 otherwise.
public static int FindPattern(BytePattern pattern, byte[] data)
{
Contract.Requires(pattern != null);
Contract.Requires(data != null);
var limit = data.Length - pattern.Length;
for (var i = 0; i < limit; ++i)
{
if (pattern.Equals(data, i))
{
return i;
}
}
return -1;
}
///
/// Creates a for the given address range.
///
/// The process to use.
/// The start of the address range.
/// The size of the address range.
/// A describing the address range.
public static BytePattern CreatePatternFromCode(RemoteProcess process, IntPtr start, int size)
{
var data = new List>();
var buffer = process.ReadRemoteMemory(start, size);
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
try
{
var eip = handle.AddrOfPinnedObject();
process.CoreFunctions.DisassembleCode(eip, size, IntPtr.Zero, true, (ref InstructionData instruction) =>
{
for (var i = 0; i < instruction.Length; ++i)
{
data.Add(Tuple.Create(instruction.Data[i], i >= instruction.StaticInstructionBytes));
}
return true;
});
}
finally
{
if (handle.IsAllocated)
{
handle.Free();
}
}
return BytePattern.From(data);
}
}
}