Skip to content

Instantly share code, notes, and snippets.

@mrexodia
Last active December 30, 2017 10:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mrexodia/f058868b81b2f1cb011a to your computer and use it in GitHub Desktop.
Save mrexodia/f058868b81b2f1cb011a to your computer and use it in GitHub Desktop.
#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;
}
#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
#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