static void GetLongestPrefixSuffices(BytePattern pattern, ref Int32[] longestPrefixSuffices) { Int32 patternLength = pattern.Bytes.Length; Int32 length = 0; Int32 patternIndex = 1; longestPrefixSuffices[0] = 0; while (patternIndex < patternLength) { if (pattern.Bytes[patternIndex] == pattern.Bytes[length]) { length++; longestPrefixSuffices[patternIndex] = length; patternIndex++; } else { if (length == 0) { longestPrefixSuffices[patternIndex] = 0; patternIndex++; } else { length = longestPrefixSuffices[length - 1]; } } } }
public List <UInt64> FindFirstPatternAddresses(AddressRange addressRange, BytePattern pattern) { List <UInt64> matchAddresses = new List <UInt64>(); UInt64 currentAddress = addressRange.Start; List <Byte[]> byteArrays = new List <Byte[]>(); while (currentAddress < addressRange.End) { if (VirtualQueryEx(process.Handle, (IntPtr)currentAddress, out MEMORY_BASIC_INFORMATION64 memoryRegion, (UInt32)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION64))) > 0 && memoryRegion.RegionSize > 0 && memoryRegion.State == 0x1000 && // MEM_COMMIT (memoryRegion.Protect & 0x20) > 0) // PAGE_EXECUTE_READ { var regionStartAddress = memoryRegion.BaseAddress; if (addressRange.Start > regionStartAddress) { regionStartAddress = addressRange.Start; } var regionEndAddress = memoryRegion.BaseAddress + memoryRegion.RegionSize; if (addressRange.End < regionEndAddress) { regionEndAddress = addressRange.End; } UInt64 regionBytesToRead = regionEndAddress - regionStartAddress; Byte[] regionBytes = new Byte[regionBytesToRead]; Int32 lpNumberOfBytesRead = 0; ReadProcessMemory(process.Handle, (IntPtr)regionStartAddress, regionBytes, regionBytes.Length, ref lpNumberOfBytesRead); byteArrays.Add(regionBytes); if (regionBytes.Length == 0 || pattern.Bytes.Length == 0 || regionBytes.Length < pattern.Bytes.Length) { continue; } List <Int32> matchedIndices = new List <Int32>(); Int32[] longestPrefixSuffices = new Int32[pattern.Bytes.Length]; GetLongestPrefixSuffices(pattern, ref longestPrefixSuffices); Int32 textIndex = 0; Int32 patternIndex = 0; while (textIndex < regionBytes.Length) { if (!pattern.Bytes[patternIndex].HasValue || regionBytes[textIndex] == pattern.Bytes[patternIndex]) { textIndex++; patternIndex++; } if (patternIndex == pattern.Bytes.Length) { matchedIndices.Add(textIndex - patternIndex); patternIndex = longestPrefixSuffices[patternIndex - 1]; break; } else if (textIndex < regionBytes.Length && (pattern.Bytes[patternIndex].HasValue && regionBytes[textIndex] != pattern.Bytes[patternIndex])) { if (patternIndex != 0) { patternIndex = longestPrefixSuffices[patternIndex - 1]; } else { textIndex++; } } } if (matchedIndices.Any()) { matchAddresses.Add(regionStartAddress + (UInt64)matchedIndices.First()); } } currentAddress = memoryRegion.BaseAddress + memoryRegion.RegionSize; } return(matchAddresses); }