Beispiel #1
0
        public void TestFromByteEnumerationWithWildcards(IEnumerable <Tuple <byte, bool> > input, int expectedLength, bool expectedHasWildcards)
        {
            var sut = BytePattern.From(input);

            Check.That(sut.Length).IsEqualTo(expectedLength);
            Check.That(sut.HasWildcards).IsEqualTo(expectedHasWildcards);
        }
Beispiel #2
0
        public void TestFromByteEnumeration(IEnumerable <byte> input, int expectedLength)
        {
            var sut = BytePattern.From(input);

            Check.That(sut.Length).IsEqualTo(expectedLength);
            Check.That(sut.HasWildcards).IsFalse();
        }
Beispiel #3
0
        public ulong AobScan(BytePattern bytePattern)
        {
            for (var moduleIndex = 0; moduleIndex < _moduleByteBuffer.Length; moduleIndex++)
            {
                // Check the beginning bytes of the module
                if (_moduleByteBuffer[moduleIndex] != bytePattern.Pattern[0])
                {
                    continue;
                }


                if (PatternCheck(moduleIndex, bytePattern.Pattern))
                {
                    if (bytePattern.HexOffset < 0)
                    {
                        return((_moduleBaseAddress + (ulong)moduleIndex) - (ulong)bytePattern.HexOffset);
                    }
                    else
                    {
                        return((_moduleBaseAddress + (ulong)moduleIndex) + (ulong)bytePattern.HexOffset);
                    }
                }
            }
            return(0);
        }
Beispiel #4
0
        public void TestParse(string input, int expectedLength, bool expectedHasWildcards)
        {
            var sut = BytePattern.Parse(input);

            Check.That(sut.Length).IsEqualTo(expectedLength);
            Check.That(sut.HasWildcards).IsEqualTo(expectedHasWildcards);
        }
Beispiel #5
0
        static bool CheckProtection(BytePattern pattern, uint flags)
        {
            var protectionFlags = (WindowsApi.RegionPageProtection)flags;

            foreach (var protectionExclusion in ProtectionExclusions)
            {
                if (protectionFlags.HasFlag(protectionExclusion))
                {
                    return(false);
                }
            }

            return(true); // we need to check only READ?

            /*
             * foreach (var protectionOrInclusive in pattern.Config.PageProtections)
             * {
             *  if (protectionFlags.HasFlag(protectionOrInclusive))
             *  {
             *      return true;
             *  }
             * }
             *
             * return false;
             */
        }
        private PlatformHeuristics LoadHeuristics(PlatformHeuristics_v1 heuristics)
        {
            if (heuristics == null)
            {
                return(new PlatformHeuristics
                {
                    ProcedurePrologs = new BytePattern[0],
                });
            }
            BytePattern[] prologs;
            if (heuristics.ProcedurePrologs == null)
            {
                prologs = new BytePattern[0];
            }
            else
            {
                prologs = heuristics.ProcedurePrologs
                          .Select(p => LoadBytePattern(p))
                          .Where(p => p.Bytes != null)
                          .ToArray();
            }

            return(new PlatformHeuristics
            {
                ProcedurePrologs = prologs
            });
        }
Beispiel #7
0
        public static ulong?FindPatternAddresses(Process process, BytePattern pattern)
        {
            List <ulong> matchAddresses = new List <ulong>();
            var          addressRange   = pattern.AddressRange;
            ulong        currentAddress = addressRange.Start;

            while (currentAddress < addressRange.End && !process.HasExited)
            {
                WindowsApi.MEMORY_BASIC_INFORMATION64 memoryRegion;
                if (WindowsApi.VirtualQueryEx(process.Handle, (IntPtr)currentAddress, out memoryRegion, (uint)Marshal.SizeOf(typeof(WindowsApi.MEMORY_BASIC_INFORMATION64))) > 0 &&
                    memoryRegion.RegionSize > 0 &&
                    memoryRegion.State == (uint)WindowsApi.RegionPageState.MEM_COMMIT &&
                    CheckProtection(pattern, memoryRegion.Protect))
                {
                    var regionStartAddress = memoryRegion.BaseAddress;
                    if (addressRange.Start > regionStartAddress)
                    {
                        regionStartAddress = addressRange.Start;
                    }

                    var regionEndAddress = memoryRegion.BaseAddress + memoryRegion.RegionSize;
                    if (addressRange.End < regionEndAddress)
                    {
                        regionEndAddress = addressRange.End;
                    }

                    ulong  regionBytesToRead = regionEndAddress - regionStartAddress;
                    byte[] regionBytes       = new byte[regionBytesToRead];

                    if (process.HasExited)
                    {
                        break;
                    }

                    int lpNumberOfBytesRead = 0;
                    WindowsApi.ReadProcessMemory(process.Handle, (IntPtr)regionStartAddress, regionBytes, regionBytes.Length, ref lpNumberOfBytesRead);

                    var matchIndices = FindPatternMatchIndices(regionBytes, pattern);

                    foreach (var matchIndex in matchIndices)
                    {
                        var matchAddress = regionStartAddress + (ulong)matchIndex;
                        matchAddresses.Add(matchAddress);

                        Logger.Log(LogLevel.Info, $"Found '{pattern.Config.Name}' at address 0x{matchAddress.ToString("X8")}");

                        break;
                    }
                }

                if (matchAddresses.Any())
                {
                    break;
                }

                currentAddress = memoryRegion.BaseAddress + memoryRegion.RegionSize;
            }

            return(matchAddresses.Count > 0 ? matchAddresses[0] : (ulong?)null);
        }
