Я Лев Ларин, инженер Unibot. Мы развиваем UNIBOT Fleet, подключаем к ней коммерческих роботов и дорабатываем их управление, интеграции и работу с данными.
Продолжение кейса: Quectel RG255C-GL в Agibot X2 Ultra. Другой модем, два диапазона CLADE и новая подпись MBNv7.
В роботе-официанте стоял Quectel EG25-GC. Вставили рабочую российскую SIM-карту: модем прочитал её, нашёл операторов, но в сети не зарегистрировался. Замена APN и второй оператор ничего не изменили.
Пришлось разбирать прошивку. В сжатом коде Qualcomm Hexagon нашлась проверка страны, которая запрещала работу в России и Иране. Для изменения российского MCC хватило одного бита. Затем потребовались новые хеши, подпись и проверка связи на устройстве.

Обложка сгенерирована по фотографии автора.
Что установлено в роботе
Это робот-официант одного известного китайского производителя. Его модель здесь несущественна: проблема оказалась в сотовом модеме.

Изображение Quectel. Здесь показана версия GB; в нашем роботе установлена GC.
Android 11 работает на плате Rockchip RK3568, которая в device tree определяется как RK3568 KXB LP4 V10 Board. Модем подключён к ней по USB. У шасси отдельный компьютер на Raspberry Pi CM4.
Компонент |
Наш экземпляр |
|---|---|
Модем |
Quectel EG25-GC |
Прошивка |
|
Подверсия и сборка |
V02, 6 сентября 2023 года |
USB VID:PID |
|
Linux модема |
|
Радиопроцессор |
Qualcomm Hexagon QDSP6 V5 |
Полную версию прошивки мы записали сразу. Для поиска совместимых образов короткого названия «EG25-G» недостаточно: GC и GB нельзя считать взаимозаменяемыми по одному имени семейства.

SIM читается, регистрации нет
Первой проверяли карту Т‑Мобайла. Активировали её в телефоне и убедились, что мобильный интернет работает без Wi-Fi.
В роботе Android показывал LOADED, модем отвечал CPIN: READY. В профиле передачи данных оставался китайский APN CMIOTCZBJC.JS. Заменили его на tt, согласовали настройки Android и модема, перезапустили радио. Регистрации по-прежнему не было.
Поставили рабочую SIM Мегафона с APN internet. Получили то же состояние:
SIM прочитана;
поиск операторов работает;
регистрация остаётся в состоянии поиска;
CGATT: 0;интерфейс
usb0на Android не поднят.
При сканировании модем видел Tele2 в LTE, Мегафон — в 2G/3G. После двух SIM и проверки APN переключились на поиск причины отказа регистрации.
Заодно пришлось восстановить Android после неудачной перезагрузки. По журналам он падал в Incremental FS при обработке двух остатков установки APK без backing store. Каталоги сохранили переименованием, после чего Android загрузился. Дальше перезапускали отдельно модем.
Региональное ограничение
На форуме Quectel нашёлся случай с той же веткой прошивки: российские SIM определяются, сети сканируются, обслуживания нет.
Затем нашли PCN 2022113001 от 30 ноября 2022 года. В этом документе Quectel сообщает об ограничении сетевого подключения и позиционирования в России и Иране. Указаны проверки MCC оператора и географические ограничения. EG25-G входит в перечень затронутых семейств; начало поставок обновлённых изделий планировалось на 1 февраля 2023 года. Поддерживаемый откат на старую прошивку не предусматривался. Документ Quectel, PDF.
Сначала хотели поставить старую GC-прошивку. Подтверждение её существования нашли, подходящий проверенный пакет — нет. Решили исследовать текущую сборку.
Доступ к Linux модема и резервная копия
В EG25-G работают две части: Linux на ARM и радиостек на Hexagon. Служебный доступ к ARM-части ранее разобрал Megi в исследовании модема PinePhone. Там же описан механизм QADBKEY.
Этот способ сработал и на нашем экземпляре: получили root shell Linux модема.
Поскольку USB-хостом был Rockchip, временный ADB-клиент запустили на нём. Серверу выделили отдельный порт и пробросили его на рабочий компьютер. Модем выбирали по USB transport: в списке появлялся также сам Android по TCP.
Для AT-запросов использовали свободный /dev/ttyUSB3. /dev/ttyUSB2 был занят процессом rild. Настройки терминала сохраняли и восстанавливали после работы.
Радиофайлы находились в /firmware/image, корневая UBIFS была смонтирована read-only. Скопировали прошивку, системные программы и библиотеки — архив примерно на 65 МиБ — и записали SHA-256.
Попытка снять сырую копию MTD закончилась зависанием чтения раздела MIBIB. Файловые ADB-запросы тоже перестали завершаться. Программный перезапуск не помог; восстановили модем отдельным отключением питания через цепь управления на нашей плате.
После этого работали с обычными файлами. Исходная радиопрошивка была сохранена, но полного проверенного EFS/QCN/NAND-бэкапа у нас не было.
Где спряталась проверка страны
В modem.b24 нашлись строки:
reg_sim.c:quectel_check_current_plmn_is_need_forbidden MCC =%d%d%d reg_sim.c:Current PLMN is Russian PLMN ,Forbidden
PLMN — идентификатор мобильной сети. Он содержит MCC страны и MNC оператора.
Ссылки на строки находились в диагностических структурах modem.b14. Найти вызывающий их код напрямую не получалось. Некоторое время предполагали, что сообщения остались от удалённой функции.
Прошивка разбита на файлы modem.bNN. Номера соответствуют записям program headers ELF; расположение сегментов восстанавливается по указанным там смещениям и размерам.
Нужный код оказался в modem.b21, сегменте размером около 9,6 МиБ. У него не было флага исполнения: это было хранилище сжатого кода. Служебная таблица указывала, что после распаковки содержимое должно попасть в виртуальный диапазон от 0xd0000000.
Для распаковки использовали qualcomm-q6zip Willem Hengeveld. У нашей сборки оказались такие параметры:
4174 страницы;
словари на 1024 и 16384 слова;
lookback — 8;
восьмибайтовый префикс у первых 3715 блоков.
После распаковки получили около 16,3 МиБ. Код смотрели в Rizin 0.9.1, задав архитектуру Hexagon и виртуальную базу. При разборе учитывали пакетное исполнение инструкций Hexagon.
По адресу 0xd0239f38 нашлась функция, которая извлекала три цифры MCC из полубайтов аргумента и возвращала признак запрета для 250 и 432 — России и Ирана. Вызывающий код использовал её результат при запрете PLMN.

