Das akheron
-Tool ist in Python geschrieben und soll dazu beitragen, die Kommunikation zwischen UART-Chips sichtbar zu machen und dabei zu helfen, diese Kommunikation zu verstehen, umzukehren und zu manipulieren, um die Gerätefunktionalität (sowohl beabsichtigte als auch unbeabsichtigte) zu erkennen. Dies geschieht durch die Unterstützung mehrerer Betriebsmodi:
Die Inter-Chip-Kommunikation über UART ist immer noch eine gängige Design-Wahl, die in vielen Geräten zu finden ist, und sie sieht in etwa so aus:
+------------+ +------------+
| TXD +-------------------------->+ RXD |
| CHIP A | | CHIP B |
| RXD +<--------------------------+ TXD |
+------------+ +------------+
In diesem Beispiel sendet Chip A Daten an Chip B, indem er Daten über den Sendepin (TX) von Chip A sendet, und Chip B empfängt die eingehenden Daten über seinen Empfangspin (RX). Chip B sendet Daten über seinen Sendepin (TX), um von Chip A am Empfangspin (RX) von Chip A empfangen zu werden.
Aber was genau schicken sie untereinander hin und her?
Wenn wir uns zu einer physischen Maschine in der Mitte machen, können wir es herausfinden!
Das akheron
-Tool ist für die Ausführung auf einem System mit zwei seriellen Ports konzipiert (USB-zu-seriell-Adapter sind in Ordnung, solange das Betriebssystem des Systems sie unterstützt) und fungiert als Proxy für die Übertragung des Datenverkehrs zwischen diesen beiden Ports. Etwas in der Art:
^ + ^ +
| v | v
+---------------------------------+
| |TXD1 RXD1| |TXD2 RXD2| |
| +---------+ +---------+ |
| UART 1 UART 2 |
| |
| Machine-in-the-Middle |
| (running Akheron Proxy) |
| |
+---------------------------------+
Wenn wir die Kommunikationsspuren zwischen Chip A und Chip B physisch durchtrennen und sie dann an die seriellen Ports unserer Machine-in-the-Middle weiterleiten, können wir sehen, was diese Chips einander über ihre UART-Kommunikation mit akheron
senden:
+------------+ +------------+
| TXD +--------+ +------->+ RXD |
| CHIP A | | | | CHIP B |
| RXD +<-+ | | +--+ TXD |
+------------+ | | | | +------------+
| | | |
| v | v
+---------------------------------+
| |TXD1 RXD1| |TXD2 RXD2| |
| +---------+ +---------+ |
| UART 1 UART 2 |
| |
| Machine-in-the-Middle |
| (running Akheron Proxy) |
| |
+---------------------------------+
Mit einem solchen Setup ist akheron
einsatzbereit!
akheron
Version 0.1 ist die erste Iteration dieser Bemühungen und basiert auf Proof-of-Concept-Code. Es handelt sich um ein Befehlszeilentool, das für die Interaktion eine Standard-REPL verwendet.
Das akheron
-Tool erfordert Python 3.6 oder höher und verwendet die pyserial
-Bibliothek für die Verbindung mit den seriellen Ports des Systems. Es wurde sowohl auf macOS 10.15 als auch auf Ubuntu 18.04 getestet.
pip install -r requirements.txt
Sie können akheron
über ein Terminalfenster im obersten Verzeichnis des Repos starten:
./akheron.py
Auf vielen Systemen ist der Zugriff auf serielle Geräte eingeschränkt. Um zu vermeiden, dass akheron
mit erhöhten Rechten ausgeführt wird, stellen Sie sicher, dass Ihr Benutzerkonto zur gleichen Gruppe gehört wie das Gerät, das Sie verwenden möchten. Unter Linux ist das serielle Gerät wahrscheinlich Mitglied der dialout
Gruppe. Wenn Sie Ihr Benutzerkonto zu dieser Gruppe hinzufügen (z. B. sudo usermod -a -G dialout $USER
), sollten Sie auf das Gerät zugreifen können. Damit Sie die Änderungen sehen können, müssen Sie sich möglicherweise abmelden und erneut bei Ihrem Konto anmelden oder möglicherweise das System neu starten.
Sobald es ausgeführt wird, sehen Sie ein Banner und eine >
-Eingabeaufforderung:
$ ./akheron.py
######################################################
Akheron Proxy, UART proxy tool for inter-chip analysis
version 0.1
######################################################
>
An dieser Eingabeaufforderung stehen eine Reihe von Befehlen zur Verfügung, auf die Sie durch Eingabe help
zugreifen können:
> help
Documented commands (type help <topic>):
========================================
capturedump checksumget delimset portget replaceset stop
capturestart checksumset help portset replay watch
capturestop delimget list replaceget start
Undocumented commands:
======================
exit quit version
Sie können weitere Hilfe zu einem bestimmten Befehl erhalten, indem Sie help <command>
eingeben.
> list
/dev/ttyS0
/dev/ttyUSB0
/dev/ttyUSB1
/dev/ttyUSB2
/dev/ttyUSB3
Sie können auch eine ausführliche Auflistung erhalten:
> list -v
/dev/ttyS0
desc: ttyS0
hwid: PNP0501
/dev/ttyUSB0
desc: Quad RS232-HS
hwid: USB VID:PID=0403:6011 LOCATION=1-1:1.0
/dev/ttyUSB1
desc: Quad RS232-HS
hwid: USB VID:PID=0403:6011 LOCATION=1-1:1.1
/dev/ttyUSB2
desc: Quad RS232-HS
hwid: USB VID:PID=0403:6011 LOCATION=1-1:1.2
/dev/ttyUSB3
desc: Quad RS232-HS
hwid: USB VID:PID=0403:6011 LOCATION=1-1:1.3
Mit den folgenden Schritten wird der Datenverkehr zwischen Ports weitergeleitet, „beobachtet“ und dann die Datenweiterleitung gestoppt:
> portset A /dev/ttyUSB1 115200
> portset B /dev/ttyUSB2 115200
> start
Data now PASSING between ports "/dev/ttyUSB1" <-> "/dev/ttyUSB2"...
> watch
Watching data passed between ports. Press CTRL-C to stop...
A -> B: 0x61 0x61 0x73 0x73 0x64 0x64
B -> A: 0x31 0x32 0x33 ^C
Watch mode exited.
> stop
Data now BLOCKED between ports "/dev/ttyUSB1" <-> "/dev/ttyUSB2".
>
Dies ist derselbe Ablauf, jedoch mit einem festgelegten Nachrichtenanfangsbegrenzer von 0x37
:
> portset A /dev/ttyUSB1 115200
> portset B /dev/ttyUSB2 115200
> delimset start 0x37
> start
Data now PASSING between ports "/dev/ttyUSB1" <-> "/dev/ttyUSB2"...
> watch
Watching data passed between ports. Press CTRL-C to stop...
A -> B: 0x37 0x71 0x77 0x65 0x65 0x72
0x37 0x64 0x66 0x61 0x64
0x37 0x73
0x37 0x68 0x68
B -> A: 0x37 0x6e 0x6d 0x62
0x37 0x69 0x69
A -> B: 0x37 0x61 0x73 0x64 ^C
Watch mode exited.
> stop
Data now BLOCKED between ports "/dev/ttyUSB1" <-> "/dev/ttyUSB2".
>
Mit den folgenden Schritten leiten Sie den Datenverkehr zwischen Ports weiter, erfassen ihn in einer Datei, beobachten ihn, stoppen dann die Erfassungsinhalte, sichern sie und stoppen dann die Datenverkehrsweiterleitung:
> portset A /dev/ttyUSB1 115200
> portset B /dev/ttyUSB2 115200
> start
Data now PASSING between ports "/dev/ttyUSB1" <-> "/dev/ttyUSB2"...
> capturestart mycap.out
Saving captured traffic to "mycap.out"...
> watch
Watching data passed between ports. Press CTRL-C to stop...
A -> B: 0x31 0x32 0x33
B -> A: 0x33 0x32 0x31
A -> B: 0x20 0x20 0x20
B -> A: 0x36 0x36 0x37 0x38 0x39 ^C
Watch mode exited.
> capturestop
Capture stopped
> capturedump mycap.out
1: A -> B: 0x31 0x32 0x33
2: B -> A: 0x33 0x32 0x31
3: A -> B: 0x20 0x20 0x20
4: B -> A: 0x36 0x36 0x37 0x38 0x39
> stop
Data now BLOCKED between ports "/dev/ttyUSB1" <-> "/dev/ttyUSB2".
>
Die folgenden Schritte zeigen die Weiterleitung des Datenverkehrs zwischen Ports mit der Wiedergabe von Daten (in diesem Beispiel eine Capture-Datei, die eine einzelne Zeile enthält) in dieser Reihenfolge:
0x64 0x61
-Sequenzen mit 0x99 0x91
auszutauschen und erneut abzuspielen (beachten Sie die ersetzten Daten in der Ausgabe).Checksum8Modulo256Plus1
der vorhergehenden Bytes zu aktualisieren und erneut abzuspielen > portset A /dev/ttyUSB1 115200
> portset B /dev/ttyUSB2 115200
> start
Data now PASSING between ports "/dev/ttyUSB1" <-> "/dev/ttyUSB2"...
> replay /tmp/aaa
Replaying data from A -> B, press CTRL-C to exit watch mode...
A -> B: 0x61 0x73 0x64 0x61 0x73 0x64 ^C
Watch mode exited.
> replaceset A 0x64 0x61 -> 0x99 0x91
> replaceget
Replace port A pattern X -> pattern Y:
0x64 0x61 -> 0x99 0x91
Replace port B pattern X -> pattern Y:
> replay /tmp/aaa
Replaying data from A -> B, press CTRL-C to exit watch mode...
A -> B: 0x61 0x73 0x99 0x91 0x73 0x64 ^C
Watch mode exited.
> checksumset A 3
> checksumget
Replace on port A using checksum 'Checksum8Modulo256Plus1'
No replace checksum specified on port B
> replay /tmp/aaa
Replaying data from A -> B, press CTRL-C to exit watch mode...
A -> B: 0x61 0x73 0x99 0x91 0x73 0x72 ^C
Watch mode exited.
> stop
Data now BLOCKED between ports "/dev/ttyUSB1" <-> "/dev/ttyUSB2".
>