A Python tool to decrypt and dump the executable code of iOS applications running on jailbroken devices.
I've been dissatisfied with existing iOS app decryption tools for a while. Many are outdated and don't handle rootless jailbreaks well, or don't work on newer iOS versions.
This tool automates the "clutching" process: it locates the encrypted __TEXT segment in memory, dumps the decrypted bytes using Frida, and surgically patches a local copy of the binary. It utilizes a hybrid approach (Raw I/O + LIEF) to ensure the binary is immediately ready for static analysis in tools like Binary Ninja, IDA Pro, or Ghidra.
- Auto-Pull Binary: Automatically downloads the encrypted binary from the device - no manual SCP required.
- Full Automation: Dumps decrypted code and updates the Mach-O header (
cryptid=0) in one pass. - Module Targeting: Can decrypt the main app executable or specific encrypted frameworks/dylibs.
- Hybrid Patching:
- Uses Raw I/O for precise, safe injection of code bytes.
- Uses LIEF for safe parsing and modification of header metadata.
- Rootless Compatible: Works on both rootful and rootless jailbreaks (Palera1n, Dopamine, etc.) on iOS 15-18.
- Frida 17+ Compatible: Updated to use the latest Frida JavaScript API.
- Analysis Ready: The output file opens directly in disassemblers without encryption warnings.
Install the tool globally using pipx:
pipx install .This makes the frida-decrypt command available from any directory.
To update after making changes:
pipx install --force .To uninstall:
pipx uninstall frida-decryptAlternatively, install with pip:
pip install .- Python 3.8 or later
- pipx (recommended) or pip
- Frida Server must be running.
- Rootless: Install
frida-servervia Sileo/Zebra. - Verification: Run
frida-ps -Ufrom your host machine to confirm connectivity.
- Rootless: Install
The simplest method - automatically pulls the binary from the device and decrypts it:
frida-decrypt "<Process Name>"Example:
frida-decrypt InstagramResult: Downloads Instagram from device and creates Instagram_decrypted ready for analysis.
If you already have the encrypted binary locally:
frida-decrypt "<Process Name>" -l "<Local Binary Path>"Example:
frida-decrypt Instagram -l ./InstagramUse this if the main logic is hidden inside an encrypted framework or dynamic library:
frida-decrypt "<Process Name>" -m "<Module Name>"Example:
frida-decrypt Instagram -m SomeFrameworkSpecify where to save the downloaded and decrypted binaries:
frida-decrypt Instagram -o ./outputpositional arguments:
process Name of the running process on the device
optional arguments:
-l, --local-binary Path to local encrypted binary (skip download)
-m, --module Specific module/dylib name to dump
-o, --output-dir Output directory (default: current directory)- Attach: The script connects to the running app process on the device via USB.
- Download (optional): Uses Frida to read the encrypted binary directly from the device filesystem.
- Locate: Injects JavaScript to parse the Mach-O headers in memory, finding the
LC_ENCRYPTION_INFO_64command. - Dump: Reads the decrypted bytes from RAM.
- Patch:
- Uses standard file I/O to overwrite the encrypted bytes in the local file with the dumped data.
- Uses LIEF to set
cryptidto0, marking the file as decrypted.
-
Error attaching to process...- Ensure the app is running in the foreground.
- Use
frida-ps -Uto verify the exact process name.
-
LIEF Error: ...- The script will still inject the raw bytes. You may need to manually hex-edit the
cryptidflag to00.
- The script will still inject the raw bytes. You may need to manually hex-edit the
-
Binary download fails
- Ensure Frida server is running on the device.
- Try using
-lwith a manually transferred binary via SCP.
- Frida 17.0.0 or later
- Python 3.8 or later
- LIEF library