© Aditya Gupta 2019
Aditya GuptaThe IoT Hacker's Handbookhttps://doi.org/10.1007/978-1-4842-4300-8_6

6. JTAG Debugging and Exploitation

Aditya Gupta1 
(1)
Walnut, CA, USA
 

In the preceding chapters, we looked at various communication protocols, such as UART, SPI, and I2C. In this chapter, we cover JTAG, which is a bit different from what we have seen so far, and is not exactly a communication protocol. JTAG is a widely misunderstood concept, even within the security community.

The Joint Test Action Group (JTAG) is an association created in the mid-1980s when a group of companies came together to solve the problem of debugging and testing chips while dealing with the increasing complexity of devices.

During that period, embedded device manufacturers realized the trouble in traditional bed of nails testing was with the new assembled PCBs, due to increasing device density, especially while working with chips having an extremely high number of pins. Imagine the manual effort needed to test hundreds of chips with multiple pins in each of them and testing whether each of them is working well and communicating properly. To overcome this problem, the manufacturers came up with a standard that allows them to embed a piece of hardware into the chip itself to allow easier testing of various pins present in different chips of the PCB. This methodology was standardized by the IEEE in 1990 and named IEEE 1149.1.

JTAG is not a standard or protocol, but rather just a way of testing different chips present on the device and debugging them. JTAG uses a technique known as boundary scan, which enables manufacturers to test and diagnose the assembled PCBs with much greater ease compared to the old traditional approach.

Boundary Scan

As just mentioned, boundary scan is a technique to debug and test various pins of the different chips present in a circuit. This is done by adding a piece of component called boundary scan cells near each pin of the chip that needs to be tested. The various I/O pins of the device are connected serially to form a chain. This chain can then be accessed by what is called the test access port (TAP).

The boundary scan happens by sending data into one of the chips and matching the output to the input to verify that everything is functioning properly. Each chip in Figure 6-1 is connected serially.
../images/473264_1_En_6_Chapter/473264_1_En_6_Fig1_HTML.jpg
Figure 6-1

Describing boundary scan cells (Source: CMOS VLSI design: A circuits and systems perspective, 3rd ed., Neil H. E. Westw & David Harris)

Notice the I/O pads and the boundary scan cell near the periphery of each chip. These boundary scan cells can be accessed and checked for the values in the pins associated with the boundary scan cells. An external file known as a boundary scan description language file defines the capabilities of any single device’s boundary scan logic.

Test Access Port

TAP is a collective name given to the JTAG interfaces present on a device. There are five signals TAP uses that control a state machine:
  • Test clock (TCK): Used to synchronize the internal state machine operation and to clock serial data into the various boundary cells.

  • Test data in (TDI): The serial input data pin to the scan cells.

  • Test data out (TDO): Sends the serial output data from the scan cells.

  • Test mode select (TMS): Used to control the state of the TAP controller.

  • Test reset (TRST, optional): The reset pin that is active low. When it is driven low, it will reset the internal state machine.

The TCK, TMS, and TRST pins drive a 16-bit TAP controller machine that manages the overall exchange of data and instructions.

The TAP controller is a 16-stage finite state machine (FSM) that proceeds from state to state, based on the TMS and TCK signals. The TAP controller controls the test data register and the instruction register with the control signals. If an instruction is to be sent, then the clock (TCK) is activated and the reset is set to active low for the clock cycle. Once that is done, the reset signal is then deactivated and the TMS is toggled to traverse the state machine for further operation.

Boundary Scan Instructions

There is set of instructions defined by the IEEE 149.1 standard that must be made available for a device in case of a boundary scan. These instructions are listed here.
  • BYPASS: The BYPASS instruction places the BYPASS register in the DR chain, so that the path from the TDI and TDO involves only a single flip-flop (shift-resistor). This allows a specific chip to be tested in a serial chain without any overhead or interference from other chips.

  • SAMPLE/PRELOAD: The SAMPLE/PRELOAD instruction places the boundary scan register in the DR chain. This instruction is used to preload the test data into the boundary scan register (BSR). It is also used to copy the chip’s I/O value into the data register, which can then be moved out in successive shift-DR states.

  • EXTEST: The EXTEST instruction allows the user to test the off-chip circuitry. It is like SAMPLE/PRELOAD but also drives the value from the data register onto the output pads.

Test Process

To give you a clear overall picture, here is how the overall test process would look like for a boundary scan process:
  • The TAP controller applies test data on the TDI pins.

  • The BSR monitors the input to the device and the data are captured by the boundary scan cell.

  • The gata then go into the device through the TDI pins.

  • The data come out of the device through the TDO pins.

  • The tester can verify the data on the output pin of the device and confirm if everything is working.

These tests can be used to find things ranging from a simple manufacturing defect, to missing components in a board, to unconnected pins or incorrect placement of the device, and even device failure conditions.

Debugging with JTAG

Even though the JTAG was originally created to assist with eliminating the old bed of nails testing, in the new-age embedded development and testing world, it is used to perform several activities such as debugging the various chips present on the device, accessing individual pin values on each chip, overall system testing, identifying faulty components in a highly dense PCB, and so on. Because JTAG is available in the systems from the very start, as soon as the system boots up, it makes it extremely useful for testers and engineers to look at all the various components present in the embedded device.

For penetration testers and security researchers, it is extremely useful as it allows us to debug the target system and its individual components. This also means if our target board has JTAG access available and contains an onboard flash chip, we would be able to dump the contents from the flash chip via JTAG. We will also be able to set breakpoints and analyze the entire stack, instruction sets, and registers while debugging with JTAG, and integrating it with a debugger.

Now that you know how useful JTAG is going to be for us to identify vulnerabilities in the target device or perform security research, the next step would be to identify the JTAG pinouts present on the target device.

Identifying JTAG Pinouts

Identifying JTAG pinouts can be a bit trickier compared to UART, where all you would need is to look for a set of three or four pins and then use multimeter to identify the individual pinouts. In the case of JTAG, we will need to use additional tools (e.g., JTAGulator) to effectively determine the individual pinouts present in our target device.

Another thing to note while working with JTAG is that in most of the devices you will find the JTAG pads, instead of JTAG pins or pads with holes, which also makes it important for us to have a bit of soldering experience if we want to exploit real-world devices via JTAG.
  • In JTAG, we are concerned with usually four pins: TDI.

  • TDO.

  • TMS.

  • TCK.

Before we look at the JTAG pinouts, let’s have a look at what JTAG pinouts possibly look like, so that it is easier for us to locate them on a given circuit board. Figures 6-2 through 6-4 show some examples of the JTAG pinouts. Figure 6-2 shows a 14-pin JTAG interface in Netgear router WG602v3.
../images/473264_1_En_6_Chapter/473264_1_En_6_Fig2_HTML.png
Figure 6-2

JTAG pinouts in Netgear WG602v3 (Source: https://www.dd-wrt.com/phpBB2/files/jtag_wg602v3_643.jpg )

../images/473264_1_En_6_Chapter/473264_1_En_6_Fig3_HTML.jpg
Figure 6-3

JTAG interfaces on a Wink Hub

../images/473264_1_En_6_Chapter/473264_1_En_6_Fig4_HTML.png
Figure 6-4

JTAG on a Linksys WRT160NL (Source: http://www.usbjtag.com/jtagnt/router/wrt160nljtag.jpg )

Figures 6-3 and 6-4 show the PCB image of Wink Hub and the different JTAG interfaces.

Now that you understand how JTAG pinouts might look on a real-world device, let’s go ahead and start identifying what the pinout is for the JTAG interface we have just found.

For this exercise, you can use any device with a JTAG interface. For starters, though, I would recommend choosing a development board that has a specified JTAG interface on it that could be used for debugging. Good examples are Raspberry Pi or Intel Galileo, both of which come with JTAG pins on them.

We can identify JTAG pinouts using two approaches, which differ based on hardware used:
  1. 1.

    Using JTAGulator.

     
  2. 2.

    Using Arduino flashed with JTAGEnum.

     

Using JTAGulator

JTAGulator is open source hardware, designed by Joe Grand of Grand Idea Studios, which helps us identify JTAG pinouts for a given target device. It has 24 I/O channels that can be used for pinout discovery and can also be used to detect UART pinouts.

It uses an FT232RL chip that allows it to handle the entire USB protocol on a single chip and enables us to just plug in the device and have it appear as a virtual serial port with which we can then interact using a screen or minicom. Figure 6-5 shows an image of JTAGulator.
../images/473264_1_En_6_Chapter/473264_1_En_6_Fig5_HTML.png
Figure 6-5

JTAGulator by Joe Grand

To use JTAGulator, we need to connect all the various pins on our target device to the JTAGulator channels while connecting the ground to ground. Once done, simply connect JTAGulator to our system and run a screen with a baud rate of 115200.
screen /dev/ttyUSB0 115200

Once you’re on the JTAGulator screen, the next step would be to set the target system voltage by pressing V to select the target voltage.

After selecting the voltage, the next step is to select a BYPASS scan to find the pinouts. On selecting this, you will be required to specify how many channels you have selected for the pinouts.

Once you have selected everything, JTAGulator will detect the various JTAG pinouts for you as shown in Figure 6-6.
../images/473264_1_En_6_Chapter/473264_1_En_6_Fig6_HTML.png
Figure 6-6

Detecting JTAG pinouts with JTAGulator

Based on which pins on your target device are connected to which channel, you will be able to identify the pinouts of the JTAG interface on the target device.

Using Arduino Flashed with JTAGEnum

Another popular technique of identifying JTAG interface is using Arduino. This is a much cheaper alternative compared to JTAGulator, but there are a few limitations, such as the scan being extremely slow and not having the ability to detect UART pinouts like JTAGulator does.

To use JTAGEnum with Arduino, the first step is to use the JTAGEnum program available at https://github.com/cyphunk/JTAGenum .

Once you have the code sample, open the Arduino integrated development environment (IDE) and paste the code into the editor window, as shown in Figure 6-7. Select the correct port and Arduino type from the menu options. In our case, we have an Arduino Nano connected to our system. Click the Upload button located on the top right and you will see that the code has been uploaded.
../images/473264_1_En_6_Chapter/473264_1_En_6_Fig7_HTML.jpg
Figure 6-7

Arduino flashed with JTAGEnum to detect JTAG pins

Now that we have uploaded the code to our Arduino, the next step is to interface with the Arduino via a serial connection. This can be done either through the Serial Monitor present in the Arduino IDE or using a utility such as a screen or minicom, as shown in Figure 6-8.
../images/473264_1_En_6_Chapter/473264_1_En_6_Fig8_HTML.png
Figure 6-8

Moving forward with the scanning

Once we have the JTAGEnum code up and running, we can then press s to start scanning for various combinations and identify the JTAG pinouts. This process might take a bit longer than what the JTAGulator took but will ultimately tell you the JTAG pinouts of the various wires connected to the Arduino, as shown in Figure 6-9.
../images/473264_1_En_6_Chapter/473264_1_En_6_Fig9_HTML.png
Figure 6-9

JTAGEnum was successful in detecting JTAG pinouts

Just like you did earlier, map those wires to the ones connected on the target device and you will have the actual JTAG pinouts of the target device.

Now that we have identified the JTAG pinouts of the target device, the next step is to connect to the JTAG interface and debug the target device and the programs running on it. For this, we need knowledge of OpenOCD, which is what we are going to be discussing in the next section.

OpenOCD

OpenOCD is a utility that allows us to perform on-chip debugging with our target device via JTAG. OpenOCD, developed by Dominic Rath, is open source software that interfaces with a hardware debugger’s JTAG port. The following are some of the things we can do with JTAG debugging:
  • Debug the various chips present on the device.

  • Set breakpoints and analyze registers and stack at a given time.

  • Analyze flashes located on the device.

  • Program and interact with the flashes.

  • Dump firmware and other sensitive information.

OpenOCD, as you can see, is an extremely useful utility when we have to work with JTAG. In the next sections, we look at how we can set up OpenOCD and use it to perform additional exploitation of our target device.

Installing Software for JTAG Debugging

Some of the tools that we will be using to debug JTAG are:
  • OpenOCD

  • GDB-Multiarch

  • Attify Badge tool

Installing OpenOCD on your system is straightforward if done using apt and can be done by running this command:
apt install openocd
You can also choose to build OpenOCD from the source if you wish, which can be done using the following commands:
wget https://downloads.sourceforge.net/project/openocd/openocd/0.10.0/openocd-0.10.0.tar.bz2
tar xvf openocd-0.10.0.tar.bz2
./configure
make && make install

Once you have installed OpenOCD, we are ready to get started with our exploitation.

An additional useful utility to install here would be GDB-Multiarch, which would allow us to use GDB to debug binaries meant for different architectures, as most of the time we would be dealing with target devices and binaries that are not meant for the typical x86 architecture.

Alternatively, if you install the Attify Badge tool from https://github.com/attify/attify-badge and run install.sh, it will automatically install all the tools required for you, including OpenOCD. You can also use the AttifyOS located at https://github.com/adi0x90/attifyos , which is preconfigured with all the required tools.

Hardware for JTAG Debugging

On the hardware side, JTAG debugging and exploitation can be done with the following hardware tools:
  • Attify Badge or other tools such as BusPirate or Segger J-Link.

  • Target device with the JTAG interface.

For the sake of simplicity, we are using an Attify Badge for our JTAG debugging purposes. To use the Attify Badge with the target device, we will need to connect the corresponding JTAG pins of the device with the Attify Badge’s pinouts for JTAG, which we look at in the next section.

To make use of the Attify Badge (or any other hardware for that matter), we need the OpenOCD configuration file for it and the configuration file for the target device (and for any other devices in the chain). Here, the Attify Badge will work like a JTAG adapter, and the target device can either be a processor or a controller.

Before jumping into making the connections for JTAG, we need to check if our target device’s controller is supported by OpenOCD. To do this, we can check the target list table provided along with the OpenOCD source as shown in Figure 6-10.
../images/473264_1_En_6_Chapter/473264_1_En_6_Fig10_HTML.jpg
Figure 6-10

OpenOCD targets

You should always ensure that your target is listed in the OpenOCD targets, which come with the source, or else you will have to create a manual configuration file for your target device.

Setting Things up for JTAG Debugging

Now that we have everything in place, we need to make the connections required for JTAG debugging. The Attify Badge pinouts for JTAG are provided in Table 6-1.
Table 6-1

Connections for JTAG with Attify Badge

Pin on the Attify Badge

Function

D0

TCK

D1

TDI

D2

TDO

D3

TMS

Once we know the connection, the next step is to figure out the pinouts for our target board and make the connections. The connections would be as follows:
  • TCK (D0) goes to CLK of the target device.

  • TDI (D1) goes to TDI of the target device.

  • TDO (D2) goes to TDO of the target device.

  • TMS (D3) goes to TMS of the target device.

The pins functioning as CLK, TDI, TDO, and TMS would differ based on the processor or controller of the target device that you are trying to exploit.

For our demonstration purposes, we will take a device with the STM32F103C8 microcontroller family. The pinout diagram taken from its data sheet is displayed for better understanding in Figure 6-11.
../images/473264_1_En_6_Chapter/473264_1_En_6_Fig11_HTML.jpg
Figure 6-11

PIN configuration of STM32F103C8 microcontroller

Once the connections have been done, the next step would be to ensure that we have the configuration (.cfg) files for the Attify Badge, as well as for our target.

The configuration file for the Attify Badge, badge.cfg, is available from the book code downloads, as shown here:
interface ftdi
ftdi_vid_pid 0x0403 0x6014
ftdi_layout_init 0x0c08 0x0f1b
adapter_khz 2000

For the configuration file of our target, the STM32 microcontroller, we can get it from the OpenOCD configurations itself.

Figure 6-12 shows a graphical representation of the connections currently.
../images/473264_1_En_6_Chapter/473264_1_En_6_Fig12_HTML.jpg
Figure 6-12

Connections for JTAG debugging

Once the connections have been made, we can run the following command to check if we can use OpenOCD to debug the target, as shown here.
$ sudo openocd –f badge.cfg –f stm32fx.cfg
Open On-Chip Debugger 0.7.0 (2013-10-22-17:42)
Licensed under GNU GPL v2
For bug reports, read
       http://openocd.sourceforge.net/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'jtag'
adapter speed: 2000 kHz
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
jtag_ntrst_delay: 100
Warn : target name is deprecated use: 'cortex_m'
DEPRECATED! use 'cortex_m' not 'cortex_m3'
cortex_m3 reset_config sysresetreq
Info : clock speed 1000 kHz
Info : JTAG tap: stm32f1x.cpu tap/device found: 0x3ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x3)
Info : JTAG tap: stm32f1x.bs tap/device found: 0x16410041 (mfg: 0x020, part: 0x6410, ver: 0x1)
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints

As we can see from that text, OpenOCD is able to connect to our target device and shows us additional information such as six breakpoints, four watchpoints, and more.

Once you have reached that screen, you can use telnet to communicate to the OpenOCD instance, which has connected to our target device over JTAG.
$ telnet localhost 4444
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> reset init
JTAG tap: stm32f1x.cpu tap/device found: 0x3ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x3)
JTAG tap: stm32f1x.bs tap/device found: 0x16410041 (mfg: 0x020, part: 0x6410, ver: 0x1)
target state: halted
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x080009f0 msp: 0x20005000
> halt

As you can see, we are able to connect to our target device and chip over JTAG using OpenOCD. This means that we were successful in identifying the correct JTAG pinouts and can now proceed with further exploitation of our target device.

Performing JTAG Exploitation

Now that you are successfully connected, at this point you can use the telnet session with OpenOCD and JTAG to write firmware to the microcontroller, debug binaries, and even dump firmware from it.

Let’s have a look at them one by one, starting with writing firmware to the device.

Writing Data and Firmware to a Device

As mentioned earlier, JTAG can be used to write firmware to the device. This is useful when you are assessing the target device and want to flash a modified version of the firmware to bypass security restrictions on the device. To write a new firmware to the device, let’s first check the address at which flash starts. We can then use this address to write a new firmware onto the device.
> flash banks
#0 : stm32f1x.flash (stm32f1x) at 0x08000000, size 0x00000000, buswidth 0, chipwidth 0

The flash memory in this case starts at the address 0x08000000 and the current size of the contents at that address is 0x0, which indicates that the target device contains no firmware at present. We use the address from the previous output and pass it on to our next command specifying to write a custom-created firmware, firmware.bin. The firmware in this case enables authentication over UART for our target board.

To write firmware to the target device, use the following command:
> flash write_image erase firmware.bin 0x08000000
auto erase enabled
Info : device id = 0x20036410
Info : flash size = 128kbytes
wrote 65536 bytes from file firmware.bin in 4.109657s (15.573 KiB/s)
As you can see, the firmware writing completed successfully. We can verify this by performing a flash banks and seeing the change in the storage size of the flash memory.
> flash banks
#0 : stm32f1x.flash (stm32f1x) at 0x08000000, size 0x00020000, buswidth 0, chipwidth 0

This technique is useful when working with devices where you want to dump the contents from various flash chips, and even write malicious values to them.

Dumping Data and Firmware from the Device

If other techniques of obtaining the firmware fail, JTAG is our fallback option. We can use JTAG with the dump_image command to dump the firmware from the file system.

This is shown here, where we have dumped the firmware from the same flash chip by indicating the address from where we want to dump the contents and the amount of data that we want to dump.
> dump_image dump.bin 0x08000000 0x00020000
dumped 131072 bytes in 1.839897s (69.569 KiB/s)

Reading Data from the Device

We can also selectively read data from specific memory addresses using JTAG. This is useful when we know the exact address that we want to read and later maybe modify.

We can use the command mdw followed by the address and the number of blocks to read.
> mdw
mdw ['phys'] address [count]
 stm32f1x.cpu mdw address [count]
in procedure 'mdw'
As mentioned earlier, this firmware contains an authentication function for UART access. The password in this case is stored at an offset of d240. Given that we know the base address of flash storage—0x08000000—we can use the mdw command to dump the password from the base address + address which is 0x0800d240, as shown here.
> mdw 0x0800d240 10
0x0800d240: 69747461 4f007966 6e656666 65766973 546f4920 70784520 74696f6c 6f697461
0x0800d260: 7962206e 74744120

Converting the value 61 74 74 69 66 79 from the output, which is in hex, to ASCII, we get the actual password, which in this case is attify. Similarly, we can also write a new value to the memory address to change the password the device uses for UART authentication.

This is a simple demonstration of how you can use reading contents from the memory to your advantage during exploitation. When performing it during your pentests, make sure to look for anything of potential interest, then figure out the address in hexdump or through a disassembler, and finally read and write values using JTAG debugging.

Debugging over JTAG with GDB

Often, you need to debug binaries and firmware over JTAG to understand the functionality in a much better way, and to modify some of the register values or instruction sets and change the program execution flow.

Now that we are already familiar with debugging using GDB, we will use GDB to debug a binary that we have flashed over JTAG. The binary can be downloaded from the code samples of the book available at https://attify.com/ihh-download . Once we have flashed the binary, we then proceed with debugging the binary runtime with JTAG and GDB.

Now you might be wondering how we can connect GDB to the target process over JTAG. The answer to that is whenever we run OpenOCD for a target to perform JTAG debugging, it also enables two different services, the first one being telnet over Port 4444, which we use to interact with OpenOCD, and the other being GDB over Port 3333, which we can use to debug binaries running on the target device.

To do this, launch GDB-Multiarch and provide the binary that we want to debug, which in this case is the binary from firmware.bin, named authentication.elf. Once connected, we will also set the architecture to arm and point it to Port 3333, where OpenOCD has attached the gdbserver with the running process.
$ gdb-multiarch -q authentication.elf
Reading symbols from Vulnerable-binary-for-gdb.elf...done.
(gdb) set architecture arm
The target architecture is assumed to be arm
(gdb) target remote localhost:3333
Remote debugging using localhost:3333
0x080009f0 in Reset_Handler ()
(gdb)

Once you have the GDB for arm up and running, you can go ahead and set up breakpoints using either hbreak or the break to better analyze the binary and analyze the entire stack and registers when the breakpoint is hit. hbreak is used to set a hardware-assisted breakpoint, whereas break can be used to set a normal breakpoint at either an instruction, memory location, or function.

The first thing that we want to do is look at the functions in this binary. To do this we will use the info functions command shown here.
(gdb) info functions
Non-debugging symbols:
0x08000000  g_pfnVectors
0x0800010c  deregister_tm_clones
0x0800012c  register_tm_clones
0x08000150  __do_global_dtors_aux
0x08000178  frame_dummy
0x08000218  mbed::Serial::~Serial()
0x08000218  mbed::Serial::~Serial()
0x0800023c  non-virtual thunk to mbed::Serial::~Serial()
0x08000244  non-virtual thunk to mbed::Serial::~Serial()
0x0800024c  doorclose()
0x08000290  dooropen()
0x080002e0  verifypass(char*)
0x08000300  main
0x08000380  mbed::Serial::~Serial()
0x08000392  non-virtual thunk to mbed::Serial::~Serial()
0x08000398  non-virtual thunk to mbed::Serial::~Serial()
0x080003a0  _GLOBAL__sub_I_pc
0x080003e4  __NVIC_SetVector
0x08000424  timer_irq_handler
0x080004f0  HAL_InitTick
0x080005ac  mbed_die
The function that we are interested in this case is the verifypass(char *) function . Let’s have a look at what verifypass does by using the disassemble command.
(gdb) disassemble verifypass(char*)
Dump of assembler code for function _Z10verifypassPc:
   0x080002e0 <+0>:    push   {r3, lr}
   0x080002e2 <+2>:    ldr    r1, [pc, #24]    ; (0x80002fc                                      <_Z10verifypassPc+28>)
   0x080002e4 <+4>:    bl     0x8003910 <strcmp>
   0x080002e8 <+8>:    cbnz    r0, 0x80002f2 <_Z10verifypassPc+18>
   0x080002ea <+10>:   ldmia.w      sp!, {r3, lr}
   0x080002ee <+14>:   b.w    0x8000290 <_Z8dooropenv>
   0x080002f2 <+18>:   ldmia.w      sp!, {r3, lr}
   0x080002f6 <+22>:   b.w    0x800024c <_Z9doorclosev>
   0x080002fa <+26>:   nop
   0x080002fc <+28>:   bcs.n  0x8000380 <_ZN4mbed6SerialD0Ev>
   0x080002fe <+30>:   lsrs   r0, r0, #32
End of assembler dump.

As we can see, verifypass is a function to compare the user input password to the actual password using the strcmp instruction at the address 0x080002e4. Based on the result, if the authentication is granted, it then branches to either 0x8000290 for dooropen or continues further if the passwords do not match.

To figure out the actual password, we can set a breakpoint at the strcmp instruction and analyze registers r0 and r1, which will hold the two values being compared. One of these values will be the user input password and the other value will be the actual password.
(gdb) b *0x080002e4
Breakpoint 1 at 0x80002e4
(gdb) c
Continuing.
Note: automatically using hardware breakpoints for read-only addresses.
Once you have set the breakpoint, you can type c to continue the program execution. The next thing to do is to connect over UART and provide an input, so that verifypass gets called and our breakpoint is hit. To connect to the same target device over UART, we will use the pins A2 and A3, which is the Tx and Rx of STM32, and connect it to D1 and D0 of Attify Badge. Figure 6-13 shows how the final connection would look like.
../images/473264_1_En_6_Chapter/473264_1_En_6_Fig13_HTML.jpg
Figure 6-13

JTAG connections with UART

We connect to the UART console in another terminal and use screen to connect to /dev/ttyUSB0 over a baud rate of 9600.
$ sudo screen /dev/ttyUSB0 9600
Offensive IoT Exploitation : Enter your Password:
Let’s enter testing as the password here and press Enter. As soon as we press Enter, we can see that we have the breakpoint hit in the GDB session as shown here.
//Terminal 1 with UART:
Offensive IoT Exploitation by Attify!
                                  Enter the password: ********
//Terminal 2 with GDB:
Breakpoint 1, 0x080002e4 in verifypass(char*) ()
(gdb)
At this point, we can analyze the registers using info registers.
(gdb) info registers
r0             0x20004fe0      536891360
r1             0x800d240       134271552
r2             0x34000000      872415232
r3             0x20004fe8      536891368
r4             0x0    0
r5             0x20004fe0      536891360
r6             0x20004fef      536891375
r7             0x20004fe7      536891367
r8             0xbd7ff3ba      -1115688006
r9             0x9aebfea5      -1695809883
r10            0x1fff5000      536825856
r11            0x0    0
r12            0x20004f50      536891216
sp             0x20004fd8      0x20004fd8
lr             0x800035d       134218589
pc             0x80002e5       0x80002e5 <verifypass(char*)+4>
xpsr           0x61000020      1627389984
Let’s see what’s in r0 and r1 using the x/s command, which examines the value as a string.
(gdb) x/s $r0
0x20004fe0:    "testing"
(gdb) x/s $r1
0x800d240 <_fini+164>:    "attify"
You can see that r0 contains the password you input, which is testing and r1 contains the actual password, which is attify. Here we can change the value of r0 and set it to be attify and type c to continue the execution.
(gdb) set $r0="attify"
You can now see in our screen terminal that we have been granted authentication, as shown in Figure 6-14.
../images/473264_1_En_6_Chapter/473264_1_En_6_Fig14_HTML.png
Figure 6-14

Authentication bypassed using JTAG debugging

That is how we can exploit a binary over JTAG and perform real-time debugging of the binary and modify one of the registers to make the authentication valid.

Conclusion

In this chapter, we had a look at one of the most interesting ways of exploiting embedded devices, which is via JTAG. However, the techniques and content covered in this chapter are intended to help you get started with JTAG debugging and I hope you will apply these skills to real-world devices to take it even further.

Also, once you have gained JTAG debugging access, it depends on how much further you want to go with it. This means that because you can debug binaries, you might find more vulnerabilities in the various binaries running on the device, which could help you compromise the device in further ways.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.225.173