doc: improve installation

This commit is contained in:
King Kévin 2022-06-21 11:09:39 +02:00
parent dabf167b5f
commit 7531f02225
1 changed files with 208 additions and 93 deletions

301
README.md
View File

@ -9,7 +9,7 @@ purpose
HDMI is mainly used to transfer audio and video, but also offers a number of additional features (e.g. HPD, CEC, HEAC, MHL).
This increases the attack surface, and since the security of their implement in embedded devices is far from ideal, an attacker could exploit them and inject malicious code.
Now your unsuspicious video equipment is compromised and threatens your IT/network security.
And your monitor could then in turn hack back any other equipment connected to it.
And your monitor could then in turn hack back any other device connected to it.
For example, let's imagine you invite an external guest for a presentation inside your company.
You offer to connect to a video-projector so he can show his slides.
@ -23,29 +23,30 @@ It is based on the research of Pierre-Michel Ricordel and José Lopes Esteves fr
usage
=====
You first have to copy the Extended Display Identification Data (EDID) information of the equipment to protect.
The HDMI firewall comes with a generic HD profile, but this might not correspond to the capabilities of your monitor.
The resulting image could be distorted, or completely missing.
Thus, you first have to copy the Extended Display Identification Data (EDID) information of the equipment to protect.
This data includes information such as the supported resolutions.
You can read it out using the I²C-based Display Data Channel (DDC) interface.
Write the EDID data on the EEPROM of the HDMI firewall, and break the tab using pliers to enable write protection.
Copy this EDID data on the EEPROM of the HDMI firewall, and break the tab using pliers to enable write protection.
It will prevent attackers from injecting any malicious payload.
This only has to be done once (per monitor to protect).
See installation for detailed instruction on copied the EDID.
See __installation__ for detailed instruction on copying the EDID.
Now plug in the HDMI firewall in the monitor to be protected.
Plug in the HDMI firewall in the monitor to be protected.
Connect the cable going to the untrusted device on the HDMI firewall.
Your equipment is now protected.
To re-write the EEPROM of the HDMI firewall in case you want to protect another monitor, you can re-disable write protection by putting a solder blob across the two pads marked WP.
By default, the 5V supplied by the monitor are forwarded to the device.
By default, the 5V supplied by the device is forwarded to the monitor.
To further reduce the attack surface, you can disable this by cutting the trace between the two pads marked 5V.
The risk is that some monitors rely on this signal to detect when a device is plugged in.
installation
============
For the HDMI firewall to be used, it needs a local copy of the EDID data from the monitor to protect.
For the HDMI firewall to be used correctly, it needs a copy of the EDID data from the monitor to protect.
These instructions are for Linux.
For Windows see the instructions provided in the [original research slides](https://www.sstic.org/media/SSTIC2021/SSTIC-actes/un_pare_feu_pour_le_hdmi/SSTIC2021-Slides-un_pare_feu_pour_le_hdmi-lopes-esteves_ricordel.pdf) (untested).
@ -53,30 +54,50 @@ For Windows see the instructions provided in the [original research slides](http
Install tools to read/write I²C devices:
- for Debian-based distributions
~~~
sudo apt install i2c-tools
~~~
- for Arch-based distributions
~~~
sudo pacman -S i2c-tools
~~~
To make the I²C buses user accessible (under /dev/i2c-*):
Make the I²C buses user accessible (under /dev/i2c-*):
~~~
sudo modprobe i2c-dev
~~~
To figure out which I²C device corresponds to your HDMI port, simply test them all.
There might be a better way, but I don't know it.
Disconnect everything from the HDMI port, and scan for devices on the I²C bus (0 corresponds to the bus number, at the end of /dev/i2c-0):
Now we have to figure out which I²C bus corresponds to the HDMI port.
First list the available buses:
~~~
sudo i2cdetect -y 0
sudo i2cdetect -l
~~~
Since nothing is connected, no device should be detected:
You should see something like this:
~~~
i2c-0 smbus SMBus PIIX4 adapter port 0 at 0b00 SMBus adapter
i2c-1 smbus SMBus PIIX4 adapter port 2 at 0b00 SMBus adapter
i2c-2 smbus SMBus PIIX4 adapter port 1 at 0b20 SMBus adapter
i2c-3 i2c AMDGPU DM i2c hw bus 0 I2C adapter
i2c-4 i2c AMDGPU DM i2c hw bus 1 I2C adapter
i2c-5 i2c AMDGPU DM i2c hw bus 2 I2C adapter
i2c-6 i2c AMDGPU DM i2c hw bus 3 I2C adapter
i2c-7 i2c AMDGPU DM aux hw bus 0 I2C adapter
i2c-8 i2c AMDGPU DM aux hw bus 2 I2C adapter
i2c-9 i2c AMDGPU DM aux hw bus 3 I2C adapter
i2c-10 i2c DPMST I2C adapter
i2c-11 i2c DPMST I2C adapter
~~~
Candidate buses are 3 to 9, used by the GPU (number after i2c- in the first column).
Disconnect everything from the HDMI port, and scan for devices on each I²C bus (replace BUS with the bus number):
~~~
sudo i2cdetect -y BUS
~~~
Since nothing is connected, no device should be detected, and the output should look like this:
~~~
0 1 2 3 4 5 6 7 8 9 a b c d e f
@ -91,7 +112,7 @@ Since nothing is connected, no device should be detected:
~~~
Now connect the HDMI firewall on the device side to your HDMI port and re-scan for devices.
If you see the following result, you found the I²C bus of the HDMI port (in this example it is bus 4).
If you see the following result, you found the I²C bus of the HDMI port.
Else continue with the next bus.
~~~
@ -107,20 +128,183 @@ Else continue with the next bus.
~~~
Now connect the monitor you want to copy the EDID from directly to the HDMI port.
We will use the [EDID-RW](https://github.com/bulletmark/edid-rw) tool to make the copy.
We will use the EEPROM module to dump the EDID:
~~~
sudo modprobe eeprom
~~~
Display the EDID overview and ensure the Model Name corresponds to your monitor (here a DELL 2408WFP on bus number 4):
~~~
ddcmon 4
Checksum: OK
EDID Version: 1.3
Manufacturer ID: DEL
Model Number: 0xA02C
Model Name: DELL 2408WFP
Serial Number: G286H9642GLS
Manufacture Time: 2009-W23
Display Input: Digital
Monitor Size (cm): 52x32
Gamma Factor: 2.20
DPMS Modes: Active Off, Suspend, Standby
Color Mode: RGB Multicolor
Vertical Sync (Hz): 56-76
Horizontal Sync (kHz): 30-83
Max Pixel Clock (MHz): 170
Timing: 640x480 @ 60 Hz
Timing: 640x480 @ 75 Hz
Timing: 720x400 @ 70 Hz
Timing: 800x600 @ 60 Hz
Timing: 800x600 @ 72 Hz
Timing: 800x600 @ 75 Hz
Timing: 1024x768 @ 87 Hz (interlaced)
Timing: 1024x768 @ 75 Hz
Timing: 1152x864 @ 75 Hz
Timing: 1280x1024 @ 60 Hz
Timing: 1600x1200 @ 60 Hz
Timing: 1920x1200 @ 60 Hz
~~~
Dump the complete EDID (replace BUS with corresponding bus number):
~~~
cat /sys/bus/i2c/devices/BUS-0050/eeprom > edid.bin
~~~
Connect the HDMI firewall device port to your HDMI output.
Ensure Write Protect is disabled (by default until the tab is broken, and no solder across the WP pads is added).
**WARNING**: writing data to the wrong I²C bus could permanently damage your computer or other devices.
Free the I²C access to the EEPROM:
~~~
sudo modprobe -r eeprom
~~~
Write the extracted EDID data to the HDMI firewall (replace BUS with corresponding bus number):
~~~
for addr in `seq 0 255`; do echo $addr; sudo i2cset -y BUS 0x50 $addr 0x`xxd -p -l 1 -s $addr edid.bin`; done
~~~
To verify the data has been written correctly, compare original data with the one on the EEPROM:
~~~
# display original dumped data
xxd -g 1 edid.bin
# display data written on EEPROM
sudo i2cdump -y BUS 0x50
~~~
Once writing the EDID to the HDMI firewall memory succeeded, break the tab using pliers to write protect the memory.
This will prevent attackers from storing a malicious payload.
You can now use the HDMI firewall (only for this monitor).
Feel free to put shrink tube or tape around the HDMI firewall.
This will prevent the electronics from getting shorted when entering in contact with neighbouring metal objects.
troubleshooting
===============
If the monitor does not detect the device or does not display anything (but should), try to re-enable the 5V forward (as per default) by putting solder across the 5V pads.
In the HDMI cable there is a 5V line, with power provided by the device.
In our case we use it is to power the HDMI firewall memory.
Forwarding it to the monitor can be disabled by cutting the trace across the 5V pads.
If the device does not detect the monitor or HDMI firewall, or writing the EDID data to the HDMI firewall fails (better indication), try connecting the HDMI firewall with another (better quality) HDMI cable.
tips
====
xrandr
------
xrandr can also dump the EDID information:
~~~
xrandr --properties
~~~
sysfs
-----
sysfs also exposes the raw EDID information (change path accordingly):
~~~
edid-decode /sys/devices/pci0000:00/0000:00:08.1/0000:05:00.0/drm/card0/card0-HDMI-A-1/edid
~~~
I²C non-root
------------
to access I²C buses as non-root:
~~~
# add UDEV rule
cat << EOF | sudo tee /etc/udev/rules.d/20-i2c.rules
KERNEL=="i2c-[0-9]*", GROUP="i2c"
EOF
# give user access to devices (you have to re-login in for the change to take effect)
sudo groupadd i2c
sudo gpasswd -a $USER i2c
# reload rules
sudo udevadm control --reload-rules
sudo udevadm trigger
~~~
erase
-----
If you want to clear the HDMI firewall memory (for usage with another monitor):
~~~
for page in `seq 50 57`; do echo 0x$page; for addr in `seq 0 255`; do echo $addr; sudo i2cset -y BUS 0x$page $addr 0xff; done; done
~~~
edid-decode
-----------
To parse and display the complete EDID information, you can use edid-decode.
- for Debian-based distributions
~~~
sudo apt-get install edid-decode
~~~
- for Arch-based distributions
~~~
pikaur -S edid-decode-git
~~~
To view the dumped EDID information:
~~~
edid-decode edid.bin
~~~
edid-rw
-------
[EDID-RW](https://github.com/bulletmark/edid-rw) makes reading and writing EDID a bit easier.
Install these prerequisites:
- for Debian-based distributions
~~~
sudo apt-get install python3-smbus edid-decode
sudo apt-get install python3-smbus
~~~
- for Arch-based distributions
~~~
pikaur -S python-smbus-git edid-decode-git
pikaur -S python-smbus-git
~~~
Get EDID-RW:
@ -136,15 +320,7 @@ To retrieve the EDID data from the monitor you connected:
sudo ./edid-rw 4 > edid.bin
~~~
To view the decoded EDID data (feel free to adjust it):
~~~
edid-decode edid.bin
~~~
Now connect the HDMI firewall device port to the your HDMI output.
Ensure Write Protect is disabled (by default until the tab is broken, and no solder across the WP pads is added).
Write the extracted EDID data to the HDMI firewall:
To write the dumped EDID on the HDMI firewall memory:
~~~
sudo ./edid-rw -w 4 < edid.bin
@ -156,67 +332,6 @@ To verify of the data has been written correctly, read it back:
sudo ./edid-rw 4 | edid-decode
~~~
If the EDID information could not be decoded, the data write was unsuccessful.
See troubleshooting for possible solutions.
Once writing the EDID to the HDMI firewall memory succeeded, break the tab using pliers to write protect the memory.
You can now use the HDMI firewall (only for this monitor).
Fell free to put shrink tube around the HDMI firewall (and shrink it using hot air at 200°C, or carefully using a lighter).
This will prevent the electronics from getting shorted when entering in contact with neighbouring metal objects.
troubleshooting
===============
If the monitor does not detect the device or does not display anything (but should), try to re-enable the 5V forward (as per default) by putting solder across the 5V pads.
In the HDMI cable there is a 5V line, with power provided by the monitor.
In our case we use it is to power the HDMI firewall memory.
Forwarding it to the device can be disabled by cutting the trace across the 5V pads.
If the device does not detect the monitor (actually the HDMI firewall), or writing the EDID data to the HDMI firewall fails (better indication), try connecting the HDMI firewall with another (better quality) HDMI cable.
Some cheap cables have a very thin 5V cable, enough to detect connected devices, but not to power the EEPROM for write operations.
tips
====
xrandr
------
xrandr can also dump the EDID information:
~~~
xrandr --properties
~~~
sysfs also exposes the raw EDID information:
~~~
edid-decode /sys/devices/pci0000:00/0000:00:08.1/0000:05:00.0/drm/card0/card0-HDMI-A-1/edid
~~~
to access I²C devices as non-root:
~~~
# add UDEV rule
cat << EOF | sudo tee /etc/udev/rules.d/20-i2c.rules
KERNEL=="i2c-[0-9]*", GROUP="i2c"
EOF
# give user access to devices
sudo groupadd i2c
sudo gpasswd -a $USER i2c
# reload rules
sudo udevadm control --reload-rules
sudo udevadm trigger
~~~
erase
-----
If you want to clear the HDMI firewall memory (for usage with another monitor):
~~~
for page in `seq 50 57`; do echo 0x$page; for addr in `seq 0 255`; do echo $addr; sudo i2cset -y 4 0x$page $addr 0xff; done; done
~~~
limitations
===========