Loading repository data…
Loading repository data…
nkhmelni / repository
macOS port of opainject - ROP-based dylib injection to arm64(e) processes.
A transparent discovery signal based on current public GitHub metadata.
This score does not audit code, security, maintainers, documentation quality, or suitability. Verify the repository and its current documentation before adoption.
A dynamic library injection tool for macOS using Return-Oriented Programming (ROP) techniques to inject dylibs into running processes.
This project is a macOS port of opainject by Lars Fröder (opa334), originally developed for iOS. The core ROP injection methodology and architecture handling are derived from the original implementation.
macOS port by: @nkhmelni
Key adaptations:
get_task_by_pid() function implements the processor set enumeration technique documented by Jonathan Levin in PST2: Doing It Again, enabling task port acquisition without requiring task_for_pid() or private entitlements on macOS.opainject_macos enables runtime dylib injection into arbitrary processes by leveraging ROP chains to execute dlopen() within the target process's address space. The tool creates a controlled pthread in the target, manipulates thread state to perform arbitrary function calls, and handles sandbox restrictions when necessary.
Supported architectures: ARM64, ARM64e
Important: System Integrity Protection (SIP) may need to be disabled for the processor set enumeration technique to succeed, particularly when targeting hardened runtime binaries. Alternatively, the implementation can be modified to use task_for_pid(), which requires the com.apple.security.cs.debugger entitlement but only functions on user binaries (not system or App Store binaries).
The project uses CMake and produces a universal binary with arm64 and arm64e slices.
mkdir build
cd build
cmake ..
make
The compiled binary will be located at build/opainject and will be automatically code-signed (ad-hoc) with the included entitlements.
sudo ./opainject <pid> /path/to/dylib
Parameters:
<pid> — Process identifier of the target process/path/to/dylib — Absolute or relative path to the dynamic library to injectInjection Method: ROP-only (Return-Oriented Programming)
The injection process uses an infinite loop gadget (b . instruction, opcode 0x00000014) as a synchronization primitive. A new pthread is created in the target process that executes at this gadget, allowing controlled thread state manipulation to perform arbitrary function calls including dlopen(), sandbox_extension_consume(), and others.
Task Port Acquisition: Processor set enumeration technique (PST2)
Rather than using task_for_pid() directly, the tool enumerates all tasks via the processor set control port, matching by PID. This approach functions without requiring private entitlements, though it may require SIP to be disabled depending on the target process's hardening configuration.
MIT License
Copyright (c) 2022 Lars Fröder (original iOS implementation) Copyright (c) 2025 Nikita Hmelnitkii (macOS port)
See LICENSE for the complete license text.
This derivative work maintains the same permissive MIT License terms as the original opainject project.