From b0555158b486001f90b5e663af1bc38078bb5545 Mon Sep 17 00:00:00 2001 From: kelson8 Date: Wed, 2 Apr 2025 14:05:28 -0400 Subject: [PATCH] Add test for getting the base memory address of a program --- src/menus/test_menu2.cpp | 31 +++++++++ src/util/misc_util.cpp | 131 +++++++++++++++++++++++++++++++++++++++ src/util/misc_util.h | 10 +++ 3 files changed, 172 insertions(+) diff --git a/src/menus/test_menu2.cpp b/src/menus/test_menu2.cpp index c5ad4db..3e2bfb0 100644 --- a/src/menus/test_menu2.cpp +++ b/src/menus/test_menu2.cpp @@ -19,6 +19,11 @@ // Functions for clamping the inputs for values and other stuff #include "imgui_functions.h" +// I don't think the exe names should really be too long +// https://www.thoughtco.com/definition-of-buffer-p2-958030 +//char* buf = new char[30]; +char memoryBaseBuffer[30] = ""; // Allocate on the stack. Choose a suitable size. + void TestMenu2::TestMenu() { // Init the random number to 0 by default @@ -99,6 +104,32 @@ void TestMenu2::TestMenu() ImGuiFunctions::Folders::OpenCurrentDirectoryButton("Open current directory"); IMGUI_SEPERATOR(); + + IMGUITEXT("Memory address testing"); + + + // Well this makes the random number glitch out.. Oops. + //ImGui::InputText("Exe Name", buf, 20); + ImGui::InputText("Exe Name", memoryBaseBuffer, sizeof(memoryBaseBuffer)); + if (IMGUIBUTTON("Display base address")) + { + // Make sure there is a value in the buffer + // TODO Add error handling to check for invalid or not found exe. + //if (buf) + if (memoryBaseBuffer) + { + if (memoryBaseBuffer[0] != '\0') { + miscUtil.LogBaseAddress(memoryBaseBuffer); + } + // TODO Fix this + //else { + // ImGui::Text("Please enter an exe name."); + //} + } + } + IMGUI_SEPERATOR(); + + // End directory testing diff --git a/src/util/misc_util.cpp b/src/util/misc_util.cpp index f503eb1..d6f92de 100644 --- a/src/util/misc_util.cpp +++ b/src/util/misc_util.cpp @@ -4,6 +4,13 @@ #include #include +#ifdef _WIN32 +// Added to header +//#include +#include +#include +#endif + #define NEW_RANDOM_NUMBER_GEN /// @@ -52,3 +59,127 @@ MiscUtil::GenerateRandomNumber(int min, int max) #endif } + +#ifdef _WIN32 + +/// +/// Get the base address, and display it in the console. +/// TODO Fix this to work, it works in my ReVC tests. +/// +//void +//MiscUtil::LogBaseAddress(LPCSTR exeName) +//{ +// // New +// uintptr_t baseAddress = 0; +// DWORD processID = 0; +// +// std::cout << "Attempting to get module handle for: \"" << exeName << "\"" << std::endl; // Debug output +// +// HMODULE hModule = GetModuleHandleA(exeName); +// if (hModule) { +// MODULEINFO moduleInfo; +// if (GetModuleInformation(GetCurrentProcess(), hModule, &moduleInfo, sizeof(moduleInfo))) { +// uintptr_t baseAddress = reinterpret_cast(moduleInfo.lpBaseOfDll); +// +// std::cout << "Base address of " << exeName << ": " << std::hex << baseAddress << std::endl; +// } +// else { +// std::cerr << "Failed to get Module information" << std::endl; +// } +// +// } +// else { +// DWORD error = GetLastError(); +// std::cout << "Exe name: " << exeName << std::endl; +// std::cerr << "Failed to get base address. Error code: " << error << std::endl; +// } +//} + +// New + +void +MiscUtil::LogBaseAddress(const char* exeName) +{ + std::cout << "Base address for " << exeName << ": 0x" << this->GetModuleBaseAddress(exeName) << std::endl; +} + + + +/// +/// Get the base address by itself without logging it. +/// This should always get the base module address. +/// +/// The exe name to get the base address from +/// The exe module base address +//uintptr_t +//MiscUtil::GetModuleBaseAddress(const char* exeName) +//{ +// HMODULE hModule = GetModuleHandleA(exeName); +// if (hModule) { +// MODULEINFO moduleInfo; +// if (GetModuleInformation(GetCurrentProcess(), hModule, &moduleInfo, sizeof(moduleInfo))) { +// return reinterpret_cast(moduleInfo.lpBaseOfDll); +// } +// } +// return 0; // Return 0 on failure +//} + +// New + +/// +/// This seems to work, although ReVC reports a different value when being logged. +/// TODO Look into this +/// +/// +/// +uintptr_t MiscUtil::GetModuleBaseAddress(const char* exeName) { + uintptr_t baseAddress = 0; + DWORD processID = 0; + + // 1. Get the Process ID (PID) + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnapshot != INVALID_HANDLE_VALUE) { + PROCESSENTRY32 processEntry; + processEntry.dwSize = sizeof(PROCESSENTRY32); + + if (Process32First(hSnapshot, &processEntry)) { + do { + if (_stricmp(processEntry.szExeFile, exeName) == 0) { + processID = processEntry.th32ProcessID; + break; + } + } while (Process32Next(hSnapshot, &processEntry)); + } + CloseHandle(hSnapshot); + } + + if (processID != 0) { + // 2. Open the Process + HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID); + if (hProcess != NULL) { + HMODULE hModules[1024]; + DWORD bytesNeeded; + + // 3. Enumerate Modules + if (EnumProcessModules(hProcess, hModules, sizeof(hModules), &bytesNeeded)) { + for (unsigned int i = 0; i < bytesNeeded / sizeof(HMODULE); ++i) { + char moduleName[MAX_PATH]; + if (GetModuleBaseNameA(hProcess, hModules[i], moduleName, sizeof(moduleName) / sizeof(char))) { + if (_stricmp(moduleName, exeName) == 0) { + MODULEINFO moduleInfo; + // 4. Get Module Information + if (GetModuleInformation(hProcess, hModules[i], &moduleInfo, sizeof(moduleInfo))) { + baseAddress = reinterpret_cast(moduleInfo.lpBaseOfDll); + break; + } + } + } + } + } + CloseHandle(hProcess); + } + } + return baseAddress; +} + +#endif //_WIN32 diff --git a/src/util/misc_util.h b/src/util/misc_util.h index 0541fb9..39f32bf 100644 --- a/src/util/misc_util.h +++ b/src/util/misc_util.h @@ -3,6 +3,10 @@ #include #include +#ifdef _WIN32 +#include +#endif + // Some of these came from my ReVC project class MiscUtil @@ -27,6 +31,12 @@ public: // Convert a float to a string std::string floatToString(float value); + // Memory address testing + // Display the base address of a program in the console + // Logs the return value of the below function, GetModuleBaseAddress. + void LogBaseAddress(const char* exeName); + // Get the base address of a program, this doesn't log it. + uintptr_t GetModuleBaseAddress(const char* exeName); };