Introduction
Hardware hacking is one of those topics that I always had a great interest in, but almost always lacked the free time and equipment to fiddle with.
You may think that it has a much more perpendicular learning curve than programing or any other security-related research, so, hopefully, this article can disperse those thoughts and it can help to start your own research.
This is the initial post of a series where I will demonstrate and explain some of the fundamentals of hardware hacking recon and internals of wire protocols. I assume the reader has basic programming and electronics skills.
Motivation
I won’t describe the tedious job of building a lab, but would like to provide a short list of tools and devices that I use. Buying all of these should not cost you more than 200USD.
Here’s the equipment you should have:
- A multimeter. I recommend one with an auto-ranging feature and a replaceable fuse (pretty cheap to fix if you manage to fry your device).
- A good soldering iron. Make sure to get one with temperature controls and replaceable tips. It’s best to avoid cheap uncontrolled irons. As for the solder, use a 0.5 mm spool.
- Hand tools, such as a screwdriver, wire cutter and nose pliers.
- Last but not least, you’ll need some programmable single-board microcontrollers. There are dozens of Arduino as well as cheap single-board RasperyPi models on the market.
- You will also need a breadboard, resistors, jumpers, capacitors, and LEDs. Since it’s hard to know exactly what you might need, I recommend getting a starter kit from a vendor, for example, an Arduino Starter Kit, and extending it on demand.
You will also need some specific tools for hardware hacking:
- a desoldering pump
- a flux pen
- pry tools
- helping hands
And some tools for interfacing, which is where we might easily go over the original 200USD budget.
- a USB TTL adapter
- a logic analyzer, a tool used to monitor and decode a wide range of digital signals.
- an oscilloscope, a multimeter on steroids; it can measure and display at least one value over time.
The First Step is Always the Hardest
Let’s start by setting up a simple hardware hacking experiment and capture I2C traffic directly from the wire. For experimenting and learning, we should use a controlled and familiar environment.
I2C protocol and components
I2C or (eye-squared-C) is a synchronous, multi-master, multi-slave, packet-switched, single-ended, serial communication bus invented in 1982 by Philips Semiconductors. Its good for our use case, as it has the simple two-wire SDA (Serial Data line) and SDC (Serial clock line) implementation.
A typical setup looks like this:
This design supports +5v and +3.3V. I will use the 3.3 V version with BeagleBone Black as the master and an Arduino and a Trinket as slaves.
Components used in this experiment:
- BeagleBoard.org – black
- Adafruit Trinket – Mini Microcontroller – 5V Logic
- Arduino – ArduinoBoardLeonardo
- Saleae Logic 8 & BitMagic Basic Logic Analyzer
- Some jumper wire
- A solderless breadboard
I want to get from here:
To here:
And get those LEDs blinking
And capture the I2C message from the wire:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
write to 0x30 ack data: 0x00 read to 0x30 ack data: 0x00 write to 0x30 ack data: 0x01 read to 0x30 ack data: 0x00 write to 0x30 ack data: 0x02 read to 0x30 ack data: 0x01 write to 0x30 ack data: 0x03 read to 0x30 ack data: 0x00 write to 0x34 ack data: 0x00 read to 0x34 ack data: 0x00 write to 0x34 ack data: 0x01 read to 0x34 ack data: 0x00 write to 0x34 ack data: 0x02 read to 0x34 ack data: 0x01 write to 0x34 ack data: 0x03 read to 0x34 ack data: 0x00 |
The Setup of My Lab Environment
Software
Software component | Description |
Arduino IDE | Integrated development environment with support for Arduino and compatible boards. |
TinyWire/TinyWireS at rollback · rambo/TinyWire | A modified TinyWire lib version that supports I2C slave functions on ATtiny85 based devices. |
Adafruit-PlatformDetect | Adafruit latest python support library. |
Arduino IDE Setup
A full description of the Adafruit Arduino IDE setup is available here.
The short version: add the following URL https://adafruit.github.io/arduino-board-index/package_adafruit_index.json as an Additional Boards Manager URL on the preference page.
USB cables
I own a huge number of micro USB, mini USB, and other USB cables. But almost half of them are worthless because the data cables are either missing (i.e. they are only for charging) or torn. All of my short cables turned out to be only suitable for charging.
I also suffered some failures because of missing or lousy insulation, as well as some of my USB hubs not cooperating for flashing Trinket firmware.
Test your cables and hubs one by one to find out which are the most suitable to work with.
Arduino Leonardo
I initially started writing my sample codes on a Trinket described in the next section, but quickly realized that it’s too limited to be used as a learning device. Thankfully, I found a spare Arduino Leonardo in my drawer. Leonardo has significant advantages with its more complete USB serial support and it’s also less picky about the USB cables than my Trinket. All the libraries are working as expected on this board.
My app on Leonardo acts as an I2C slave listening on 0x30. Whenever it gets the number 2, it switches the LED on, otherwise it switches it off. If the I2C master asks, the board can tell the state of the LED.
The wiring is also easy, as the SDA and SCL pins are clearly indicated on the board.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
/// Arduino Leonardo #include <Wire.h> |
Trinket @I2C 0x34
When I initially started working on the Trinket code, I thought that I was using the standard Arduino – Wire lib. But I quickly realized that something was odd when my first build failed with strange missing functions and missing parameter messages.
When I enabled the Adafruit board support described in the section on the Arduino IDE setup, it also installed a device-specific and horribly incomplete Wire lib. Namely, the Trinket’s I2C lib TinyWireM/README.md at master · adafruit/TinyWireM .
While the standard lib support is somewhat complete, the TinyWireM lacks the I2C slave support altogether. So technically, you can only use the Trinket as an I2C master. Fortunately, someone ran into this pitfall earlier and created the GitHub – rambo/TinyWire: My modifications to TinyWire Arduino libs lib.
The TinyWireS lib was almost perfect, it lacked only the proper ATtiny85 pinout support data.
Trinket itself lacks serial port support, so you cannot really debug your code or print any message to your console. It’s also a bit cumbersome to use your only LED for debugging as well as the target function.
After some investigation and experimenting, I was able to build a working I2C app on my little Trinket.
My app is hard wired to use the address 0x34 and it sets the integrated LED pin to high and switches it on if it receives the number 2 via the I2C channel.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
/* add TinyWireS as the Adafruit wire lib lacks the I2C slave implementation https://github.com/rambo/TinyWire/tree/rollback/TinyWireS |
BeagleBone Black I2C Master
In my setup, BeagleBone acts as the I2C master, so it controls the clock and requests data from 0x30 and 0x34. It took me some time to figure out which I2C bus I should use, as my first app was listening to 0x34, but whenever I sent a message to the bus 0 with chip address 0x34, I did not get anything back.
My first suspect was my Arduino code and, after 2 hours of not getting anywhere, I tested bus 2 and everything worked. Later, I also found that bus 0 is not accessible via pins: Beaglebone Black I2C Tutorial | Microcontroller Tutorials
Wrong bus:
1 2 3 4 5 6 7 8 9 10 11 |
$ i2cdetect -yf 0 |
And the correct one:
1 2 3 4 5 6 7 8 9 10 11 |
$ i2cdetect -yf 2 |
Standard Linux I2C tools to test
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#!/bin/bash S1=0x30 S2=0x34 |
And my bus scanner Python script:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# python 3 scan_i2c.py # pip3 install "--upgrade adafruit-blinka adafruit-platformdetect" |
So there you have it – a simple setup to start hardware hacking with I2C sniffing!
As the popularity of IoT devices continues to grow, hardware hacking can help IoT owners to understand their gadgets and improve device security. If you haven’t already, read our latest IoT botnet report and stay tuned for more insights from CUJO AI Labs: subscribe to our newsletter and follow CUJO AI Labs on Twitter.
The post Hardware Hacking 101: E01 I2C Sniffing, How to Listen to Your Arduino’s I2C Bus appeared first on CUJO AI.
Article Link: Hardware Hacking 101: E01 I2C Sniffing, How to Listen to Your Arduino's I2C Bus - CUJO AI