This is the 4th part of our IoT blog series. So before we get into reverse engineering of I2C protocol, let’s dive deep into understanding of I2C protocol.


So what is I2C?

I2C (Inter-integrated Circuit protocol) a hardware protocol designed to allow multiple, slave integrated circuits to communicate with one or more master. It uses two bidirectional open-drain lines, Serial Data Line (SDA) and Serial Clock Line (SCL), pulled up with resistors. Generally voltages used are +5 V or +3.3 V.

It was developed by Philips Semiconductors over 20 years ago and has extensive specific use and general purpose devices. It provides a simple way to talk between IC’s by using minimum number of pins.


Where can I find I2C communication happening?

Typical I2C is used to communicate between two microcontrollers.

To store firmware to an I2C EEPROM, where you can use your favourite microcontroller to read and write data, these EEPROM chips of various size use a simple I2C communication.

Reading configuration data from SPD EEPROMs on SDRAM and other tacked PC boards.

ADXL345 a very commonly used accelerometer sensor uses I2C protocol.

If you are short of GPIO pins to connect to your 16×2 Char LCD, I2C LCD1602 Controller can be very handy. Driver chip SSD1306 on OLED display, communicates via I2C. Commonly used digital temperature sensor MCP9808 also uses I2C. These are few of many endless applications.


I2C protocol in detail:


Features of I2C Bus:

  • In I2C only two buses for communication, serial data bus (SDA) and serial clock bus (SCL).
  • There is a master and slave relationships in I2C, where the communication is initiated by the master.
  • Each slave in I2C bus is software addressable by a unique address, this unique address is used by the master to communicate with a particular slave.
  • The I2C bus provides the ability of the arbitration and collision detection.


Start and Stop Condition:

The default state of SDA and SCL line are high. When the master wishes to talk to a slave it begins by issuing a start sequence on the I2C bus. The I2C bus is considered busy after the assertion of the START bit. A start sequence is one of two special sequences defined for the I2C bus, the other is the stop sequence. The start sequence and stop sequence are the only cases where the SDA (data line) is allowed to change while the SCL (clock line) is high. The start and stop sequences mark the beginning and end of a transaction with the slave device.


Start-Stop Condition.


Clock diagram:

Address and Data Frame


Basic I2C communication transfers 8 bits or bytes, where each I2C slave device has a 7-bit unique address on the bus. Some devices have fixed I2C address while others have few address lines which determine lower bits of the I2C address. This makes it very easy to have all I2C devices on the bus with unique I2C address. There are also devices which have 10-bit address depending on the specification.

7-bit address represents bits 7 to 1 (A0 to A6 from the below image) while bit 0 (R/W from the below image) is used to signal reading from or writing to the device. If bit 0 (in the address byte) is set to 1 then the master device will read from the slave I2C device.

Master device needs no address since it generates the clock (via SCL) and addresses individual I2C slave devices.

Address Frame

Data Frame:

Data is transferred in sequences of 8 bits. The bits are placed on the SDA (data line) line starting with the MSB (Most Significant Bit). The SCL (clock line) line is then pulsed high, then low. For every 8 bits transferred, the device receiving the data sends back an acknowledge bit, so there are actually 9 SCL clock pulses to transfer each 8 bit byte of data. If the receiving device sends back a low ACK bit, then it has received the data and is ready to accept another byte. If it sends back a high then it is indicating it cannot accept any further data and the master should terminate the transfer by sending a stop sequence.

Data Frame

Read/Write command:

Commands for Read are as follows: If we transmit 1010000[0] / A0 to the slave chip, it means it’s a write command, followed by address and data.

And if we transmit 1010000[1]/A1 to the slave chip, it means it’s a read command. 24LC256 contains an address counter that maintains the address of the last word accessed, internally incremented by ‘1’. Therefore, if the previous read access was to address n (n is any legal address), the next current address read operation would access data from address n + 1.


I2C is the 8-bit serial bidirectional communication, there are following speed mode in I2C.

MODE                          SPEED
Standard-mode 100 kbit/s
Fast-mode 400 kbit/s
Fast-mode Plus 1 Mbit/s
High-speed mode 3.4 Mbit/s

 Security analysis:

IoT products have EEPROMs where the microcontroller stores important links, keys or maybe the whole firmware. An example of Electronic Voting Machine can be taken into account, Security Analysis of India’s EVM’s was done by Hari K. Prasad where two EEPROM chips where used for non-volatile storage of vote data. I2C protocol was implemented between EEPROM and CPU. An attacker can simply take the EVM after the election and before the counting and tamper with the EEPROM chip.


Tools used for sniffing and hacking:

Tool1: CH341a

Let’s consider we have a micro controller which stores plain text password on an I2C EEPROM. There are various method to analyse that chip.

1) Static analysis
  • Extracting data from I2C EEPROM chip using CH341a.
    Let’s assume you have successfully de-soldered the EEPROM chip from the PCB and attached on CH341a EEPROM reader. After dumping the data it using CH341a programmer you should see the data in such a form

We can distinctly make out that ‘mohammedpota’ as a readable string and d399f031b5f3d5ecc7658694f1f6135d can be some important data. Let’s not get into what that data means since we are trying to understand how to use the tool.

Similarly, in some cases, we can dump the whole firmware from I2C EEPROM memories.

Tool2: Saleae Logic Analyzer

2) Dynamic analysis
  • Sniffing I2C communication using Saleae Logic Analyzer.
    Well this is a separate blog post and click here for more details —-> Logic analyses

