From 7286fb0f6815a01114e84572edb7cadc5a786134 Mon Sep 17 00:00:00 2001 From: davidebeatrici Date: Sun, 19 Nov 2017 21:46:29 +0100 Subject: 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. --- plugins/mumble_plugin.h | 4 ++ plugins/mumble_plugin_linux.h | 75 ++++++++++++++++++++++++++-------- plugins/mumble_plugin_linux_32bit.h | 16 -------- plugins/mumble_plugin_linux_64bit.h | 16 -------- plugins/mumble_plugin_win32_32bit.h | 20 --------- plugins/mumble_plugin_win32_64bit.h | 20 --------- plugins/mumble_plugin_win32_ptr_type.h | 64 ++++++++++++++++++++++------- plugins/plugins.pri | 4 -- 8 files changed, 110 insertions(+), 109 deletions(-) delete mode 100644 plugins/mumble_plugin_linux_32bit.h delete mode 100644 plugins/mumble_plugin_linux_64bit.h delete mode 100644 plugins/mumble_plugin_win32_32bit.h delete mode 100644 plugins/mumble_plugin_win32_64bit.h (limited to 'plugins') 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 #include 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 #include #include @@ -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(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(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 -T peekProc(PTR_TYPE base) { - T v = 0; - if (!peekProc(base, reinterpret_cast(&v), sizeof(T))) { - return 0; - } - return v; -} - -template -bool peekProc(PTR_TYPE base, T &dest) { +bool peekProc(procptr_t base, T &dest) { struct iovec in; in.iov_base = reinterpret_cast(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(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 &pids, const wchar_t *procname, const wchar_t *modname = NULL) { pModule = 0; @@ -210,6 +242,13 @@ static bool inline initialize(const std::multimap. - -#ifndef MUMBLE_PLUGIN_LINUX_32BIT_H_ -#define MUMBLE_PLUGIN_LINUX_32BIT_H_ - -#include - -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 . - -#ifndef MUMBLE_PLUGIN_LINUX_64BIT_H_ -#define MUMBLE_PLUGIN_LINUX_64BIT_H_ - -#include - -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 . - -#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 . - -#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 #include @@ -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(me.modBaseAddr); - ret = static_cast(addr); + ret = static_cast(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(base); BOOL ok=ReadProcessMemory(hProcess, reinterpret_cast(addr), dest, len, &r); @@ -85,17 +108,20 @@ static inline bool peekProc(PTR_TYPE base, VOID *dest, SIZE_T len) { } template -bool peekProc(PTR_TYPE base, T &dest) { +bool peekProc(procptr_t base, T &dest) { SIZE_T r; uintptr_t addr = static_cast(base); BOOL ok=ReadProcessMemory(hProcess, reinterpret_cast(addr), reinterpret_cast(& dest), sizeof(T), &r); return (ok && (r == sizeof(T))); } -template -T peekProc(PTR_TYPE base) { - T v = 0; - peekProc(base, reinterpret_cast(&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