Link to this headingiOS Platform

iOS Hacking Resources

Link to this headingImportant Folders

Applications: /private/var/containers/Bundle/Application
System Applications:
Application Data Directories: /private/var/mobile/Containers/Data/Application/
Install Programs: /usr/local/sbin
Keyboard Cache: /private/var/mobile/Library/Keyboard/dynamic-text.dat
Screenshot Directory: /private/var/mobile/Media/DCIM/100APPLE

Get data from application sandbox directory

Link to this headingPush notifications

TODO
Send notifications to the user’s device with a JSON payload.
Sending notification requests to APNs
Pushing background updates to your App

Link to this headingFirebase

Check Firebase settings by finding the https://\<firebaseProjectName\>.firebaseio.com/.json request

Link to this headingCrypto

New Crypto should use the Swift Crypto Library.

Apple CryptoKit- New for iOS 13

Things to Grep for:

  • CommonCryptor
  • CCCrypt
  • CCCryptorCreate
  • SecRandomCopyBytes

Link to this headingT2 Chip

Official Apple Documentation on the T2 Chip

Contains Device specific AES 256-bit hardware key that only the crypto engine can access. This is used to encrypt all of the data on the device.

Creating a key in the secure enclave:*

// private key parameters let privateKeyParams = [ kSecAttrLabel as String: "privateLabel", kSecAttrIsPermanent as String: true, kSecAttrApplicationTag as String: "applicationTag", ] as CFDictionary // public key parameters let publicKeyParams = [ kSecAttrLabel as String: "publicLabel", kSecAttrIsPermanent as String: false, kSecAttrApplicationTag as String: "applicationTag", ] as CFDictionary // global parameters let parameters = [ kSecAttrKeyType as String: kSecAttrKeyTypeEC, kSecAttrKeySizeInBits as String: 256, kSecAttrTokenID as String: kSecAttrTokenIDSecureEnclave, kSecPublicKeyAttrs as String: publicKeyParams, kSecPrivateKeyAttrs as String: privateKeyParams, ] as CFDictionary var pubKey, privKey: SecKey? let status = SecKeyGeneratePair(parameters, &pubKey, &privKey) if status != errSecSuccess { // Keys created successfully }

Link to this headingFile Data Protections

  • Every file on the file system can have a different iOS File Protection set.
  • This encryption key is derived from the UID and the [PBKDF2](/Crypto/Key Derivation/PBKDF2) of the passcode.
  • Each file has a different key that is stored in the File Metadata

Listing the files and their corresponding File Protections in Objection:

Listing the files and their corresponding File Protections in Frida:

frida -U -f com.tinyspeck.chatlyio --no-pause -l /opt/Memory/Mobile/frida_iOS_helper_functions.js -e "getDataProtectionKeysForAllPaths()" ____ / _ | Frida 12.8.7 - A world-class dynamic instrumentation toolkit | (_| | > _ | Commands: /_/ |_| help -> Displays the help system . . . . object? -> Display information about 'object' . . . . exit/quit -> Exit . . . . . . . . More info at https://www.frida.re/docs/home/ Spawning `com.tinyspeck.chatlyio`... Spawned `com.tinyspeck.chatlyio`. Resuming main thread! [iOS Device::com.tinyspeck.chatlyio]-> getDataProtectionKeysForAllPaths() [ { "fileProtectionKey": "NSFileProtectionCompleteUntilFirstUserAuthentication", "path": "/private/var/mobile/Containers/Data/Application/2E1B100C-CD63-4241-AAF9-58E6C4DFC09C/StoreKit/receipt" }, { "fileProtectionKey": "NSFileProtectionNone", "path": "/private/var/mobile/Containers/Data/Application/2E1B100C-CD63-4241-AAF9-58E6C4DFC09C/.com.apple.mobile_container_manager.metadata.plist" }, { "fileProtectionKey": "NSFileProtectionCompleteUntilFirstUserAuthentication", "path": "/private/var/mobile/Containers/Data/Application/2E1B100C-CD63-4241-AAF9-58E6C4DFC09C/Library/Caches/com.hackemist.SDImageCache/default/e062188527582103ec63e729fc92c3af.png" }, { "fileProtectionKey": "NSFileProtectionCompleteUntilFirstUserAuthentication", "path": "/private/var/mobile/Containers/Data/Application/2E1B100C-CD63-4241-AAF9-58E6C4DFC09C/Library/Caches/Snapshots/com.tinyspeck.chatlyio/40E763A9-4529-4E29-B454-38D4C7FDE671@2x.ktx" }, [...]

NSFileProtectionComplete: The class key is protected with a key derived from the user passcode and the device UID. Shortly after the user locks a device (10 seconds, if the ‘Require Password’ setting is set to ‘Immediately’), the decrypted class key is discarded, rendering all data in this class inaccessible until the user enters the passcode again.

NSFileProtectionCompleteUntilFirstUserAuthentication: This class behaves in the same way as the ‘NSFileProtectionComplete’ attribute, except that the decrypted class key is not removed from memory when the device is locked. The protection in this class has similar properties to desktop full-disk encryption, and protects data from attacks that involve a reboot.

NSFileProtectionCompleteUnlessOpen: Some files may need to be written while the device is locked. A good example of this is a mail attachment downloading in the background. This behavior is achieved by using asymmetric elliptic curve cryptography. The ephemeral public key for the agreement is stored alongside the wrapped per-file key. As soon as the file is closed, the per-file key is wiped from memory. To open the file again, the shared secret is recreated using the Protected Unless Open class’s private key and the file’s ephemeral public key, which are used to unwrap the per-file key that is then used to decrypt the file.

NSFileProtectionNone: This class key is only protected by device level encryption. Since all the keys needed to decrypt files in this class are stored on the device, the encryption only affords the benefit of fast remote wipe.

Link to this headingKeychain

  • Data is stored in a SQLLite Database but can only be accessed through the Keychain API.
  • Can be accessed through the API with the SecItemAdd, SecItemUpdate, SecItemCopyMatching, SecItemDelete

Accessibility Values:

  • kSecAttrAccessibleAlways: The data in the Keychain item can always be accessed, regardless of whether the device is locked.
  • kSecAttrAccessibleAlwaysThisDeviceOnly: The data in the Keychain item can always be accessed, regardless of whether the device is locked. The data won’t be included in an iCloud or local backup.
  • kSecAttrAccessibleAfterFirstUnlock: The data in the Keychain item can’t be accessed after a restart until the device has been unlocked once by the user.
  • kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly: The data in the Keychain item can’t be accessed after a restart until the device has been unlocked once by the user. Items with this attribute do not migrate to a new device. Thus, after restoring from a backup of a different device, these items will not be present.
  • kSecAttrAccessibleWhenUnlocked: The data in the Keychain item can be accessed only while the device is unlocked by the user.
  • kSecAttrAccessibleWhenUnlockedThisDeviceOnly: The data in the Keychain item can be accessed only while the device is unlocked by the user. The data won’t be included in an iCloud or local backup.
  • kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly: The data in the Keychain can be accessed only when the device is unlocked. This protection class is only available if a passcode is set on the device. The data won’t be included in an iCloud or local backup.

Control Flags:

  • kSecAccessControlDevicePasscode: Access the item via a passcode.
  • kSecAccessControlBiometryAny: Access the item via one of the fingerprints registered to Touch ID. Adding or removing a fingerprint won’t invalidate the item. Data with this flag are stored in the Secure Enclave itself
  • kSecAccessControlBiometryCurrentSet: Access the item via one of the fingerprints registered to Touch ID. Adding or removing a fingerprint will invalidate the item. Data with this flag are stored in the Secure Enclave itself
  • kSecAccessControlUserPresence: Access the item via either one of the registered fingerprints (using Touch ID) or default to the passcode.

Dump all keychain data using keychain_dumper.

Link to this headingiOS Versions

Link to this headingiOS 11 Changes

Certificates in iOS 11 & 12

Root Certs have to be installed then manually trusted.

Settings -> General -> About -> Certificate Trust Settings

Link to this headingiOS Sandbox

The App Sandbox restricts apps to specific containers.

Apps are prevented from executing mmap and mmprotect to making pages executable if they are writable.

Sandblaster is a tool for reversing (decompiling) binary Apple sandbox profiles.

Link to this headingSSH

Through Network:

ssh -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null [email protected]

Through USB:

python2 /opt/iOS/needle/needle/libs/usbmuxd/tcprelay.py -t 22:2222 ssh -p 2222 -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null [email protected]

Link to this headingFiles

Binary Cookie Files are stored in the Application directory and can contain sensitive cookies.

Use BinaryCookieReader.py to read these files.

Example:

python BinaryCookieReader.py Cookies.binarycookies

Link to this headingPList Files

Plist files can either be a XML data or a Binary equivalent of xml data.

Example:

file some_file.plist plist some_file.plist

Link to this headingSQLite

Example:

Link to this headingSQLite cipher

Link to this headingRealm Databases

Objective C Realm Database SDK
Swift Realm Database SDK

How to encrypt databases:

// Open the encrypted Realm file where getKey() is a method to obtain a key from the Keychain or a server let config = Realm.Configuration(encryptionKey: getKey()) do { let realm = try Realm(configuration: config) // Use the Realm as normal } catch let error as NSError { // If the encryption key is wrong, `error` will say that it's an invalid database fatalError("Error opening realm: \(error)") }

Link to this headingCouchbase Lite Databases

Lightweight, embedded, syncable NoSQL database engine for iOS and MacOS apps.

Link to this headingYapDatabase

YapDB is a collection/key/value store with a plugin architecture. It’s built atop sqlite, for Swift & objective-c developers.

Link to this headingDump Process Memory

LLDB:

  1. Pull an iOS-compatible version of the debugserver binary (requires Xcode and command-line tool installation)
hdiutil attach /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/<LATESTiOSVERSION>/DeveloperDiskImage.dmg cp /Volumes/DeveloperDiskImage/usr/bin/debugserver .
  1. Push debugserver binary to device
  2. chmod +x the binary on the device
  3. Run ./debugserver *:1234 -a <TARGETAPP> on the iOS device
  4. Run lldb on your testing machine
  5. On LLDB run the commands
process connect connect://<DEVICEIP>:1234 process save-core <OUTPUTFILENAME>

Link to this headingFrida

  1. Download the fridump tool (a bit outdated, but still works) from this link
mkdir memorydumpout python fridump.py -o memorydumpout -u <TARGETPROCESSNAME>

Link to this headingUnique ID

UDID is not accessible through the API since iOS 5. This is because it is used in other apple requests to identify the device.

identifierForVendor: A UUID that is the same for each application certificate on the same device. This ID can change when every app that is signed by the same key is removed from the device.

advertisingIdentifier: The same ID for every app on the device. This can be changed through a Reset All Content and Settings or a Reset Advertising Identifier.

Source

Link to this headingUnique Device Identifier

  • has not been used as an Identifier since iOS 5
  • You can get this identifier from itunes

Get UDID from ioreg:

$ ioreg -p IOUSB -l | grep "USB Serial" | "USB Serial Number" = "9e8ada44246cee813e2f8c1407520bf2f84849ec"

Get UDID from idevice Installer:

$ brew install ideviceinstaller $ idevice_id -l 316f01bd160932d2bf2f95f1f142bc29b1c62dbc

Get UDID from system_profiler:

system_profiler SPUSBDataType | sed -n -e '/iPad/,/Serial/p;/iPhone/,/Serial/p;/iPod/,/Serial/p' | grep "Serial Number:" 2019-09-08 10:18:03.920 system_profiler[13251:1050356] SPUSBDevice: IOCreatePlugInInterfaceForService failed 0xe00002be Serial Number: 64655621de6ef5e56a874d63f1e1bdd14f7103b1

Get UDID from instruments:

instruments -s devices

Link to this headingNetworking

Link to this headingRedirect traffic

Though /etc/hosts

127.0.0.1 localhost ::1 localhost 255.255.255.255 broadcasthost 192.168.1.6 example.com

Link to this headingNon-Jailbroken TCPdump

rvictl -s <UDID> Starting device <UDID> [SUCCEEDED] with interface rvi0

Link to this headingSetting up Full Proxy of TCP

TODO:

Link to this headingBurp traffic through USB

Port Forward:

ssh -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null -R 8080:localhost:8080 root@localhost -p 2222

Link to this headingCertificate Pinning

Using Standard Apple:

  • connection: canAuthenticateAgainstProtectionSpace:
  • connection: forAuthenticationChallenge

TrustKit:
AlamoFire:

  • ServerTrustPolicy
    AFNetworking:
  • AFSecurityPolicy

Things to Grep For:

  • NSURLSession
  • CFStream
  • AFNetworking

Link to this headingInter Process Communication (IPC)

Link to this headingXPC Services

  • Is managed by launchd to send information from one process to another.
  • Uses the NSXPCConnection and XPC Services APIs

Classes to grep for:

  • NSXPCConnection
  • NSXPCInterface
  • NSXPCListener
  • NSXPCListenerEndpoint

Security Attributes:

Link to this headingMach Ports

  • Kernel level IPC messages

Things to grep for:

  • mach_port_t
  • mach_msg_*
  • CFMachPort
  • CFMessagePort
  • NSMachPort
  • NSMessagePort

Link to this headingNSFileCoordinator

  • Used to share files with another app.
    • Example Sharing photos with another app.

Things to grep for:

  • NSFileCoordinator

Link to this headingURL Schema

URLs are contained in the Entitlements file.

  • application:continueUserActivity:restorationHandler:
  • openURL:options:completionHandler:
  • application:openURL:options:
  • application:will-FinishLaunchingWithOptions:
  • application:didFinishLaunchingWithOptions:
  • application:handleOpenURL:
  • application:openURL:sourceApplication:annotation:

In Info.plist

  • LSApplicationQueriesSchemes

Open URL with Frida:

function openURL(url) { var UIApplication = ObjC.classes.UIApplication.sharedApplication(); var toOpen = ObjC.classes.NSURL.URLWithString_(url); return UIApplication.openURL_(toOpen); } openURL("tel://234234234")

Link to this headingUIActivity Sharing

  • Sharing data though specific mechanism like airdrop

Things to grep for:

  • initWithActivityItems:applicationActivities:
  • application:openURL:options:
  • application:openURL:sourceApplication:annotation:
  • excludedActivityTypes

Link to this headingApp Extensions

These are located in the applicaiton IPA /var/containers/Bundle/Application/15E6A58F-1CA7-44A4-A9E0-6CA85B65FA35/Telegram X.app/PlugIns directory

[NSExtensionContext openURL:completionHandler:]
application:shouldAllowExtensionPointIdentifier:
NSExtensionContext - inputItems

Link to this headingWebView

Things to Grep for:

  • WKWebView/UIWebView
    • javaScriptEnabled
    • JavaScriptCanOpenWindowsAutomatically
    • hasOnlySecureContent
    • loadHTMLString:baseURL:
    • loadData:MIMEType:textEncodingName:baseURL:
    • pathForResource:ofType:
    • URLForResource:withExtension:
    • loadRequest:
    • loadFileURL:allowingReadAccessToURL:
  • SFSafariViewController
  • WKScriptMessageHandler

Link to this headingLog Files

Read Log Files on Device:

iPhone:~ root# socat - UNIX-CONNECT:/var/run/lockdown/syslog.sock

Reading Log Files from Computer:

idevicesyslog > app_name_$(date +%Y-%m-%d).log

Link to this headingWhiteBox

Check for these functions

  • NSLog
  • NSAssert
  • NSCAssert
  • fprintf

Link to this headingBackup

You can use the NSURLIsExcludedFromBackupKey and CFURLIsExcludedFromBackupKey file system properties to exclude files and directories from backups.

ObjC Example:

- (BOOL)addSkipBackupAttributeToItemAtPath:(NSString *) filePathString { NSURL* URL= [NSURL fileURLWithPath: filePathString]; assert([[NSFileManager defaultManager] fileExistsAtPath: [URL path]]); NSError *error = nil; BOOL success = [URL setResourceValue: [NSNumber numberWithBool: YES] forKey: NSURLIsExcludedFromBackupKey error: &error]; if(!success){ NSLog(@"Error excluding %@ from backup %@", [URL lastPathComponent], error); } return success; }

Swift Example:

enum ExcludeFileError: Error { case fileDoesNotExist case error(String) } func excludeFileFromBackup(filePath: URL) -> Result<Bool, ExcludeFileError> { var file = filePath do { if FileManager.default.fileExists(atPath: file.path) { var res = URLResourceValues() res.isExcludedFromBackup = true try file.setResourceValues(res) return .success(true) } else { return .failure(.fileDoesNotExist) } } catch { return .failure(.error("Error excluding \(file.lastPathComponent) from backup \(error)")) } }

Link to this headingBacking Up the iPhone

  • Setting up password is not Mandatory????

Setting a Backup Password (Optional):

>>> idevicebackup2 -i encryption on Started "com.apple.mobilebackup2" service on port 49439. Negotiated Protocol Version 2.1 Enter new backup password: ********* Enter new backup password (repeat): ********* Backup encryption has been enabled successfully.

Backing up the Device:

idevicebackup2 -u 70a58077f305c2a6e64f5eb74660a8619cfda34e --debug -i backup --full . Backup directory is "."

Link to this headingClipboard

iOS < 9 malicious apps can retrieve clipboard information when backgrounded using [UIPasteboard generalPasteboard].string. iOS >= 9 can only retrieve this information when in the foreground.

There are two types of Pasteboards. A System and a TeamID pasteboard.

Things to grep for:

  • generalPasteboard
  • pasteboardWithName:create:
  • pasteboardWithUniqueName
  • removePasteboardWithName:
  • setItems:options:
  • UIPasteboardOptionLocalOnly
  • UIPasteboardOptionExpirationDate
  • setPersistent:

Link to this headingKeyboard

By default iOS caches keyboard data and stores it in /private/var/mobile/Library/Keyboard/dynamic-text.dat.

This can be disabled using the textObject.autocorrectionType = UITextAutocorrectionTypeNo; or the textObject.secureTextEntry = YES; flag.

Link to this headingNon Jailbroken Devices

Go to another app, see enter a partial match to some sensitive data and if a completion is offered.

Link to this headingScreenshots

iOS takes a screenshot when the application is backgrounded so it can show its self on the application switching screen. For sensitive screens the application should put a screen overlay to prevent sensitive information from leaking to another application.

The screenshots are located in the /var/mobile/Containers/Data/Application/$APP_ID/Library/Caches/Snapshots/ folder.

Screen Overlay Code:

@property (UIImageView *)backgroundImage; - (void)applicationDidEnterBackground:(UIApplication *)application { UIImageView *myBanner = [[UIImageView alloc] initWithImage:@"overlayImage.png"]; self.backgroundImage = myBanner; [self.window addSubview:myBanner]; }