Что изменили
В проверке MCC 250 заменили среднюю цифру: 5 → 7. Получился MCC 270 — Люксембург. Ветку для 432 оставили прежней.
То есть мы перенесли одну запись запрета с российского MCC на люксембургский. Идентификаторы SIM и сети не менялись.
В машинной инструкции замена константы затрагивала один бит. Оставалось внести её в сжатый сегмент.
q6zip использует словари и ссылки на ранее распакованные слова. Мы проследили декодирование нужной страницы и выяснили, что целевая инструкция записана самостоятельным 32-битным литералом. Её можно было изменить без правки общего словаря и пересжатия сегмента.
Изменили один бит в исходном modem.b21, заново распаковали страницу и сравнили результат. Отличалась только нужная инструкция. Размер файла, словари, указатели страниц и служебные данные сохранились.

Хеши и подпись
Одного изменённого modem.b21 для загрузки недостаточно. В modem.b01 находились:
40 байт MBN-заголовка;
832 байта таблицы SHA-256 для 26 позиций ELF;
256 байт RSA-подписи;
6144 байта области сертификатов.
Файл modem.mdt в этой сборке равнялся объединению modem.b00 и modem.b01. Поэтому обновить требовалось три файла: нагрузку, hash-сегмент и копию метаданных.
Сначала проверили исходные сегментные хеши и разобрали подпись QPSA. В ней хеш заголовка и таблицы дополнительно обрабатывается с идентификаторами SW_ID и HW_ID. В нашем образе они равнялись 2 и 0. Полученный 32-байтовый результат подписывается RSA-2048 с PKCS#1 v1.5.
Алгоритм проверили на исходном образе: восстановленное через открытый ключ значение совпало с нашим расчётом. Формат описан в открытой реализации QPSA.
В цепочке сертификатов обнаружились QPSA F4 TEST CA и QPSA F4 TEST ROOT. Открытый ключ промежуточного CA побайтно совпал с ключом из публичных тестовых материалов SecImage.
Используя этот тестовый CA, выпустили новый конечный сертификат с собственным ключом, сохранили атрибуты исходного сертификата и исходные CA/root. Затем обновили хеш сегмента и сформировали подпись образа.
Проверили новую цепочку сертификатов, подпись радиопрошивки и сегментные хеши.