Beispiel #8
0
        static void GetLongestPrefixSuffices(BytePattern pattern, ref int[] longestPrefixSuffices)
        {
            int patternLength = pattern.Bytes.Length;
            int length        = 0;
            int 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];
                    }
                }
            }
        }
Beispiel #9
0
        /// <summary>Reads a string from the address in the remote process with the given length and encoding. The string gets truncated at the first zero character.</summary>
        /// <param name="encoding">The encoding used by the string.</param>
        /// <param name="address">The address of the string.</param>
        /// <param name="length">The length of the string.</param>
        /// <returns>The string.</returns>
        public string ReadRemoteStringUntilFirstNullCharacter(Encoding encoding, IntPtr address, int length)
        {
            Contract.Requires(encoding != null);
            Contract.Requires(length >= 0);
            Contract.Ensures(Contract.Result <string>() != null);

            var data = ReadRemoteMemory(address, length * encoding.GetSimpleByteCountPerChar());

            // TODO We should cache the pattern per encoding.
            var index = PatternScanner.FindPattern(BytePattern.From(new byte[encoding.GetSimpleByteCountPerChar()]), data);

            if (index == -1)
            {
                index = data.Length;
            }

            try
            {
                return(Encoding.UTF8.GetString(data, 0, Math.Min(index, data.Length)));
            }
            catch
            {
                return(string.Empty);
            }
        }
Beispiel #10
0
        public void TestToString(string input, PatternMaskFormat format, string expectedPattern, string expectedMask)
        {
            var sut = BytePattern.Parse(input);

            var(pattern, mask) = sut.ToString(format);

            Check.That(pattern).IsEqualTo(expectedPattern);
            Check.That(mask).IsEqualTo(expectedMask);
        }
Beispiel #11
0
        private void Given_Data(Address addr, string hexBytes)
        {
            bool foundSeg = program.SegmentMap.TryFindSegment(addr, out var seg);

            Assert.IsTrue(foundSeg);
            var w = seg.MemoryArea.CreateLeWriter(addr);

            w.WriteBytes(BytePattern.FromHexBytes(hexBytes));
        }
Beispiel #12
0
        private void AssertEqual(float fExpected, string bytes)
        {
            var mem     = BytePattern.FromHexBytes(bytes).ToArray();
            var uFloat  = MemoryArea.ReadLeUInt32(mem, 0);
            var mbf     = new MBFFloat32(uFloat);
            var fActual = mbf.ToSingle(null);

            Assert.AreEqual(fExpected, fActual, 1e-30);
        }
Beispiel #13
0
        private void AssertEqual(string sHexString, params byte[] expected)
        {
            var actual = BytePattern.FromHexBytes(sHexString);

            Assert.AreEqual(expected.Length, actual.Length);
            for (int i = 0; i < expected.Length; ++i)
            {
                Assert.AreEqual(expected[i], actual[i], $"Different at position {i}");
            }
        }
Beispiel #14
0
        private void Given_Data(uint uAddr, string hexBytes)
        {
            var addr  = Address.Ptr32(uAddr);
            var isSeg = program.SegmentMap.TryFindSegment(addr, out var seg);

            Assert.IsTrue(isSeg);
            var w = program.Architecture.CreateImageWriter(seg.MemoryArea, addr);

            w.WriteBytes(BytePattern.FromHexBytes(hexBytes).ToArray());
        }
