diff --git a/plugins/windows/include/content/providers/process_memory_provider.hpp b/plugins/windows/include/content/providers/process_memory_provider.hpp index 89b0f0325..bb09a035c 100644 --- a/plugins/windows/include/content/providers/process_memory_provider.hpp +++ b/plugins/windows/include/content/providers/process_memory_provider.hpp @@ -36,7 +36,7 @@ namespace hex::plugin::windows { void save() override {} void saveAs(const std::fs::path &) override {} - [[nodiscard]] std::string getName() const override { return "hex.windows.provider.process_memory"_lang; } + [[nodiscard]] std::string getName() const override { return hex::format("hex.windows.provider.process_memory.name"_lang, this->m_selectedProcess != nullptr ? this->m_selectedProcess->name : ""); } [[nodiscard]] std::vector> getDataInformation() const override { return { { "hex.windows.provider.process_memory.process_name"_lang, this->m_selectedProcess->name }, @@ -61,6 +61,9 @@ namespace hex::plugin::windows { [[nodiscard]] std::pair getRegionValidity(u64) const override; + private: + void reloadProcessModules(); + private: struct Process { u32 id; diff --git a/plugins/windows/romfs/lang/en_US.json b/plugins/windows/romfs/lang/en_US.json index 6c56378bf..b2cac3be2 100644 --- a/plugins/windows/romfs/lang/en_US.json +++ b/plugins/windows/romfs/lang/en_US.json @@ -6,12 +6,17 @@ "hex.windows.provider.process_memory": "Process Memory Provider", "hex.windows.provider.process_memory.enumeration_failed": "Failed to enumerate processes", "hex.windows.provider.process_memory.memory_regions": "Memory Regions", + "hex.windows.provider.process_memory.name": "'{0}' Process Memory", "hex.windows.provider.process_memory.process_name": "Process Name", - "hex.windows.provider.process_memory.process_id": "Process ID", + "hex.windows.provider.process_memory.process_id": "PID", "hex.windows.provider.process_memory.region.commit": "Commit", "hex.windows.provider.process_memory.region.reserve": "Reserved", "hex.windows.provider.process_memory.region.private": "Private", "hex.windows.provider.process_memory.region.mapped": "Mapped", + "hex.windows.provider.process_memory.utils": "Utils", + "hex.windows.provider.process_memory.utils.inject_dll": "Inject DLL", + "hex.windows.provider.process_memory.utils.inject_dll.success": "Successfully injected DLL '{0}'!", + "hex.windows.provider.process_memory.utils.inject_dll.failure": "Failed to inject DLL '{0}'!", "hex.builtin.setting.general.context_menu_entry": "Windows context menu entry", "hex.windows.title_bar_button.debug_build": "Debug build", "hex.windows.title_bar_button.feedback": "Leave Feedback", diff --git a/plugins/windows/source/content/providers/process_memory_provider.cpp b/plugins/windows/source/content/providers/process_memory_provider.cpp index f00d9a1c3..865e93782 100644 --- a/plugins/windows/source/content/providers/process_memory_provider.cpp +++ b/plugins/windows/source/content/providers/process_memory_provider.cpp @@ -8,6 +8,7 @@ #include #include #include +#include namespace hex::plugin::windows { @@ -16,46 +17,7 @@ namespace hex::plugin::windows { if (this->m_processHandle == nullptr) return false; - DWORD numModules = 0; - std::vector modules; - - do { - modules.resize(modules.size() + 1024); - if (EnumProcessModules(this->m_processHandle, modules.data(), modules.size() * sizeof(HMODULE), &numModules) == FALSE) { - modules.clear(); - break; - } - } while (numModules == modules.size() * sizeof(HMODULE)); - - modules.resize(numModules / sizeof(HMODULE)); - - for (auto &module : modules) { - MODULEINFO moduleInfo; - if (GetModuleInformation(this->m_processHandle, module, &moduleInfo, sizeof(MODULEINFO)) == FALSE) - continue; - - char moduleName[MAX_PATH]; - if (GetModuleFileNameExA(this->m_processHandle, module, moduleName, MAX_PATH) == FALSE) - continue; - - this->m_memoryRegions.insert({ { (u64)moduleInfo.lpBaseOfDll, (u64)moduleInfo.lpBaseOfDll + moduleInfo.SizeOfImage }, std::fs::path(moduleName).filename().string() }); - } - - MEMORY_BASIC_INFORMATION memoryInfo; - for (u64 address = 0; address < 0xFFFF'FFFF'FFFF; address += memoryInfo.RegionSize) { - if (VirtualQueryEx(this->m_processHandle, (LPCVOID)address, &memoryInfo, sizeof(MEMORY_BASIC_INFORMATION)) == 0) - break; - - std::string name; - if (memoryInfo.State & MEM_IMAGE) continue; - if (memoryInfo.State & MEM_FREE) continue; - if (memoryInfo.State & MEM_COMMIT) name += hex::format("{} ", "hex.windows.provider.process_memory.region.commit"_lang); - if (memoryInfo.State & MEM_RESERVE) name += hex::format("{} ", "hex.windows.provider.process_memory.region.reserve"_lang); - if (memoryInfo.State & MEM_PRIVATE) name += hex::format("{} ", "hex.windows.provider.process_memory.region.private"_lang); - if (memoryInfo.State & MEM_MAPPED) name += hex::format("{} ", "hex.windows.provider.process_memory.region.mapped"_lang); - - this->m_memoryRegions.insert({ { (u64)memoryInfo.BaseAddress, (u64)memoryInfo.BaseAddress + memoryInfo.RegionSize }, name }); - } + this->reloadProcessModules(); return true; } @@ -198,8 +160,9 @@ namespace hex::plugin::windows { void ProcessMemoryProvider::drawInterface() { ImGui::Header("hex.windows.provider.process_memory.memory_regions"_lang, true); - if (ImGui::BeginTable("##module_table", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollY, ImVec2(0, 400_scaled))) { + if (ImGui::BeginTable("##module_table", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollY, ImVec2(0, 400_scaled))) { ImGui::TableSetupColumn("hex.builtin.common.region"_lang); + ImGui::TableSetupColumn("hex.builtin.common.size"_lang); ImGui::TableSetupColumn("hex.builtin.common.name"_lang); ImGui::TableSetupScrollFreeze(0, 1); @@ -212,6 +175,10 @@ namespace hex::plugin::windows { ImGui::TableNextColumn(); ImGui::Text("0x%016llX - 0x%016llX", memoryRegion.region.getStartAddress(), memoryRegion.region.getEndAddress()); + ImGui::TableNextColumn(); + ImGui::TextUnformatted(hex::toByteString(memoryRegion.region.getSize()).c_str()); + + ImGui::TableNextColumn(); if (ImGui::Selectable(memoryRegion.name.c_str(), false, ImGuiSelectableFlags_SpanAllColumns)) ImHexApi::HexEditor::setSelection(memoryRegion.region); @@ -221,6 +188,77 @@ namespace hex::plugin::windows { ImGui::EndTable(); } + + ImGui::Header("hex.windows.provider.process_memory.utils"_lang); + + if (ImGui::Button("hex.windows.provider.process_memory.utils.inject_dll"_lang)) { + hex::fs::openFileBrowser(fs::DialogMode::Open, { { "DLL File", "dll" } }, [this](const std::fs::path &path) { + const auto &dllPath = path.native(); + const auto dllPathLength = (dllPath.length() + 1) * sizeof(std::fs::path::value_type); + + if (auto pathAddress = VirtualAllocEx(this->m_processHandle, nullptr, dllPathLength, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); pathAddress != nullptr) { + if (WriteProcessMemory(this->m_processHandle, pathAddress, dllPath.c_str(), dllPathLength, nullptr) != FALSE) { + auto loadLibraryW = reinterpret_cast(reinterpret_cast(GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryW"))); + if (loadLibraryW != nullptr) { + if (auto threadHandle = CreateRemoteThread(this->m_processHandle, nullptr, 0, loadLibraryW, pathAddress, 0, nullptr); threadHandle != nullptr) { + WaitForSingleObject(threadHandle, INFINITE); + hex::View::showInfoPopup(hex::format("hex.windows.provider.process_memory.utils.inject_dll.success"_lang, path.filename().string())); + this->reloadProcessModules(); + CloseHandle(threadHandle); + return; + } + } + } + } + + hex::View::showErrorPopup(hex::format("hex.windows.provider.process_memory.utils.inject_dll.failure"_lang, path.filename().string())); + }); + } + } + + void ProcessMemoryProvider::reloadProcessModules() { + this->m_memoryRegions.clear(); + + DWORD numModules = 0; + std::vector modules; + + do { + modules.resize(modules.size() + 1024); + if (EnumProcessModules(this->m_processHandle, modules.data(), modules.size() * sizeof(HMODULE), &numModules) == FALSE) { + modules.clear(); + break; + } + } while (numModules == modules.size() * sizeof(HMODULE)); + + modules.resize(numModules / sizeof(HMODULE)); + + for (auto &module : modules) { + MODULEINFO moduleInfo; + if (GetModuleInformation(this->m_processHandle, module, &moduleInfo, sizeof(MODULEINFO)) == FALSE) + continue; + + char moduleName[MAX_PATH]; + if (GetModuleFileNameExA(this->m_processHandle, module, moduleName, MAX_PATH) == FALSE) + continue; + + this->m_memoryRegions.insert({ { u64(moduleInfo.lpBaseOfDll), size_t(moduleInfo.SizeOfImage) }, std::fs::path(moduleName).filename().string() }); + } + + MEMORY_BASIC_INFORMATION memoryInfo; + for (u64 address = 0; address < this->getActualSize(); address += memoryInfo.RegionSize) { + if (VirtualQueryEx(this->m_processHandle, (LPCVOID)address, &memoryInfo, sizeof(MEMORY_BASIC_INFORMATION)) == 0) + break; + + std::string name; + if (memoryInfo.State & MEM_IMAGE) continue; + if (memoryInfo.State & MEM_FREE) continue; + if (memoryInfo.State & MEM_COMMIT) name += hex::format("{} ", "hex.windows.provider.process_memory.region.commit"_lang); + if (memoryInfo.State & MEM_RESERVE) name += hex::format("{} ", "hex.windows.provider.process_memory.region.reserve"_lang); + if (memoryInfo.State & MEM_PRIVATE) name += hex::format("{} ", "hex.windows.provider.process_memory.region.private"_lang); + if (memoryInfo.State & MEM_MAPPED) name += hex::format("{} ", "hex.windows.provider.process_memory.region.mapped"_lang); + + this->m_memoryRegions.insert({ { (u64)memoryInfo.BaseAddress, (u64)memoryInfo.BaseAddress + memoryInfo.RegionSize }, name }); + } } } \ No newline at end of file