Запись на устройство
На корневой файловой системе оставалось около 8,6 МБ. Новый временный modem.b21 размером больше 10 МБ туда не помещался.
Поэтому изменили один байт обычного файла на месте. Небольшие modem.b01 и modem.mdt заменили через временные файлы и переименование. Исходные метаданные и старое значение байта сохранили на модеме, полную нагрузку — на компьютере.
Перед записью сверили исходные хеши, после — новые. Предусмотрели откат при ошибке, выполнили синхронизацию и вернули корень в read-only. Загрузчики, сырые разделы, NV и IMEI не записывали. Замена трёх файлов оставалась неатомарной, поэтому потеря питания во время записи могла сорвать загрузку радиопрошивки.
После проверки перезапустили модем. Он появился на USB, вернул root shell и поднял DSP. Android продолжал работать с прежним boot ID.
Мегафон зарегистрировался в 3G, Т‑Мобайл — в LTE
Сначала проверили Мегафон. Появились регистрация в домашней сети, CGATT: 1 и IP-адрес на модеме. Android поднял usb0. Соединение работало в HSDPA/WCDMA 900.
В режиме LTE-only обслуживания не было. Вернули автоматический выбор: в исходном сканировании Мегафон здесь и до изменения определялся только в 2G/3G. Успешного веб-ответа на этой карте не получили — запросы завершались тайм-аутами.
Для проверки LTE вернули Т‑Мобайл. После замены SIM появилось CARD_IO_ERROR; один перезапуск модема восстановил чтение карты. RIL сам поменял APN с оставшегося internet на tt.
SIM определялась как 25062, обслуживающая сеть — Tele2 25020.
Проверка |
Результат |
|---|---|
Регистрация |
|
Пакетное присоединение |
|
Сеть |
FDD LTE, Tele2 25020 |
Диапазон |
Band 7, EARFCN 3400 |
APN |
|
Android |
|
HTTP и HTTPS с модема |
200 OK через |
HTTP с Android |
200 OK через |
Wi-Fi оставался включённым, поэтому проверочные запросы привязывали к сотовым интерфейсам.
На модеме использовали curl с интерфейсом rmnet_data0. На Android подходящего curl не оказалось: запустили временную DEX-пробу, которая создавала TCP-сокет с SO_BINDTODEVICE=usb0 и запрашивала example.com. Получили HTTP 200 и содержимое Example Domain.
Ping до 1.1.1.1 при этом не отвечал.

После тестов выключили внутренний ADB модема, восстановили состав USB-интерфейсов, остановили временный сервер и удалили пробу. Повторный HTTP-запрос с Android через usb0 прошёл успешно.
На момент проверки сигнал был слабым: RSRP −114 дБм, RSRQ −18 дБ, SINR −6 дБ. Скорость, длительную устойчивость, GNSS и автоматическое переключение приложений между Wi-Fi и LTE мы не проверяли.
На нашем EG25-GC изменение одного бита в радиокоде, с обновлением хешей и подписи, позволило зарегистрироваться в российской сети и передать трафик через LTE.
Комментарии (18)

Tigramaan Автор
24.10.2026 21:05Это вы ещё не видели как я пишу полностью сам. Примерно вообще не пишу. Если бы не ИИ я бы никогда не добрался до того чтобы поделиться тем чем занимаюсь.
А по робототехнике и решению реальных проблем - вообще очень мало инфы. Индустрия коммерческих роботов очень молодая. Китайчких брендов куча. Моделей и модификаций ещё больше.
.Да и большую часть работы описанной тут тоже делал ИИ. В такое время живём...
Представьте, мне каждую неделю привозят по 2-3 совершенно разных робота на интеграцию с разными задачами и проблемами. Разные модели разные бренды разные задачи. Без ИИ я бы над каждым сидел по пол года с командой таких же инженеров.

Krypt
24.10.2026 21:05И не увижу, пока вы свой текст не опубликуете.
Понятно, что от использования ИИ сейчас некуда не деться, и что он предоставляет новые возможности, инструменты, и новые же проблемы.
У меня вопросы именно к самой статье: Каждый текст написанный ИИ выглядит абсолютно одинаково.
Вы вероятно взяли агентный ИИ, который вы используете для программирования. В тексте он предельно сух, и при этом зачастую разбавляет текст водой там, где она совершенно не нужна, вот просто чтобы было больше текста. И конкретно использованный вами понимает стилистику русского языка довольно плохо.
Возможно это моё личное, но я после ИИ даже комменты и документацию предназначенную для людей переписываю.

