Exetools  

Go Back   Exetools > General > Source Code

Notices

Reply
 
Thread Tools Display Modes
  #1  
Old 02-09-2016, 08:50
atom0s's Avatar
atom0s atom0s is offline
Family
 
Join Date: Jan 2015
Location: 127.0.0.1
Posts: 396
Rept. Given: 26
Rept. Rcvd 126 Times in 63 Posts
Thanks Given: 54
Thanks Rcvd at 730 Times in 279 Posts
atom0s Reputation: 100-199 atom0s Reputation: 100-199
[C++] Pattern Scanner

I wrote a pattern scanner that makes use of C++11 features a while back and decided to adjust it to no longer require a mask be passed with it. Instead, the pattern is parsed for wildcards and handled accordingly.

This should be cross-platform and 64bit friendly.

PHP Code:

/**
 * Scans the given data for the pattern.
 *
 * @param {vector} data                     The data to scan within for the given pattern.
 * @param {intptr_t} baseAddress            The base address of where the scan is starting from.
 * @param {const char*} lpPattern           The pattern to scan for. (Wildcards are marked as ?? per byte.)
 * @param {intptr_t} offset                 The offset to add to the found location.
 * @param {intptr_t} resultUsage            The result offset to use when locating signatures that match multiple locations.
 * @returns {intptr_t}                      The address where the pattern was found, 0 otherwise.
 */
