diff options
author | Davide Beatrici <git@davidebeatrici.dev> | 2020-11-11 07:25:52 +0300 |
---|---|---|
committer | Davide Beatrici <git@davidebeatrici.dev> | 2020-11-11 07:25:52 +0300 |
commit | 8542c9a8574e52873c0aac53348a515d84c6b617 (patch) | |
tree | 9707d56da83772093c887afc471bf56218e6089c /plugins | |
parent | 04faa580084bb447f01df87ef096f40e8f30f892 (diff) |
FEAT(positional-audio): Add searchInBuffer() and findPattern()
searchInBuffer() searches for the specified pattern in the specified buffer. "?" is used as wildcard.
findPattern(), given a start address and the size of the area, reads memory in chunks of 32 KiB.
It stops when a match is found, the end is reached or an error is encountered (peek() fails).
There's also an overload which iterates through the specified module's readable regions.
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/Process.cpp | 50 | ||||
-rw-r--r-- | plugins/Process.h | 9 | ||||
-rw-r--r-- | plugins/mumble_plugin_utils.h | 24 |
3 files changed, 83 insertions, 0 deletions
diff --git a/plugins/Process.cpp b/plugins/Process.cpp index ad5a6b7c7..631ceb7b2 100644 --- a/plugins/Process.cpp +++ b/plugins/Process.cpp @@ -63,6 +63,56 @@ procptr_t Process::virtualFunction(const procptr_t classObject, const size_t ind return peekPtr(vTable + (index * m_pointerSize)); } +procptr_t Process::findPattern(const std::vector< uint8_t > &pattern, const Module &module) { + for (const auto ®ion : module.regions()) { + if (!region.readable) { + continue; + } + + const auto ret = findPattern(pattern, region.address, region.size); + if (ret) { + return ret; + } + } + + return 0; +} + +procptr_t Process::findPattern(const std::vector< uint8_t > &pattern, procptr_t address, const size_t size) { + // 32 KiB appears to be a good balance + constexpr uint16_t bufferSize = 32768; + std::vector< uint8_t > buffer(bufferSize); + + const auto chunks = size / buffer.size(); + for (size_t i = 0; i < chunks; ++i) { + if (!peek(address, &buffer[0], buffer.size())) { + return 0; + } + + const auto ret = searchInBuffer(pattern, buffer); + if (ret != SIZE_MAX) { + return address + ret; + } + + address += buffer.size(); + } + + const auto remainder = size % buffer.size(); + if (remainder >= pattern.size()) { + buffer.resize(remainder); + if (!peek(address, &buffer[0], buffer.size())) { + return 0; + } + + const auto ret = searchInBuffer(pattern, buffer); + if (ret != SIZE_MAX) { + return address + ret; + } + } + + return 0; +} + procid_t Process::find(const std::string &name, const std::multimap< std::wstring, unsigned long long int > &pids) { if (pids.empty()) { return 0; diff --git a/plugins/Process.h b/plugins/Process.h index df78a2a2e..7beb35f92 100644 --- a/plugins/Process.h +++ b/plugins/Process.h @@ -95,6 +95,15 @@ public: procptr_t virtualFunction(const procptr_t classObject, const size_t index) const; + /// Iterates through all readable memory regions, until findPattern() succeeds. + /// Returns 0 if the pattern is not found. + procptr_t findPattern(const std::vector< uint8_t > &pattern, const Module &module); + + /// Reads memory in chunks until either the pattern is found, the end is reached or peek() fails. + /// Refer to searchInBuffer() for the pattern format. + /// Returns 0 if the pattern is not found. + procptr_t findPattern(const std::vector< uint8_t > &pattern, procptr_t address, const size_t size); + static procid_t find(const std::string &name, const std::multimap< std::wstring, unsigned long long int > &pids); Process(const procid_t id, const std::string &name); diff --git a/plugins/mumble_plugin_utils.h b/plugins/mumble_plugin_utils.h index 260b0b20a..cb6c6e5bb 100644 --- a/plugins/mumble_plugin_utils.h +++ b/plugins/mumble_plugin_utils.h @@ -11,6 +11,7 @@ #include <fstream> #include <locale> #include <sstream> +#include <vector> #ifdef OS_LINUX # include <fenv.h> @@ -150,6 +151,29 @@ static inline bool skipUntil(std::stringstream &stream, const std::stringstream: return true; } +/// Returns the index of the specified pattern in the specified buffer. +/// "?" is used as wildcard character. +/// If the pattern is not found, the function returns SIZE_MAX. +static inline size_t searchInBuffer(const std::vector< uint8_t > &pattern, const std::vector< uint8_t > &buffer) { + for (size_t i = 0; i < buffer.size() - pattern.size(); ++i) { + const auto *buf = &buffer[i]; + bool match = true; + + for (size_t j = 0; j < pattern.size(); ++j) { + if (pattern[j] != '?' && buf[j] != pattern[j]) { + match = false; + break; + } + } + + if (match) { + return buf - &buffer[0]; + } + } + + return SIZE_MAX; +} + /// Calculates sine and cosine of the specified value. /// On Linux the calculation is guaranteed to be simultaneous. static inline bool sinCos(const float value, float &outSin, float &outCos) { |