Browse Source

Updated FindPattern implementation to use boyre-moore pattern for faster scanning.

pull/45/head
atom0s 7 years ago
parent
commit
a2038c1e33
  1. BIN
      Ashita.dll
  2. BIN
      injector.exe
  3. 151
      plugins/ADK/AS_Memory.h

BIN
Ashita.dll

Binary file not shown.

BIN
injector.exe

Binary file not shown.

151
plugins/ADK/AS_Memory.h

@ -31,7 +31,6 @@ @@ -31,7 +31,6 @@
#endif
#include <Windows.h>
#include <algorithm>
#include <sstream>
#include <vector>
@ -41,16 +40,80 @@ namespace Ashita @@ -41,16 +40,80 @@ namespace Ashita
{
public:
/**
* Locates a pattern of data within a large block of memory.
* Determines the length of data from the given offset valid to scan with.
*
* @param {std::vector} data - The data to scan for the pattern within.
* @param {uintptr_t} baseAddress - The base address to add to the offset when the pattern is found.
* @param {const char*} pattern - The pattern to scan for.
* @param {uintptr_t} offset - The offset to add after the pattern has been found.
* @param {uintptr_t} count - The result count to use if the pattern is found multiple times.
* @param {std::vector} pattern - The pattern to find the length within.
* @param {uintptr_t} offset - The offset to begin iterating at.
* @returns {uintptr_t} The length of data from the given offset.
*/
static uintptr_t FindLength(const std::vector<std::pair<uint8_t, bool>>& pattern, uintptr_t offset)
{
// Ensure the offset is within the pattern range..
if (offset >= pattern.size())
return 0;
auto len = 0;
for (size_t x = 0; x < pattern.size(); x++)
{
// Compare the data for wildcards or null characters..
if (pattern[x].second == false ||
pattern[x].first == 0x00)
break;
len++;
}
return len;
}
/**
* Finds the largest chunk of valid data within the pattern to scan for.
*
* @param {std::vector} pattern - The pattern to find the chunk within.
* @param {int32_t [2]} output - The output data to store the offset and length of data to use.
*/
static void FindLargestChunk(const std::vector<std::pair<uint8_t, bool>>& pattern, uintptr_t output[2])
{
auto offset = (uintptr_t)0;
auto length = (uintptr_t)FindLength(pattern, 0);
auto maxlen = (uintptr_t)pattern.size();
// Loop the pattern and find its largest chunk..
for (auto x = length; x < maxlen; x++)
{
// Ensure the data is required..
if (pattern[x].second != true)
continue;
// Find the length at the given offset..
auto count = FindLength(pattern, x);
if (count > length)
{
offset = x;
length = count;
}
// Step past the current data..
if (count > 0)
x += count - 1;
}
// Return the largest offset and length..
output[0] = offset;
output[1] = length;
}
/**
* Finds a pattern within the given range of data.
*
* @param {uintptr_t} baseAddress - The address of the data to begin searching within.
* @param {uintptr_t} baseSize - The size of the data to search within.
* @param {const char*} pattern - The pattern to search for.
* @param {uintptr_t} offset - The offset from the found location to add to the pointer.
* @param {uintptr_t} count - The result count to use if the pattern is found more than once.
* @returns {uintptr_t} The address where the pattern was located, 0 otherwise.
*/
static uintptr_t FindPattern(const std::vector<uint8_t>& data, uintptr_t baseAddress, const char* pattern, uintptr_t offset, uintptr_t count)
static uintptr_t FindPattern(uintptr_t baseAddress, uintptr_t baseSize, const char* pattern, uintptr_t offset, uintptr_t count)
{
// Ensure the incoming pattern is properly aligned..
if (strlen(pattern) % 2 > 0)
@ -73,33 +136,69 @@ namespace Ashita @@ -73,33 +136,69 @@ namespace Ashita
}
}
auto scanStart = data.begin();
auto result = (uintptr_t)0;
// Find the largest chunk of valid data to scan with..
uintptr_t p[2] = { 0 };
FindLargestChunk(vpattern, p);
// Prepare the required variables..
const auto psize = vpattern.size();
const auto pstart = p[0];
const auto plen = (intptr_t)p[1];
const auto pfirst = vpattern[0].first;
// Build the wildcard table..
uint8_t wildcard[UCHAR_MAX + 1] = { 0 };
for (auto x = pstart; x < pstart + plen; x++)
wildcard[(uint8_t)vpattern[x].first] = 1;
const auto data = (uint8_t*)baseAddress;
const auto size = (uint32_t)baseSize;
while (true)
std::vector<uintptr_t> matches;
// Loop the data and look for the pattern..
for (intptr_t x = size - psize; x >= 0; x--)
{
// Search for the pattern..
auto ret = std::search(scanStart, data.end(), vpattern.begin(), vpattern.end(),
[&](uint8_t curr, std::pair<uint8_t, bool> currPattern)
auto c = data[x];
auto w = wildcard[c];
auto k = 0;
// Step over wildcard characters..
while (w == 0 && x > (intptr_t)plen)
{
return (!currPattern.second) || curr == currPattern.first;
});
x -= plen;
w = wildcard[data[x]];
k = 1;
}
// Did we find a match..
if (ret != data.end())
if (k == 1)
{
// If we hit the usage count, return the result..
if (result == count || count == 0)
return (std::distance(data.begin(), ret) + baseAddress) + offset;
x++;
continue;
}
// Ensure the first byte matches..
if (c != pfirst) continue;
// Increment the found count and scan again..
++result;
scanStart = ++ret;
// Validate the size..
if (x - pstart < 0 || x - pstart + psize > size)
return 0;
// Walk the pattern and match its data..
for (size_t y = 0; y < psize - 1; y++)
{
if (y == pstart || vpattern[y].second != true)
continue;
if (data[x - pstart + y] != vpattern[y].first)
break;
if (y + 1 == psize - 1)
matches.insert(matches.begin(), (uintptr_t)(data + (x - pstart)) + offset);
}
else
break;
}
// Handle the count match..
if (count < matches.size())
return matches[count];
return 0;
}

Loading…
Cancel
Save