Saleae Logic analyzer (LA) has similar but very few functionalities of an Oscilloscope.  Similar to oscilloscope, an LA is a tool for examining electrical waveforms. An oscilloscope is used to view analog waveforms with a continuously varying voltage, whereas a logic analyzer displays digital waveforms whose value is either 0 or 1.

Let’s take a quick example here. Pick a device where I2C communication is already established. If you don’t have such a device make your own prototype with the help of this link

Connect your Saleae logic analyzer to you laptop via USB cable. If you have a Saleae Logic 8 that means you have 8 channel max sampling rate is reduced to 100 MS/sec.

Note: Saleae recommends 4x oversampling when capturing a signal.


Wiring between product/prototype and LA:

SCL and SDA of the product/prototype will be connected to channel 0 and channel 1 of LA. GND (ground) of product/prototype will be connected to GND of LA.

Once you are done with the wiring you can start the Logic software on your laptop. Click on Analyzers (+) on the right side and select I2C. A pop up box will appear where you need to set the appropriate channel numbers to SDA and SCL. Click on SAVE and you are good to go!

Before you click on simulation make sure that you have set the correct Sampling rate.

Tool3: Bus Pirate

What is a bus pirate?????

Well, it’s a flexible electronic device that interfaces with low-level communication buses and has the ability to program various microcontrollers, in other words, it’s a multi-tool that talks to electronic stuff.

Let’s take an example of EEPROM chip (24LC256) and connect with your bus pirate.

Firstly, let’s understand the datasheet ( of this EEPROM.

EEPROM memory size:  Page 1 of this datasheet mentions the size of EEPROM and operational voltage range.

EEPROM Pinouts: The package type of my chip is DIP.

Pinout’s of DIP package IC


I am using Bus pirate v4.0 with firmware version 7.0 on Linux terminal make sure if you have the same versions and tools. If not just keep an eye on all the options appearing and click accordingly. 😀


  1. Interface with Bus Pirate
  • Mount the EEPROM chip on the breadboard.
  • Connect buspirate with the chip using jumper cables. Notice the notch on the chip for pin numbering, pin1 is on the left of the notch.


On Bus Pirate side                             On EEPROM side

  • BusPirtate MOSI            ————  SDA (5)
  • BusPirtate CLK               ————  SCL (6)
  • BusPirtate 5.0V/VPU    ———— Vcc (8)
  • BusPirtate GND              ———— GND, WP (4,7)


So far we have successfully wired Bus pirate with 24LC256 I2C EEPROM chip. 😀

  1. Connect the bus pirate to the laptop.
  2. Identify the serial port of buspirate by typing the following command in the terminal
  3. ls /dev/tty and press tab
  4. Open minicom by typing :
    1. $ sudo minicom –s in the terminal
    2. $ minicom -D <dev_file_path> -b <baudrate>
  • Ex: $ minimum -D /dev/ttyUSB0 -b 115200
  1. Go to Serial port setup, set the correct serial device and set the baud rate as 115200

This Baudrate setting is for communication between Laptop and Bus pirate

  1. Steps for setting up buspirate in I2C mode.
  • After setting up minicom correctly press Exit
  • Press m to select I2C
  • HiZ>m # View the Mode menu
  • (1)>4 # Select I2c mode
  • (1)>2 # Choose Hardware (This option is new in BP V4)
  • (1)>3 # Select ~1 Mhz clock frequency
  • I2C>W  # Switch the power supply ON
  • I2C>P # Switch the Pull up resistors ON
  • I2C>v # View the Pins status

We already saw what A0 (write) and A1 (read) commands are for.

  1. Using the control byte from lab 1 we need to type [0xA0] to write the data followed by 16 bit address i.e [0 0] and then data. In this case we are entering [0x70 0xaa and 0xbb]

Command: I2C>[0xA0 0 0 0x70 0xaa 0xbb]

  • I2C START CONDITION<<<I2C start condition
  • WRITE: 0xA0 GOT ACK: YES<<<24LC- write address
  • WRITE: 0x00 GOT ACK: YES<<<write address byte 1
  • WRITE: 0x00 GOT ACK: YES<<<write address byte 2
  • WRITE: 0x70 GOT ACK: YES<<<3 values to write
  • I2C STOP BIT<<<I2C stop condition
  1. We type [0xA0] followed by 16 bit address i.e [0 0] to set the pointer at that location

Command: I2C>[0xA0 0 0]

  • I2C START CONDITION<<<I2C start condition
  • WRITE: 0xA0 GOT ACK: YES<<<24AA- write address
  • WRITE: 0x00 GOT ACK: YES<<<write address byte 1
  • WRITE: 0x00 GOT ACK: YES<<<write address byte 2
  • I2C STOP BIT <<<I2C stop condition
  1. Using the control byte from lab 1 we need to type [0xA1] to read the data followed by r:3 where r is ‘read’ and 3 is the bytes to be read.

Command: I2C>[0xA1 r:3]

  • I2C START CONDITION <<<I2C start condition
  • WRITE: 0xA1 GOT ACK: YES<<<24AA- read address
  • BULK READ 0x03 BYTES:<<<read 3 values
  • 0x70 0xAA 0xBB
  • I2C STOP BIT<<<I2C stop condition

  1. Steps for exiting minicom:
  • Press CTRL-A followed by Z
  • Press X (release Z first and then press X)
  • Press Enter on Yes/No

Is this enough for me to become an IoT hacker?


This is one of the initial steps for reverse engineering from the hardware perspective. There are many more protocols to learn. Stay tuned with our IoT blog series and learn how to use these basics tools.

A famous hacker once said

“If you‘re hacking and you know it, clap your hands!!”

😀 😀



-Mohammed Pota.

Leave a Reply

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

3 × 3 =