feat: Added limited support for the process memory provider to macOS
This commit is contained in:
parent
4540e1b561
commit
de8465a8f4
@ -268,7 +268,7 @@ macro(createPackage)
|
|||||||
find_program(CODESIGN_PATH codesign)
|
find_program(CODESIGN_PATH codesign)
|
||||||
if (CODESIGN_PATH)
|
if (CODESIGN_PATH)
|
||||||
install(CODE "message(STATUS \"Signing bundle '${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}'...\")")
|
install(CODE "message(STATUS \"Signing bundle '${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME}'...\")")
|
||||||
install(CODE "execute_process(COMMAND ${CODESIGN_PATH} --force --deep --sign - ${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME} COMMAND_ERROR_IS_FATAL ANY)")
|
install(CODE "execute_process(COMMAND ${CODESIGN_PATH} --force --deep --entitlements ${CMAKE_SOURCE_DIR}/resources/macos/Entitlements.plist --sign - ${CMAKE_INSTALL_PREFIX}/${BUNDLE_NAME} COMMAND_ERROR_IS_FATAL ANY)")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if defined(OS_WINDOWS) || (defined(OS_LINUX) && !defined(OS_FREEBSD))
|
#if !defined(OS_FREEBSD)
|
||||||
|
|
||||||
#include <hex/providers/provider.hpp>
|
#include <hex/providers/provider.hpp>
|
||||||
#include <hex/api/localization_manager.hpp>
|
#include <hex/api/localization_manager.hpp>
|
||||||
@ -28,9 +28,9 @@ namespace hex::plugin::builtin {
|
|||||||
~ProcessMemoryProvider() override = default;
|
~ProcessMemoryProvider() override = default;
|
||||||
|
|
||||||
[[nodiscard]] bool isAvailable() const override {
|
[[nodiscard]] bool isAvailable() const override {
|
||||||
#ifdef _WIN32
|
#if defined(OS_WINDOWS)
|
||||||
return m_processHandle != nullptr;
|
return m_processHandle != nullptr;
|
||||||
#elif __linux__
|
#else
|
||||||
return m_processId != -1;
|
return m_processId != -1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -102,9 +102,9 @@ namespace hex::plugin::builtin {
|
|||||||
return hex::containsIgnoreCase(memoryRegion.name, search);
|
return hex::containsIgnoreCase(memoryRegion.name, search);
|
||||||
});
|
});
|
||||||
|
|
||||||
#ifdef _WIN32
|
#if defined(OS_WINDOWS)
|
||||||
HANDLE m_processHandle = nullptr;
|
HANDLE m_processHandle = nullptr;
|
||||||
#elif __linux__
|
#else
|
||||||
pid_t m_processId = -1;
|
pid_t m_processId = -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -421,6 +421,7 @@
|
|||||||
"hex.builtin.provider.motorola_srec.name": "Motorola SREC {0}",
|
"hex.builtin.provider.motorola_srec.name": "Motorola SREC {0}",
|
||||||
"hex.builtin.provider.process_memory": "Process Memory Provider",
|
"hex.builtin.provider.process_memory": "Process Memory Provider",
|
||||||
"hex.builtin.provider.process_memory.enumeration_failed": "Failed to enumerate processes",
|
"hex.builtin.provider.process_memory.enumeration_failed": "Failed to enumerate processes",
|
||||||
|
"hex.builtin.provider.process_memory.macos_limitations": "macOS doesn't properly allow reading memory from other processes, even when running as root. If System Integrity Protection (SIP) is enabled, it only works for applications that are unsigned or have the 'Get Task Allow' entitlement which generally only applies to applications compiled by yourself.",
|
||||||
"hex.builtin.provider.process_memory.memory_regions": "Memory Regions",
|
"hex.builtin.provider.process_memory.memory_regions": "Memory Regions",
|
||||||
"hex.builtin.provider.process_memory.name": "'{0}' Process Memory",
|
"hex.builtin.provider.process_memory.name": "'{0}' Process Memory",
|
||||||
"hex.builtin.provider.process_memory.process_name": "Process Name",
|
"hex.builtin.provider.process_memory.process_name": "Process Name",
|
||||||
|
@ -37,7 +37,7 @@ namespace hex::plugin::builtin {
|
|||||||
ContentRegistry::Provider::add<MemoryFileProvider>(false);
|
ContentRegistry::Provider::add<MemoryFileProvider>(false);
|
||||||
ContentRegistry::Provider::add<ViewProvider>(false);
|
ContentRegistry::Provider::add<ViewProvider>(false);
|
||||||
|
|
||||||
#if defined(OS_WINDOWS) || (defined(OS_LINUX) && !defined(OS_FREEBSD))
|
#if !defined(OS_FREEBSD)
|
||||||
ContentRegistry::Provider::add<ProcessMemoryProvider>();
|
ContentRegistry::Provider::add<ProcessMemoryProvider>();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#if defined(OS_WINDOWS) || (defined(OS_LINUX) && !defined(OS_FREEBSD))
|
#if !defined(OS_FREEBSD)
|
||||||
|
|
||||||
#include <content/providers/process_memory_provider.hpp>
|
#include <content/providers/process_memory_provider.hpp>
|
||||||
|
|
||||||
@ -6,6 +6,14 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <psapi.h>
|
#include <psapi.h>
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
|
#elif defined(OS_MACOS)
|
||||||
|
#include <mach/mach_types.h>
|
||||||
|
#include <mach/message.h>
|
||||||
|
#include <mach/arm/kern_return.h>
|
||||||
|
#include <mach/arm/vm_types.h>
|
||||||
|
#include <mach/vm_map.h>
|
||||||
|
#include <mach-o/dyld_images.h>
|
||||||
|
#include <libproc.h>
|
||||||
#elif defined(OS_LINUX)
|
#elif defined(OS_LINUX)
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#endif
|
#endif
|
||||||
@ -29,7 +37,7 @@ namespace hex::plugin::builtin {
|
|||||||
m_processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_selectedProcess->id);
|
m_processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_selectedProcess->id);
|
||||||
if (m_processHandle == nullptr)
|
if (m_processHandle == nullptr)
|
||||||
return false;
|
return false;
|
||||||
#elif defined(OS_LINUX)
|
#else
|
||||||
m_processId = pid_t(m_selectedProcess->id);
|
m_processId = pid_t(m_selectedProcess->id);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -42,7 +50,7 @@ namespace hex::plugin::builtin {
|
|||||||
#if defined(OS_WINDOWS)
|
#if defined(OS_WINDOWS)
|
||||||
CloseHandle(m_processHandle);
|
CloseHandle(m_processHandle);
|
||||||
m_processHandle = nullptr;
|
m_processHandle = nullptr;
|
||||||
#elif defined(OS_LINUX)
|
#else
|
||||||
m_processId = -1;
|
m_processId = -1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -50,6 +58,18 @@ namespace hex::plugin::builtin {
|
|||||||
void ProcessMemoryProvider::readRaw(u64 address, void *buffer, size_t size) {
|
void ProcessMemoryProvider::readRaw(u64 address, void *buffer, size_t size) {
|
||||||
#if defined(OS_WINDOWS)
|
#if defined(OS_WINDOWS)
|
||||||
ReadProcessMemory(m_processHandle, reinterpret_cast<LPCVOID>(address), buffer, size, nullptr);
|
ReadProcessMemory(m_processHandle, reinterpret_cast<LPCVOID>(address), buffer, size, nullptr);
|
||||||
|
#elif defined(OS_MACOS)
|
||||||
|
task_t t;
|
||||||
|
task_for_pid(mach_task_self(), m_processId, &t);
|
||||||
|
|
||||||
|
vm_size_t dataSize = 0;
|
||||||
|
vm_read_overwrite(t,
|
||||||
|
address,
|
||||||
|
size,
|
||||||
|
reinterpret_cast<vm_address_t>(buffer),
|
||||||
|
&dataSize
|
||||||
|
);
|
||||||
|
|
||||||
#elif defined(OS_LINUX)
|
#elif defined(OS_LINUX)
|
||||||
const iovec local {
|
const iovec local {
|
||||||
.iov_base = buffer,
|
.iov_base = buffer,
|
||||||
@ -70,6 +90,15 @@ namespace hex::plugin::builtin {
|
|||||||
void ProcessMemoryProvider::writeRaw(u64 address, const void *buffer, size_t size) {
|
void ProcessMemoryProvider::writeRaw(u64 address, const void *buffer, size_t size) {
|
||||||
#if defined(OS_WINDOWS)
|
#if defined(OS_WINDOWS)
|
||||||
WriteProcessMemory(m_processHandle, reinterpret_cast<LPVOID>(address), buffer, size, nullptr);
|
WriteProcessMemory(m_processHandle, reinterpret_cast<LPVOID>(address), buffer, size, nullptr);
|
||||||
|
#elif defined(OS_MACOS)
|
||||||
|
task_t t;
|
||||||
|
task_for_pid(mach_task_self(), m_processId, &t);
|
||||||
|
|
||||||
|
vm_write(t,
|
||||||
|
address,
|
||||||
|
reinterpret_cast<vm_address_t>(buffer),
|
||||||
|
size
|
||||||
|
);
|
||||||
#elif defined(OS_LINUX)
|
#elif defined(OS_LINUX)
|
||||||
const iovec local {
|
const iovec local {
|
||||||
.iov_base = const_cast<void*>(buffer),
|
.iov_base = const_cast<void*>(buffer),
|
||||||
@ -176,6 +205,18 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
m_processes.push_back({ u32(processId), processName, std::move(texture) });
|
m_processes.push_back({ u32(processId), processName, std::move(texture) });
|
||||||
}
|
}
|
||||||
|
#elif defined(OS_MACOS)
|
||||||
|
std::array<pid_t, 2048> pids;
|
||||||
|
const auto bytes = proc_listpids(PROC_ALL_PIDS, 0, pids.data(), sizeof(pids));
|
||||||
|
const auto processCount = bytes / sizeof(pid_t);
|
||||||
|
for (u32 i = 0; i < processCount; i += 1) {
|
||||||
|
proc_bsdinfo proc;
|
||||||
|
const auto result = proc_pidinfo(pids[i], PROC_PIDTBSDINFO, 0,
|
||||||
|
&proc, PROC_PIDTBSDINFO_SIZE);
|
||||||
|
if (result == PROC_PIDTBSDINFO_SIZE) {
|
||||||
|
m_processes.emplace_back(pids[i], proc.pbi_name, ImGuiExt::Texture());
|
||||||
|
}
|
||||||
|
}
|
||||||
#elif defined(OS_LINUX)
|
#elif defined(OS_LINUX)
|
||||||
for (const auto& entry : std::fs::directory_iterator("/proc")) {
|
for (const auto& entry : std::fs::directory_iterator("/proc")) {
|
||||||
if (!std::fs::is_directory(entry)) continue;
|
if (!std::fs::is_directory(entry)) continue;
|
||||||
@ -202,6 +243,11 @@ namespace hex::plugin::builtin {
|
|||||||
if (m_enumerationFailed) {
|
if (m_enumerationFailed) {
|
||||||
ImGui::TextUnformatted("hex.builtin.provider.process_memory.enumeration_failed"_lang);
|
ImGui::TextUnformatted("hex.builtin.provider.process_memory.enumeration_failed"_lang);
|
||||||
} else {
|
} else {
|
||||||
|
#if defined(OS_MACOS)
|
||||||
|
ImGuiExt::TextFormattedWrapped("{}", "hex.builtin.provider.process_memory.macos_limitations"_lang);
|
||||||
|
ImGui::NewLine();
|
||||||
|
#endif
|
||||||
|
|
||||||
ImGui::PushItemWidth(500_scaled);
|
ImGui::PushItemWidth(500_scaled);
|
||||||
const auto &filtered = m_processSearchWidget.draw(m_processes);
|
const auto &filtered = m_processSearchWidget.draw(m_processes);
|
||||||
ImGui::PopItemWidth();
|
ImGui::PopItemWidth();
|
||||||
@ -356,6 +402,26 @@ namespace hex::plugin::builtin {
|
|||||||
m_memoryRegions.insert({ { reinterpret_cast<u64>(memoryInfo.BaseAddress), reinterpret_cast<u64>(memoryInfo.BaseAddress) + memoryInfo.RegionSize }, name });
|
m_memoryRegions.insert({ { reinterpret_cast<u64>(memoryInfo.BaseAddress), reinterpret_cast<u64>(memoryInfo.BaseAddress) + memoryInfo.RegionSize }, name });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif defined(OS_MACOS)
|
||||||
|
vm_region_submap_info_64 info;
|
||||||
|
mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64;
|
||||||
|
vm_address_t address = 0;
|
||||||
|
vm_size_t size = 0;
|
||||||
|
natural_t depth = 0;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (vm_region_recurse_64(mach_task_self(), &address, &size, &depth, reinterpret_cast<vm_region_info_64_t>(&info), &count) != KERN_SUCCESS)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Get region name
|
||||||
|
std::array<char, 1024> name;
|
||||||
|
if (proc_regionfilename(m_processId, address, name.data(), name.size()) != 0) {
|
||||||
|
std::strcpy(name.data(), "???");
|
||||||
|
}
|
||||||
|
|
||||||
|
m_memoryRegions.insert({ { address, size }, name.data() });
|
||||||
|
address += size;
|
||||||
|
}
|
||||||
#elif defined(OS_LINUX)
|
#elif defined(OS_LINUX)
|
||||||
|
|
||||||
wolv::io::File file(std::fs::path("/proc") / std::to_string(m_processId) / "maps", wolv::io::File::Mode::Read);
|
wolv::io::File file(std::fs::path("/proc") / std::to_string(m_processId) / "maps", wolv::io::File::Mode::Read);
|
||||||
|
7
resources/dist/macos/Entitlements.plist
vendored
Normal file
7
resources/dist/macos/Entitlements.plist
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.cs.debugger</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
Loading…
Reference in New Issue
Block a user