Close

iPhone, JTAG and Bonobo

Introduction

This article describes how to demote a “production/retail fused” iPhone by applying the “checkm8” exploit in order to activate the JTAG interface. Then, the Bonobo JTAG cable is setup, allowing us to have a look live into the boot code execution.

Resources

The Bonobo JTAG/SWD Debug Cable shopping page
https://shop.lambdaconcept.com/home/37-bonobo-debug-cable.html

Video “Debugging an iPhone with Bonobo JTAG cable + OpenOCD + GDB demoted by checkm8”, showing what is described in this article
→ https://www.youtube.com/watch?v=3zpwSUXlz6A

[10] Video “IDA Pro debug + OpenOCD attached to an iPhone with a Bonobo Cable”, going a step further by live debugging the boot room code via the JTAG cable
→ https://www.youtube.com/watch?v=wYQDlP–glU

[5] Bonobo cable documentation
→ http://docs.bonoboswd.com/index.html
→ http://blog.lambdaconcept.com/doku.php?id=products:bonobo:iphone_bootrom_debug

[4] Bonobo OpenOCD target configuration files
http://docs.bonoboswd.com/targets.html

[1] Deep dive into the iOS boot process – “*OS Internals” Volume II by Jonathan Levin
http://newosxbook.com/bonus/iBoot.pdf

[2] Deep dive into JTAG, by Senrio
https://blog.senr.io/blog/jtag-explained

Deep dive into iPhone kernel debugging
https://www.youtube.com/watch?v=66oqzuQ_khI

[7] iPwnDFU tool
→ Original: https://github.com/axi0mX/ipwndfu
→ Version including a patch for iPhone 6s: https://github.com/imifos/ipwndfu-s8000

[5] Checkm8
https://www.theiphonewiki.com/wiki/Checkm8_Exploit
https://www.reddit.com/r/jailbreak/comments/d9yyit/release_introducing_checkm8_read_checkmate_a/

[3] DFU Mode
https://www.theiphonewiki.com/wiki/DFU_Mode

[9] ARM GNU Toolchain
https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a/downloads

[6] ARM Debug Interface Architecture Specification v5 / Serial Wire Debug (SWD)
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ihi0031c/index.html
https://developer.arm.com/architectures/cpu-architecture/debug-visibility-and-trace/coresight-architecture/serial-wire-debug

[8] OpenOCD RESET commands
http://openocd.org/doc/html/Reset-Configuration.html

Phase 1 – Demoting

Introduction

In order to activate the iPhone JTAG interface, we need to demote the “production fused” device.

Extract from the book “*OS Internals”, Volume II, by Jonathan Levin [1]:

“The SecureROM is responsible for loading the CPDM values during early startup and enforcing security. Code execution at the SecureROM level allows demotion, which enables overriding the CPFM bits from the fused value. Although the fuses are immutable, they are loaded into a memory mapped register, whose value can be changed. Overriding the CPFM is thus simply a matter of writing to that memory mapped address. Note, that the demotion does not actually change the state of the fuses, and therefore is only temporary, persisting until the next reboot.”

Thanks to the checkm8 exploit, we are now able to intervene on the CPFM register at the moment we need. Note that checkm8 has limitations when it comes to supported iPhone models [1][5].

Some notes, before getting started:

  • We are going to use the tool iPwnDFU, which requires Python 2 to run. Forks porting it to Python 3 are around though. Alternatively, pyenv is a nice tool helping to keeping a clean environment.
  • Applying checkm8 does not work in a VM. The below procedure has been tested on a bare-metal UBUNTU 18 64-bit installation. Once the iPhone is “pwned” (sic), it can be connected to a VM for the rest of the process, including using iPwnDFU again to demote the device.
  • iPwnDFU does not require the Bonobo cable. The classic Lightning connector is fine.

Step 1) Monitoring

In preparation, we open a terminal window and start “dmesg –follow”. This displays and follows the kernel messages ring-buffer, allowing us to see what is going on in terms of devices detached from and attached to the system. This window should remain open all the time.

Step 2) DFU

Prior to running the tool, the iPhone must be put in DFU (Device Firmware Update) mode (see [1] and [3]). The button sequence that needs to be performed depends on the iPhone model and can be found via your favourite search engine.

