MASTG-TECH-0055: Launching a Repackaged App in Debug Mode
If you've repackaged an application with a Frida Gadget, or if you want to attach lldb to the application, you have to launch the application in debug mode. When you launch the application via SpringBoard, it will not launch in debug mode and the application will crash.
After the application has been installed using Installing Apps, you can launch it in debug mode using the following commands.
Note that the commands that are part of libimobiledevice suite refer to the latest version available from Github. If you installed them via brew or other package managers, you may have an older version with different command line flags.
iOS 17 and newer¶
First, make sure you know the correct Bundle Identifier. Depending on how you signed the application, the actual Bundle Identifier might be different from the original Bundle Identifier. To get an overview of the installed applications, use the ideviceinstaller
tool (see libimobiledevice suite):
$ ideviceinstaller list
CFBundleIdentifier, CFBundleShortVersionString, CFBundleDisplayName
sg.vp.UnCrackable1.QH868V5764, "1.0", "UnCrackable1"
org.owasp.mastestapp.MASTestApp, "3.0.0", "Adyen3DS2Demo"
com.apple.TestFlight, "3.5.2", "TestFlight"
In this example, Sideloadly appended the team identifier (QH868V5764
) to the original Bundle Identifier.
Next, we need to get the correct device identifier, which we can get using idevice_id
(see libimobiledevice suite):
$ idevice_id
00008101-1234567890123456 (USB)
00008101-1234567890123456 (Network)
Now that we have the correct Bundle Identifier and device ID, we can launch the app using xcrun
(see xcrun):
xcrun devicectl device process launch --device 00008101-1234567890123456 --start-stopped sg.vp.UnCrackable1.QH868V5764
13:00:43 Enabling developer disk image services.
13:00:43 Acquired usage assertion.
Launched application with sg.vp.UnCrackable1.QH868V5764 bundle identifier.
Finally, you can attach lldb using the following commands:
# Execute the lldb debugger
$ lldb
# Select the iOS device you want to interact with
(lldb) device select 00008101-1234567890123456
# Query the processes on a device.
(lldb) device process list
PID PARENT USER TRIPLE NAME
====== ====== ========== ============================== ============================
1 0 launchd
...
771 0 <anonymous>
774 0 <anonymous>
781 0 ReportCrash
783 0 UnCrackable Level 1
# Attach to a specific process by their process ID
(lldb) device process attach --pid 783
Process 783 stopped
* thread #1, stop reason = signal SIGSTOP
frame #0: 0x0000000104312920 dyld`_dyld_start
dyld`_dyld_start:
-> 0x104312920 <+0>: mov x0, sp
0x104312924 <+4>: and sp, x0, #0xfffffffffffffff0
0x104312928 <+8>: mov x29, #0x0 ; =0
0x10431292c <+12>: mov x30, #0x0 ; =0
Target 0: (UnCrackable Level 1) stopped.
# Continue execution of all threads in the current process.
(lldb) c
Process 783 resuming
(lldb)
More information about debugging iOS apps can be found in Debugging.
If you manually injected a Frida Gadget, Frida will now be waiting for you to attach to it. Until you do so, the application will appear frozen.
$ frida-ps -Ua
PID Name Identifier
--- ------------- -------------------------------
389 Calendar com.apple.mobilecal
783 Gadget re.frida.Gadget
336 TestFlight com.apple.TestFlight
783 UnCrackable1 sg.vp.UnCrackable1.QH868V5764
339 Weather com.apple.weather
The 783
process has launched a new thread called Gadget to which you can attach:
$ frida -U -n Gadget
____
/ _ | Frida 16.5.9 - A world-class dynamic instrumentation toolkit
| (_| |
> _ | Commands:
/_/ |_| help -> Displays the help system
. . . . object? -> Display information about 'object'
. . . . exit/quit -> Exit
. . . .
. . . . More info at https://frida.re/docs/home/
. . . .
. . . . Connected to iPhone (id=00008101-000628803A69001E)
[iPhone::Gadget ]-> ObjC.available
true
After attaching, the application will continue executing as normal.
iOS 16 and older¶
On older versions of iOS, you can use either idevicedebug
(see libimobiledevice suite) or ios-deploy to launch the app in debug mode.
Using idevicedebug¶
# Get the package name
$ ideviceinstaller list
CFBundleIdentifier, CFBundleShortVersionString, CFBundleDisplayName
sg.vp.UnCrackable1.QH868V5764, "1.0", "UnCrackable1"
com.apple.TestFlight, "3.7.0", "TestFlight"
com.google.Maps, "24.50.0", "Google Maps"
# Run in debug mode
$ idevicedebug -d run sg.vp.UnCrackable1.QH868V5764
working_directory: /private/var/mobile/Containers/Data/Application/438DE865-2714-4BD9-B1EE-881AD4E54AD1
Setting logging bitmask...
Setting maximum packet size...
Setting working directory...
Setting argv...
app_argv[0] = /private/var/containers/Bundle/Application/E21B5B13-DD85-4C83-9A0E-03FCEBF95CF5/UnCrackable Level 1.app/UnCrackable Level 1
Checking if launch succeeded...
Setting thread...
Continue running process...
Using ios-deploy¶
To use ios-deploy, you first have to unzip the IPA file:
$ unzip Uncrackable1-frida-codesigned.ipa -d unzipped
Next, use ios-deploy with the path of the app folder inside of the unzipped IPA:
$ ios-deploy --bundle 'unzipped/Payload/UnCrackable Level 1.app' -W -d -v
ios-deploy --bundle 'pram/Payload/UnCrackable Level 1.app' -W -d -v
[....] Waiting for iOS device to be connected
Handling device type: 1
Already found device? 0
Hardware Model: D211AP
Device Name: NVISO’s iPhone JBE
Model Name: iPhone 8 Plus
SDK Name: iphoneos
Architecture Name: arm64
Product Version: 16.6.1
Build Version: 20G81
[....] Using 593ad60af30ad045b9cb99d2901031226c1b8c84 (D211AP, iPhone 8 Plus, iphoneos, arm64, 16.6.1, 20G81) a.k.a. '**NVISO**’s iPhone JBE'.
------ Install phase ------
[ 0%] Found 593ad60af30ad045b9cb99d2901031226c1b8c84 (D211AP, iPhone 8 Plus, iphoneos, arm64, 16.6.1, 20G81) a.k.a. 'NVISO’s iPhone JBE' connected through USB, beginning install
[ 5%] Copying /Users/MAS/unzipped/Payload/UnCrackable Level 1.app/META-INF/ to device
[ 5%] Copying /Users/MAS/unzipped/Payload/UnCrackable Level 1.app/META-INF/com.apple.ZipMetadata.plist to device
[ 6%] Copying /Users/MAS/unzipped/Payload/UnCrackable Level 1.app/META-INF/com.apple.ZipMetadata.plist to device
...
Attaching Frida¶
If your application was repackaged with a Frida Gadget, the application will wait for you to attach to it before it continues launching.
In a new terminal window, connect to the Frida gadget, just like in the iOS 17 scenario:
$ frida-ps -Ua
PID Name Identifier
--- ------------- -----------------------------
...
468 Gadget re.frida.Gadget
...
468 UnCrackable1 sg.vp.UnCrackable1.QH868V5764
$ frida -U -n Gadget
____
/ _ | Frida 16.5.9 - A world-class dynamic instrumentation toolkit
| (_| |
> _ | Commands:
/_/ |_| help -> Displays the help system
. . . . object? -> Display information about 'object'
. . . . exit/quit -> Exit
. . . .
. . . . More info at https://frida.re/docs/home/
. . . .
. . . . Connected to iPhone (id=593ad60af30ad045b9cb99d2901031226c1b8c84)
[iPhone::Gadget ]-> ObjC.available
true