Beispiel #15
0
        public void RemoveVideoCardCheck(string pattern, int startIndex)
        {
            var bytePattern = new BytePattern
            {
                Pattern = pattern.Replace("\n", " ").Replace("\r", " ").Split(' '),
            };
            var index = bytePattern.Match(inputString) + startIndex;

            Output[index] = Convert.ToByte("EB", 16);
        }
Beispiel #16
0
        private void Given_Data(uint uAddr, string hexBytes)
        {
            var  addr     = Address.Ptr32(uAddr);
            bool foundSeg = program.SegmentMap.TryFindSegment(addr, out var seg);

            Assert.IsTrue(foundSeg);
            var w = seg.MemoryArea.CreateLeWriter(addr);

            w.WriteBytes(BytePattern.FromHexBytes(hexBytes).ToArray());
        }
Beispiel #17
0
        // KMP algorithm modified to search bytes with a nullable/wildcard search
        static List <int> FindPatternMatchIndices(byte[] bytes, BytePattern pattern, bool stopAfterFirst)
        {
            List <int> matchedIndices = new List <int>();

            int textLength    = bytes.Length;
            int patternLength = pattern.Bytes.Length;

            if (textLength == 0 || patternLength == 0 || textLength < patternLength)
            {
                return(matchedIndices);
            }

            int[] longestPrefixSuffices = new int[patternLength];

            GetLongestPrefixSuffices(pattern, ref longestPrefixSuffices);

            int textIndex    = 0;
            int patternIndex = 0;

            while (textIndex < textLength)
            {
                if (!pattern.Bytes[patternIndex].HasValue || // Ignore compare if the pattern index is nullable - this treats it like a * wildcard
                    bytes[textIndex] == pattern.Bytes[patternIndex])
                {
                    textIndex++;
                    patternIndex++;
                }

                if (patternIndex == patternLength)
                {
                    matchedIndices.Add(textIndex - patternIndex);
                    patternIndex = longestPrefixSuffices[patternIndex - 1];

                    if (stopAfterFirst)
                    {
                        break;
                    }
                }
                else if (textIndex < textLength &&
                         (pattern.Bytes[patternIndex].HasValue && // Only compare disparity if the pattern byte isn't a null wildcard
                          bytes[textIndex] != pattern.Bytes[patternIndex]))
                {
                    if (patternIndex != 0)
                    {
                        patternIndex = longestPrefixSuffices[patternIndex - 1];
                    }
                    else
                    {
                        textIndex++;
                    }
                }
            }

            return(matchedIndices);
        }
Beispiel #18
0
        private static void AssertEqual(IProcessorArchitecture arch, string sExpected, string hexString)
        {
            var bytes   = BytePattern.FromHexBytes(hexString);
            var mem     = new ByteMemoryArea(Address.Ptr32(0x0010_0000), bytes);
            var rdr     = mem.CreateLeReader(0);
            var dasm    = arch.CreateDisassembler(rdr);
            var instr   = (X86Instruction)dasm.First();
            var sActual = instr.ToString("A");

            Assert.AreEqual(sExpected, sActual);
        }
Beispiel #19
0
        public ArrayOfBytesMemoryComparer(BytePattern pattern)
        {
            Contract.Requires(pattern != null);

            bytePattern = pattern;

            if (!bytePattern.HasWildcards)
            {
                byteArray = bytePattern.ToByteArray();
            }
        }
Beispiel #20
0
 private void Given_Type(int typeIndex, string hexString)
 {
     var bytes = BytePattern.FromHexBytes(hexString);
     var rdr = new LeImageReader(bytes);
     this.typesByIndex.Add(typeIndex, new TypeDefinition
     {
         Leaves = new object[]
         {
             CodeViewTypeLoader.ReadLeaf(rdr)
         }
     });
 }
Beispiel #21
0
 private Program LoadProgram(Dictionary <string, object> pArgs, LoadDetails loadDetails)
 {
     if (pArgs.ContainsKey("--data"))
     {
         var hexBytes = (string)pArgs["--data"];
         var image    = BytePattern.FromHexBytes(hexBytes).ToArray();
         return(decompiler.LoadRawImage(image, loadDetails));
     }
     else
     {
         return(decompiler.LoadRawImage((string)pArgs["filename"], loadDetails));
     }
 }