The dmesg kernel log output will show messages similar to the ones below when connecting a device in DFU mode to the machine or mode-switching the currently attached device:

$ dmesg --follow
[15241.484880] usb 1-2: new high-speed USB device number 26 using ehci-pci
[15241.648194] usb 1-2: New USB device found, idVendor=05ac, idProduct=1227, bcdDevice= 0.00
[15241.648196] usb 1-2: New USB device strings: Mfr=2, Product=3, SerialNumber=4
[15241.648197] usb 1-2: Product: Apple Mobile Device (DFU Mode)
[15241.648197] usb 1-2: Manufacturer: Apple Inc.
[15241.648198] usb 1-2: SerialNumber: CPID:8010 CPRV:11 CPFM:03 SCEP:01 BDID:0C ECID:000AAAAAAAA00000 IBFL:3C SRTG:[iBoot-2696.0.0.1.33]

The vendor ID 0x05AC is Apple and the product ID is 0x1227 for any device in DFU Mode. The Chip ID (CPID) represents the internal SoC (System on Chip) number, in this case 8010 associated to the branding “A10 Fusion” and used in the iPhone 7. A Chip Fuse Mode (CPFM) of 03 indicates that the bits “secure mode” and “production modes” are set [1].

Step 3) iPwnDFU

NOTE: It is also now possible to use the https://checkra.in/ jailbeak application to demote the device. Installation on Linux is done by adding the APT source and the tool can be invoked at the command line: sudo checkra1n –help. Be however very careful from where you download, as many scam sites are up already.

To start, we install iPwnDFU [7], then we apply the exploit and demote the device.

Note: I has issues with conflicting versions of libusb when doing this on MacOS with homebrew, pyenv and a lot of other tools installed. Finally, I decided to switch to a clean Ubuntu installation.

# Pre-requisite is Python 2, see above
# Dependencies
$ sudo apt install -y git libusb-1.0

$ mkdir -p ~/tools
$ cd ~/tools

# Original tool from the original author [7]:
$ git clone https://github.com/axi0mX/ipwndfu

# Alternative version, that fixes the “The device has no langid” error
# and includes @a1exdandy patch to add support for t7000/s8000/s8003 (iPhone 6s) [7]
# git clone https://github.com/imifos/ipwndfu-s8000

The exploit (in this version) is not 100% reliable (timing), so it might be needed to execute multiple times.

$ cd ~/tools/ipwndfu
$ sudo python ./ipwndfu -p

Kernel log output:

[ 1157.772991] usb 2-5: New USB device found, idVendor=05ac, idProduct=1227
[ 1157.772997] usb 2-5: New USB device strings: Mfr=2, Product=3, SerialNumber=4
[ 1157.773002] usb 2-5: Product: Apple Mobile Device (DFU Mode)
[ 1157.773006] usb 2-5: Manufacturer: Apple Inc.
[ 1157.773010] usb 2-5: SerialNumber: CPID:8000 CPRV:20 CPFM:03 SCEP:01 BDID:04 ECID:000AAAAAAAA00000 IBFL:1C SRTG:[iBoot-2234.0.0.3.3]
[ 1158.092128] usb 2-5: reset high-speed USB device number 8 using ehci-pci
[ 1158.248274] usb 2-5: device firmware changed
[ 1158.256071] usb 2-5: USB disconnect, device number 8
[ 1158.384165] usb 2-5: new high-speed USB device number 9 using ehci-pci
[ 1158.540869] usb 2-5: New USB device found, idVendor=05ac, idProduct=1227
[ 1158.540873] usb 2-5: New USB device strings: Mfr=2, Product=3, SerialNumber=6
[ 1158.540875] usb 2-5: Product: Apple Mobile Device (DFU Mode)
[ 1158.540877] usb 2-5: Manufacturer: Apple Inc.
[ 1158.540879] usb 2-5: SerialNumber: CPID:8000 CPRV:20 CPFM:03 SCEP:01 BDID:04 ECID:000AAAAAAAA00000 IBFL:1C SRTG:[iBoot-2234.0.0.3.3] PWND:[checkm8]

The log file shows that “PWND:[checkm8]” has been added to the device serial identification string, confirming the exploit being applied.

Once the previous step is successfully completed, we demote the device by patching the CPFM flags in memory. This will not be visible in the kernel messages log and it will not change the CPFM value reported by the phone as part of the serial number string.

$ cd ~/tools/ipwndfu

$ sudo python ./ipwndfu --demote
Demotion register: 0x287
Attempting to demote device.
Demotion register: 0x286
Success!

While plugged in, the state of the phone can always be checked by consulting the kernel message log:

$ dmesg | grep -e Apple -e iBoot

USB related low-level information can be displayed the following way. This is specially useful when having timing issues when applying the exploit.

$ lsusb -d 05ac: -v

Phase 2 – JTAG, Bonobo and Debugger

Introduction

The process described in this sections has been written for Linux and a VM can be used without issues. We just need to make sure that all USB devices that the Bonobo cable provides, namely the FTDI USB RS232 serial adapters and the Bonobo device, are attached to the VM instead of the host.

There is a lot of confudion are the term JTAG. Thus, before getting into the details, we should get the context that we need from SENRIO’s excellent explanations on JTAG [2]. Here some key points:

“JTAG is a common hardware interface that provides your computer with a way to communicate directly with the chips on a board.
../..
The JTAG specification doesn’t even define the protocol for how data is passed between debugger and debugee.”

Step 1) OpenOCD

Let’s start with installing OpenOCD.

Again, SENRIO’s blog [2] gives us the right picture on OpenOCD:

“JTAG is an interface and does not know how a chip will react to
command strings. Trying to hack a device using JTAG alone would
technically be possible, but it would be extremely time consuming and
require a deep, holistic understanding of all the internal workings and
architecture of the chip. For JTAG to be an effective research tool you
need something that can translate between human-readable code and
the low-level instructions coming in and out of the JTAG TAP controller. The true power of JTAG is unlocked by giving debugging software like OpenOCD control over the JTAG interface. OpenOCD is the only Open Source repository (knowledge base) for a variety of chips and interfaces. OpenOCD can (when paired with a JTAG interface device) manipulate the JTAG’s TAP (Test Access Port) controller on a target device to send bits to it (via the state machine above), which the chip will then interpret as valid commands.
../..
Running OpenOCD over the JTAG interface will allow you to pause and step through an operation, inspect memory, write bytes directly into memory, set watch-points and break-points, and even inject code into the
process or process memory. We call this technique “Hardware-based Software Debugging.” We are manipulating the hardware to perform traditional software debugging tasks. In fact, OpenOCD even allows you to use familiar software debugging tools by spawning a GDB server, allowing you to debug firmware and software in devices via GDB, IDA Pro, or anything that is capable of acting as a GDB client.”
../..
The config file teaches OpenOCD the correct way to manipulate the TAP controller for that particular chip’s architecture.”

The easiest way to get started with OpenOCD for the Bonobo cable is to use LambdaConcept’s fork that includes the Bonobo drivers. At the time of writing, this version is quite some commits behind original OpenOCD source code repository, but for our purpose it works well. We need to compile the tool from source:

# Dependencies
$ mkdir -p ~/tools
$ sudo apt install -y curl git make libtool pkg-config autoconf automake texinfo libusb-1.0

# Download, compile and install OpenOCD
$ cd ~/tools
$ git clone https://github.com/lambdaconcept/openocd.git
$ cd openocd
$ ./bootstrap
$ ./configure --enable-bonobo --disable-werror
:
OpenOCD configuration summary
--------------------------------------------------
MPSSE mode of FTDI based devices yes (auto)
ST-Link Programmer yes (auto)
TI ICDI JTAG Programmer yes (auto)
Keil ULINK JTAG Programmer yes (auto)
Altera USB-Blaster II Compatible yes (auto)
Bitbang mode of FT232R based devices yes (auto)
Versaloon-Link JTAG Programmer yes (auto)
TI XDS110 Debug Probe yes (auto)
OSBDM (JTAG only) Programmer yes (auto)
eStick/opendous JTAG Programmer yes (auto)
Andes JTAG Programmer yes (auto)
USBProg JTAG Programmer no
Raisonance RLink JTAG Programmer no
Olimex ARM-JTAG-EW Programmer no
CMSIS-DAP Compliant Debugger no
Cypress KitProg Programmer no
Altera USB-Blaster Compatible no
ASIX Presto Adapter no
OpenJTAG Adapter no
SEGGER J-Link Programmer yes (auto)
LambdaConcept Bonobo Cable yes

$ make -j
$ sudo make install

# Scripts and config files are installed into /usr/local/share/openocd/scripts

# Test
$ openocd --help
Open On-Chip Debugger 0.10.0+dev-00951-gac08bc8a (2020-02-23-11:05)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Open On-Chip Debugger
Licensed under GNU GPL v2
--help       | -h display this help
--version    | -v display OpenOCD version
--file       | -f use configuration file
--search     | -s dir to search for config files and scripts
--debug      | -d set debug level to 3
--log_output | -l redirect log output to file
--command    | -c run 
>

2) Cross-platform ARM toolchain

The GNU Toolchain for the Cortex-A Family is an open-source suite of tools for C, C++ and Assembly programming targeting processors from the ARM Cortex-A family and implementing the ARM A-profile architecture. The toolchain includes the GNU Compiler (GCC) and Debugger (GDB), which we are going to use soon.

The LINUX version of the ARM GNU Toolchain can be obtained directly from the ARM developer website (269MB) [9]: https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a/downloads

At the time of writing, the published version is 9.2-2019.12 (December 19, 2019, 269MB). Later, the below download link may need to be updated.

# Download from ARM website
$ curl https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu-a/9.2-2019.12/binrel/gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu.tar.xz -o ~/Downloads/gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu.tar.xz

# Extract
$ cd ~/tools 
$ tar -xf ~/Downloads/gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu.tar.xz

# Include in path, reset the shell
$ echo 'export PATH=$PATH:~/tools/gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu/bin' >> ~/.bashrc
$ source ~/.bashrc

# Test
$ aarch64-none-linux-gnu-gdb -v

GNU gdb (GNU Toolchain for the A-profile Architecture 9.2-2019.12 (arm-9.10)) 8.3.0.20190709-git
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Step 3) Bonobo support files

The bonobo-configs repository contains OpenOCD configuration files for the various supported idevices. The list can be found here [4]: http://docs.bonoboswd.com/targets.html.

The bonobo-helpers are not required strictly speaking, but the included “phonereset” tool may come handy when the device state has been messed up by playing around with the debugger and can not easily be reset using OpenOCD.

# Bonobo configuration files and helper tools
cd ~/tools
git clone https://github.com/lambdaconcept/bonobo-configs.git
git clone https://github.com/lambdaconcept/bonobo-helpers.git
~/tools/bonobo-helpers/phonereset
make

Step 4) Additions

The Bonobo controller [5] mounts four Serial interfaces based on FTDI’s RS232 to USB chipset. To read these serial console lines, we need a “modem control and terminal emulation program” – like minicom. Generally, the lines use the setting of 115200 8N1 – 115200 baud, bits per second in our case, one start bit, eight data bits, no parity bit and one stop bit. This is the default when starting minicom without editing the configuration.

$ sudo apt install -y minicom

Step 5) Start-up and Connections

Once everything installed, it’s time to start-up the tools and connect the devices. We need to open multiple terminal windows at the same time, so a tool à la “terminator” or “tmux” comes handy.

Open a terminal to monitor our devices:

$ dmesg --follow

Optionally, we can attach, in separate console windows, a terminal emulator to each serial port, or just the one we know will be used when connecting the device to examine:

$ sudo minicom --device /dev/ttyUSB2

Welcome to minicom 2.7.1

OPTIONS: I18n
Compiled on Aug 13 2017, 15:25:34.
Port /dev/ttyUSB3, 08:55:47

Press CTRL-A Z for help on special keys
:

Likewise:

$ sudo minicom --device /dev/ttyUSB0
$ sudo minicom --device /dev/ttyUSB1
$ sudo minicom --device /dev/ttyUSB3

As soon as the Bonobo cable is connected, the message “Cannot open /dev/ttyUSBx!” should disappear. To open the minicom help menu, hit “CTRL+a” (or CTRL+SHIFT+a via VNC) then “Z”, followed by “q” to quit.

The next step is connecting the Bonobo cable and watching the kernel log show interesting things:

[15419.686678] usb 1-2: new high-speed USB device number 27 using ehci-pci
[15419.849702] usb 1-2: New USB device found, idVendor=ffff, idProduct=1234, bcdDevice= 0.00
[15419.849703] usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=4
[15419.849704] usb 1-2: Product: Bonobo
[15419.849705] usb 1-2: Manufacturer: LambdaConcept
[15420.821925] usb 1-3: new high-speed USB device number 28 using ehci-pci
[15420.985714] usb 1-3: New USB device found, idVendor=0403, idProduct=6011, bcdDevice= 8.00
[15420.985716] usb 1-3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[15420.985717] usb 1-3: Product: Quad RS232-HS
[15420.985717] usb 1-3: Manufacturer: FTDI
[15421.020084] ftdi_sio 1-3:1.0: FTDI USB Serial Device converter detected
[15421.020239] usb 1-3: Detected FT4232H
[15421.023167] usb 1-3: FTDI USB Serial Device converter now attached to ttyUSB0
[15421.023795] ftdi_sio 1-3:1.1: FTDI USB Serial Device converter detected
[15421.023810] usb 1-3: Detected FT4232H
[15421.026443] usb 1-3: FTDI USB Serial Device converter now attached to ttyUSB1
[15421.027211] ftdi_sio 1-3:1.2: FTDI USB Serial Device converter detected
[15421.027225] usb 1-3: Detected FT4232H
[15421.029996] usb 1-3: FTDI USB Serial Device converter now attached to ttyUSB2
[15421.030777] ftdi_sio 1-3:1.3: FTDI USB Serial Device converter detected
[15421.030792] usb 1-3: Detected FT4232H
[15421.033468] usb 1-3: FTDI USB Serial Device converter now attached to ttyUSB3

Now, we attach Bonobo’s Lightning connector to the demoted iPhone. The kernel message log will indicate that an Apple device in DFU mode has been connected. We (should) see the typical “checkm8” flag, but we cannot verify in this logfile if the device has been demoted or not.

[ 9765.084559] usb 1-4: new high-speed USB device number 8 using ehci-pci
[ 9765.247941] usb 1-4: New USB device found, idVendor=05ac, idProduct=1227, bcdDevice= 0.00
[ 9765.247942] usb 1-4: New USB device strings: Mfr=2, Product=3, SerialNumber=6
[ 9765.247943] usb 1-4: Product: Apple Mobile Device (DFU Mode)
[ 9765.247944] usb 1-4: Manufacturer: Apple Inc.
[ 9765.247944] usb 1-4: SerialNumber: CPID:8010 CPRV:11 CPFM:03 SCEP:01 BDID:0C ECID:000AAAAAAAA00000 IBFL:3C SRTG:[iBoot-2696.0.0.1.33] PWND:[checkm8]

Time to engage OpenOCD, specifying the configuration file matching your hardware [4]. In my case, t8010 (A10) iPhone 7. Optionally, adding “-d3” to the command line activates a verbose debug output. Note the various network ports that the tool opens.

$ sudo openocd -f ~/tools/bonobo-configs/t8010.cfg
Open On-Chip Debugger 0.10.0+dev-00951-gac08bc8a (2020-02-08-21:58)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : clock speed 10000 kHz
Info : SWD DPIDR 0x4ba02477
Info : iphone.cpu0: hardware has 6 breakpoints, 4 watchpoints
Error: iphone.cpu1 powered down!
Error: target-> coreid 0 powered down!
Info : Listening on port 3333 for gdb connections
Info : Listening on port 3334 for gdb connections
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections

SWD, as seen above, stands for Serial Wire Debug protocol. It’s a bi-directional serial-wire hardware debugging protocol, by ARM, specified in the ARM Debug Interface v5 (and beyond) document [6]. On JTAG devices offering a SWD capability, two electrical signals are re-purposed to implement the serial interface [6]. With the modern Bonobo controler and the iPhone, the negocation if the serial SWD or the parallel JTAG connector layout is used happens under the hood.

Let’s have a look at some notable log events in the log file (below). When OpenOCD connects to a device, it performs an “examination” to determine the capabilities that the target devices provides. This can be seen in the log output. Should this examination fail, for instance when the phone is not demoted, the message “Target not examined yet” will be issue when performing operations against the target device at later stage. In case of a configuration file that is badly describing the target hardware or likewise when using the wrong configuration.

:
Debug: 19 1 configuration.c:42 add_script_search_dir(): adding /home/user/.openocd
:
Debug: 22 1 configuration.c:97 find_file(): found /home/user/tools/bonobo-configs/t8010.cfg
Debug: 23 1 command.c:143 script_debug(): command - interface interface bonobo
Debug: 25 1 command.c:143 script_debug(): command - transport transport select swd
Debug: 26 1 command.c:355 register_command_handler(): registering 'swd'...
:
Debug: 41 1 tcl.c:567 jim_newtap_cmd(): Creating New Tap, Chip: iphone, Tap: cpu, Dotted: iphone.cpu, 8 params
:
Debug: 107 1 command.c:143 script_debug(): command - target target create iphone.cpu0 aarch64 -endian little -dap iphone.dap -ap-num 1 -dbgbase 0xc2010000 -cti iphone.cpu0.cti -coreid 0 -apple-utt 4 0x202040000 64
Debug: 158 2 command.c:143 script_debug(): command - target target create iphone.cpu1 aarch64 -endian little -dap iphone.dap -ap-num 1 -dbgbase 0xc2110000 -cti iphone.cpu1.cti -coreid 1 -apple-utt 4 0x202140000 64
:
Debug: 208 2 command.c:143 script_debug(): command - target target create iphone.sep cortex_a -endian little -dap iphone.dap -ap-num 1 -dbgbase 0xcda20000
:
Debug: 351 7 command.c:355 register_command_handler(): registering 'target_request'...
Debug: 352 7 command.c:355 register_command_handler(): registering 'trace'...
Debug: 353 7 command.c:355 register_command_handler(): registering 'trace'...
:
Debug: 383 7 command.c:355 register_command_handler(): registering 'reset_nag'...
Debug: 384 7 command.c:355 register_command_handler(): registering 'ps'...
Debug: 385 7 command.c:355 register_command_handler(): registering 'test_mem_access'...
:
ebug: 420 45 aarch64.c:2376 aarch64_examine_first(): cpuid = 0x611f0061
Debug: 421 45 aarch64.c:2377 aarch64_examine_first(): ttypr = 0xf0100001
Debug: 422 45 aarch64.c:2378 aarch64_examine_first(): debug = 0x10305f06
Info : 423 48 armv8_dpm.c:1481 armv8_dpm_setup(): iphone.cpu0: hardware has 6 breakpoints, 4 watchpoints
:
Debug: 466 126 gdb_server.c:3397 gdb_target_start(): starting gdb server for iphone.cpu0 on 3333
Info : 467 126 server.c:311 add_service(): Listening on port 3333 for gdb connections
Debug: 468 126 gdb_server.c:3397 gdb_target_start(): starting gdb server for iphone.sep on 3334
Info : 469 126 server.c:311 add_service(): Listening on port 3334 for gdb connections
Info : 470 126 server.c:311 add_service(): Listening on port 6666 for tcl connections
Info : 471 126 server.c:311 add_service(): Listening on port 4444 for telnet connections
Debug: 472 126 command.c:143 script_debug(): command - init init

Time to open a shell into OpenOCD using its console:

$ telnet localhost 4444
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger

> targets
TargetName Type Endian TapName State
-- ------------------ ---------- ------ ------------------ ------------
0 iphone.dbg mem_ap little iphone.cpu running
1 iphone.mem mem_ap little iphone.cpu running
2 iphone.cpu0 aarch64 little iphone.cpu running
3 iphone.cpu1 aarch64 little iphone.cpu poweroff
4* iphone.sep cortex_a little iphone.cpu unknown

> targets iphone.cpu0

The “mem_ap” stands for “Memory Access Port” and is a TAP to directly access memory. “iphone.sep” represents the Security Enclave Processor (SEP) TAP, which we should not be able to access on production devices in any case, demoted or not.

If all looks good, head over to the debugger and attach it the the OpenOCD bridge that then acts as standardisation layer between debugging tools and the specific JTAG interface:

$ aarch64-none-linux-gnu-gdb

GNU gdb (GNU Toolchain for the A-profile Architecture 9.2-2019.12 (arm-9.10)) 8.3.0.20190709-git
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-pc-linux-gnu --target=aarch64-none-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
Find the GDB manual and other documentation resources online at:

For help, type "help".
Type "apropos word" to search for commands related to "word".

(gdb) target remote :3333

Remote debugging using :3333
warning: No executable has been specified and target does not support
determining executable automatically. Try using the "file" command.
0x0000000100000508 in ?? ()

(gdb) info registers
:
<lotofinformation>

OpenOCD console (telnet):

accepting 'gdb' connection on tcp/3333
iphone.cpu0 cluster 0 core 0 multi core
target halted in AArch64 state due to debug-request, current mode: EL1T
cpsr: 0x800002c4 pc: 0x100000508
MMU: enabled, D-Cache: enabled, I-Cache: enabled
New GDB Connection: 1, Target iphone.cpu0, state: halted

OpenOCD log:

Info : 477 1250106 server.c:100 add_connection(): accepting 'gdb' connection on tcp/3333
Debug: 478 1250106 breakpoints.c:359 breakpoint_clear_target_internal(): Delete all breakpoints for target: iphone.cpu0
Debug: 479 1250106 breakpoints.c:359 breakpoint_clear_target_internal(): Delete all breakpoints for target: iphone.cpu1
Debug: 480 1250106 breakpoints.c:499 watchpoint_clear_target(): Delete all watchpoints for target: iphone.cpu0
Debug: 481 1250107 target.c:1612 target_call_event_callbacks(): target event 19 (gdb-attach) for core iphone.cpu0
Debug: 482 1250107 target.c:4562 target_handle_event(): target(2): iphone.cpu0 (aarch64) event: 19 (gdb-attach) action: halt
Debug: 483 1250107 command.c:143 script_debug(): command - halt halt
Debug: 485 1250111 target.c:3049 handle_halt_command(): -
Debug: 486 1250111 aarch64.c:349 aarch64_prepare_halt_smp(): target iphone.cpu0 exc 0
Debug: 487 1250119 aarch64.c:373 aarch64_prepare_halt_smp(): target iphone.cpu0 prepared
Debug: 488 1250119 aarch64.c:394 aarch64_halt_one(): iphone.cpu0
Debug: 489 1250133 aarch64.c:573 aarch64_poll(): Target iphone.cpu0 halted
Debug: 490 1250142 aarch64.c:1013 aarch64_debug_entry(): iphone.cpu0 dscr = 0x03057d13
:
Info : 507 1250269 armv8.c:656 armv8_read_mpidr(): iphone.cpu0 cluster 0 core 0 multi core
:
User : 512 1250269 armv8.c:1141 armv8_aarch64_state(): target halted in AArch64 state due to debug-request, current mode: EL1T
cpsr: 0x800002c4 pc: 0x100000508
User : 513 1250269 armv8.c:1168 armv8_arch_state(): MMU: enabled, D-Cache: enabled, I-Cache: enabled
Info : 514 1250269 gdb_server.c:1012 gdb_new_connection(): New GDB Connection: 1, Target iphone.cpu0, state: halted
Debug: 515 1250269 gdb_server.c:3164 gdb_input_inner(): received packet: 'qSupported:multiprocess+;swbreak+;hwbreak+;qRelocInsn+;fork-events+;vfork-events+;exec-events+;vContSupported+;QThreadEvents+;no-resumed+'
Debug: 516 1250269 armv8.c:1768 armv8_get_gdb_reg_list(): Creating Aarch64 register list for target iphone.cpu0
Debug: 517 1250269 gdb_server.c:3164 gdb_input_inner(): received packet: 'vMustReplyEmpty'
:
Debug: 530 1250275 gdb_server.c:3164 gdb_input_inner(): received packet: 'qAttached'
Debug: 531 1250275 gdb_server.c:3164 gdb_input_inner(): received packet: 'g'
Debug: 532 1250276 armv8.c:1768 armv8_get_gdb_reg_list(): Creating Aarch64 register list for target iphone.cpu0
Debug: 533 1250284 armv8_dpm.c:667 dpmv8_read_reg(): READ: x2, 1801b8810
Debug: 534 1250294 armv8_dpm.c:667 dpmv8_read_reg(): READ: x3, 1801b8887
:

In the OpenOCD log output, if debug output is enabled, we see the various commands exchanged between the devices.

Step 5) Contemplate

Everything looks ready to use. We can live-debug the SecureROM boot code, dump memory and even attach tools like IDA Pro. This will be part of another post – or of your own research if you don’t want to wait.

Step 6) Exit DFU and reset Phone

The GDB “monitor” operation is a pass-though to the underlying OpenOCD bridge. Thus, the next command tells OpenOCD to perform “as hard a reset as possible” (sic), using SRST if possible [7]. Likewise, the “reset” command can be issued directly in the OpenOCD telnet console.

(gdb) monitor reset

iphone.cpu1 powered down!
target->coreid 0 powered down!
Bulk read failed

SWD DPIDR 0x4ba02477
(gdb)

OpenOCD console (telnet):

iphone.cpu1 powered down!
target->coreid 0 powered down!
Bulk read failed

SWD DPIDR 0x4ba02477
Polling target iphone.cpu0 failed, trying to reexamine
SWD DPIDR 0x4ba02477
iphone.cpu0 powered down!

dmesg kernel message log:

[14125.737420] usb 1-4: USB disconnect, device number 8
[14143.087881] usb 1-4: new high-speed USB device number 9 using ehci-pci
[14143.257057] usb 1-4: New USB device found, idVendor=05ac, idProduct=12a8, bcdDevice= 9.03
[14143.257059] usb 1-4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[14143.257059] usb 1-4: Product: iPhone
[14143.257060] usb 1-4: Manufacturer: Apple Inc.
[14145.364443] ipheth 1-4:4.2: Apple iPhone USB Ethernet device attached

The iPhone restarts, leaving the DFU state and re-entering normal production mode.  

OpenOCD log:

Debug: 629 2689150 gdb_server.c:3164 gdb_input_inner(): received packet: 'qRcmd,7265736574'
Debug: 630 2689154 command.c:143 script_debug(): command - reset reset
Error: 666 2689184 aarch64.c:2395 aarch64_examine_first(): iphone.cpu1 powered down!
Error: 677 2689207 cortex_a.c:2697 cortex_a_examine_first(): target->coreid 0 powered down!
Debug: 703 2689218 cortex_a.c:1645 cortex_a_assert_reset():
Debug: 725 2689218 aarch64.c:1741 aarch64_deassert_reset():
Debug: 726 2689218 core.c:647 swd_add_reset(): SRST line released
User : 729 2690223 command.c:695 command_run_line():
Info : 730 2690243 adi_v5_swd.c:136 swd_connect(): SWD DPIDR 0x4ba02477
User : 739 2696127 target.c:2815 handle_target(): Polling target iphone.cpu0 failed, trying to reexamine
Info : 741 2696143 adi_v5_swd.c:136 swd_connect(): SWD DPIDR 0x4ba02477
Error: 753 2696162 aarch64.c:2395 aarch64_examine_first(): iphone.cpu0 powered down!
Warn : 756 2708952 log.c:404 keep_alive(): keep_alive() was not invoked in the 1000ms timelimit. GDB alive packet not sent! (2096). Workaround: increase "set remotetimeout" in GDB
Error: 765 2718680 target.c:2234 target_read_buffer(): Target not examined yet

The JTAG targets cannot be “re-examined”, as it’s not demoted anymore.

Step 7) What’s Next

Our JTAG set-up allows us to live-debug the boot code, dump memory and even attach tools like IDA Pro. This will be part of another post. In the meantime, LabdaConcept has a video up showing how IDA can be used to debug the iPhone SecureROM boot code [10].

Et zou!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

By continuing to use the site, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close