intptr_t FindPattern(std::vector<unsigned chardataintptr_t baseAddress, const charlpPatternintptr_t offsetintptr_t resultUsage)
{
    
// Ensure the incoming pattern is properly aligned..
    
if (strlen(lpPattern) % 0)
        return 
0;

    
// Convert the pattern to a vector of data..
    
std::vector<std::pair<unsigned charbool>> pattern;
    for (
size_t x 0strlen(lpPattern) / 2yx++)
    {
        
// Obtain the current byte..
        
std::stringstream stream(std::string(lpPattern + (2), 2));

        
// Check if this is a wildcard..
        
if (stream.str() == "??")
            
pattern.push_back(std::make_pair(00false));
        else
        {
            
auto byte strtol(stream.str().c_str(), nullptr16);
            
pattern.push_back(std::make_pair((unsigned char)bytetrue));
        }
    }

    
auto scanStart data.begin();
    
auto resultCnt 0;

    while (
true)
    {
        
// Search for the pattern..
        
auto ret std::search(scanStartdata.end(), pattern.begin(), pattern.end(),
            [&](
unsigned char currstd::pair<unsigned charboolcurrPattern)
        {
            return (!
currPattern.second) || curr == currPattern.first;
        });

        
// Did we find a match..
        
if (ret != data.end())
        {
            
// If we hit the usage count, return the result..
            
if (resultCnt == resultUsage || resultUsage == 0)
                return (
std::distance(data.begin(), ret) + baseAddress) + offset;

            
// Increment the found count and scan again..
            
++resultCnt;
            
scanStart = ++ret;
        }
        else
            break;
    }

    return 
0;

Example usage:
PHP Code:
    // Obtain the raw data of the memory to scan..
    
std::vector<unsigned charrawdata(0x004000000x00400000 0x01000000);

    
// Scan for the pattern..
    
auto result FindPattern(std::ref(rawdata), (intptr_t)0x00400000"8B0D????????8B15????????83EC18535556"20);
    if (
result == 0)
        
// Not found..
    
else
        
// Found.. 
Reply With Quote
The Following 2 Users Gave Reputation+1 to atom0s For This Useful Post:
b30wulf (02-10-2016), mr.exodia (02-09-2016)
The Following 6 Users Say Thank You to atom0s For This Useful Post:
Arkshine (03-26-2016), CryptXor (02-10-2016), Insid3Code (02-10-2016), Nacho_dj (02-10-2016), niculaita (02-10-2016), sh3dow (07-29-2019)
  #2  
Old 02-10-2016, 14:41
atom0s's Avatar
atom0s atom0s is offline
Family
 
Join Date: Jan 2015
Location: 127.0.0.1
Posts: 396
Rept. Given: 26
Rept. Rcvd 126 Times in 63 Posts
Thanks Given: 54
Thanks Rcvd at 730 Times in 279 Posts
atom0s Reputation: 100-199 atom0s Reputation: 100-199
A version in C# that I made for my Steamless project:
PHP Code:
        /// <summary>
        /// Scans the given data for the given pattern.
        /// 
        /// Notes:
        ///     Patterns are assumed to be 2 byte hex values with spaces.
        ///     Wildcards are represented by ??.
        /// </summary>
        /// <param name="data"></param>
        /// <param name="pattern"></param>
        /// <returns></returns>
        
public static uint FindPattern(byte[] datastring pattern)
        {
            try
            {
                
// Trim the pattern from extra whitespace..
                
var trimPattern pattern.Replace(" """).Trim();

                
// Convert the pattern to a byte array..
                
var patternMask = new List<bool>();
                var 
patternData Enumerable.Range(0trimPattern.Length).Where(=> == 0)
                                            .
Select(=>
                                                {
                                                    var 
bt trimPattern.Substring(x2);
                                                    
patternMask.Add(!bt.Contains('?'));
                                                    return 
bt.Contains('?') ? (byte)Convert.ToByte(bt16);
                                                }).
ToArray();

                
// Scan the given data for our pattern..
                
for (var 0data.Lengthx++)
                {
                    if (!
patternData.Where((ty) => patternMask[y] && != data[y]).Any())
                        return (
uint)x;
                }

                return 
0;
            }
            catch
            {
                return 
0;
            }
        } 
Example usage can be seen in Steamless here:
Code:
https://github.com/atom0s/Steamless
Reply With Quote
The Following User Says Thank You to atom0s For This Useful Post:
CryptXor (02-10-2016)
  #3  
Old 02-10-2016, 22:00
mr.exodia mr.exodia is offline
Retired Moderator
 
Join Date: Nov 2011
Posts: 784
Rept. Given: 492
Rept. Rcvd 1,122 Times in 305 Posts
Thanks Given: 90
Thanks Rcvd at 711 Times in 333 Posts
mr.exodia Reputation: 1100-1299 mr.exodia Reputation: 1100-1299 mr.exodia Reputation: 1100-1299 mr.exodia Reputation: 1100-1299 mr.exodia Reputation: 1100-1299 mr.exodia Reputation: 1100-1299 mr.exodia Reputation: 1100-1299 mr.exodia Reputation: 1100-1299 mr.exodia Reputation: 1100-1299
Here is a version I did. It supports nibble wildcards for the more fine-grained users. It also has a parallel signature scanner.

https://github.com/mrexodia/PatternFinder
Reply With Quote
The Following User Says Thank You to mr.exodia For This Useful Post:
atom0s (02-11-2016)
  #4  
Old 02-11-2016, 05:53
atom0s's Avatar
atom0s atom0s is offline
Family
 
Join Date: Jan 2015
Location: 127.0.0.1
Posts: 396
Rept. Given: 26
Rept. Rcvd 126 Times in 63 Posts
Thanks Given: 54
Thanks Rcvd at 730 Times in 279 Posts
atom0s Reputation: 100-199 atom0s Reputation: 100-199
Quote:
Originally Posted by mr.exodia View Post
Here is a version I did. It supports nibble wildcards for the more fine-grained users. It also has a parallel signature scanner.

https://github.com/mrexodia/PatternFinder
Just a question, but have you ever really put the nibble support to use much? I personally never found it useful in scanners and felt it just added bloat to the code for something that could just be a full wildcard byte. Just wondering what some situations are that others found it useful.
Reply With Quote
  #5  
Old 02-11-2016, 06:03
mr.exodia mr.exodia is offline
Retired Moderator
 
Join Date: Nov 2011
Posts: 784
Rept. Given: 492
Rept. Rcvd 1,122 Times in 305 Posts
Thanks Given: 90
Thanks Rcvd at 711 Times in 333 Posts
mr.exodia Reputation: 1100-1299 mr.exodia Reputation: 1100-1299 mr.exodia Reputation: 1100-1299 mr.exodia Reputation: 1100-1299 mr.exodia Reputation: 1100-1299 mr.exodia Reputation: 1100-1299 mr.exodia Reputation: 1100-1299 mr.exodia Reputation: 1100-1299 mr.exodia Reputation: 1100-1299
@atom0s: sure, I mainly use it for a more fine-grained matching on instructions with wildcard registers, for example FF D0 (call eax), for call reg you need to match FF D?, so without nibbles you would match on FF and this also matches a lot of other shit (invalid instructions, inc [reg], call [] etc). I agree that in signature matching it isn't quite useful, but if you need to find the next 'call reg' in a reliable way you need nibble matching. Same applies to 'push reg'.

Obviously if you feel it's a bloat you shouldn't use it I just commented so other people don't have to implement it themselves.

Greetings
Reply With Quote
The Following User Says Thank You to mr.exodia For This Useful Post:
tonyweb (02-15-2016)
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is On


Similar Threads
Thread Thread Starter Forum Replies Last Post
Reversing Key using pattern Maltese General Discussion 11 11-16-2007 19:49
pattern matching algorithm OHPen General Discussion 9 10-10-2003 05:11


All times are GMT +8. The time now is 18:35.


Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX, chessgod101
( 1998 - 2024 )