Dobrotin
24.10.2026 21:05По той-же причине приходится EM12-G держать на старой прошивке (когда уже есть минимум 4 более свежих с региональной блокировкой РФ и Ирана).

Tigramaan Автор
24.10.2026 21:05Ну вот да, а к нам роботы уже приезжают с новыми прошивками, поэтому приходится колупать чтобы запустить. Но вот нашлось решение поменять Россию на Люксембург - 1 бит, и все заработало.. мне кажется изящно вышло

ru_vlad
24.10.2026 21:05Можно глупый вопрос, а может надо продавцу разлочивать или ему не интересно вам продавать?

Tigramaan Автор
24.10.2026 21:05Я думаю что пока Россия для Китая в плане роботов - это микроскопический рынок.
Не все модемы залочены. Но конкретно эти - производитель просто ставит компонент и отправляет. Куда он уедет - в Россию или в Уругвай - становится известно только продавцам на складе.

PatakinVVV
24.10.2026 21:05У производителя есть строгие экспортные ограничения в контракте с чипмейкером. Если Quectel начнет официально продавать разлоченные модули в обход своих же документов, им быстро перекроют поставки кристаллов Qualcomm. Поэтому они просто шьют лок на конвейере и закрывают глаза на серый импорт

HappyGroundhog
24.10.2026 21:05Из этого не следовало, что антенна и все диапазоны идеальны, но версия «модем вообще ничего не слышит» уже не соответствовала данным.
Последовательность «спросили модем — перезагрузили Android — получили bootloop» легко принять за причинную связь. Но журналы показали другой механизм.
Как же больно читать такой ИИ слоп.... Статья интересная, но продираться через вот такое это просто лютые страдания!

Tigramaan Автор
24.10.2026 21:05Благодарю за конкретику. Я хотел как то разбавить техническую часть. А так как писатель из меня вообще никакой, то просил ИИ. Но возможно лучше без этого. Перепишу статью, уберо слоп максимально.
Прошу меня простить, я всего месяц назад сделал первую публикацию в жизни ;)

HappyGroundhog
24.10.2026 21:05Все понимаю) Мы тут все технари и не ждем идеального слога. Для этого есть корп. блоги)) Поэтому, даже если статья будет короткой, но технически емкой - она все равно будет прекрасной!

pistoletov
24.10.2026 21:05А почему quectel? Я начал с foxcon так на нем и сижу пока t77w968 и t99w175. Особых проблем вроде нет если нет проблем со связью от оператора. Модемы конечно очень капризная вещь во всей системе

Tigramaan Автор
24.10.2026 21:05Потому что приезжает техника уже готовая в сборе.. Я не выбираю какой модем ставить в робота.. Что приехало с тем и работаем. То есть можно проапгрейдить железо, но если проблему можно решить программно то зачем лезть в железо?

PatakinVVV
24.10.2026 21:05Отдельное спасибо за наводку на публичные тестовые ключи QPSA в цепочке подписи)

Timmek
24.10.2026 21:05Сама тема, и то чем вы занимаетесь, это очень интересно. Но вот этот ИИ слоп от ChatGPT 6… его невозможно читать. Это очень трудно. Непонятный лишние уточнения, этот английский стиль письма. Я рад за вас и за вашу компанию, но превозмогать себя на полное прочтение я не смог.

Tigramaan Автор
24.10.2026 21:05Ну я не писатель. Тут или писать статьи или работать. Поэтому просто делюсь как могу. С другой стороны тут то что написано - просто скормить статью агенту чтобы он перепрошил модем ваш по инструкции и долго не ковыряться )) тут как бы читать не оч интересно. Идея простая. Меняем код России 250 на код Люксембурга 270. Всего 1 бит. Упаковываем обратно всея пересчитываем хэш и заливаем обратно.
Krypt
Вот похоже я буду ходить и под каждой статьёй отредактированной через ИИ писать:
Дайте мне человеческий оригинал, текст ИИ читается ужасно, и лично мне хватает личного общения с ним в рамках работы/личных проектов. Я текст живого человека хочу!
badkun
И что? В чем объективно проблема? Пусть лучше не пишет вообще? Инфа то реально полезная, уже столько с этими модемами встряло людей.