Инструмент akheron
написан на Python и предназначен для обеспечения наглядности межчиповой связи UART, а также для понимания, реверсирования и манипулирования этой связью для определения функциональности устройства (как запланированной, так и непреднамеренной). Это достигается за счет поддержки нескольких режимов работы:
Межчиповая связь через UART по-прежнему является распространенным вариантом конструкции, встречающимся во многих устройствах, и выглядит она примерно так:
+------------+ +------------+
| TXD +-------------------------->+ RXD |
| CHIP A | | CHIP B |
| RXD +<--------------------------+ TXD |
+------------+ +------------+
В этом примере чип A отправляет данные на чип B, отправляя данные на вывод передачи (TX) чипа A, а чип B получает эти входящие данные на свой приемный вывод (RX). Микросхема B отправляет данные со своего вывода передачи (TX) для приема микросхемой A на вывод приема (RX) микросхемы A.
Но что именно они пересылают друг другу?
Если мы сделаем себя физической машиной посередине, мы сможем это выяснить!
Инструмент akheron
предназначен для запуска в системе с двумя последовательными портами (адаптеры USB-последовательный порт подходят, если операционная система системы их поддерживает), выступая в качестве прокси для отправки трафика между этими двумя портами. Что-то вроде этого:
^ + ^ +
| v | v
+---------------------------------+
| |TXD1 RXD1| |TXD2 RXD2| |
| +---------+ +---------+ |
| UART 1 UART 2 |
| |
| Machine-in-the-Middle |
| (running Akheron Proxy) |
| |
+---------------------------------+
Если мы физически обрежем линии связи между чипом A и чипом B, а затем направим их к последовательным портам нашей машины посередине, мы сможем увидеть, что эти чипы отправляют друг другу через UART-связь с akheron
:
+------------+ +------------+
| 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) |
| |
+---------------------------------+
При такой настройке akheron
готов к использованию!
akheron
версии 0.1 — это первая итерация этой попытки, созданная на основе кода, подтверждающего концепцию. Это инструмент командной строки, использующий для взаимодействия стандартный REPL.
Для инструмента akheron
требуется Python 3.6 или новее, и он использует библиотеку pyserial
для взаимодействия с последовательными портами системы. Он был протестирован как на macOS 10.15, так и на Ubuntu 18.04.
pip install -r requirements.txt
Запустить akheron
можно из окна терминала в каталоге верхнего уровня репозитория:
./akheron.py
Во многих системах доступ к последовательным устройствам ограничен. Чтобы избежать запуска akheron
с повышенными привилегиями, убедитесь, что ваша учетная запись принадлежит к той же группе, что и устройство, которое вы хотите использовать. В Linux последовательное устройство, скорее всего, является членом группы dialout
. Добавление вашей учетной записи пользователя в эту группу (например, sudo usermod -a -G dialout $USER
) должно позволить вам получить доступ к устройству. Чтобы увидеть изменения, вам может потребоваться выйти из системы и снова войти в свою учетную запись или, возможно, перезагрузить систему.
После запуска вы увидите баннер и приглашение >
:
$ ./akheron.py
######################################################
Akheron Proxy, UART proxy tool for inter-chip analysis
version 0.1
######################################################
>
В этом приглашении доступен ряд команд, доступ к которым можно получить, набрав help
:
> 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
Вы можете получить дополнительную справку по конкретной команде, набрав help <command>
.
> list
/dev/ttyS0
/dev/ttyUSB0
/dev/ttyUSB1
/dev/ttyUSB2
/dev/ttyUSB3
Вы также можете получить подробный список:
> 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
Следующие шаги перенаправят трафик между портами, «наблюдут» за ним, а затем прекратят пересылку трафика:
> 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".
>
Это тот же поток, но с установленным разделителем начала сообщения 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".
>
Следующие шаги перенаправляют трафик между портами, записывают его в файл, просматривают его, затем останавливают и сбрасывают содержимое перехваченного трафика, а затем останавливают пересылку трафика:
> 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".
>
Следующие шаги показывают пересылку трафика между портами с воспроизведением данных (в данном примере — файла захвата, содержащего одну строку) в следующей последовательности:
0x64 0x61
на 0x99 0x91
и повтора (обратите внимание на замененные данные в выходных данных)Checksum8Modulo256Plus1
предыдущих байтов и воспроизвести его. > 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".
>