iPhone Setup for Reversing and Debugging
There are a few configurations that I apply to almost every research iPhone. While these methods are documented publicly, the information is at many different places. Driven by laziness to search them on the Internet every time, I document them here, hoping that it also helps other researchers :)
Logs
Increase log level
For many targets, Apple has predefined debug profiles. They will print contents to log messages that otherwise only show <private>. These profiles are publicly available.
Following this post one can also show all <private> logs with the following change:
iPhone# vim /Library/Preferences/Logging/com.apple.system.logging.plist
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
iPhone# killall -9 logd
Note that recent iOS versions also added a privacy level, which can be Private or Sensitive.
Of course, this requires a jailbroken iPhone, whereas debug profiles work on any device.
Logging Bluetooth packets
A great debug profile is the Bluetooth debug profile. All Bluetooth developer tools by Apple are linked on the site https://developer.apple.com/bluetooth.
Install the Bluetooth debug profile to your iPhone. The profile can be airdropped or downloaded and then activated in the settings. Then, on a MacBook, run the Additional Tools for Xcode. In the Hardware folder, the PacketLogger can now also record packet traces on iOS. After saving these traces, they are also compatible with Wireshark.
debugserver
Enhancing debugserver privileges
Apple has a debugserver meant to work with Xcode for regular app debugging. Debugging any process with debugserver is possible after moving it from the developer disk image to the main disk and providing it with more entitlements. IDA Pro can use the debugserver to debug these processes then.
Minimal setup for debugserver works as follows:
ldid -Sdebugserver_ent.xml /usr/bin/debugserver
<!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.backboardd.debugapplications</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.springboard.debugapplications</key>
<true/>
<key>com.apple.system-task-ports</key>
<true/>
<key>get-task-allow</key>
<true/>
<key>platform-application</key>
<true/>
<key>run-unsigned-code</key>
<true/>
<key>task_for_pid-allow</key>
<true/>
</dict>
</plist>
Entitlements are subject to change. If it doesn't work, check this online again.
Note that as of May 2022, Frida has a bug where it loads a file from disk when attaching to a process. This violates sandboxes of some process. They will be killed with the following error message:
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Termination Reason: Namespace SANDBOX, Code 0x1
This log can be found in /var/mobile/Library/Logs/CrashReporter/ on the iPhone.
Attaching with the debugserver or lldb still works. Not a clean workaround but one of the many reasons why having different tooling for the same job can be important :)
Directly connecting to debugserver with lldb
Integrating debugserver with VirtualBox
For some setups, it can be helpful to have the debugging setup not on your main host but within VirtualBox. You then need to forward the debugserver ports as follows:
- On the host, add a host only interface to VirtualBox (if not existent).
localhost# VBoxManage hostonlyif create
- On the iPhone, attach to a process.
iPhone# debugserver 0.0.0.0:3456 -a CommCenter
- Forward this port of debugserver to the VirtualBox network. IP addresses might differ.
localhost# iproxy 4567 3456 -s 192.168.56.1
Memory limits
When attaching to a process for Fuzzing, e.g., with Frida, it easily happens that the process exceeds its memory limits. For processes with a strict memory limit, already running frida-trace can exceed limits. In this case, the memory manager Jetsam will kill the process.
Adjust daemon limits
There are global settings for daemons that can be edited, see this fuzzing setup. Jetsam limits are configured in plist files in /System/Library/LaunchDaemons/. These can be edited with plistutil. The highest priority is 19, and memory limits can be adjusted as well:
<key>ActiveSoftMemoryLimit</key>
<integer>24000</integer>
<key>InactiveHardMemoryLimit</key>
<integer>24000</integer>
<key>EnablePressuredExit</key>
<false/>
<key>JetsamPriority</key>
<integer>19</integer>
</dict>
Adjust app limits
There's a tool called jetsamctl. I recently tested it on jailbroken iOS 14.2 on an iPhone 12 and it still works. Use this to set memory limits on apps during runtime.
Symbols via developer disk image
Frida can only trace system libraries (DYLD shared cache) with symbols if the device is ready for development. The easiest way to achieve this is to connect the iPhone to a Mac with Xcode, click Devices and Simulators, and wait until the device is ready for development.
In this tab, logs can also be symbolicated if needed, e.g., if a crash log was produced but not symbolicated by Frida. It is possible to symbolicate a single crash log by hand without waiting for Xcode by calling this command:
/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash
Something is missing?
If there's some configuration that you add to all your research phones, feel free to add this in the comments. I might add other blog posts about how to work with Apple's firmware and kernel, but these are quite different to work with.
Comments
Post a Comment