Last active
December 30, 2017 10:22
-
-
Save mrexodia/f058868b81b2f1cb011a to your computer and use it in GitHub Desktop.
FindPattern (based on: http://atom0s.com/forums/viewtopic.php?f=5&t=4 and https://bitbucket.org/mrexodia/patternfind)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "FindPattern.h" | |
#include <algorithm> | |
#include <cctype> | |
#include <string> | |
using namespace std; | |
struct PatternByte | |
{ | |
struct PatternNibble | |
{ | |
unsigned char data; | |
bool wildcard; | |
} nibble[2]; | |
}; | |
static string FormatPattern(string patterntext) | |
{ | |
string result; | |
int len = patterntext.length(); | |
for(int i = 0; i < len; i++) | |
if(patterntext[i] == '?' || isxdigit(patterntext[i])) | |
result += toupper(patterntext[i]); | |
return result; | |
} | |
static int HexChToInt(char ch) | |
{ | |
if(ch >= '0' && ch <= '9') | |
return ch - '0'; | |
else if(ch >= 'A' && ch <= 'F') | |
return ch - 'A' + 10; | |
else if(ch >= 'a' && ch <= 'f') | |
return ch - 'a' + 10; | |
return 0; | |
} | |
static bool TransformPattern(string patterntext, vector<PatternByte> & pattern) | |
{ | |
pattern.clear(); | |
patterntext = FormatPattern(patterntext); | |
int len = patterntext.length(); | |
if(!len) | |
return false; | |
if(len % 2) // not a multiple of 2 | |
{ | |
patterntext += '?'; | |
len++; | |
} | |
PatternByte newByte; | |
for(int i = 0, j = 0; i < len; i++) | |
{ | |
if(patterntext[i] == '?') // wildcard | |
{ | |
newByte.nibble[j].wildcard = true; // match anything | |
} | |
else //hex | |
{ | |
newByte.nibble[j].wildcard = false; | |
newByte.nibble[j].data = HexChToInt(patterntext[i]) & 0xF; | |
} | |
j++; | |
if(j == 2) // two nibbles = one byte | |
{ | |
j = 0; | |
pattern.push_back(newByte); | |
} | |
} | |
return true; | |
} | |
static bool MatchByte(const unsigned char byte, const PatternByte & pbyte) | |
{ | |
int matched = 0; | |
unsigned char n1 = (byte >> 4) & 0xF; | |
if(pbyte.nibble[0].wildcard) | |
matched++; | |
else if(pbyte.nibble[0].data == n1) | |
matched++; | |
unsigned char n2 = byte & 0xF; | |
if(pbyte.nibble[1].wildcard) | |
matched++; | |
else if(pbyte.nibble[1].data == n2) | |
matched++; | |
return (matched == 2); | |
} | |
size_t FindPattern(vector<unsigned char> data, const char* pszPattern, size_t baseAddress, size_t offset, int occurrence) | |
{ | |
// Build vectored pattern.. | |
vector<PatternByte> patterndata; | |
if(!TransformPattern(pszPattern, patterndata)) | |
return -1; | |
// The result count for multiple results.. | |
int resultCount = 0; | |
vector<unsigned char>::iterator scanStart = data.begin(); | |
while(true) | |
{ | |
// Search for the pattern.. | |
vector<unsigned char>::iterator ret = search(scanStart, data.end(), patterndata.begin(), patterndata.end(), MatchByte); | |
// Did we find a match.. | |
if(ret != data.end()) | |
{ | |
// If we hit the usage count, return the result.. | |
if(occurrence == 0 || resultCount == occurrence) | |
return baseAddress + distance(data.begin(), ret) + offset; | |
// Increment the found count and scan again.. | |
resultCount++; | |
scanStart = ++ret; | |
} | |
else | |
break; | |
} | |
return -1; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef _FINDPATTERN_H | |
#define _FINDPATTERN_H | |
#include <vector> | |
/** | |
* @brief Scans a given chunk of data for a given pattern. | |
* | |
* @param data The data to scan within for the given pattern. | |
* @param pszPattern The pattern to scan for. | |
* @param baseAddress The base address to add to the final result. | |
* @param offset The offset to add to final address. | |
* @param occurrence Zero-based occurrence of the pattern to return. | |
* | |
* @return Address of the pattern found, -1 otherwise. | |
*/ | |
std::size_t FindPattern(std::vector<unsigned char> data, const char* pszPattern, std::size_t baseAddress = 0, std::size_t offset = 0, int occurrence = 0); | |
#endif //_FINDPATTERN_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "FindPattern.h" | |
#include <iostream> | |
using namespace std; | |
int main() | |
{ | |
unsigned char test[16] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }; | |
vector<unsigned char> data(test, test + sizeof(test)); | |
size_t result = FindPattern(data, "?7 8? ?? CD"); | |
cout << "result: 0x" << hex << result << endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment