Skip to content

IPA

IPA File

An IPA file is just a Zip File with the folder information below

Example IPA File Structure:

Payload
└── APPNAME.app
  ├── _CodeSignature
  │  └── CodeResources
  ├── [email protected]
  ├── AppIcon76x76@2x~ipad.png
  ├── Assets.car
  ├── Base.lproj
  │  └── Localizable.strings
  ├── Frameworks
  │  ├── AFNetworking.framework
  │  ├── DoubleConversion.framework
  │  ├── Eureka.framework
  │  ├── FMDB.framework
  │  ├── libswiftAccelerate.dylib
  │  ├── SQLCipher.framework
  │  │  ├── _CodeSignature
  │  │  │  └── CodeResources
  │  │  ├── Info.plist
  │  │  ├── SC_Info
  │  │  │  ├── SQLCipher.sinf
  │  │  │  ├── SQLCipher.supf
  │  │  │  ├── SQLCipher.supp
  │  │  │  └── SQLCipher.supx
  │  │  ├── SQLCipher
  │  │  └── SQLCipher.i64
  │  │     ├── info.png
  │  │     ├── [email protected]
  │  │     ├── [email protected]
  │  │     ├── success.png
  │  │     ├── [email protected]
  │  │     └── [email protected]
  │  └── yoga.framework
  │     ├── _CodeSignature
  │     │  └── CodeResources
  │     ├── Info.plist
  │     ├── SC_Info
  │     │  ├── yoga.sinf
  │     │  ├── yoga.supf
  │     │  ├── yoga.supp
  │     │  └── yoga.supx
  │     └── yoga
  ├── FullscreenImageVC.nib

Look at the .plist and .json files sensitive data can be included in the application.

Check the Info.plist for application configuration.

Permissions

The user Grants the Permissions at runtime like the new android model.

Permissions:
- Contacts
- Microphone
- Calendars
- Camera
- Reminders
- HomeKit
- Photos
- Health
- Motion activity and fitness
- Speech recognition
- Location Services
- Bluetooth sharing
- Media Library
- Social media accounts

Entitlements

Entitlements are Permissions to iOS Sanboxed data.
These are stored in a Plist file called archived-expanded-entitlements.xcent.

Example archived-expanded-entitlements.xcent file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>application-identifier</key>
    <string>69CN5HMUNT.co.razio.RS-Exchange</string>
    <key>keychain-access-groups</key>
    <array>
        <string>69CN5HMUNT.co.razio.RS-Exchange</string>
    </array>
    <key>com.apple.developer.associated-domains</key>
    <array>
        <string>applinks:telegram.me</string>
        <string>applinks:t.me</string>
    </array>
</dict>
</plist>

Contains URLs this app can open:

plist Files

Read though objection:

OWASP.iGoat-Swift on (iPhone: 12.0) [usb] # ios plist cat <myfile.plist>

Read through plutil:

plutil -convert xml1 Info.plist

Info.plist

Contains Information about the application. Similar to Application Manifest.xml from Android.
- NSAppTransportSecurity
- NSAllowsArbitraryLoads
- NSAllowsArbitraryLoadsForMedia
- NSAllowsArbitraryLoadsInWebContent
- NSAllowsLocalNetworking
- NSExceptionDomains
- NSIncludesSubdomains
- NSExceptionAllowsInsecureHTTPLoads
- NSExceptionMinimumTLSVersion
- NSExceptionRequiresForwardSecrecy
- NSRequiresFCertificateTransparency

Full list of Keys.

More info found here

Encrypted Executable

When downloading from the App store the Executable code is encrypted. Apple uses a custom DRM technology called FairPlay. To decrypt it it needs to be run then dumped from memory.
- The Decryption key is associated with the Apple Id that downloaded the application.
- The Private key is stored on the iOS device when signing into the apple store.
- The decryption keys are in the SC_Info folder.

Todo

Look into https://github.com/ChiChou/bagbak

Is the Executable Encrypted:

>>> otool -l Safari | grep -A4 LC_ENCRYPTION_INFO_64
          cmd LC_ENCRYPTION_INFO_64
      cmdsize 24
     cryptoff 16384
    cryptsize 1146880
      cryptid 1

Check if PIE flag is enabled:

otool -Vh <TARGETMACHO>

Check if stack smashing protections are enabled:

otool -Iv <TARGETMACHO> | grep -i stack

Check if Automatic Reference Counting (ARC) is enabled:

otool -Iv <TARGETMACHO> | grep -iE "objc_autorelease|objc_release"

Convert Fat binary into a thin binary:*

>>> otool -hv DamnVulnerableIOSApp

