Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mumble-voip/mumble.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavide Beatrici <git@davidebeatrici.dev>2020-11-11 07:25:52 +0300
committerDavide Beatrici <git@davidebeatrici.dev>2020-11-11 07:25:52 +0300
commit8542c9a8574e52873c0aac53348a515d84c6b617 (patch)
tree9707d56da83772093c887afc471bf56218e6089c /plugins
parent04faa580084bb447f01df87ef096f40e8f30f892 (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.cpp50
-rw-r--r--plugins/Process.h9
-rw-r--r--plugins/mumble_plugin_utils.h24
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 &region : 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) {