Introduction
In this article, we present a Proof of Concept (POC) that demonstrates the capability to overwrite an I2C message during its transmission. This method allows for the alteration or invalidation of any frame or message transmitted over a bus-type protocol. Distinct from traditional Man-In-The-Middle attacks, this approach is effective across the entire bus and is independent of the attacker's physical placement within the network.
The POC specifically targets an I2C serial memory device. It involves requesting a byte of memory from this device and then actively overwriting the returned value while the data is still in transit.
Setup
The experimental setup for this POC is straightforward, consisting of an Arduino connected to a serial memory module via an I2C bus. Below is an image illustrating the breadboard configuration with the two components wired together:
The Arduino is programmed to read memory from the serial memory device. The code for this operation is available here.
The memory reading process occurs in two primary steps:
- Write Phase: The controller initiates a write transaction by sending two bytes. These bytes represent the address from which data will be read.
- Read Phase: Subsequently, the controller initiates a read transaction to retrieve one byte of data from the specified address.
A logic analyzer is used to capture these two I2C frames, as shown in the image below:
- Write Frame: Write 0x50 0x00 0x10
- Read Frame: Read 0x50 0x3C
With this setup, we successfully demonstrate a standard memory read operation. The next step is to detect when the memory module transmits data (in this case, the byte 0x3C) and manipulate the voltage level on the SDA line. This manipulation will alter the value received by the controller, thus achieving our objective of overwriting the I2C message.
The I2C physical layer
Understanding the basics of the I2C physical layer is crucial to executing this attack. The I2C bus typically consists of two lines: SDA (data line) and SCL (clock line). Both lines are pulled high to VCC (supply voltage) using pull-up resistors. Nodes communicate by writing on the bus through an Open-Drain output configuration within the I2C transceiver. Here is a simulation of the I2C bus, featuring a simplified circuit.
By default, the bus state is 1 (high). When any node on the bus writes a 0 (low), the voltage level drops below a certain threshold, and as a result, all nodes on the bus interpret this as a 0.
Now, let's explore how to overwrite bits on the line:
- Overwriting with a 0: This is straightforward and involves using an open-collector configuration, akin to standard I2C nodes. The bus state will read as 0, overriding any conflicting signals from other nodes.
- Overwriting with a 1: This is more challenging, if one node (e.g., the serial memory) is sending a 0. Since the voltage is pulled down in an open-drain configuration, to force the bus into a 1 state, we need to create an open-emitter configuration. This setup should have a lower resistance than the sender's open-drain, effectively pulling the line voltage above the threshold and enforcing a 1 state.
Initially, MOSFETs were used to overwrite the SDA voltage level. However, due to their inherent internal resistance and parasitic capacitance, they proved ineffective. Thus, the approach was switched to using transistors.
Here's another simulation demonstrating the overwrite stages in action, showcasing their effectiveness regardless of the current bus state or the data being transmitted.
Attacker Logic Implementation
With the physical mechanisms for overwriting the bus state in place, the next step involves synchronizing with the transmitted frames to timely execute the overwrites. This synchronization is crucial for modifying the message accurately.
Given the high-speed nature and the precision required for this operation, an FPGA (Field-Programmable Gate Array) is utilized instead of a simpler solution like an Arduino. The FPGA's capability to process information rapidly and handle complex operations between each clock pulse makes it ideal for this task.
Here is the Verilog code used in the FPGA. This code specifically targets the read operation at address 0x50 on the I2C bus. Its function is to intercept the read operation and overwrite the byte being read with the value 0x55. This overwriting is a critical part of the POC, demonstrating the ability to manipulate data as it is being transmitted over the I2C bus.
The FPGA's logic is programmed to detect when the memory device initiates a read operation. Upon detection, it intervenes at the precise moment to alter the data being transmitted. This approach exemplifies a sophisticated method of data manipulation in real-time, showcasing the potential vulnerabilities in bus-type communication protocols like I2C.
Assembling the Components and run the Attack
With all the necessary components and logic in place, it's time to integrate them into a functional attack setup. This involves carefully wiring each component to create a cohesive system capable of executing the overwrite attack on the I2C bus.
Below are the images showing the complete setup:
Complete Breadboard Setup:
This image provides an overview of the entire setup, illustrating how each component is connected.
Detailed Breadboard with Labels:
This close-up image of the breadboard highlights specific areas, particularly the output stages, with labels for easier understanding.
Generated Schematic:
To aid in understanding the connections and flow of the setup, here's a schematic diagram.
Arduino Serial Output:
Finally, to confirm that the attack is successful and the byte is indeed being overwritten, here's the Arduino serial output.
These visuals are critical in demonstrating the practical application of the theoretical concepts discussed earlier. They provide a clear representation of how the physical setup is arranged and how the attack functions in a real-world scenario.
Conclusion
This article demonstrates that with the appropriate hardware configuration and precise coding, it is entirely feasible for an attacker to manipulate messages transmitted over an I2C bus. This method underscores a significant vulnerability in bus-type communication protocols, particularly in scenarios where security and data integrity are paramount.
The practical implementation of this attack, using common components like an Arduino, an FPGA, and standard electronic components, highlights the accessibility of such methods to individuals with basic technical skills and resources. It serves as a reminder of the importance of considering physical layer security in system design and the need for robust countermeasures against such vulnerabilities.
In conclusion, while this Proof of Concept (POC) is a powerful demonstration of the ability to intercept and alter data on an I2C bus, it also serves as a call to action for enhanced security measures in communication protocols to protect against such sophisticated attacks.
Comments
Post a Comment