DamnVulnerableIOSApp (architecture armv7):
Mach header
     magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
  MH_MAGIC     ARM         V7  0x00     EXECUTE    38       4292   NOUNDEFS DYLDLINK TWOLEVEL WEAK_DEFINES BINDS_TO_WEAK PIE

DamnVulnerableIOSApp (architecture arm64):
Mach header
     magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
MH_MAGIC_64   ARM64        ALL  0x00     EXECUTE    38       4856   NOUNDEFS DYLDLINK TWOLEVEL WEAK_DEFINES BINDS_TO_WEAK PIE
>>> lipo -thin armv7 DamnVulnerableIOSApp -output DVIA32

Without Jailbreak

https://github.com/DerekSelander/yacd

Through Frida Script (Old Don't Use)

Using the Frida Script:

>>> frida -U "Test App" /opt/Memory/Mobile/frida_iOS_dump_ipa.js
     ____
    / _  |   Frida 12.3.6 - A world-class dynamic instrumentation toolkit
   | (_| |
    > _  |   Commands:
   /_/ |_|       help      -> Displays the help system
   . . . .       object?   -> Display information about 'object'
   . . . .       exit/quit -> Exit
   . . . .
   . . . .   More info at http://www.frida.re/docs/home/
                                                                                
[iOS Device::Test App]-> dumpModule(".app")
Fix decrypted at:ca0
Fix decrypted at:4000
Decrypted file at:/var/mobile/Containers/Data/Application/1BD09CA5-BFB1-4223-99A4-4FCD6EC8A784/Library/mscrmapp.decrypted 0x550000
undefined
[iOS Device::Test App]->

Copy decrypted File:

scp -P 2222 -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null [email protected]:/var/mobile/Containers/Data/Application/1BD09CA5-BFB1-4223-99A4-4FCD6EC8A784/Library/mscrmapp.decrypted .

Through Frida Python (Old Donot use)

Checkout Python3 Version:

git clone https://github.com/AloneMonkey/frida-ios-dump
cd frida-ios-dump
git checkout 3.x

Change SSH Connection information:

vim dump.py 

Dump app:

>>> python2 dump.py -o Test\ App\ 13.19043.32_decrypted.ipa com.test.iphone.app
/usr/lib/python3.7/site-packages/paramiko/kex_ecdh_nist.py:39: CryptographyDeprecationWarning: encode_point has been deprecated on EllipticCurvePublicNumbers and will be removed in a future version. Please use EllipticCurvePublicKey.public_bytes to obtain both compressed and uncompressed point encoding.
  m.add_string(self.Q_C.public_numbers().encode_point())
/usr/lib/python3.7/site-packages/paramiko/kex_ecdh_nist.py:96: CryptographyDeprecationWarning: Support for unsafe construction of public numbers from encoded data will be removed in a future version. Please use EllipticCurvePublicKey.from_encoded_point
  self.curve, Q_S_bytes
/usr/lib/python3.7/site-packages/paramiko/kex_ecdh_nist.py:111: CryptographyDeprecationWarning: encode_point has been deprecated on EllipticCurvePublicNumbers and will be removed in a future version. Please use EllipticCurvePublicKey.public_bytes to obtain both compressed and uncompressed point encoding.
  hm.add_string(self.Q_C.public_numbers().encode_point())
Start the target app com.test.iphone.app
Dumping Test App to /tmp
[frida-ios-dump]: IntuneMAMWalledGarden.framework has been loaded. 
start dump /var/containers/Bundle/Application/D9187540-72A8-465E-88E5-E86C9ADD6B0D/mscrmapp.app/mscrmapp
mscrmapp.fid: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████| 6.82M/6.82M [00:00<00:00, 15.9MB/s]
start dump /private/var/containers/Bundle/Application/D9187540-72A8-465E-88E5-E86C9ADD6B0D/mscrmapp.app/Frameworks/IntuneMAMWalledGarden.framework/IntuneMAMWalledGarden
IntuneMAMWalledGarden.fid: 100%|██████████████████████████████████████████████████████████████████████████████████████████| 5.27M/5.27M [00:00<00:00, 20.9MB/s]
Resources.strings: 53.3MB [00:09, 5.73MB/s]                                                                                                                    
0.00B [00:00, ?B/s]
Generating "13.19043.32_decrypted.ipa"

Before iOS 11

Use Clutch to list the installed applications on your device:

>>> ./Clutch-2.0.4 -i
Installed apps:
[...]
2:   Duo Mobile <com.duosecurity.DuoMobile>

Use Clutch to decrypt the application you just downloaded by passing its index:

Clutch -d 1

Wait for Clutch to finish, then in the output you'll see Clutch saved the decrypted application in /private/var/mobile/Documents/Dumped.

On your computer, on a different terminal window, copy the dumped application to your machine:

scp -P 2222 -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null root@localhost:/private/var/mobile/Documents/Dumped/<app-name>.ipa .

Through bfinject (Old Do not use)

Note

Tweaks must be disabled in Electra

Copy the bfinject directory to idevice:

scp -P 2222 -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null -r /opt/iOS/tools/bfinject [email protected]:/electra/

Run bfinject on the app:

cd /electra/bfinject
bash ./bfinject -P RubyBrowser.app -l dylibs/bfdecrypt.dylib

Use Netcat to copy the file to an IPA file:

>>> nc 172.20.10.6 31336 > decrypted.ipa
>>> ls -l decrypted.ipa
-rw-r--r--  1 carl  wheel  14649063 Jan 25 16:57 decrypted.ipa
>>> file decrypted.ipa
decrypted.ipa: iOS App Zip archive data, at least v2.0 to extract

Manually through lldb

https://labs.f-secure.com/blog/repacking-and-resigning-ios-applications/

Third Party Libraries

View Library from the Frameworks folder.
Get the Version from XXXXX.

LocalAuthentication.framework

  • Fingerprint check can be bypassed.

Security.framework

  • Fingerprint check can be bypassed.

AFNetworking.framework

  • Version 2.5.1 has Certificate Checking bug

Code Signing

Every application must be signed for iOS. But at least it is possible to sign an application for free for 7 days at a time.

View code signing information:

$ codesign -dvvv YOURAPP.app
Executable=/Users/Documents/YOURAPP/Payload/YOURAPP.app/YOURNAME
Identifier=com.example.example
Format=app bundle with Mach-O universal (armv7 arm64)
CodeDirectory v=20200 size=154808 flags=0x0(none) hashes=4830+5 location=embedded
Hash type=sha256 size=32
CandidateCDHash sha1=455758418a5f6a878bb8fdb709ccfca52c0b5b9e
CandidateCDHash sha256=fd44efd7d03fb03563b90037f92b6ffff3270c46
Hash choices=sha1,sha256
CDHash=fd44efd7d03fb03563b90037f92b6ffff3270c46
Signature size=4678
Authority=iPhone Distribution: Example Ltd
Authority=Apple Worldwide Developer Relations Certification Authority
Authority=Apple Root CA
Signed Time=4 Aug 2017, 12:42:52
Info.plist entries=66
TeamIdentifier=8LAMR92KJ8
Sealed Resources version=2 rules=12 files=1410
Internal requirements count=1 size=176

Signing with iOS App Signer

https://dantheman827.github.io/ios-app-signer/

Signing with Impactor (Doesn't Currently Work)

Use Cydia Impactor on OSX, Windows or Linux.

  1. Start Impactor
  2. Drag the target application IPA file (from GUI application, such as Explorer or Finder) into the Impactor window
  3. Enter the throw-away Apple ID credentials when prompted
  4. Navigate (on the iOS device) to Settings > General > Profiles or Profiles & Device Management and tap the profile listed with the email address associated with your Apple ID
  5. Choose "Trust [APPLE ID]" and tap through warnings
  6. Choose "Verify App" and tap through warnings

Changes Signature files which may affect the application

Signing Semi Manually with Xcode

Source

Export Mobile Provision Profiles:
1. Start a project in XCode
2. Setup Auto Signing under the Signing and Capabilities.
3. Make a unique Bundle Identifier.
4. Go to Settings -> Accounts -> Apple IDs -> Click the Gear -> Export Apple ID and Code Signing
5. unzip the file
6. Will be located in ./developer/profile/*.mobileprovision

Get provision profile information:

security cms -D -i ./developer/profile/*.mobileprovision

Sign the app with applesign:

./node-applesign-master/bin/applesign.js -w -c -b com.example.bundleid -m "~/Downloads/developer/profile/c*.mobileprovision" 1.3.9-12.0-12.4.ipa -o Chimera.ipa

Install the app:

ios-deploy --id <device_id> -b Chimera.ipa

Manually

Do it manually - a good white-paper to understand it:

# create a backup of the IPA file - so if something goes wrong you can restart
cp <IPA_FILE> <IPA_FILE>.bak
# unzip the file
unzip <IPA_FILE>
# download last version of frida-gadget
curl -O https://build.frida.re/frida/ios/lib/FridaGadget.dylib
mv FridaGadget.dylib Payload/<CLIENT_APP>/

Use insert_dylib

# patch the binary to load frida-gadget upon startup
insert_dylib --strip-codesig --inplace  @executable_path/FridaGadget.dylib Payload/<CLIENT_APP>/<CLIENT_BIN>
zip -r <CLIENT_APP>.ipa Payload

Use node-applesign to resign the application

# it overrides your IPA file -> make sure to have a backup of the file first
./bin/applesign.js -i  <CODE_SIGN_ID> -c -m <MOB_PROVISION_FILE> <IPA_FILE>

Get Developer account CODE_SIGN_ID:

# retrieve your signing IDs
>>> security find-identity -v -p codesigning
  1) 0A765C06838ED4FD[REMOVED] "Apple Development: <emailaddress> (SHORTHASH)"
     1 valid identities found

Get MOB_PROVISION_FILE:
- Create a hello-world project in xcode and run it. Grab the mobile provision file using xcode. How to find it's described in the white-paper above

Get ENTITLMENTS_FILE:

# fetch ents from the unencrypted IPA file unzipped
codesign -d --entitlements :- "Payload/<CLIENT_APP>" > ents.xml
# you need to manually update the Team ID value in this ents.xml, according to your mobile
# provision file. You can use the ID of the hello-world app you created with xcode
# The ID is usually the value in all capital letters/numbers.
# use vim
# :%s/<CLIENT_APP_ID>/<YOUR_APP_ID>/g

Redeploy the IPA file:

unzip <IPA_FILE_RESIGNED>
ios-deploy -b Payload/<YOUR_APP>
# or
ipa-deploy <IPA_FILE_RESIGNED>

Manualy sign the IPA file:

codesign -f -s 'iPhone Developer: <emailaddress> (SHORTHASH)' --entitlements entitlements.xml <Binarry>

Pushing to the iPhone

https://github.com/ios-control/ios-deploy

ios-deploy -b PAYLOAD/<CLIENT_APP> -d

Installing Unsigned Applications (Deprecated)

Appsync for iOS 5.X -13.X

Debugging

Debug Server Setup

Getting the Developer Tools:

>>> hdiutil attach /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/<LATESTiOSVERSION>/DeveloperDiskImage.dmg
>>> cp /Volumes/DeveloperDiskImage/usr/bin/debugserver .

Sign and push the binary:

>>> cat entitlements.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/ PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.private.security.no-container</key>
    <true/>
    <key>com.apple.private.skip-library-validation</key>
    <true/>
    <key>com.apple.backboardd.launchapplications</key>
    <true/>
    <key>com.apple.diagnosticd.diagnostic</key>
    <true/>
    <key>com.apple.frontboard.debugapplications</key>
    <true/>
    <key>com.apple.frontboard.launchapplications</key>
    <true/>
    <key>com.apple.security.network.client</key>
    <true/>
    <key>com.apple.security.network.server</key>
    <true/>
    <key>com.apple.system-task-ports</key>
    <true/>
    <key>platform-application</key>
    <true/>
    <key>get-task-allow</key>
    <true/>
    <key>task_for_pid-allow</key>
    <true/>
    <key>com.apple.backboardd.debugapplications</key>
    <true/>
    <key>com.apple.springboard.debugapplications</key>
    <true/>
    <key>run-unsigned-code</key>
    <true/>
    <key>com.apple.private.librarian.can-get-application-info</key>
    <true/>
    <key>com.apple.private.mobileinstall.allowedSPI</key>
    <array>
        <string>Lookup</string>
        <string>CopyInstalledAppsForLaunchServices</string>
    </array>
</dict>
</plist>
>>> codesign -s --entitlements entitlements.plist -f debugserver
>>> scp -P 2222 -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null  debugserver root@localhost:/var/root/debugserver
````

#### Debugging a iOS Application (lldb)

**Launch App from iOS:**
```bash
# to launch the app in debug mode
/var/root/debugserver 0.0.0.0:6666 -x auto /var/containers/Bundle/Application/4F2E06A0-B1C7-4F08-A00A-55644FEC55FE/DuoMobileApp.app/DuoMobileApp
# otherwise just wait for lldb
/var/root/debugserver 0.0.0.0:6666

Connect to the iOS Device from a Mac:

(lldb) platform select remote-ios
(lldb) process connect connect://<DEVICE_IP>:6666
(lldb) process attach --name <CLIENT_APP> --wait-for

Anti Anti Debugging stuff

Install Anti Debugging Tools:

#Install chisel
brew update
brew install chisel

#Edit lldb initialization file
touch ~/.lldbinit 
echo "command script import /usr/local/opt/chisel/libexec/fblldb.py" >> ~/.lldbinit 
echo "settings set target.load-cwd-lldbinit true" >> ~/.lldbinit 

Anti Debug Tweak AntiAntiDebug