Приветствую, пока у меня идет буйная работа з эмуляциями модемов и прочей сатанинской эзотерикой, я решил разбавить молчание в разделе фрикинга базовой статьей по эксплуатации протокольчика UART, контента этой статьи хватит для того что бы можно было медленно и неуверенно начать свой путь к embedded hardware эксплуатации, если будет понятен интерес со стороны сообщества то можно продвинутся дальше и затронуть JTAG, I2C и SPI в будущем.
Основные линии:
В типичных конфигурациях всегда присутствует один старт-бит (сигнал переходит с высокого уровня на низкий — с положительного напряжения на нулевое или близкое к земле, в соответствии со стандартом TTL, используемым в embedded-устройствах).
Затем следует 5–8 бит данных (или даже 9, если используется режим без бита чётности).
После данных идёт один стоп-бит (сигнал возвращается в высокий уровень — положительное напряжение, такое как 3.3 В или 5 В).
Бит чётности (parity: even, odd или none) иногда добавляют для контроля ошибок передачи.
Всегда первым передаётся младший бит (LSB first).
Передающая сторона UART берёт данные, которые внутри микроконтроллера идут "параллельно" (байт целиком), и превращает их в поток битов — один за другим — и отправляет по линии передачи.
Принимающая сторона UART делает обратное: получает этот поток битов, собирает их обратно в байты и отдаёт процессору.
Иными словами: всё, что выходит из TX одного устройства, приходит в RX другого — именно так они "разговаривают"между собой.
Это простая и очень надёжная схема, именно поэтому UART до сих пор так популярен.
В отличие от сложных шин вроде USB, UART не заботится о пакетах, адресации или подтверждениях (наподобии ACK), данные передаются асинхронно, что делает его простым, но потенциально уязвимым каналом. Этот протокол часто остаётся включённым на готовых устройствах даже в продакшн-прошивках, и частенько дает нам доступ к рут шеллу, сниффингу траффика и общей манипуляций сигналами (можно менять поведении устройства на low level)
Дальше в ход идёт мультиметр, у меня он вот такой, находится на алике без проблем.
Процесс определения такой:
На больших платах или в роутерах можно встретить несколько UART — тогда помогает логический анализатор или JTAGulator, который сам определяет, какие пины активны и на какой скорости идёт обмен.
Прежде мы перейдем к копанию во всей этой шняге, надо пройтись по терминологии что бы мой лексикон не сбивал вас з толку, вот парочка ключевых терминов:
TX <-> RX,
RX <-> TX,
GND <-> GND.
ВНИМАНИЕ - Никогда не подключайте питание от адаптера, чтобы не спалить плату!
Наглядная схема подключения на примере малинки:
Важный параметр это скорость — с ней часто промахиваются новички. Начинаем с 115200 бод, если видим кракозябры - тогда пробуйте 57600, 38400, 9600. Есть даже утилита baudrate.py (baudrate.py -p /dev/ttyUSB0) , которая сама подбирает скорость — экономит время.
Полезные утилиты для доступа к serial console:
Minicom/picocom - https://wiki.emacinc.com/wiki/Getting_Started_With_Minicom
Screen - https://www.cyberciti.biz/faq/unix-linux-apple-osx-bsd-screen-set-baud-rate/
Открываем screen /dev/ttyUSB0 115200 — и если повезло, видим священные строки загрузки ядра или U-Boot. Иногда если успеть нажать пробел то можно попасть в консоль загрузчика. А там можно дать полет творческому мышлению: дампить память, изменять переменные окружения, грузить альтернативный initramfs.
Немного автоматизации
Если в консоли много команд, их можно перебрать скриптом с pySerial: отправляю строку, читаю ответ. Так можно находить скрытые команды быстрее, чем вручную:
После того как вы получили доступ к serial console через UART, можно выдохнуть, самая геморойная часть уже позади.
Можно начать проходится по нашему чек листу:
Для начала рекомендую понаблюдать за логами, просто смотреть что пишет железка:
На многих устройствах, если при старте нажать пробел или Ctrl+C, загрузчик останавливается и даёт командную строку (=>):
Тут можно попробовать:
Тогда пробуй:
Что такое UART
UART (Universal Asynchronous Receiver-Transmitter) — это двухпроводный протокол последовательной передачи данных, который используется почти во всех embedded устройствах.Основные линии:
В типичных конфигурациях всегда присутствует один старт-бит (сигнал переходит с высокого уровня на низкий — с положительного напряжения на нулевое или близкое к земле, в соответствии со стандартом TTL, используемым в embedded-устройствах).
Затем следует 5–8 бит данных (или даже 9, если используется режим без бита чётности).
После данных идёт один стоп-бит (сигнал возвращается в высокий уровень — положительное напряжение, такое как 3.3 В или 5 В).
Бит чётности (parity: even, odd или none) иногда добавляют для контроля ошибок передачи.
Всегда первым передаётся младший бит (LSB first).
- Tx (Transmit) — передача данных (базар)
- Rx (Receive) — приём данных (терпение базара)
- GND (Ground) — общий провод (обязателен для корректной работы) (заземление индивидума кулаком после завершения процедуры обмена)
- (опционально) Vcc — питание, обычно 3.3 В или 5 В, используется для ориентирования на плате, но не подключается при работе с внешним адаптером.
Передающая сторона UART берёт данные, которые внутри микроконтроллера идут "параллельно" (байт целиком), и превращает их в поток битов — один за другим — и отправляет по линии передачи.
Принимающая сторона UART делает обратное: получает этот поток битов, собирает их обратно в байты и отдаёт процессору.
Иными словами: всё, что выходит из TX одного устройства, приходит в RX другого — именно так они "разговаривают"между собой.
- В типичных конфигурациях всегда присутствует один старт-бит (сигнал переходит с высокого уровня на низкий — с положительного напряжения на нулевое или близкое к земле, в соответствии со стандартом TTL, используемым в embedded-устройствах).
- Затем следует 5–8 бит данных (или даже 9, если используется режим без бита чётности).
- После данных идёт один стоп-бит (сигнал возвращается в высокий уровень — положительное напряжение, такое как 3.3 В или 5 В).
- Бит чётности (parity: even, odd или none) иногда добавляют для контроля ошибок передачи.
- Всегда первым передаётся младший бит (LSB first).
Это простая и очень надёжная схема, именно поэтому UART до сих пор так популярен.
В отличие от сложных шин вроде USB, UART не заботится о пакетах, адресации или подтверждениях (наподобии ACK), данные передаются асинхронно, что делает его простым, но потенциально уязвимым каналом. Этот протокол часто остаётся включённым на готовых устройствах даже в продакшн-прошивках, и частенько дает нам доступ к рут шеллу, сниффингу траффика и общей манипуляций сигналами (можно менять поведении устройства на low level)
Как найти пины
Первое, что делаю — открываю корпус и ищу группу из 3–5 пинов. Иногда они подписаны — праздник! Намного чаще такого удовольствия нам архитектор PCB-шки не дает.Дальше в ход идёт мультиметр, у меня он вот такой, находится на алике без проблем.
Процесс определения такой:
- используем мультиметр в режиме прозвонки (continuity mode). Один щуп прикладываем к металлическому корпусу устройства (или к болту, винту, любому корпусному элементу), второй — к подозреваемому пину. Если мультиметр пищит / показывает низкое сопротивление — пин “земля” / GND.
- VCC показывает стабильные 3.3 или 5 В.
- TX выдаёт пульсирующее напряжение при включении устройства (это микроконтроллер "здоровается").
- а оставшийся пин — очевидно RX (еще можно определить по постоянному низкому напряжению).
На больших платах или в роутерах можно встретить несколько UART — тогда помогает логический анализатор или JTAGulator, который сам определяет, какие пины активны и на какой скорости идёт обмен.
Прежде мы перейдем к копанию во всей этой шняге, надо пройтись по терминологии что бы мой лексикон не сбивал вас з толку, вот парочка ключевых терминов:
- Oversample rate — частота оверсэмплинга: 4, 8, 16, 32.
При приёме UART контроллер многократно "сэмплирует" входной сигнал в пределах одного бита, чтобы устойчиво определить, соответствует ли уровень 0 или 1. Чем выше oверсэмплинг — тем точнее приём при шуме или рассинхронизации, но тем выше требования к тактированию. Типичные значения — 4, 8, 16 или 32. - Peripheral clock — тактовая частота периферии.
Это тактовый сигнал, который питает UART-модуль микроконтроллера (например, 48 MHz, 80 MHz и т.д.). От него вычисляется реальная скоростная частота передачи (baud). - Baud rate divider — делитель для получения нужной скорости.
Внутри UART есть регистр (делитель), который делит тактовую частоту периферии с учётом выбранного oversample, чтобы получить требуемую скорость передачи (baud). Иначе говоря, контроллер настраивается так, чтобы периферийный такт / (oversample * divider) = желаемый baud. - Standard baudrates — стандартные скорости: 9600, 38400, 115200 и т.д.
Это «обычные» значения скорости, которые поддерживаются большинством устройств и терминалов. 115200 бод — наиболее распространённая скорость для современных MCU; 9600 и 38400 — часто встречаются в старых модулях.
Первый контакт: подключение и настройка
Далее берем USB-TTL адаптер (обычно чип CP2102 или FTDI), цепляем:TX <-> RX,
RX <-> TX,
GND <-> GND.
ВНИМАНИЕ - Никогда не подключайте питание от адаптера, чтобы не спалить плату!
Наглядная схема подключения на примере малинки:
Важный параметр это скорость — с ней часто промахиваются новички. Начинаем с 115200 бод, если видим кракозябры - тогда пробуйте 57600, 38400, 9600. Есть даже утилита baudrate.py (baudrate.py -p /dev/ttyUSB0) , которая сама подбирает скорость — экономит время.
Полезные утилиты для доступа к serial console:
Minicom/picocom - https://wiki.emacinc.com/wiki/Getting_Started_With_Minicom
Screen - https://www.cyberciti.biz/faq/unix-linux-apple-osx-bsd-screen-set-baud-rate/
Открываем screen /dev/ttyUSB0 115200 — и если повезло, видим священные строки загрузки ядра или U-Boot. Иногда если успеть нажать пробел то можно попасть в консоль загрузчика. А там можно дать полет творческому мышлению: дампить память, изменять переменные окружения, грузить альтернативный initramfs.
Немного автоматизации
Если в консоли много команд, их можно перебрать скриптом с pySerial: отправляю строку, читаю ответ. Так можно находить скрытые команды быстрее, чем вручную:
Python:
import serial, time
ser = serial.Serial('/dev/ttyUSB0', 115200, timeout=0.5)
for cmd in ["help","debug","factory","reboot"]:
ser.write((cmd+"\n").encode())
time.sleep(0.2)
print(ser.read(4096).decode(errors='ignore'))
После того как вы получили доступ к serial console через UART, можно выдохнуть, самая геморойная часть уже позади.
Можно начать проходится по нашему чек листу:
Наблюдаем за логами
Для начала рекомендую понаблюдать за логами, просто смотреть что пишет железка:
- Сообщения загрузчика (U-Boot, RedBoot и т.д.): версии прошивки, параметры загрузки, пути к rootfs.
- Логи ядра: монтирование разделов, запуск демонов, ошибки.
- Сообщения сервисов: иногда прямо на консоль выводятся пароли по умолчанию или ключи от API.
На многих устройствах, если при старте нажать пробел или Ctrl+C, загрузчик останавливается и даёт командную строку (=>):
- printenv — посмотреть переменные окружения.
- setenv / saveenv — изменить поведение загрузки (например, загрузить систему в режим отладки).
- bootm, tftpboot, mmc read — команды, которые можно использовать для дампа памяти или запуска своих образов.
Промты для авторизации
Если устройство грузит Linux или RTOS, после логов часто появляется приглашение:Тут можно попробовать:
- Дефолтные логины: root, admin, user.
- Дефолтные пароли: root, admin, 1234, пустой пароль.
- Если пароль известен из прошивки (или отреверсен из нее) — использовать его.
Сбор информации внутри устройства (если ядро линукс)
- Проверяем версии (uname -a, cat /etc/release).
- Смотрим запущенные процессы (ps, top).
- Ищем файлы с паролями и ключами (grep -R password /etc).
- Читаем и если есть привелегии пишем конфиги (/etc/config, /etc/network, /etc/shadow ).
Тогда пробуй:
- Комманды на подобии help, ?, .h, debug, factory.
- Перебрать команды с помощью небольшого скрипта и смотреть, на что устройство реагирует.
Дамп и модификация прошивки
- Пробуем читать флеш-память (md, dump, sf read) и сохранять её через UART (или через TFTP).
- Если чуствуете себе черезмерно смелым то пробуйте заливать свою прошивку или initramfs (например, для отладки или получения полноценного shell).
Вложения
Последнее редактирование: