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 char> data, intptr_t baseAddress, const char* lpPattern, intptr_t offset, intptr_t resultUsage)
{
// Ensure the incoming pattern is properly aligned..
if (strlen(lpPattern) % 2 > 0)
return 0;
// Convert the pattern to a vector of data..
std::vector<std::pair<unsigned char, bool>> pattern;
for (size_t x = 0, y = strlen(lpPattern) / 2; x < y; x++)
{
// Obtain the current byte..
std::stringstream stream(std::string(lpPattern + (x * 2), 2));
// Check if this is a wildcard..
if (stream.str() == "??")
pattern.push_back(std::make_pair(00, false));
else
{
auto byte = strtol(stream.str().c_str(), nullptr, 16);
pattern.push_back(std::make_pair((unsigned char)byte, true));
}
}
auto scanStart = data.begin();
auto resultCnt = 0;
while (true)
{
// Search for the pattern..
auto ret = std::search(scanStart, data.end(), pattern.begin(), pattern.end(),
[&](unsigned char curr, std::pair<unsigned char, bool> currPattern)
{
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 char> rawdata(0x00400000, 0x00400000 + 0x01000000);
// Scan for the pattern..
auto result = FindPattern(std::ref(rawdata), (intptr_t)0x00400000, "8B0D????????8B15????????83EC18535556", 2, 0);
if (result == 0)
// Not found..
else
// Found..