Dumping and repacking decrypted iOS binaries
Overview
App Store binaries are protected by FairPlay DRM on disk. When an app starts, iOS decrypts the executable pages in memory so the process can run. A reverse engineering workflow can use that runtime state to copy the decrypted Mach-O data, replace the encrypted copy in the app bundle, and package the result for analysis.
frida-ios-dump automates that workflow with Frida and SSH. This article explains the parts of the Mach-O format that matter for the dump process and how the decrypted binary is reconstructed into an IPA.
iOS app encryption and decryption
How FairPlay DRM encrypts iOS applications
When an iOS app is downloaded from the App Store, the executable Mach-O binary is encrypted with Apple’s FairPlay DRM. The protected data is typically the __TEXT segment, which contains executable instructions.
- The encrypted range is described by the
LC_ENCRYPTION_INFOorLC_ENCRYPTION_INFO_64load command. - The
cryptidfield indicates whether the binary is encrypted:cryptid = 1: The binary is encrypted.cryptid = 0: The binary is decrypted.
- The
cryptoffandcryptsizefields define the encrypted range.
Example otool -l output for an encrypted binary:
Load command 9
cmd LC_ENCRYPTION_INFO
cmdsize 20
cryptoff 16384
cryptsize 102400
cryptid 1 # Indicates encryption is active
How decryption happens at runtime
When an encrypted app is launched, iOS decrypts it in memory so the operating system can execute it:
- The kernel loads the encrypted Mach-O binary into memory.
- If the app is FairPlay-protected, the kernel decrypts the encrypted segments in memory.
- The decrypted instructions are executed as normal by the CPU.
The decrypted bytes are available in process memory while the app runs. The file on disk remains encrypted.
Mach-O load commands
What are load commands?
Mach-O load commands describe the structure and behavior of an executable. The dynamic linker uses them to map segments, load libraries, locate entry points, and interpret metadata.
Each Mach-O binary has a header that contains:
- The number of load commands (
ncmds) - The size of all load commands combined
Common load commands include:
LC_SEGMENTandLC_SEGMENT_64: Define memory segments such as__TEXTand__DATA.LC_ENCRYPTION_INFOandLC_ENCRYPTION_INFO_64: Store encryption metadata.LC_LOAD_DYLIB: List dynamically linked libraries.LC_MAIN: Define the entry point.
Understanding __TEXT and __DATA segments
In every Mach-O binary, there are multiple segments, each containing different types of data. Two of the most important segments are:
__TEXT segment
- Stores executable code (compiled machine instructions).
- Read-only memory (cannot be modified at runtime).
- Contains function implementations, constants, and metadata.
- In encrypted binaries, FairPlay DRM encrypts this segment, requiring decryption at runtime.
__DATA segment
- Stores writable program data, such as global variables.
- Contains sections like:
__data: Initialized global/static variables.__bss: Uninitialized global variables.__objc_data: Objective-C runtime metadata.
Key differences between __TEXT and __DATA
| Feature | `__TEXT` Segment | `__DATA` Segment |
|--------------------|-----------------|-----------------|
| Stores | Executable code | Modifiable data (variables, metadata) |
| Memory Permissions | Read-only (`r-x`) | Read-Write (`rw-`) |
| Encrypted by FairPlay? | Yes | No |
How frida-ios-dump uses these segments
When extracting a decrypted binary, frida-ios-dump targets the __TEXT segment because that is the encrypted region. The tool:
- Reads the
LC_SEGMENTcommands to locate the__TEXTsegment. - Extracts the
__TEXTsegment’s virtual memory address and size. - Dumps the decrypted contents from memory into a new Mach-O file.
var text_segment;
for (var i = 0; i < segments.length; i++) {
if (segments[i].name == "__TEXT") {
text_segment = segments[i];
break;
}
}
var decrypted_data = Memory.readByteArray(modbase.add(text_segment.vmaddr), text_segment.vmsize);
The decrypted Mach-O binary is saved to disk. An iOS app bundle can contain additional Mach-O binaries, frameworks, and resources, so the dump process must preserve the bundle structure.
Reconstructing the IPA file
Once all decrypted Mach-O binaries have been dumped, frida-ios-dump restructures them into an IPA file:
- Replaces the encrypted Mach-O binaries inside the app bundle with the decrypted ones.
- Maintains the app’s original structure, including Info.plist, frameworks, and resources.
- Packages everything into a new IPA file that can be sideloaded or analyzed.
Summary
frida-ios-dumpautomates extraction with Frida and SSH.- iOS decrypts FairPlay-protected executable pages when the app launches.
- Frida reads the decrypted region from memory and writes it to disk.
- The
cryptidflag is set to0so analysis tools treat the output as decrypted. - The app bundle is repacked into an IPA after encrypted Mach-O files are replaced.
The resulting IPA is useful for static analysis, instrumentation, and repeatable reverse engineering workflows.