Beispiel #1
0
 public PatternScanInstructionSet MakeInstructionSetWithoutMaskLong()
 {
     return(PatternScanInstructionSet.FromStringPattern("DA 69 DD AA FE B9 BB CC DD EE FF"));
 }
        /// <summary>
        /// Attempts to find a given pattern inside the memory region this class was created with.
        /// This method generates a list of instructions, which more efficiently determine at any array index if pattern is found.
        /// This method generally works better when the expected offset is bigger than 4096.
        /// </summary>
        /// <param name="pattern">
        ///     The pattern to look for inside the given region.
        ///     Example: "11 22 33 ?? 55".
        ///     Key: ?? represents a byte that should be ignored, anything else if a hex byte. i.e. 11 represents 0x11, 1F represents 0x1F
        /// </param>
        /// <returns>A result indicating an offset (if found) of the pattern.</returns>
        public PatternScanResult CompiledFindPattern(string pattern)
        {
            var instructionSet       = PatternScanInstructionSet.FromStringPattern(pattern);
            int numberOfInstructions = instructionSet.NumberOfInstructions;
            int dataLength           = _data.Length;

            byte *dataBasePointer = _dataPtr;
            byte *currentDataPointer;
            int   lastIndex = dataLength - Math.Max(instructionSet.Length, sizeof(long)) + 1;

            // Note: All of this has to be manually inlined otherwise performance suffers, this is a bit ugly though :/
            fixed(GenericInstruction *instructions = instructionSet.Instructions)
            {
                var firstInstruction = instructions[0];

                /*
                 *  There is an optimization going on in here apart from manual inlining which is why
                 *  this function is a tiny mess of more goto statements than it seems necessary.
                 *
                 *  Basically, it is considerably faster to reference a variable on the stack, than it is on the heap.
                 *
                 *  This is because the compiler can address the stack bound variable relative to the current stack pointer,
                 *  as opposing to having to dereference a pointer and then take an offset from the result address.
                 *
                 *  This ends up being considerably faster, which is important in a scenario where we are entirely CPU bound.
                 */

                int x = 0;

                while (x < lastIndex)
                {
                    currentDataPointer = dataBasePointer + x;
                    var compareValue = *(ulong *)currentDataPointer & firstInstruction.Mask;
                    if (compareValue != firstInstruction.LongValue)
                    {
                        goto singleInstructionLoopExit;
                    }

                    if (numberOfInstructions <= 1)
                    {
                        return(new PatternScanResult(x));
                    }

                    /* When NumberOfInstructions > 1 */
                    currentDataPointer += sizeof(ulong);
                    int y = 1;
                    do
                    {
                        compareValue = *(ulong *)currentDataPointer & instructions[y].Mask;
                        if (compareValue != instructions[y].LongValue)
                        {
                            goto singleInstructionLoopExit;
                        }

                        currentDataPointer += sizeof(ulong);
                        y++;
                    }while (y < numberOfInstructions);

                    return(new PatternScanResult(x));

                    singleInstructionLoopExit :;
                    x++;
                }


                // Check last few bytes in cases pattern was not found and long overflows into possibly unallocated memory.
                return(SimpleFindPattern(pattern, lastIndex));

                // PS. This function is a prime example why the `goto` statement is frowned upon.
                // I have to use it here for performance though.
            }
        }
Beispiel #3
0
 public PatternScanInstructionSet MakeInstructionSetWithoutMask()
 {
     return(PatternScanInstructionSet.FromStringPattern("DA 69 DD AA FE B9"));
 }