diff --git a/Ashita.dll b/Ashita.dll index 3db7829..8b582c4 100644 Binary files a/Ashita.dll and b/Ashita.dll differ diff --git a/injector.exe b/injector.exe index 32c3898..0dfde7f 100644 Binary files a/injector.exe and b/injector.exe differ diff --git a/plugins/ADK/AS_Memory.h b/plugins/ADK/AS_Memory.h index 2e2437c..3af5ca8 100644 --- a/plugins/ADK/AS_Memory.h +++ b/plugins/ADK/AS_Memory.h @@ -31,7 +31,6 @@ #endif #include -#include #include #include @@ -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>& 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>& 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& 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 } } - 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 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 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; }