Beispiel #22
0
        public void RemoveSignatureCheck(string pattern, int startIndex)
        {
            var bytePattern = new BytePattern
            {
                Pattern = pattern.Replace("\n", " ").Replace("\r", " ").Split(' '),
            };
            var index = bytePattern.Match(inputString);

            Output[index + startIndex]     = Convert.ToByte("E9", 16);
            Output[index + startIndex + 1] = (byte)(Output[index + startIndex + 2] + 1);
            Output[index + startIndex + 2] = Output[index + startIndex + 3];
            Output[index + startIndex + 3] = 0;
            Output[index + startIndex + 5] = Convert.ToByte("90", 16);;
        }
Beispiel #23
0
        static bool CheckProtection(BytePattern pattern, uint flags)
        {
            var protectionFlags = (WindowsApi.RegionPageProtection)flags;

            foreach (var protectionExclusion in ProtectionExclusions)
            {
                if (protectionFlags.HasFlag(protectionExclusion))
                {
                    return(false);
                }
            }

            return(true);
        }
        private void AssertCode(string hexBytes, params string[] sExpectedInstrs)
        {
            byte[]         bytes   = BytePattern.FromHexBytes(hexBytes);
            ByteMemoryArea mem     = new ByteMemoryArea(LoadAddress, bytes);
            var            dasm    = arch.CreateDisassembler(arch.CreateImageReader(mem, 0U));
            var            sInstrs = dasm.Select(i => i.ToString()).ToArray();
            var            c       = Math.Min(sExpectedInstrs.Length, sInstrs.Length);

            for (int i = 0; i < c; ++i)
            {
                Assert.AreEqual(sExpectedInstrs[i], sInstrs[i]);
            }
            Assert.AreEqual(sExpectedInstrs.Length, sInstrs.Length, "Incorrect # of instructions");
        }
        private MemoryArea HexStringToMemoryArea(string sBytes)
        {
            int shift = 12;
            int bb    = 0;
            var words = new List <ushort>();

            for (int i = 0; i < sBytes.Length; ++i)
            {
                char c = sBytes[i];
                if (BytePattern.TryParseHexDigit(c, out byte b))
                {
                    bb    |= (b << shift);
                    shift -= 4;
                    if (shift < 0)
                    {
                        words.Add((ushort)bb);
                        shift = 12;
                        bb    = 0;
                    }
                }
            }
            return(new Word16MemoryArea(this.LoadAddress, words.ToArray()));
        }
 private void Disassemble()
 {
     try
     {
         if (this.arch is null)
         {
             return;
         }
         if (!arch.TryParseAddress(control.Address.Text, out var addr))
         {
             return;
         }
         var bytes = BytePattern.FromHexBytes(control.HexBytes.Text).ToArray();
         if (bytes.Length > 0)
         {
             var mem    = arch.CreateMemoryArea(addr, bytes);
             var dumper = new Dumper(new Program())
             {
                 ShowAddresses = true,
                 ShowCodeBytes = true,
             };
             var sw = new StringWriter();
             dumper.DumpAssembler(arch, mem, mem.BaseAddress, bytes.Length, new Core.Output.TextFormatter(sw));
             control.Disassembly.Text = sw.ToString();
         }
         else
         {
             control.Disassembly.Text = "";
         }
     }
     catch (Exception ex)
     {
         var diagSvc = services.RequireService <IDiagnosticsService>();
         diagSvc.Error(ex, "An error occurred during disassembly.");
     }
 }
        //$REFACTOR: this is so generic it should live somewhere else.
        public static List <byte> LoadHexBytes(string sBytes)
        {
            int shift = 4;
            int bb    = 0;
            var bytes = new List <byte>();

            for (int i = 0; i < sBytes.Length; ++i)
            {
                char c = sBytes[i];
                byte b;
                if (BytePattern.TryParseHexDigit(c, out b))
                {
                    bb     = bb | (b << shift);
                    shift -= 4;
                    if (shift < 0)
                    {
                        bytes.Add((byte)bb);
                        shift = 4;
                        bb    = 0;
                    }
                }
            }
            return(bytes);
        }
