Я хотел исполнить свою давнюю мечту — запустить DOOM на собственных наушниках.
В итоге вместе с портом я создал проект для полной модификации их софтверной части. Это первая часть статьи — она рассказывает о создании патчера стоковой прошивки. Читать далее
Демонстрация порта DOOM (порт будет разобран в следующих частях):
Часть 1: из чего состоят наушники, софтверная часть и создание патчера стоковой прошивкиПримерно год назад я заинтересовался тем, что находится внутри моих наушников soundcore Life Q35 с точки зрения софта и железа. Я захотел модифицировать их прошивку, а может, ещё и запустить DOOM (спойлер: у меня получилось).
soundcore Life Q35 — наушники на базе SoC Bestechnic BES2300P (YP).
Характеристики чипа:
Два ядра ARM Cortex M4F (до 300 МГц)
4 МБ Flash памяти
~ 1 МБ SRAM
Даташит можно посмотреть здесь.
Начало: разборка и дамп прошивки
Всё началось с того, что я перехватил и подменил трафик приложения soundcore, скачал с серверов файл с апдейтом с помощью собственного запроса к серверу через curl, что‑то попытался из него вытащить, да забросил это дело.
Через полгода я решил взяться за это исследование серьёзно и разобрать их. Купил UART‑адаптер, паяльник и переборол страх сломать свои основные наушники.
В интернете никаких инструкций по разборке и распиновок не было, поэтому пришлось исследовать это самостоятельно. Я разобрал левую чашу наушников, перевернул плату, нашёл пины UART, подпаялся к ним и... застрял на некоторое время.

UART‑пины на левой плате (зарядной)
В интернете есть утилиты для прошивки, оставленные и созданные комьюнити проекта openpinebuds (репозиторий, спасибо pine64!), а также официальный SDK для сборки собственной прошивки.
Для начала я, конечно же, решил прочитать память наушников, но как?
В официальной инструкции для PineBuds писалось, что нужно положить наушники в кейс, а у меня полноразмерные наушники...
Я давно замечал: когда наушники выключены, при нажатии кнопки ANC в левом динамике раздается треск с каким‑то странным промежутком, будто просыпается процессор. Это наблюдение стало ключом к режиму загрузчика.
После нескольких тестов методом тыка я выяснил: если запустить утилиту для прошивки bestool и зажать кнопку ANC на выключенных наушниках, они просыпаются, шлют sync пакет в UART, входят в режим загрузчика и, наконец, позволяют считать или перезаписать память!
Из чего состоит прошивка и с чем её едят?
После считывания дампа возник вопрос: как модифицировать прошивку и из чего она вообще состоит?Binwalk на неё плохо работает, ничего не выдает, а значит, нужно исследовать её вручную.
Заметил в конце прошивки метаданные, которые облегчили начало анализа:

Метаданные прошивки
Из них я узнал, что прошивка работает на основе RTX (RTOS), какой в наушниках чип, размеры и оффсеты некоторых разделов, а также выяснил характеристики памяти и базовый адрес загрузки (в будущем оказалось полезным для Ghidra)
Проблемы стоковой прошивки (причина создания проекта)
Кстати, почему я захотел модифицировать наушники?
Меня раздражала пара проблем в них (как потом оказалось, я не один такой), к примеру:
Дешёвые, раздражающие звуки роботизированной женщины с частотой дискретизации 16 кГц в моно, которые даже нельзя отключить!
Периодический треск в ушах при разряде батареи
Gate‑эффект при подключенном 3,5 мм в активном режиме (не слышны тихие звуки по кабелю)
Помимо этого, мне хотелось полностью контролировать наушники, чтобы в любой момент я (и любой другой пользователь) мог поменять в них что угодно.
Реверс‑инжиниринг (Загрузка прошивки в Ghidra)
Перед тем, как начать анализировать прошивку в Ghidra, её нужно правильно загрузить, чтобы все строки из прошивки привязались к функциям, а декомпилятор работал правильно.
Для этого рекомендую использовать утилиты для поиска базы. Например, я пользуюсь basefind2:
python basefind2.py firmwareflash.bin
scanning binary for strings
len>=10…
total strings found: 4516
scanning binary for pointers…
total pointers found: 225712
finding differences of length: 10
possible offset 0x1ffe7404 06.20%
possible offset 0x3c000000 76.17% Что делать, если скрипт не сработает и что нужно учесть при загрузке прошивки?
Можно поискать базу в метаданных прошивки (в нашем случае она есть)
Если Ghidra все равно плохо декомпилирует прошивку, можно попробовать прибавить к адресу в метаданных 0x4000000 (иногда в метаданных прошивок BES базовый адрес указывается как NC, то есть non‑cached).
Если вы скачали прошивку с серверов (обновление), к базовому адресу нужно прибавить смещение из OTA_CODE_OFFSET, поскольку загрузчик OTA_BOOT не обновляется по воздуху и отсутствует в обновлениях.
Началась работа над патчером:
Я начал с замены звуков, поднятия их частоты дискретизации и добавления возможности проигрывать их в стерео (так как память на 70% пустая, место есть), для этого я:
Провел анализ прошивки с помощью Ghidra
Нашёл switch-case функцию, которая отвечает за системные звуки и плеер этих звуков
С помощью ИИ написал универсальный патчер на python, который на данный момент неплохо анализирует разные прошивки (не только от Q35), находит в них нужные функции, делает несколько патчей и записывает кастомные звуки после конца прошивки
Стоит отметить, что при поиске функции для системных звуков возникли некоторые трудности — функция не имеет отладочных выводов и я её нашёл довольно интересным оригинальным методом.
Для поиска функции я создал с помощью ИИ экстрактор звуков из прошивки (они лежат в прошивке в SBC формате), вытащил звуки, посмотрел, на каком адресе они извлекались, а затем перешёл по начальному адресу любого найденного звука в Ghidra и посмотрел перекрёстные ссылки (XREF). Единственной функцией в ссылке как раз и оказался менеджер звуков!

XREF на звук из функции менеджера звуков (Sync‑word кодека SBC — байт 0×9c)
Подведём итоги первой части и взглянем на рабочий патчер!
В итоге за несколько месяцев я создал самую первую часть от своего проекта — openqore. Патчер получил название qorepatcher.
Скоро выйдет большое обновление для всего проекта, которое позволит обновлять наушники по воздуху!
В следующих частях я расскажу о портировании SDK от PineBuds на эти (и в будущем на другие) наушники и про порт DOOM, где действия в игре привязаны к кнопкам на наушниках.
А теперь предлагаю взглянуть на итог моей первой работы! Я заменил стоковые звуки на собственные, которые написал сам.
До встречи в следующей части!
| # | Наименование новости | Тональность | Информативность | Дата публикации |
|---|---|---|---|---|
| 1 | Панорамный DOOM 1.1 на трёх экранах: повторяем легенду под MS-DOS | 0 | 5 | 06-07-2026 |
| 2 | Диктофон на микроконтроллере (WM8731 + I2S + STM32 + SDIO + FAT16) | 5 | 7 | 06-07-2026 |
| 3 | Проигрыватель WAV файлов на STM32 | 5 | 7 | 02-07-2026 |
| 4 | [Перевод] Самодельный BIOS для микшерного пульта и запуск DOS на нём | 0 | 5 | 26-06-2026 |
| 5 | Программный ремонт RAM DDR 4\5 | 0 | 7 | 02-07-2026 |
| 6 | Диктофон на микроконтроллере (WM8731 + I2S + STM32 + SDIO + FAT16) | 5 | 7 | 06-07-2026 |
| 7 | Путь к миллиону точек: как я переписывал плоттер три раза, прежде чем он перестал лагать | 2 | 6 | 22-06-2026 |
| 8 | Компактные и интеллектуальные (роботизированные) DIY-тренажёры для дома? Вполне себе реальность… | 5 | 7 | 25-06-2026 |
| 9 | Не вы а ты👐🤞👀🫀🦻👣👂🧠 Volume97Вопрос интересный! Сразу оговорюсь: перечислить абсолютно ... | 2 | 7 | 08-07-2026 |