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); } } }