Beispiel #28
0
        public MaskedPattern?LoadMaskedPattern(BytePattern_v1 sPattern)
        {
            List <byte> bytes;
            List <byte> mask;

            if (sPattern.Bytes == null)
            {
                return(null);
            }
            if (sPattern.Mask == null)
            {
                bytes = new List <byte>();
                mask  = new List <byte>();
                int shift = 4;
                int bb    = 0;
                int mm    = 0;
                for (int i = 0; i < sPattern.Bytes.Length; ++i)
                {
                    char c = sPattern.Bytes[i];
                    if (BytePattern.TryParseHexDigit(c, out byte b))
                    {
                        bb    |= (b << shift);
                        mm    |= (0x0F << shift);
                        shift -= 4;
                        if (shift < 0)
                        {
                            bytes.Add((byte)bb);
                            mask.Add((byte)mm);
                            shift = 4;
                            bb    = mm = 0;
                        }
                    }
                    else if (c == '?' || c == '.')
                    {
                        shift -= 4;
                        if (shift < 0)
                        {
                            bytes.Add((byte)bb);
                            mask.Add((byte)mm);
                            shift = 4;
                            bb    = mm = 0;
                        }
                    }
                }
                Debug.Assert(bytes.Count == mask.Count);
            }
            else
            {
                bytes = BytePattern.FromHexBytes(sPattern.Bytes);
                mask  = BytePattern.FromHexBytes(sPattern.Mask);
            }
            if (bytes.Count == 0)
            {
                return(null);
            }
            return(new MaskedPattern
            {
                Bytes = bytes.ToArray(),
                Mask = mask.ToArray()
            });
        }
Beispiel #29
0
        /// <summary>
        /// Creates the comparer from the user input.
        /// </summary>
        /// <returns>The scan comparer.</returns>
        private IScanComparer CreateComparer(ScanSettings settings)
        {
            Contract.Requires(settings != null);
            Contract.Ensures(Contract.Result <IScanComparer>() != null);

            var compareType          = compareTypeComboBox.SelectedValue;
            var checkBothInputFields = compareType == ScanCompareType.Between || compareType == ScanCompareType.BetweenOrEqual;

            if (settings.ValueType == ScanValueType.Byte || settings.ValueType == ScanValueType.Short || settings.ValueType == ScanValueType.Integer || settings.ValueType == ScanValueType.Long)
            {
                var numberStyle = isHexCheckBox.Checked ? NumberStyles.HexNumber : NumberStyles.Integer;
                if (!long.TryParse(dualValueBox.Value1, numberStyle, null, out var value1))
                {
                    throw new InvalidInputException(dualValueBox.Value1);
                }
                if (!long.TryParse(dualValueBox.Value2, numberStyle, null, out var value2) && checkBothInputFields)
                {
                    throw new InvalidInputException(dualValueBox.Value2);
                }

                switch (settings.ValueType)
                {
                case ScanValueType.Byte:
                    return(new ByteMemoryComparer(compareType, (byte)value1, (byte)value2));

                case ScanValueType.Short:
                    return(new ShortMemoryComparer(compareType, (short)value1, (short)value2));

                case ScanValueType.Integer:
                    return(new IntegerMemoryComparer(compareType, (int)value1, (int)value2));

                case ScanValueType.Long:
                    return(new LongMemoryComparer(compareType, value1, value2));
                }
            }
            else if (settings.ValueType == ScanValueType.Float || settings.ValueType == ScanValueType.Double)
            {
                int CalculateSignificantDigits(string input, NumberFormatInfo numberFormat)
                {
                    Contract.Requires(input != null);
                    Contract.Requires(numberFormat != null);

                    var digits = 0;

                    var decimalIndex = input.IndexOf(numberFormat.NumberDecimalSeparator, StringComparison.Ordinal);

                    if (decimalIndex != -1)
                    {
                        digits = input.Length - 1 - decimalIndex;
                    }

                    return(digits);
                }

                var nf1 = Utils.GuessNumberFormat(dualValueBox.Value1);
                if (!double.TryParse(dualValueBox.Value1, NumberStyles.Float, nf1, out var value1))
                {
                    throw new InvalidInputException(dualValueBox.Value1);
                }
                var nf2 = Utils.GuessNumberFormat(dualValueBox.Value2);
                if (!double.TryParse(dualValueBox.Value2, NumberStyles.Float, nf2, out var value2) && checkBothInputFields)
                {
                    throw new InvalidInputException(dualValueBox.Value2);
                }

                var significantDigits = Math.Max(
                    CalculateSignificantDigits(dualValueBox.Value1, nf1),
                    CalculateSignificantDigits(dualValueBox.Value2, nf2)
                    );

                var roundMode = roundStrictRadioButton.Checked ? ScanRoundMode.Strict : roundLooseRadioButton.Checked ? ScanRoundMode.Normal : ScanRoundMode.Truncate;

                switch (settings.ValueType)
                {
                case ScanValueType.Float:
                    return(new FloatMemoryComparer(compareType, roundMode, significantDigits, (float)value1, (float)value2));

                case ScanValueType.Double:
                    return(new DoubleMemoryComparer(compareType, roundMode, significantDigits, value1, value2));
                }
            }
            else if (settings.ValueType == ScanValueType.ArrayOfBytes)
            {
                var pattern = BytePattern.Parse(dualValueBox.Value1);

                return(new ArrayOfBytesMemoryComparer(pattern));
            }
            else if (settings.ValueType == ScanValueType.String)
            {
                if (string.IsNullOrEmpty(dualValueBox.Value1))
                {
                    throw new InvalidInputException(dualValueBox.Value1);
                }

                var encoding = encodingUtf8RadioButton.Checked ? Encoding.UTF8 : encodingUtf16RadioButton.Checked ? Encoding.Unicode : Encoding.UTF32;

                return(new StringMemoryComparer(dualValueBox.Value1, encoding, caseSensitiveCheckBox.Checked));
            }

            throw new InvalidOperationException();
        }
