- 1 How to assemble
- 2 How to install the software
- 3 Installing the desktop client controller software
- 4 How to use
- 5 Connecting the ground pin
- 6 Connecting the GPIO pins
- 7 Detecting UART
- 8 UART passthrough
- 9 Detecting JTAG
- 10 Dumping SPI
- 11 Discovering the I2C slave address
- 12 Dumping I2C
- 13 Limitations
- 14 Troubleshooting
How to assemble
- 4 x 4-pin female header strips
- 1 x 10-pin male header strip
- 1 x NodeMCU v2
- 1 x 10-rainbow cable
- USB cable
2 Capacitors are optional and not necessary, nor given.
How to install the software
Download the software from https://github.com/BSidesCbr/BUSSide
- Install the Arduino IDE
- Install the NodeMCU board into the IDE
- Set the board to NodeMCU 1.0
- Set the speed to 160MHz (via the IDE in the Tools dropdown)
- Compile and upload the program
The Arduino IDE can be downloaded via https://www.arduino.cc/en/Main/Software
To install the NodeMCU v1.0 board into the Arduino IDE do the following:
Go into the IDE under File -> Preferences and in “Additional Boards Manager URLs” add “http://arduino.esp8266.com/stable/package_esp8266com_index.json”
Now go to Tools -> Boards -> Boards Manager. Search for esp8266 and install the package.
Now go to Tools -> Boards and select the NodeMCU 1.0
Don't forget to go into Tools and set the NodeMCU speed to 160MHz.
Installing the desktop client controller software
The desktop client controller software must run on Linux. This is because the Windows serial driver for the NodeMCU is not well supported. The easiest way to do this is fire up a Linux VM and use USB passthrough in your virtualization software for the serial device.
The controller software is written as a set of Python scripts. You will need to run a python interpreter to execute the scripts. Only Python 2.7 is currently supported. The controllers you have are:
How to use
The BUSSide can be used in a number of different ways. The following list shows the functions of the BUSSide.
- Detecting UART
- Detecting JTAG
- Dumping SPI Flash
- I2C Slave Discovery
- Dumping I2C Flash
You plug in your Busside via USB. Remember, use Linux and USB passthrough. You will need to connect the BUSSide to the device that you're testing. More on this is presented later for connecting ground and the GPIO pins. Lets assume you've connected the BUSSide to the device.
The BUSSide is ready to take commands. You do this by running scripts from your Linux command line which communicates back and forth with the BUSSide via the USB serial connection.
Each python client script relates to a function of the BUSSide. You run the script and the BUSSide will output information to your screen. If you run the script to detect UART, then it might print the pinout it detected and the line settings of the UART. If you wanted the BUSSide to dump SPI flash, then it will create an output file with the dump.
The arguments for each script can be different. However, each script normally takes the Linux serial device (e.g., /dev/ttyUSB0) as its 1st argument.
Connecting the ground pin
The first thing you want to do to use the BUSSide on a device is to identify the ground pin on the headers you are interrogating. It's quite easy to determine ground pins. You take your multimeter and put it into the continuity test mode. Now you connect one probe to the pin you are testing and the other probe to somewhere on the ground plane. The ground plane often includes things like metal shielding internal to the device. If that doesn't work, you might need to connect it to ground on the DC socket. If your multimeter beeps, you have identified a ground pin. If you can't detect any ground pins, you might not have found the ground plane. Try any other shielding if it is available.
Now you need to connect the ground pin on the device to the BUSSide.
Connecting the GPIO pins
Now you want to connect the other pins to the BUSSide. If you want to detect UART or determine if test points are JTAG pins, then connect them. It doesn't matter what order you connect the pins, but if the BUSSide detects a pinout, you need to recogonise which GPIO pin on the BUSSide is connected to which pin on the device.
Note that GPIO 1-9 on the BUSSide corresponds to D0-D8 when using the controller. Also note that the pin immediately adjacent too the ground pin on the BUSSide corresponds to D0.
The BUSSide can detect the transmit (tx) pin of a UART connection if it is present and automatically determine the line settings including the baudrate, the number of data and stop bits, and the parity, if any, that is used.
To perform the detection, the UART must be transmitting data. The easiest way to make this happen is to boot the device. During bootup, it is common for boot messages to be sent over serial console via UART. The BUSSide will suggest that you boot the device, and wait until you are ready to begin the detection.
Here is an example of detecting UART in a DLINK DSL-502T ADSL router:
root@kali:~/Desktop# time python2.7 uartdetect.py /dev/ttyUSB0 +++ Connecting to the BUSSide +++ Initiating comms Need the attached device to send data via UART. E.g., reboot the device. Press enter to continue. +++ Sending data discovery command +++ Reading response from the BUSSide --- GPIO D0 had 0 signal changes --- GPIO D1 had 0 signal changes --- GPIO D2 had 0 signal changes --- GPIO D3 had 3702 signal changes --- GPIO D4 had 0 signal changes --- GPIO D5 had 0 signal changes --- GPIO D6 had 0 signal changes --- GPIO D7 had 0 signal changes --- GPIO D8 had 0 signal changes +++ Sending UART line settings detection command +++ Reading response from the BUSSide --- Trying UART on GPIO 3 BITWIDTH: 103.00 BAUDRATE measured=9708 nearest=9600 FRAMESIZE 10 STOPBITS: 1 PARITY: NONE DATABITS: 8 --- Detected UART line settings. +++ SUCCESS real 0m10.366s user 0m0.004s sys 0m0.019s
The UART connection above was detected during the bootloader process of an ADSL router. If we waited another 5 seconds after booting the device before continuing, we enter the main OS, and get a different baudrate.
root@kali:~/Desktop# time python2.7 uartdetect.py /dev/ttyUSB0 +++ Connecting to the BUSSide +++ Initiating comms Need the attached device to send data via UART. E.g., reboot the device. Press enter to continue. +++ Sending data discovery command +++ Reading response from the BUSSide --- GPIO D0 had 0 signal changes --- GPIO D1 had 0 signal changes --- GPIO D2 had 0 signal changes --- GPIO D3 had 30320 signal changes --- GPIO D4 had 0 signal changes --- GPIO D5 had 0 signal changes --- GPIO D6 had 0 signal changes --- GPIO D7 had 0 signal changes --- GPIO D8 had 0 signal changes +++ Sending UART line settings detection command +++ Reading response from the BUSSide --- Trying UART on GPIO 3 BITWIDTH: 8.00 BAUDRATE measured=125000 nearest=115200 FRAMESIZE 10 STOPBITS: 1 PARITY: NONE DATABITS: 8 --- Detected UART line settings. +++ SUCCESS real 0m15.980s user 0m0.000s sys 0m0.018s
Once you have identified the transmit pin of a UART interface, you should connect your serial to tty converter or bus pirate. This is so you can get serial console access or see what's being transmitted. You will need to connect the appropriate pin of the bus pirate to the detected TX. You'll need to set the baudrate and other line settings to what the BUSSide detected.
Boot the device again. Do you see human readable text?
Now you need to identify the receive (rx) pin. This is quite easy but this is done without using the BUSSide. Just connect each pin you think is potentially the rx pin to the appropriate pin on your bus pirate (or equivalent). Type a letter or two on your keyboard. Do you see an echo? If you do, you got the right pin. If nothing happens, then try another pin.
The BUSSide can detect JTAG pinouts if JTAG is present. This is similar to what the JTagulator does.
root@kali:~/Desktop# time python2.7 jtagdetect.py /dev/ttyUSB0 +++ Connecting to the BUSSide +++ Initiating comms Need the attached device powered on. Press enter to continue. +++ Sending jtag detection command +++ Reading response from the BUSSide --- Found JTAG connection ntrst:D8 tck:D7 tms:D2 tdo:D6 tdi:D5 IR length: 5 --- JTAG DETECTED +++ SUCCESS real 0m8.349s user 0m0.001s sys 0m0.020s
If you have issues with detecting the JTAG pinout, then try reorganizing the order of the GPIOs. This sometimes helps.
If you have identified a SPI serial flash chip on a board, you can dump the flash contents using the BUSSide. You need to know how big the flash memory is and to do this normally you will take the part number off the chip and look up its datasheet. In actual fact, the flash size is not contained in a viewable configuration and serial flash is designed to rollover back to the beginning if you dump a size bigger than it holds.
There are multiple ways of physically interfacing with an SPI chip. You can desolder the chip and use the supplied SOP8/SOIC8 to DIP adapters. The top DIP adapter on the BUSSide is the SPI interface. Below it is the I2C interface. Another option is using something like a Pomona test clip and attaching the jumpers to the BUSSide. In this scenario, you don't need to desolder the chip.
The important pins are MOSI, MISO, SCK, and GND. HOLD is also required for serial flash.
The BUSSide dumps SPI serial flash much faster than the Bus Pirate v3.6. The Bus Pirate would normally take 15-20 minutes to dump 8M of flash. The BUSSide can do it in 3 and a half minutes.
You also need to specify an output file. In the command below, we're dumping 100,00 bytes into the file 1.bin.
root@kali:~/Desktop# time python2.7 spidump.py /dev/ttyUSB0 100000 1.bin +++ Connecting to the BUSSide +++ Initiating comms +++ Sending SPI dump command +++ Dumping SPI to file... +++ SUCCESS real 0m4.398s user 0m0.614s sys 0m0.441s
A bigger example is dumping 8M from the flash of an ADSL router.
root@kali:~/Desktop/BUSSide# time python2.7 spidump.py /dev/ttyUSB0 8388608 1.bin +++ Connecting to the BUSSide +++ Initiating comms +++ Dumping SPI +++ Retransmitting a block +++ Retransmitting a block +++ Retransmitting a block +++ SUCCESS real 3m33.090s user 0m43.080s sys 0m21.753s
Note that 3 retransmissions were made. This is indicating error correction took place due to noise in the serial connection. This is perfectly normal and expected in large dumps.
Lets take it 1 step further and run binwalk on the dump.
root@kali:~/Desktop# binwalk -e 1.bin DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 14772 0x39B4 LZMA compressed data, properties: 0x6D, dictionary size: 4194304 bytes, uncompressed size: 144236 bytes 65536 0x10000 Broadcom 96345 firmware header, header size: 256, firmware version: "8", board id: "6328ang", ~CRC32 header checksum: 0xF8EFE9AD, ~CRC32 data checksum: 0x40BC74E0 65792 0x10100 Squashfs filesystem, little endian, non-standard signature, version 4.0, compression:gzip, size: 6103538 bytes, 711 inodes, blocksize: 1048576 bytes, created: 2012-01-11 07:31:58 6172940 0x5E310C LZMA compressed data, properties: 0x6D, dictionary size: 4194304 bytes, uncompressed size: 3673532 bytes root@kali:~/Desktop# cd _1.bin.extracted/ root@kali:~/Desktop/_1.bin.extracted# ls '[' mtab 0 mtd0 1 mtd1 10100.squashfs mtdblock0 2.6.30 mtdblock1 39B4 mtdblock2 39B4.7z mtdblock3 3g-mngr mtdblock4 5E310C mtdblock5 5E310C.7z mtdblock6 ac97 mtdblock7 adsl multicast.html adslcfgadv.html multinatadd.html adslcfgc.html multinat.html adslcfg.html mxp adslcfgtone.html nas adslctl nas4not adsldd.ko natcfg2.html adsl_phy.bin NB14WN3_banner_v2.jpg advanced_1.xml NB14WN3_banner_v2_tianchong.jpg advanced_2.xml nc advanced.xml net algcfg.html netcomm_log.jpg arl netctl arpview.html netfilter atmdelerr.html nf_conntrack_ftp.ko b28n.js nf_conntrack_h323.ko backupsettings.html nf_conntrack_ipsec.ko bcm nf_conntrack_ipv4.ko bcm43112_map.bin nf_conntrack_ipv6.ko bcm4312_map.bin nf_conntrack_irc.ko ...
You can see we pulled out a lot of data. You can now try mounting the squash filesystem.
Discovering the I2C slave address
Like the SPI interface, you can interface with I2C on the BUSSide using the DIP adapter or using jumpers. The pinout is as follows.
The requires pins are SDA (data), SCL (clock), and VSS (ground). You don't have to supply power if you are attaching to a powered on device via jumpers.
Here I've attached the BUSSide to a digital answering machine which exposes an I2C EEPROM.
Each I2C device has an 'address'. To discover this address, we use the following:
root@kali:~/Desktop/BUSSide# time python2.7 i2cdiscover.py /dev/ttyUSB0 +++ Connecting to the BUSSide +++ Initiating comms +++ Sending i2c slave discovery command +++ Reading response from the BUSSide --- Slave address found: 0x50 +++ SUCCESS real 0m0.329s user 0m0.010s sys 0m0.010s
Now that we have I2C slave address, we can dump the EEPROM. In the following example, we are dumping the size of the eeprom which is 64k to the output file 1.bin.
root@kali:~/Desktop/BUSSide# time python2.7 i2cdump.py /dev/ttyUSB0 0x50 65536 1.bin +++ Connecting to the BUSSide +++ Initiating comms +++ Sending I2C dump command +++ Dumping I2C to file... +++ SUCCESS real 0m7.458s user 0m0.557s sys 0m0.576s
Large I2C eeproms might cause problems due to a lack of error connection between the client script and the BUSSide. SPI dumping does not have this problem as error correction is used.
Solution: Keep retrying until you get an error free dump. Or avoid dumping large eeproms.
The BUSSide does not like to be interrupted during an operation. Try to let each operation complete before doing something else. Don't hit ctrl^c to interrupt a client controller.
Although generally unlikely, if the client scripts start reporting timeouts in connecting to the BUSSide, just unplug the BUSSide and plug it back in. Almost all problems can be resolved by turning it off and on again.
If you want to confirm that your BUSSide flashed correctly and is alive, open a serial connection to it with the baudrate of 500,000 in a program like putty. Hit enter a few times. Type 'h' and hit enter. You should get a list of commands that the BUSSide knows.
Although this direct serial connection is available, it is not supported and only available for debugging. Only the client controller scripts are supported.
If you have issues with detecting the JTAG pinout, then try reorganizing the order of the GPIOs. This sometimes helps.