When to use / when not to use
- Use: when you have an IPA / installed iOS app and need to inspect Mach-O structure, OC class structure, code signing, jailbreak environment dynamic analysis
- Use: App Store encrypted binaries need to be decrypted
- Don't use: the target is only Mach-O structure / load commands (go directly to [[re-format-macho]])
- Don't use: when runtime hook / bypass is needed (go to [[re-frida]])
- Don't use: dynamic analysis scenarios without jailbreak or managed devices (static first; for dynamic limitations, see pitfall 3)
Tool preparation
Static analysis (unpacking / class-dump / otool) can be done outside a sandbox; dynamic (jailbroken device / simulator / managed device) should be executed in a controlled environment according to the highest principle in [[re-analyze/platform-tips]].
unzip / zipinfo —— ipa unpacking
- Linux:
apt install unzip/dnf install unzip/pacman -S unzip - macOS: built-in /usr/bin/unzip; Windows/WSL: Linux version inside WSL
- Verify:
unzip -v
class-dump —— OC header export
- macOS: official repo nygard/class-dump latest release 3.4 is source-only with no precompiled binary——build from source (xcodebuild) to use;
brew install class-dumpthe formula has been removed from homebrew-core (tested in 2026, formulae.brew.sh has no such formula), no longer available - Alternative: class-dump-swift (mxms0/class-dump-swift) also supports OC and Swift class/method export, built from source (depends on LLVM + make, not the Swift toolchain)——prefer it for Swift targets
- Linux/Windows: no official version; compile class-dump-swift from source (depends on LLVM + make, not the Swift toolchain), or run on a macOS virtual machine / remote macOS
- Verify:
class-dump --help(outputting usage is sufficient)
otool —— Mach-O structure / symbol inspection (built into Apple)
- macOS:
xcode-select --install(Xcode Command Line Tools) - Linux alternative:
llvm-otool(apt install llvm/brew install llvm) - Verify:
otool -h /bin/ls
idevice toolchain (libimobiledevice) —— device identification / information
- macOS:
brew install libimobiledevice(includes idevice_id / ideviceinfo / ideviceinstaller) - Linux:
apt install libimobiledevice-utils(Debian/Ubuntu);Arch:pacman -S libimobiledevice - Verify:
idevice_id -llists connected device UDIDs;ideviceinfooutputs device model/iOS version/UDID
Jailbreak environment (optional)
- Jailbreak tools: unc0ver / checkra1n / palera1n (choose by device model and iOS version); after jailbreaking, install OpenSSH + package manager (Sileo / Cydia)
- Verify:
ssh root@<设备IP>can log in - Not jailbroken but need a real device: sign and install with an Apple developer account (free account signatures are valid for 7 days, see pitfall 2); for jailbreak environment specifics (tweak development/jailbreak detection) see [[re-ios-jb]]
iOS FairPlay decryption / unpacking (backend chosen by environment)
For App Store encrypted apps, the decryption backend should be chosen based on the target iOS and jailbreak version from a maintained implementation adapted to the current Frida API; there is no single tool that works across versions.
- Prerequisite: jailbroken device + frida-server (see [[re-frida]] tool preparation) + usbmuxd forwarding
- Selection: first align
frida --versionwith the device frida-server version, then choose a dumper compatible with that Frida generation. Starting with Frida 17, staticModulelookup/enumeration APIs were removed (see [[re-frida]] common pitfalls); dumpers that still rely on these old APIs will error out directly under Frida 17 - legacy / reference implementation:
AloneMonkey/frida-ios-dump's Frida agent usesModule.ensureInitialized, staticMemory.read*、Module.findExportByName(null, …)、Process.enumerateModulesSync——These APIs have been removed in Frida 17; this repository is better used as a reference for unpacking algorithms and Mach-O reassembly logic; to use it directly, Frida 16 or below's frida-server is required, or port it yourself to the new API. - Another approach: based on
mremap_encryptedimplementations (UnFairPlay / unfaird and the like), which do not rely on frida runtime instrumentation; evaluate usability based on the target iOS version. - Device channel: macOS
brew install libusbmuxd(the former usbmuxd formula has been renamed); Linuxapt install usbmuxd(Debian/Ubuntu, includes iproxy); Archpacman -S libusbmuxd - Verification:
iproxy -h(forwarding tool usability); for the selected dumper, confirm parameters according to its own-houtput.
Procedure
Execute in order, and record the results of each step (evidence path + sha256, see [[re-triage]]).
-
ipa unpacking and signature check:
unzip app.ipa -d app/ file app/Payload/*.app/* # 确认主二进制是 arm64 Mach-O codesign -dv app/Payload/*.app/ 2>&1 # 签名类型(Apple Distribution / Development / adhoc) otool -l app/Payload/*.app/ | grep -B1 -A4 LC_ENCRYPTION_INFO # 查 cryptidcryptid 1= App Store encrypted; the code on disk is ciphertext; unpack first (step 5) before continuing.- Package structure overview:
Payload/<App>.app/is the main binary and resources;SwiftSupport/is the system Swift library (common in simulator packages);embedded.mobileprovisionis the signature description file (on macOSsecurity cms -D -ican read entitlements and expiration time) fileConfirm that the main binary is an arm64/arm64e real-device architecture——x86_64 simulator artifacts have no dynamic analysis value; skip them directly.
- Package structure overview:
-
class-dump headers:
class-dump -H app/Payload/*.app/ -o headers/Class names / method names / properties are most of the business interfaces; look at headers before decompiling. For encrypted binaries, unpack first (step 5) before dumping; otherwise you only get the shell's classes. Swift methods do not enter OC headers (see pitfall 4).
-
Binary goes through [[re-format-macho]]:
otool -h app/Payload/*.app/ # 架构 / cputype otool -L app/Payload/*.app/ # 依赖 dylib(framework 清单)Structure, load commands, entry point, segments, and signatures are executed according to the steps in [[re-format-macho]]; for Swift binaries use
strings -n 6to find symbols and error messages to assist in locating. -
Dynamic debugging in jailbroken environment:
iproxy 2222 22 & # usbmuxd 转发设备 ssh 到本机 2222 ssh -p 2222 root@127.0.0.1 # 登录越狱设备Launch the target App on the device; breakpoints / single-step debugging via debugserver + lldb (see [[re-lldb]]); hooking / bypassing prioritizes [[re-frida]] (for frida-server installation see that skill).
-
Unpacking (FairPlay decryption):
frida --version # 主机 Frida 世代——选 dumper 前先定 iproxy 2222 22 & <选定 dumper> <BundleID 或 App 名> # 按目标 iOS / Frida 版本选维护实现,拉取并解密 file <输出>.ipa otool -l <输出>/Payload/*.app/ | grep -A4 LC_ENCRYPTION_INFO # 确认 cryptid 0Idea: read the Mach-O header and segments from the decrypted memory image, and reassemble them into a decrypted ipa. The dumper must match the generation of the host
frida --versionand the device frida-server (see tool preparation); the unpacked artifact goes back to steps 1-3 and is rerun.
Cross-domain combination
- [[re-mobile]]: workflow step 2 (iOS branch) always calls this skill
- Binary parsing → [[re-format-macho]]; breakpoint debugging → [[re-lldb]]; instrumentation / bypass / unpacking execution → [[re-frida]]
- This skill is called by the triage "Mobile App Analysis" path of [[re-analyze]] (re-mobile → re-ios).
- Desktop macOS ecosystem (signing/entitlements/Secure Enclave) → [[re-macos]]
- Swift-layer analysis (mangling/witness table) → [[re-swift]]
- Jailbroken environment special topics (tweak analysis and development, jailbreak detection identification and bypass) → [[re-ios-jb]]
Common pitfalls and traps
- Directly analyzing App Store encrypted binaries: symptom——class-dump has no output / otool structure is incomplete, and decompilation only shows the shell; cause——
cryptid 1encrypted, the code on disk is ciphertext; countermeasure——in step 1 first check LC_ENCRYPTION_INFO, if encrypted first unpack according to step 5. - Invalid signature prevents installation: Symptom — after repackaging / modification, installation on a real device reports "Unable to verify App" or fails to install; Cause — the signature does not match the content, or the free certificate has expired after 7 days; Countermeasure —
codesign -f -s -adhoc re-signing (self-signed scenarios only) or re-signing with a developer certificate; for free accounts, reinstall upon expiration - No jailbreak → dynamic analysis is limited: Symptom — without a jailbroken device, decryption / lldb attach / frida are all unavailable; Cause — the iOS sandbox and code signing enforcement restrict dynamic debugging; Countermeasure — static analysis first (steps 1-3), then move dynamic work to a simulator (requires an unencrypted app) or a managed device (Apple Configurator deployment + development certificate); if all else fails, do static only
- Swift methods do not appear in class-dump headers: Symptom — business methods cannot be found in class header files; Cause — Swift does not export Objective-C runtime metadata; Countermeasure —
strings/swift-demanglelook for symbols, and rely on [[re-format-macho]] + decompilation ([[re-binary-core]]) for logic analysis - class-dump errors on arm64e binaries: Symptom — class-dump crashes or outputs nothing; Cause — arm64e pointer authentication (PAC) interferes with metadata traversal; Countermeasure — switch to a newer class-dump / class-dump-swift, or decrypt first and then dump
- Mistaking a simulator build for a real-device artifact: Symptom —
fileshows the main binary is x86_64, and dynamic analysis is entirely unavailable; Cause — the distributor provided a simulator package (often with SwiftSupport/); Countermeasure — in step 1, usefileto confirm the arm64/arm64e real-device architecture, and skip simulator artifacts - class-dump cannot be installed (brew formula removed): Symptom —
brew install class-dumpreports No available formula; Cause — homebrew-core has removed this formula (tested in 2026); Countermeasure — build from the nygard/class-dump source, or switch to class-dump-swift (see tool preparation)