Beispiel #30
0
        public static List <ulong> FindPatternAddresses(Process process, AddressRange addressRange, BytePattern pattern, bool stopAfterFirst)
        {
            List <ulong> matchAddresses = new List <ulong>();

            ulong currentAddress = addressRange.Start;

            while (currentAddress < addressRange.End && !process.HasExited)
            {
                WindowsApi.MEMORY_BASIC_INFORMATION64 memoryRegion;
                var structByteCount = WindowsApi.VirtualQueryEx(process.Handle, (IntPtr)currentAddress, out memoryRegion, (uint)Marshal.SizeOf(typeof(WindowsApi.MEMORY_BASIC_INFORMATION64)));
                if (structByteCount > 0 &&
                    memoryRegion.RegionSize > 0 &&
                    memoryRegion.State == (uint)WindowsApi.RegionPageState.MEM_COMMIT &&
                    CheckProtection(pattern, memoryRegion.Protect))
                {
                    var regionStartAddress = memoryRegion.BaseAddress;
                    if (addressRange.Start > regionStartAddress)
                    {
                        regionStartAddress = addressRange.Start;
                    }

                    var regionEndAddress = memoryRegion.BaseAddress + memoryRegion.RegionSize;
                    if (addressRange.End < regionEndAddress)
                    {
                        regionEndAddress = addressRange.End;
                    }

                    if (process.HasExited)
                    {
                        break;
                    }

                    ulong  regionBytesToRead = regionEndAddress - regionStartAddress;
                    byte[] regionBytes       = new byte[regionBytesToRead];

                    int lpNumberOfBytesRead = 0;
                    WindowsApi.ReadProcessMemory(process.Handle, (IntPtr)regionStartAddress, regionBytes, regionBytes.Length, ref lpNumberOfBytesRead);

                    var matchIndices = FindPatternMatchIndices(regionBytes, pattern, stopAfterFirst);

                    if (matchIndices.Any() && stopAfterFirst)
                    {
                        var matchAddress = regionStartAddress + (ulong)matchIndices.First();
                        matchAddresses.Add(matchAddress);

                        break;
                    }
                    else
                    {
                        foreach (var matchIndex in matchIndices)
                        {
                            var matchAddress = regionStartAddress + (ulong)matchIndex;
                            matchAddresses.Add(matchAddress);
                        }
                    }
                }

                if (structByteCount == 0)
                {
                    Log.WriteLine("Page query returned 0 bytes");
                    break;
                }

                currentAddress = memoryRegion.BaseAddress + memoryRegion.RegionSize;
            }

            return(matchAddresses);
        }
        private PlatformHeuristics LoadHeuristics(PlatformHeuristics_v1 heuristics)
        {
            if (heuristics == null)
            {
                return new PlatformHeuristics
                {
                    ProcedurePrologs = new BytePattern[0],
                };
            }
            BytePattern[] prologs;
            if (heuristics.ProcedurePrologs == null)
            {
                prologs = new BytePattern[0];
            }
            else
            {
                prologs = heuristics.ProcedurePrologs
                    .Select(p => LoadBytePattern(p))
                    .Where(p => p.Bytes != null)
                    .ToArray();
            }

            return new PlatformHeuristics
            {
                ProcedurePrologs = prologs
            };
        }