mirror of
https://github.com/mumble-voip/mumble.git
synced 2025-10-26 11:19:16 +00:00
Since most of the functions are already using C++, why not use classes as well? This commit introduces the following classes: - HostLinux: can only be compiled on Linux. Implements peek() and module(). - HostWindows: can only be compiled on Windows. Implements peek() and module(). - Process: abstract (cannot be instantiated directly). Inherits from HostLinux on Linux and from HostWindows on Windows. Provides functions that can be used with both Linux and Windows processes. Pure virtual functions are implemented in the following classes: - ProcessLinux: meant to be used with Linux processes, inherits from Process. Only implements exportedSymbol(), due to the other functions being universal. The constructor detects the architecture through the ELF header. - ProcessWindows: meant to be used with Windows processes, inherits from Process. Only implements exportedSymbol(), due to the other functions being universal. The constructor detects the architecture through the NT header.
163 lines
3.2 KiB
C++
163 lines
3.2 KiB
C++
// Copyright 2020 The Mumble Developers. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license
|
|
// that can be found in the LICENSE file at the root of the
|
|
// Mumble source tree or at <https://www.mumble.info/LICENSE>.
|
|
|
|
#include "HostLinux.h"
|
|
|
|
#include "mumble_plugin_utils.h"
|
|
|
|
#include <cstring>
|
|
#include <sstream>
|
|
|
|
#include <sys/uio.h>
|
|
|
|
HostLinux::HostLinux(const procid_t pid) : m_ok(true), m_pid(pid) {
|
|
}
|
|
|
|
HostLinux::~HostLinux() {
|
|
}
|
|
|
|
bool HostLinux::peek(const procptr_t address, void *dst, const size_t size) const {
|
|
iovec in;
|
|
in.iov_base = reinterpret_cast< void * >(address);
|
|
in.iov_len = size;
|
|
|
|
iovec out;
|
|
out.iov_base = dst;
|
|
out.iov_len = size;
|
|
|
|
const auto ret = process_vm_readv(m_pid, &out, 1, &in, 1, 0);
|
|
|
|
return (ret != -1 && static_cast< size_t >(ret) == in.iov_len);
|
|
}
|
|
|
|
procptr_t HostLinux::module(const std::string &module) const {
|
|
std::stringstream ss;
|
|
ss << "/proc/";
|
|
ss << m_pid;
|
|
ss << "/maps";
|
|
const auto maps = readFile(ss.str());
|
|
|
|
if (maps.size() == 0) {
|
|
return 0;
|
|
}
|
|
|
|
std::stringstream ssPath(maps);
|
|
while (ssPath.good()) {
|
|
std::string baseaddr;
|
|
|
|
int ch;
|
|
while (1) {
|
|
ch = ssPath.get();
|
|
if (ch == '-') {
|
|
break;
|
|
} else if (ch == EOF) {
|
|
return 0;
|
|
}
|
|
baseaddr.push_back(static_cast< char >(ch));
|
|
}
|
|
|
|
// seek to perms
|
|
do {
|
|
ch = ssPath.get();
|
|
if (ch == EOF) {
|
|
return 0;
|
|
}
|
|
} while (ch != ' ');
|
|
|
|
// seek to offset
|
|
do {
|
|
ch = ssPath.get();
|
|
if (ch == EOF) {
|
|
return 0;
|
|
}
|
|
} while (ch != ' ');
|
|
|
|
// seek to dev
|
|
do {
|
|
ch = ssPath.get();
|
|
if (ch == EOF) {
|
|
return 0;
|
|
}
|
|
} while (ch != ' ');
|
|
|
|
// seek to inode
|
|
do {
|
|
ch = ssPath.get();
|
|
if (ch == EOF) {
|
|
return 0;
|
|
}
|
|
} while (ch != ' ');
|
|
|
|
// seek to pathname
|
|
do {
|
|
ch = ssPath.get();
|
|
if (ch == EOF) {
|
|
return 0;
|
|
}
|
|
} while (ch != ' ');
|
|
|
|
// eat spaces until we're at the beginning of pathname.
|
|
while (ch == ' ') {
|
|
if (ch == EOF) {
|
|
return 0;
|
|
}
|
|
ch = ssPath.get();
|
|
}
|
|
ssPath.unget();
|
|
|
|
std::string pathname;
|
|
while (1) {
|
|
ch = ssPath.get();
|
|
if (ch == '\n') {
|
|
break;
|
|
} else if (ch == EOF) {
|
|
return 0;
|
|
}
|
|
pathname.push_back(static_cast< char >(ch));
|
|
};
|
|
|
|
// OK, we found 'em!
|
|
// Only treat path as a real path if it starts with /.
|
|
if (pathname.size() > 0 && pathname.at(0) == '/') {
|
|
// Find the basename.
|
|
size_t lastSlash = pathname.find_last_of('/');
|
|
if (pathname.size() > lastSlash + 1) {
|
|
std::string basename = pathname.substr(lastSlash + 1);
|
|
if (basename == module) {
|
|
unsigned long addr = strtoul(baseaddr.c_str(), nullptr, 16);
|
|
return addr;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool HostLinux::isWine(const procid_t id) {
|
|
std::stringstream ss;
|
|
ss << "/proc/";
|
|
ss << id;
|
|
ss << "/exe";
|
|
|
|
char *path = realpath(ss.str().c_str(), nullptr);
|
|
if (!path) {
|
|
return false;
|
|
}
|
|
|
|
const char *filename = basename(path);
|
|
if (!filename) {
|
|
return false;
|
|
}
|
|
|
|
const auto ret = strcmp(filename, "wine-preloader") == 0 || strcmp(filename, "wine64-preloader") == 0;
|
|
|
|
// basename() returns a pointer to the basename's position in the string passed as argument.
|
|
// For that reason we cannot free 'path' before performing the check.
|
|
free(path);
|
|
|
|
return ret;
|
|
}
|