Дизассемблирование прошивки ЭБУ: от дампа до читаемого кода
Ghidra · Реверс-инжиниринг ЭБУ
Дизассемблирование прошивки ЭБУ: от дампа до читаемого кода
У вас есть файл прошивки и установленная Ghidra. Вы импортируете бинарник, жмёте «дизассемблировать» — и получаете экран, полный переходов в никуда, ссылок в пустоту и кода, который читается как помехи. Отсюда вывод: либо Ghidra — не тот инструмент, либо этот ЭБУ слишком сложный. Ни то, ни другое не верно. Дизассемблирование сломалось ещё до того, как Ghidra запустилась, — в самом файле. В этом материале мы проанализируем реальную последовательность, начиная с того, что лежит внутри считанного файла ЭБУ: ловушку сжатия, из-за которой рушится большинство первых попыток, настройку процессора и чтение кода, когда он наконец разрешился.
Что лежит внутри считанного файла ЭБУ
Полностью считанный файл ЭБУ — это не «много байтов». Это несколько отдельных структур, живущих бок о бок в одном файле, и первый навык дизассемблирования — научиться отличать их друг от друга.
Их пять. Загрузчик (bootloader) запускает ЭБУ. Программа — один или несколько блоков кода — это софт, который управляет двигателем. Таблицы векторов хранят адреса, на которые процессор переходит при сбросе и прерываниях. В 16-битном hex-виде они выделяются как 32-битные значения с характерным рисунком «вверх-вниз, вверх-вниз». Есть пустые области — заполнение между блоками. И есть калибровка: карты и отдельные значения, которые редактирует WinOLS®.
Вот разделение труда, которое имеет значение. WinOLS работает с калибровкой. Ghidra работает с программой. Когда вы правите карты, вы живёте в последнем блоке. Когда дизассемблируете — вы живёте в коде, который читает эти карты и решает, что с ними делать. Именно поэтому дизассемблирование открывает двери, которые картам недоступны: там живёт логика, а не только числа.
Прежде чем что-либо дизассемблировать, посмотрите на файл один раз и найдите эти блоки на глаз: где сидит загрузчик, где кончается программа, где начинается калибровка. Именно эта привычка делает следующую проблему видимой, а не невидимой.
Ловушка сжатия, ломающая большинство попыток
Вот самая частая причина, по которой первое дизассемблирование выглядит мусором, — и почти ни один гайд её не упоминает.
Большинство программаторов сжимают файл при чтении ЭБУ. Это не zip-архив — всё проще и вреднее. Программатор удаляет пустое пространство между программой и калибровкой, и файл становится меньше. Но код внутри по-прежнему хранит исходные абсолютные адреса со времени сборки. Эти адреса рассчитаны на то, что пустое пространство всё ещё на месте. Уберите его — и программа с картами окажутся ближе друг к другу, чем они когда-либо были в реальном ЭБУ.
Ловушка в одну строку
Сжатый дамп кладёт правильные байты по неправильным адресам. Код говорит «переход на 0x38000», но после сжатия данные, которым место по адресу 0x38000, лежат где-то ещё — поэтому переход попадает в бессмыслицу.
Признак заметить легко, если знаешь, что искать: промежуток между концом программы и началом калибровки подозрительно короткий. Программа не может «дотянуться» до калибровки, потому что в файле они почти касаются друг друга. На Bosch MED17.1, например, калибровка должна начинаться с адреса 0x38000. Если в вашем файле она начинается заметно раньше, и после кода почти нет промежутка, — у вас в руках сжатый дамп.
Дизассемблируйте его как есть, и Ghidra сделает ровно то, что вы ей велели. Она читает адреса в коде и идёт по ним — прямиком в данные, которых там нет. Бессвязные переходы, ссылки, разрешающиеся в мусор, функции, обрывающиеся в воздухе. Инструмент не ошибается. Ошибается файл.
Решение — восстановить правильную карту памяти до дизассемблирования: вернуть пустое пространство, чтобы каждый блок снова сел на свой истинный адрес. Как только раскладка верна, тот же файл, что выдавал помехи, теперь выдаёт код. Это тот самый шаг, который отделяет людей, читающих ЭБУ, от людей, винящих Ghidra.
Освойте восстановление раскладки на боевой прошивке
Курс Ghidra TriCore Fundamental проходит восстановление карты памяти на реальных файлах Bosch MED17 и EDC17 — не на упрощённых учебных дампах. Это единственный структурированный курс по Ghidra, построенный для калибровщиков, а не для программистов.
Смотреть курс по реверс-инжинирингу →Настройка процессора: PSPEC и LDEFS
С правильной раскладкой следующий вопрос — понимает ли Ghidra сам чип. Из коробки она поставляется с языковым определением Universal TriCore. Это определение знает базовую адресацию — Flash по 0x80000000, основная RAM по 0xD0000000 — и почти ничего больше. Оно не знает ни портов CAN, ни Scratchpad RAM, ни Cache RAM конкретного чипа перед вами.
Для автомобильной работы конкретный чип обычно — это TC1796 или TC1797, два самых распространённых контроллера внутри ЭБУ EDC17. Чтобы получить более богатое дизассемблирование, где эти области подписаны, а не показаны голыми адресами, вы ставите две вещи:
- Файл PSPEC (спецификация процессора), описывающий порты CAN, Scratchpad RAM и Cache RAM именно этой модели. Файлы PSPEC кладутся в
{Ghidra}/Processors/TriCore/Data/Languages/. - Обновление файла LDEFS в той же папке — индекса, который говорит Ghidra, какие языковые определения и спецификации доступны. Новый PSPEC, не указанный в LDEFS, просто не появится.
Практическое правило с верстака: лучше иметь больше определённых областей памяти и удалить лишние, чем позже упереться в адрес и рыться в даташитах, выясняя, что это. Когда программа обращается к регистру CAN, вы хотите читать имя регистра, а не голый hex-адрес. Именно эта разница делает навигацию по коду в следующих главах быстрой, а не мучительной.
Импорт и правильные адреса
Теперь сам импорт. Причина, по которой правильная раскладка и правильный процессор важны до этого шага, в том, что Ghidra перебазирует файл относительно тех адресов, которые вы ей дадите. На TriCore программный Flash лежит по 0x80000000. Если файл импортирован с неправильной базой, каждая абсолютная ссылка в коде смещена на константу — и вы снова получаете промахивающиеся переходы.
Поэтому порядок не косметический, а причинный:
- Восстановить карту памяти, чтобы блоки сели на свои истинные смещения (фикс сжатия).
- Установить PSPEC и обновить LDEFS, чтобы области чипа были известны.
- Импортировать и переадресовать относительно
0x80000000, чтобы абсолютные адреса программы совпали. - Дизассемблировать — и теперь ссылки разрешаются.
Почему порядок решает всё
Каждый шаг предполагает, что предыдущий выполнен. Дизассемблируете до восстановления раскладки — читаете сдвинутые байты. Импортируете с неправильной базой — каждая ссылка смещена на константу. Соблюдите последовательность — и код прочитает себя сам.
Есть и вторая причина хотеть правильные базовые регистры пораньше. Код TriCore добирается до значительной части своих данных через базовые регистры — A0, A1, A8, A9 — а не через полные абсолютные адреса. Дамп, где не хватает части файла (например, считанный только application software), оставляет эти базово-относительные ссылки висящими, пока вы не скажете Ghidra, чему на самом деле равна база. Восстановите базу — и тысячи ссылок разрешаются разом. Ровно этот случай — Bosch MG1 на AURIX TC298, только ASW, адресация через A9 — разбирается на курсе по реверс-инжинирингу шаг за шагом.
Чтение окна Listing по слоям
Как только дизассемблирование удалось, вы проводите время в окне Listing — главном представлении Ghidra. Оно выглядит плотным, пока вы не осознаете, что каждая строка собрана из одних и тех же пяти зон, читаемых слева направо:
- Адрес — и эта колонка синхронизирована с WinOLS. Скопируйте адрес в Ghidra, вставьте в WinOLS — и вы в том же месте. Два инструмента работают с одним файлом с двух сторон.
- Байты инструкции — сырой бинарный код инструкции и её операндов, те же байты, что вы увидели бы в hex-дампе.
- Инструкция — мнемоника TriCore (
MOV,MOVH.A,LEA,LD/ST,CALL/RETи семейство переходов). - Операнды — параметры инструкции, подсвеченные цветом, чтобы регистры и константы различались с первого взгляда.
- Ссылки — откуда пришёл переход в эту точку. Стрелка показывает источник;
Jотмечает переход.
Читайте строку так — адрес, потом байты, потом мнемоника, потом операнды, потом ссылки — и любая строка становится читаемой, ещё до того как вы знаете каждую инструкцию. Здесь же преимущество Ghidra над WinOLS становится конкретным. WinOLS показывает вам карты. Ghidra показывает весь файл: дизассемблированный код, области RAM, метаданные и карты. Это более полное представление того, чем ЭБУ является на самом деле.
Зачем это вообще нужно тюнеру
Всё это — не реверс-инжиниринг ради самого реверс-инжиниринга. Отдача прямая: чтение кода позволяет делать то, что картам недоступно.
Первый практический результат в программе — отключение ограничителя скорости без единой правки карты, потому что ограничитель — это логика, а логика живёт в коде. Оттуда тот же навык открывает работу, у которой карты нет вовсе: сборка MapSwitch с нуля для переключения калибровок на ходу, RAM-кодирование для изменения поведения ЭБУ без полной перепрошивки, внедрение своих функций вроде launch control или перекодирования VIN. Это те задачи, которые клиент просит, когда референсная карта из похожего файла не работает, — потому что алгоритм другой, а алгоритм показывает только код.
Вот настоящая граница между работой с картами и пониманием ЭБУ. Карты говорят, что ЭБУ делает. Дизассемблированный код говорит почему — и как только вы умеете читать «почему», вы можете это изменить.
Читайте любой ЭБУ, а не только знакомые
Ghidra TriCore Fundamental ведёт вас от подготовки файла прошивки до чтения и редактирования реального кода TriCore — фундамент для каждой своей доработки в Practice и Mastery. Структурно, с сертификацией, для калибровщиков.
Смотреть карьерный путь →Частые вопросы
Какой инструмент нужен, чтобы дизассемблировать прошивку ЭБУ?
Ghidra. Она бесплатна, с открытым исходным кодом и из коробки поддерживает семейства процессоров современных ЭБУ — TriCore, Renesas и PowerPC. Изначально её создало АНБ США для задач кибербезопасности, и она оказалась хорошо приспособлена для прошивок ЭБУ. Коммерческая альтернатива существует (IDA Pro), но для автомобильной работы Ghidra покрывает всё, что нужно калибровщику, и бесплатно.
Почему дизассемблированный код показывает переходы «в никуда»?
Почти всегда потому, что считанный файл сжат. Большинство программаторов при чтении ЭБУ выбрасывают пустое пространство между программой и калибровкой, и файл получается меньше реальной карты памяти. Код по-прежнему содержит исходные абсолютные адреса, но байты больше не лежат по этим адресам — поэтому каждый переход и каждая ссылка промахиваются мимо цели. Восстановите правильную карту памяти перед дизассемблированием — и переходы разрешатся.
Можно ли дизассемблировать прошивку ЭБУ без DAMOS?
Да. DAMOS ускоряет идентификацию карт, но для дизассемблирования он не нужен. Ghidra читает сам код. Как только вы начинаете видеть программу, калибровку вы находите, прослеживая данные, к которым обращается код, — без DAMOS и A2L. DAMOS делает это быстрее; чтение кода делает это возможным.
Нужно ли знать ассемблер, прежде чем начинать?
Нет. Строку в окне Listing читают по слоям — адрес, байты инструкции, мнемоника, операнды, ссылки, — и словарь ассемблера, который реально нужен, невелик. Горстка инструкций TriCore покрывает почти всё, что вы встретите, и их учат в контексте, прослеживая реальный код, а не из учебника с самого начала.
Законно ли дизассемблировать прошивку ЭБУ?
Анализ прошивки для калибровки двигателя, которым владеете вы или ваш клиент, — стандартная отраслевая практика; само дизассемблирование — это диагностический и инженерный шаг. А то, что вы дальше делаете с результатом, должно соответствовать местным нормам по выбросам и допуску к дорогам, которые различаются от страны к стране. Разберитесь в правилах, действующих там, где эксплуатируется автомобиль.
Читайте также: Таблицы DTC в EDC17 · Курс по реверс-инжинирингу ЭБУ · Карьерный путь калибровщика ЭБУ · Форум сообщества
