public static PatternByte[] Parse(string pattern) { //check pattern if (pattern.Split(' ').Any(a => a.Length % 2 != 0)) { throw new Exception("Bad pattern"); } //TODO: first split by spaces, in case user passes "FF 3 23 0" string noSpaces = pattern.Replace(" ", string.Empty); if (noSpaces.Length % 2 != 0) { throw new Exception("Bad pattern"); } int byteCount = noSpaces.Length / 2; var arr = new PatternByte[byteCount]; for (int i = 0; i < byteCount; i++) { arr[i] = byte.TryParse(noSpaces.Substring(i * 2, 2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out byte b) ? Normal(b) : Wildcard; } return(arr); }
/// <summary> /// Scans a memory section for a pattern. /// </summary> /// <param name="handle">A handle to the process</param> /// <param name="pattern">The pattern array to scan for</param> /// <param name="baseAddress">The address to start at</param> /// <param name="size">The size of the region to scan</param> /// <param name="result">The address, or <see cref="IntPtr.Zero"/> on failure</param> /// <returns>Whether the scan was successful or not</returns> public static bool Scan(IntPtr handle, PatternByte[] pattern, IntPtr baseAddress, int size, out IntPtr result) { //TODO: ready for 64-bit uint step = (uint)Math.Min(size, ScanStep); uint min = (uint)baseAddress.ToInt32(); uint max = (uint)(min + size); byte[] buffer = new byte[step + pattern.Length - 1]; //skip wildcards, since they would always match uint firstNonWildcard = PatternByte.FirstNonWildcardByte(pattern); var sw = new Stopwatch(); sw.Start(); for (uint i = min; i < max; i += step) { //read buffer //TODO: limit to not go outside region? Native.ReadProcessMemory(handle, (IntPtr)i, buffer, buffer.Length, out _); //loop through buffer for (uint j = 0; j < step; ++j) { bool match = true; //loop through pattern for (uint k = firstNonWildcard; k < pattern.Length; ++k) { if (pattern[k].Match(buffer[j + k])) { continue; } match = false; break; } if (match) { result = (IntPtr)(i + j); sw.Stop(); Debug.WriteLine("Stopwatch sigscan: " + sw.Elapsed); return(true); } } } result = IntPtr.Zero; return(false); }