diff options
author | davidebeatrici <davidebeatrici@gmail.com> | 2017-11-19 23:46:29 +0300 |
---|---|---|
committer | davidebeatrici <davidebeatrici@gmail.com> | 2017-11-19 23:48:49 +0300 |
commit | 7286fb0f6815a01114e84572edb7cadc5a786134 (patch) | |
tree | d65fa9570e534ce02f4a172465a53e050a132d6d | |
parent | 8bf71ba16d0c0c8e3ae030fd2fbe5b666bed6212 (diff) |
Determine correct pointer size automatically, without the need of specific headers and variables
This commit removes the architecture-specific headers, by keeping only the OS-specific ones.
The different headers were needed to keep the legacy Windows header, after we created the "procptr32_t" (4 bytes) and "procptr64_t" (8 bytes) variables.
We created these variables because the "peekProc" functions read as many bytes as the variable can hold. A pointer is 4 bytes on 32 bit platforms and 8 bytes on 64 bit ones.
Now there's a new variable, called "procptr_t" and with a size of 8 bytes (unsigned long long).
We had a "peekProc" template function which returned the value stored at the specified memory address, but it has been used only to read pointers so far.
Since we needed a new function that checks the process architecture and sets the correct size of the memory to read, I decided to "recycle" it.
-rw-r--r-- | plugins/mumble_plugin.h | 4 | ||||
-rw-r--r-- | plugins/mumble_plugin_linux.h | 75 | ||||
-rw-r--r-- | plugins/mumble_plugin_linux_32bit.h | 16 | ||||
-rw-r--r-- | plugins/mumble_plugin_linux_64bit.h | 16 | ||||
-rw-r--r-- | plugins/mumble_plugin_win32_32bit.h | 20 | ||||
-rw-r--r-- | plugins/mumble_plugin_win32_64bit.h | 20 | ||||
-rw-r--r-- | plugins/mumble_plugin_win32_ptr_type.h | 64 | ||||
-rw-r--r-- | plugins/plugins.pri | 4 |
8 files changed, 110 insertions, 109 deletions
diff --git a/plugins/mumble_plugin.h b/plugins/mumble_plugin.h index 0e2c72f00..3d717c4d6 100644 --- a/plugins/mumble_plugin.h +++ b/plugins/mumble_plugin.h @@ -6,6 +6,10 @@ #ifndef MUMBLE_MUMBLE_PLUGIN_H_ #define MUMBLE_MUMBLE_PLUGIN_H_ +typedef unsigned long long procptr_t; + +#define LENGTH_OF(array) (sizeof(array) / sizeof((array)[0])) + #include <string> #include <map> diff --git a/plugins/mumble_plugin_linux.h b/plugins/mumble_plugin_linux.h index fe2b6a6ae..5229e50b4 100644 --- a/plugins/mumble_plugin_linux.h +++ b/plugins/mumble_plugin_linux.h @@ -6,10 +6,6 @@ #ifndef MUMBLE_PLUGIN_LINUX_H_ #define MUMBLE_PLUGIN_LINUX_H_ -#ifndef PTR_TYPE_CONCRETE -# define PTR_TYPE_CONCRETE PTR_TYPE -#endif - #include <sys/uio.h> #include <stdio.h> #include <stdlib.h> @@ -23,7 +19,8 @@ #include "mumble_plugin.h" pid_t pPid; -static PTR_TYPE_CONCRETE pModule; +int is64Bit; +static procptr_t pModule; static inline std::string readAll(std::string fn) { std::ifstream ifs; @@ -43,7 +40,41 @@ static inline std::string readAll(std::string fn) { return content; } -static inline PTR_TYPE_CONCRETE getModuleAddr(pid_t pid, const wchar_t *modname) { +// This function returns 0 if the process is 32-bit and 1 if it's 64-bit. +// In case of failure, it returns -1. +static inline int checkProcessIs64Bit(const pid_t pid) +{ + // We can know the process architecture by looking at its ELF header. + char elf[5]; + + std::stringstream ss; + ss << "/proc/"; + ss << static_cast<unsigned long>(pid); + ss << "/exe"; + + std::ifstream ifs; + ifs.open(ss.str(), std::ifstream::binary); + if (!ifs.is_open()) { + return -1; + } + + ifs.read(elf, LENGTH_OF(elf)); + ifs.close(); + + if (ifs.gcount() != LENGTH_OF(elf)) { + return -1; + } + + // The first 4 bytes constitute the magical number in ASCII: 0x7F 45 4c 46. + if (!(elf[0] == 0x7f && elf[1] == 'E' && elf[2] == 'L' && elf[3] == 'F')) { + return -1; + } + + // The fifth byte is 1 in case the process is 32-bit or 2 in case it's 64-bit. + return elf[4] != 1; +} + +static inline procptr_t getModuleAddr(pid_t pid, const wchar_t *modname) { std::wstring modnameWide(modname); std::string modnameNonWide(modnameWide.begin(), modnameWide.end()); @@ -151,11 +182,11 @@ static inline PTR_TYPE_CONCRETE getModuleAddr(pid_t pid, const wchar_t *modname) return 0; } -static inline PTR_TYPE_CONCRETE getModuleAddr(const wchar_t *modname) { +static inline procptr_t getModuleAddr(const wchar_t *modname) { return getModuleAddr(pPid, modname); } -static inline bool peekProc(PTR_TYPE base, void *dest, size_t len) { +static inline bool peekProc(procptr_t base, void *dest, size_t len) { struct iovec in; in.iov_base = reinterpret_cast<void *>(base); // Address from target process in.iov_len = len; // Length @@ -170,16 +201,7 @@ static inline bool peekProc(PTR_TYPE base, void *dest, size_t len) { } template<class T> -T peekProc(PTR_TYPE base) { - T v = 0; - if (!peekProc(base, reinterpret_cast<T *>(&v), sizeof(T))) { - return 0; - } - return v; -} - -template<class T> -bool peekProc(PTR_TYPE base, T &dest) { +bool peekProc(procptr_t base, T &dest) { struct iovec in; in.iov_base = reinterpret_cast<void *>(base); // Address from target process in.iov_len = sizeof(T); // Length @@ -193,6 +215,16 @@ bool peekProc(PTR_TYPE base, T &dest) { return (nread != -1 && static_cast<size_t>(nread) == in.iov_len); } +static inline procptr_t peekProcPtr(procptr_t base) { + procptr_t v = 0; + + if (!peekProc(base, &v, is64Bit ? 8 : 4)) { + return 0; + } + + return v; +} + static bool inline initialize(const std::multimap<std::wstring, unsigned long long int> &pids, const wchar_t *procname, const wchar_t *modname = NULL) { pModule = 0; @@ -210,6 +242,13 @@ static bool inline initialize(const std::multimap<std::wstring, unsigned long lo if (pPid == 0) return false; + int result = checkProcessIs64Bit(pPid); + if (result == -1) { + return false; + } + + is64Bit = result; + pModule = getModuleAddr(modname ? modname : procname); if (pModule == 0) { diff --git a/plugins/mumble_plugin_linux_32bit.h b/plugins/mumble_plugin_linux_32bit.h deleted file mode 100644 index 31c1f49cf..000000000 --- a/plugins/mumble_plugin_linux_32bit.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2005-2017 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>. - -#ifndef MUMBLE_PLUGIN_LINUX_32BIT_H_ -#define MUMBLE_PLUGIN_LINUX_32BIT_H_ - -#include <stdint.h> - -typedef uint32_t procptr32_t; - -#define PTR_TYPE procptr32_t -#include "mumble_plugin_linux.h" - -#endif diff --git a/plugins/mumble_plugin_linux_64bit.h b/plugins/mumble_plugin_linux_64bit.h deleted file mode 100644 index f9e036c6f..000000000 --- a/plugins/mumble_plugin_linux_64bit.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2005-2017 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>. - -#ifndef MUMBLE_PLUGIN_LINUX_64BIT_H_ -#define MUMBLE_PLUGIN_LINUX_64BIT_H_ - -#include <stdint.h> - -typedef uint64_t procptr64_t; - -#define PTR_TYPE procptr64_t -#include "mumble_plugin_linux.h" - -#endif diff --git a/plugins/mumble_plugin_win32_32bit.h b/plugins/mumble_plugin_win32_32bit.h deleted file mode 100644 index 488fa0245..000000000 --- a/plugins/mumble_plugin_win32_32bit.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2005-2017 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>. - -#ifndef MUMBLE_MUMBLE_PLUGIN_WIN32_32BIT_H_ -#define MUMBLE_MUMBLE_PLUGIN_WIN32_32BIT_H_ - -#if defined(__linux__) -# include "mumble_plugin_linux_32bit.h" -#else - -typedef unsigned long procptr32_t; - -#define PTR_TYPE procptr32_t -#include "mumble_plugin_win32_ptr_type.h" - -#endif - -#endif diff --git a/plugins/mumble_plugin_win32_64bit.h b/plugins/mumble_plugin_win32_64bit.h deleted file mode 100644 index 5ef883c49..000000000 --- a/plugins/mumble_plugin_win32_64bit.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2005-2017 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>. - -#ifndef MUMBLE_MUMBLE_PLUGIN_WIN32_64BIT_H_ -#define MUMBLE_MUMBLE_PLUGIN_WIN32_64BIT_H_ - -#if defined(__linux__) - #include "mumble_plugin_linux_64bit.h" -#else - -typedef unsigned long long procptr64_t; - -#define PTR_TYPE procptr64_t -#include "mumble_plugin_win32_ptr_type.h" - -#endif - -#endif diff --git a/plugins/mumble_plugin_win32_ptr_type.h b/plugins/mumble_plugin_win32_ptr_type.h index d5c71caa5..f573c97de 100644 --- a/plugins/mumble_plugin_win32_ptr_type.h +++ b/plugins/mumble_plugin_win32_ptr_type.h @@ -6,10 +6,6 @@ #ifndef MUMBLE_MUMBLE_PLUGIN_WIN32_PTR_TYPE_H_ #define MUMBLE_MUMBLE_PLUGIN_WIN32_PTR_TYPE_H_ -#ifndef PTR_TYPE_CONCRETE -# define PTR_TYPE_CONCRETE PTR_TYPE -#endif - #define _USE_MATH_DEFINES #include <stdio.h> #include <stdlib.h> @@ -28,8 +24,9 @@ #include "mumble_plugin.h" DWORD dwPid; +int is64Bit; static HANDLE hProcess; -static PTR_TYPE_CONCRETE pModule; +static procptr_t pModule; static inline DWORD getProcess(const wchar_t *exename) { PROCESSENTRY32 pe; @@ -52,9 +49,35 @@ static inline DWORD getProcess(const wchar_t *exename) { return pid; } -static inline PTR_TYPE_CONCRETE getModuleAddr(DWORD pid, const wchar_t *modname) { +static inline int checkProcessIs64Bit(const DWORD pid) +{ + // This function returns 0 if the process is 32-bit and 1 if it's 64-bit. + // In case of failure, it returns -1. + + HANDLE handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, pid); + if (!handle) { + return -1; + } + + // IsWow64Process() returns true if the process is 32-bit, running on a 64-bit system. + // It returns false in case the process is 64-bit, running on a 64-bit system. + // It also returns false if the process is 32-bit, running on a 32-bit system. + + BOOL isWow64Process; + if (!IsWow64Process(handle, &isWow64Process)) { + CloseHandle(handle); + return -1; + } + + CloseHandle(handle); + + bool is32 = isWow64Process || sizeof(void*) == 4; + return !is32; +} + +static inline procptr_t getModuleAddr(DWORD pid, const wchar_t *modname) { MODULEENTRY32 me; - PTR_TYPE_CONCRETE ret = 0; + procptr_t ret = 0; me.dwSize = sizeof(me); HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE|TH32CS_SNAPMODULE32, pid); if (hSnap != INVALID_HANDLE_VALUE) { @@ -63,7 +86,7 @@ static inline PTR_TYPE_CONCRETE getModuleAddr(DWORD pid, const wchar_t *modname) while (ok) { if (wcscmp(me.szModule, modname)==0) { uintptr_t addr = reinterpret_cast<uintptr_t>(me.modBaseAddr); - ret = static_cast<PTR_TYPE_CONCRETE>(addr); + ret = static_cast<procptr_t>(addr); break; } ok = Module32Next(hSnap, &me); @@ -73,11 +96,11 @@ static inline PTR_TYPE_CONCRETE getModuleAddr(DWORD pid, const wchar_t *modname) return ret; } -static inline PTR_TYPE_CONCRETE getModuleAddr(const wchar_t *modname) { +static inline procptr_t getModuleAddr(const wchar_t *modname) { return getModuleAddr(dwPid, modname); } -static inline bool peekProc(PTR_TYPE base, VOID *dest, SIZE_T len) { +static inline bool peekProc(procptr_t base, VOID *dest, SIZE_T len) { SIZE_T r; uintptr_t addr = static_cast<uintptr_t>(base); BOOL ok=ReadProcessMemory(hProcess, reinterpret_cast<VOID *>(addr), dest, len, &r); @@ -85,17 +108,20 @@ static inline bool peekProc(PTR_TYPE base, VOID *dest, SIZE_T len) { } template<class T> -bool peekProc(PTR_TYPE base, T &dest) { +bool peekProc(procptr_t base, T &dest) { SIZE_T r; uintptr_t addr = static_cast<uintptr_t>(base); BOOL ok=ReadProcessMemory(hProcess, reinterpret_cast<VOID *>(addr), reinterpret_cast<VOID *>(& dest), sizeof(T), &r); return (ok && (r == sizeof(T))); } -template<class T> -T peekProc(PTR_TYPE base) { - T v = 0; - peekProc(base, reinterpret_cast<T *>(&v), sizeof(T)); +static inline procptr_t peekProcPtr(procptr_t base) { + procptr_t v = 0; + + if (!peekProc(base, &v, is64Bit ? 8 : 4)) { + return 0; + } + return v; } @@ -117,6 +143,14 @@ static bool inline initialize(const std::multimap<std::wstring, unsigned long lo if (!dwPid) return false; + int result = checkProcessIs64Bit(dwPid); + if (result == -1) { + dwPid = 0; + return false; + } + + is64Bit = result; + pModule=getModuleAddr(modname ? modname : procname); if (!pModule) { dwPid = 0; diff --git a/plugins/plugins.pri b/plugins/plugins.pri index f004c6360..0155aa99c 100644 --- a/plugins/plugins.pri +++ b/plugins/plugins.pri @@ -16,10 +16,6 @@ CONFIG(static) { CONFIG += qt_dynamic_lookup } -!CONFIG(no-plugin-legacy-ptr) { - DEFINES += USE_PLUGIN_LEGACY_PTR -} - CONFIG(debug, debug|release) { CONFIG += console DESTDIR = ../../debug/plugins |