1
0
mirror of synced 2024-11-27 17:10:51 +01:00

feat: Added limited support for the process memory provider to macOS

This commit is contained in:
WerWolv 2024-06-07 19:17:14 +02:00
parent 4540e1b561
commit de8465a8f4
6 changed files with 84 additions and 10 deletions

View File

@ -268,7 +268,7 @@ macro(createPackage)
find_program(CODESIGN_PATH codesign)
if (CODESIGN_PATH)
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()

View File

@ -1,6 +1,6 @@
#pragma once
#if defined(OS_WINDOWS) || (defined(OS_LINUX) && !defined(OS_FREEBSD))
#if !defined(OS_FREEBSD)
#include <hex/providers/provider.hpp>
#include <hex/api/localization_manager.hpp>
@ -28,9 +28,9 @@ namespace hex::plugin::builtin {
~ProcessMemoryProvider() override = default;
[[nodiscard]] bool isAvailable() const override {
#ifdef _WIN32
#if defined(OS_WINDOWS)
return m_processHandle != nullptr;
#elif __linux__
#else
return m_processId != -1;
#endif
}
@ -102,9 +102,9 @@ namespace hex::plugin::builtin {
return hex::containsIgnoreCase(memoryRegion.name, search);
});
#ifdef _WIN32
#if defined(OS_WINDOWS)
HANDLE m_processHandle = nullptr;
#elif __linux__
#else
pid_t m_processId = -1;
#endif

View File

@ -421,6 +421,7 @@
"hex.builtin.provider.motorola_srec.name": "Motorola SREC {0}",
"hex.builtin.provider.process_memory": "Process Memory Provider",
"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.name": "'{0}' Process Memory",
"hex.builtin.provider.process_memory.process_name": "Process Name",

View File

@ -37,7 +37,7 @@ namespace hex::plugin::builtin {
ContentRegistry::Provider::add<MemoryFileProvider>(false);
ContentRegistry::Provider::add<ViewProvider>(false);
#if defined(OS_WINDOWS) || (defined(OS_LINUX) && !defined(OS_FREEBSD))
#if !defined(OS_FREEBSD)
ContentRegistry::Provider::add<ProcessMemoryProvider>();
#endif

View File

@ -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>
@ -6,6 +6,14 @@
#include <windows.h>
#include <psapi.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)
#include <sys/uio.h>
#endif
@ -29,7 +37,7 @@ namespace hex::plugin::builtin {
m_processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_selectedProcess->id);
if (m_processHandle == nullptr)
return false;
#elif defined(OS_LINUX)
#else
m_processId = pid_t(m_selectedProcess->id);
#endif
@ -42,7 +50,7 @@ namespace hex::plugin::builtin {
#if defined(OS_WINDOWS)
CloseHandle(m_processHandle);
m_processHandle = nullptr;
#elif defined(OS_LINUX)
#else
m_processId = -1;
#endif
}
@ -50,6 +58,18 @@ namespace hex::plugin::builtin {
void ProcessMemoryProvider::readRaw(u64 address, void *buffer, size_t size) {
#if defined(OS_WINDOWS)
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)
const iovec local {
.iov_base = buffer,
@ -70,6 +90,15 @@ namespace hex::plugin::builtin {
void ProcessMemoryProvider::writeRaw(u64 address, const void *buffer, size_t size) {
#if defined(OS_WINDOWS)
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)
const iovec local {
.iov_base = const_cast<void*>(buffer),
@ -176,6 +205,18 @@ namespace hex::plugin::builtin {
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)
for (const auto& entry : std::fs::directory_iterator("/proc")) {
if (!std::fs::is_directory(entry)) continue;
@ -202,6 +243,11 @@ namespace hex::plugin::builtin {
if (m_enumerationFailed) {
ImGui::TextUnformatted("hex.builtin.provider.process_memory.enumeration_failed"_lang);
} else {
#if defined(OS_MACOS)
ImGuiExt::TextFormattedWrapped("{}", "hex.builtin.provider.process_memory.macos_limitations"_lang);
ImGui::NewLine();
#endif
ImGui::PushItemWidth(500_scaled);
const auto &filtered = m_processSearchWidget.draw(m_processes);
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 });
}
#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)
wolv::io::File file(std::fs::path("/proc") / std::to_string(m_processId) / "maps", wolv::io::File::Mode::Read);

View 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>