Application Structure
Every iOS app is a directory bundle. Understanding the bundle layout, the IPA format, and the code signature is the first step in static analysis.
The .app Bundle
An app bundle is a directory ending in .app containing the executable and all resources:
MyApp.app/
├── MyApp # the Mach-O executable (main binary)
├── Info.plist # metadata, permissions, keys
├── Frameworks/ # embedded dynamic frameworks
├── .nib / .storyboardc/ # compiled Interface Builder UI
├── Assets.car # compiled asset catalog
├── embedded.mobileprovision # provisioning profile (dev builds)
├── PkgInfo # legacy 8-byte file
├── _CodeSignature/CodeResources # signature hashes
└── CodeSignature # code signature data
Info.plist
The metadata plist drives a lot of security-relevant behavior. Read it first:
plutil -p MyApp.app/Info.plist
Pay attention to: CFBundleURLTypes (URL schemes), NSAppTransportSecurity, NSLocationUsageDescription (privacy strings), UIRequiredDeviceCapabilities, and any custom keys.
The executable
- A Mach-O binary (
MH_EXECUTE), arm64 slice. - Inspect with
otool -L(linked libraries),nm,strings,jtool2, orradare2/Ghidra for reversing.
Frameworks
- Embedded frameworks under
Frameworks/are bundled with the app (vs. system frameworks). - Embedded frameworks are a classic weak point: they are signed as part of the app and can be swapped/replaced to hijack behavior on jailbroken devices.
Compiled UI
.niband.storyboardcare compiled XIB/storyboard archives; useibtoolto dump their content, or just look at them with a plist editor.
Assets and provisioning
Assets.caris the compiled asset catalog (images/icons); extract withassetutiloracextract.embedded.mobileprovisionis the provisioning profile (see publishing note).
IPA Files
An IPA (iOS App) is just a ZIP archive containing a Payload/ folder with the .app bundle inside, plus optional SwiftSupport/ and WatchKitSupport/ directories.
unzip -l MyApp.ipa
Archive: MyApp.ipa
Length Date Time Name
--------- ---------- ----- ----
0 2024-05-11 09:32 Payload/
0 2024-05-11 09:32 Payload/MyApp.app/
8431424 2024-05-11 09:32 Payload/MyApp.app/MyApp
822 2024-05-11 09:32 Payload/MyApp.app/Info.plist
28761 2024-05-11 09:32 Payload/MyApp.app/Assets.car
... ...
4358 2024-05-11 09:32 Payload/MyApp.app/embedded.mobileprovision
32580 2024-05-11 09:32 Payload/MyApp.app/_CodeSignature/CodeResources
--------- -------
Extract an IPA with unzip, and read the bundle directly. Since an IPA is just a ZIP, you can even inspect it without an Apple device.
The Code Signature
Every bundle is signed with a signature embedded in the Mach-O (LC_CODE_SIGNATURE) plus _CodeSignature/CodeResources for resources.
codesign -dvv MyApp.app # dump signature info
codesign -d --entitlements - MyApp.app # dump entitlements
codesign --verify --deep MyApp.app # verify integrity
- The signature binds the binary hash, entitlements, and provisioning profile together.
- On a jailbroken device you can resign or patch: tools (like
ldid) re-sign modified binaries, and resource-hash checks are relaxed, this is exactly what lets testers tamper with apps and observe the result.
Pentest workflow
- Unzip the IPA and read
Info.plistfor attack surface (schemes, permissions, ATS). - Dump linked frameworks and the binary's entitlements.
- Extract embedded frameworks for standalone analysis.
- Re-sign and install the modified bundle on a test device to observe patched behavior.