diff --git a/cmake/build_helpers.cmake b/cmake/build_helpers.cmake index 9b0551a6e..1900861e1 100644 --- a/cmake/build_helpers.cmake +++ b/cmake/build_helpers.cmake @@ -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() diff --git a/plugins/builtin/include/content/providers/process_memory_provider.hpp b/plugins/builtin/include/content/providers/process_memory_provider.hpp index 53c024dcc..b8868d96e 100644 --- a/plugins/builtin/include/content/providers/process_memory_provider.hpp +++ b/plugins/builtin/include/content/providers/process_memory_provider.hpp @@ -1,6 +1,6 @@ #pragma once -#if defined(OS_WINDOWS) || (defined(OS_LINUX) && !defined(OS_FREEBSD)) +#if !defined(OS_FREEBSD) #include #include @@ -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 diff --git a/plugins/builtin/romfs/lang/en_US.json b/plugins/builtin/romfs/lang/en_US.json index b2cc62aaf..8fc109d2c 100644 --- a/plugins/builtin/romfs/lang/en_US.json +++ b/plugins/builtin/romfs/lang/en_US.json @@ -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", diff --git a/plugins/builtin/source/content/providers.cpp b/plugins/builtin/source/content/providers.cpp index 618d2bfe2..b39af67f9 100644 --- a/plugins/builtin/source/content/providers.cpp +++ b/plugins/builtin/source/content/providers.cpp @@ -37,7 +37,7 @@ namespace hex::plugin::builtin { ContentRegistry::Provider::add(false); ContentRegistry::Provider::add(false); - #if defined(OS_WINDOWS) || (defined(OS_LINUX) && !defined(OS_FREEBSD)) + #if !defined(OS_FREEBSD) ContentRegistry::Provider::add(); #endif diff --git a/plugins/builtin/source/content/providers/process_memory_provider.cpp b/plugins/builtin/source/content/providers/process_memory_provider.cpp index d5d9efffd..54b1bfdcb 100644 --- a/plugins/builtin/source/content/providers/process_memory_provider.cpp +++ b/plugins/builtin/source/content/providers/process_memory_provider.cpp @@ -1,4 +1,4 @@ -#if defined(OS_WINDOWS) || (defined(OS_LINUX) && !defined(OS_FREEBSD)) +#if !defined(OS_FREEBSD) #include @@ -6,6 +6,14 @@ #include #include #include +#elif defined(OS_MACOS) + #include + #include + #include + #include + #include + #include + #include #elif defined(OS_LINUX) #include #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(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(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(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(buffer), + size + ); #elif defined(OS_LINUX) const iovec local { .iov_base = const_cast(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 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(memoryInfo.BaseAddress), reinterpret_cast(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(&info), &count) != KERN_SUCCESS) + break; + + // Get region name + std::array 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); diff --git a/resources/dist/macos/Entitlements.plist b/resources/dist/macos/Entitlements.plist new file mode 100644 index 000000000..1362c4506 --- /dev/null +++ b/resources/dist/macos/Entitlements.plist @@ -0,0 +1,7 @@ + + + + com.apple.security.cs.debugger + + + \ No newline at end of file