Исследование реверс-инжиниринга WinKFP / EDIABAS — ищу тестировщиков на реальном оборудовании

Сообщение #1

Arkayda

Под наблюдением

С нами
26.09.2026
Сообщения
4
Реакции
1
Всем привет!

Я работаю над открытым исследовательским проектом, посвящённым реверс-инжинирингу и воспроизведению частей стека прошивки BMW WinKFP / EDIABAS:


Проект направлен на понимание фактического поведения во время работы, а не просто на создание нового инструмента для прошивки.

На данный момент я исследую и тестирую:

  • поток выполнения WinKFP / winkfpt
  • взаимодействие с API EDIABAS
  • последовательность программирования VDLE
  • INIT_VDLE / REQUEST_SEGMENTINFO / SEND_SEGMENT / RESEND
  • обработку TesterPresent и диагностических сессий
  • поток WinKFP security-access/authentication
  • контейнеры аутентификации SGIDC / SGIDD
  • симметричные / простые / асимметричные пути аутентификации
  • дифференциальное тестирование с реконструированными реализациями
  • эмуляцию API EDIABAS и работу с реальным API EDIABAS
  • проверку безопасности и состояния программирования

Следующий этап — проверка на реальном оборудовании через K+DCAN.

Меня особенно интересует сравнение оригинальной сессии WinKFP с реконструированной реализацией:

WinKFP -> EDIABAS -> IFH -> K+DCAN -> BMW ECU

Ищу людей с опытом работы с:

  • BMW E60/E9x и похожими автомобилями E-серии
  • WinKFP + EDIABAS
  • интерфейсами K+DCAN
  • EDIABAS/IFHтрассировкой
  • логами программирования WinKFP
  • BMW SP-Daten
  • реверс-инжинирингом ПО BMW diagnostic/flashing

На начальном этапе меня в основном интересует сбор трасс diagnostic/session и понимание последовательности обмена. Я не ищу человека, который будет экспериментировать с неизвестным ECU или выполнять рискованную прошивку.

Если у кого-то уже есть полезные трассы WinKFP/EDIABAS, снятые через K+DCAN, или есть опыт инструментирования слоя EDIABAS/IFH, мне было бы очень интересно сравнить результаты.

Цель — задокументировать протокол и поведение во время работы воспроизводимым способом, а в дальнейшем понять, насколько функциональность оригинального WinKFP можно воспроизвести в независимой реализации.

Буду рад любой технической информации, исправлениям, наблюдениям или ссылкам на существующие исследования.

Спасибо!
Arkayda
 
5.00
1 Рейтинг

Сообщение #2

Небольшое обновление по прогрессу с момента исходного поста.

С тех пор удалось воспроизвести гораздо больше, включая несколько частей, которые изначально были лишь гипотезами.

Что касается WinKFP, мне удалось воспроизвести и дифференциально проверить фактическое поведение исходного исполняемого файла во время работы, а не просто реализовать предполагаемый протокол.

Некоторые результаты на данный момент:

- Воспроизведён поток задания VDLE из исходного WinKFP runtime:
INIT_VDLE -> REQUEST_SEGMENTINFO -> SEND_SEGMENT / RESEND
  • Восстановлена фактическая структура блока FLASH_SCHREIBEN, включая little-endian кодирование адреса и дублирующиеся поля длины.
  • Воспроизведено планирование TesterPresent и связанная с ним обработка диагностической сессии.
  • Восстановлены и проверены три пути аутентификации WinKFP: Symmetric, Simple и Asymmetric.
  • Воспроизведено поведение MSVC rand(), используемое в пути аутентификации Symmetric.
  • Воспроизведена обработка порядка байтов RSA / bignum, используемая исходным кодом.
  • Разобран фактический формат контейнера аутентификации SGIDC / SGIDD и определена связь между методом аутентификации и типом ключа.
  • Исходный код authentication/key-generation был выполнен под эмуляцией, а полученный вывод сравнен с исходным runtime.
  • Собран реконструированный слой EDIABAS и проведено поэтапное дифференциальное тестирование относительно исходного поведения WinKFP.
  • Реализован нативный адаптер API EDIABAS и независимо проверен жизненный цикл API.
  • Воспроизведена семантика проверки подписей / результатов опроса, используемая исходным потоком программирования.
  • Реконструированы части исходного пути связи EDIABAS/IFH, включая низкоуровневое транспортное поведение.

Интересно то, что теперь работа дошла и до физического уровня.

Я реализовал автономный нативный транспорт K+DCAN в исследовательском репозитории (без зависимости во время работы от другого моего проекта) и подключил его напрямую к реальному E60/ZF 6HP EGS.

Первая физическая проверка была намеренно только на чтение.

Например, следующий запрос был отправлен напрямую из реконструированного транспорта:

TX:
82 18 F1 1A 86 2B

ECU вернул AIF-ответ ожидаемого формата, а повторные запуски выдавали побайтно идентичные кадры TX/RX. Отличалось только время ответа.

Также я захватил и воспроизвёл физический ответ на:

TX:
82 18 F1 3E 00 C9

Опять же, сырой трафик по линии теперь рассматривается отдельно от высокоуровневых сопоставлений заданий.

Это различие важно: я отмечаю что-либо как наблюдаемое сопоставление задания WinKFP только при наличии прямых доказательств из исходного выполнения EDIABAS/SGBD. Сам по себе физически наблюдаемый диагностический кадр не используется для утверждения, что его создаёт конкретное задание WinKFP.

На данный момент у проекта фактически есть три независимо тестируемых уровня:

1. Поведение исходного WinKFP runtime
2. Поведение реконструированного WinKFP/EDIABAS
3. Прямая физическая связь K+DCAN с ECU

Следующий этап — сопоставить эти уровни, используя контролируемые аппаратные трассы только для чтения, прежде чем переходить к каким-либо операциям программирования.

Исследовательский репозиторий также был очищен: ранее восстановленный проприетарный ключевой материал OEM удалён из публичной истории, а публичные фикстуры аутентификации теперь синтетические.

Всё ещё очень интересно сравнить трассы с теми, у кого есть логи WinKFP/EDIABAS с автомобиля E-серии, особенно сырой трафик IFH/K+DCAN :sneaky::unsure:
 

Сообщение #3

В области реверс-инжиниринга у вас впечатляющий прогресс. Подход с дифференциальной валидацией — особенно эмуляция исходного x86-кода и сравнение вывода событие за событием — это надёжная методика, позволяющая подтвердить, что вы воспроизводите реальное поведение во время выполнения, а не гадаете о семантике протокола.

Несколько наблюдений по вашему описанию:

Охват путей аутентификации
Вы выявили и проверили все три метода аутентификации (симметричный MD5, простой XOR, асимметричный RSA). Воспроизведение rand() MSVC — хорошая деталь, которую удалось заметить: генерация nonce тестера важна для защиты от повторного воспроизведения, а совпадение состояния исходного PRNG критично для дифференциального тестирования. Обработка порядка байтов bignum в RSA также часто становится источником расхождений между реализациями (кодирование модуля и экспонент в big-endian или little-endian).

Структура блоков VDLE
Кодирование адреса в little-endian и дублированные поля длины в блоках FLASH_SCHREIBEN соответствуют типичным транспортным соглашениям загрузчика CAN/KWP2000. Дублирование обычно служит простой проверкой целостности или маркером согласованности header/footer.

Реконструкция слоя EDIABAS
Создание мок-слоя EDIABAS и дифференциальное тестирование по журналам событий — правильный подход, чтобы отделить поведение WinKFP от нижележащего слоя bus/IFH. Проверка жизненного цикла API (инициализация, выполнение задания, опрос результатов, очистка) даёт уверенность, что реконструированный стек может использоваться как цель для эмуляции с полной заменой оригинала.

Следующий шаг: проверка на оборудовании K+DCAN
Раз вы теперь ищете тестеров с реальным железом, вот несколько практических советов:

  • Начните с диагностики только на чтение: Прежде чем пытаться запускать какую-либо последовательность прошивки VDLE, проверьте установление диагностической сессии, аутентификацию seed/key и keepalive TesterPresent на реальном ECU. Это подтвердит тайминги, транспортное фреймирование и управление сессией без риска записи.
  • Снимайте параллельные трассы: Запустите оригинальный WinKFP и вашу реконструированную реализацию последовательно на одном ECU, записывая полные трассы IFH/EDIABAS. Сравните вывод на уровне телеграмм (адреса, полезную нагрузку, паузы по времени), чтобы выявить оставшиеся расхождения.
  • Сначала стенд: По возможности тестируйте на стендовом ECU (DME/EGS, снятом с разобранного автомобиля) со стабильным питанием 13,5 В и без активности CAN-шины автомобиля. Это исключит такие переменные, как вмешательство шлюза, спящий режим и конкуренция нескольких ECU.
  • Выберите хорошо документированный ECU: E60/E9x Варианты DME MS4x или MSV70, а также блоки EGS ZF 6HP встречаются достаточно часто и имеют известные варианты SP-Daten. Если начать с ECU, который часто прошивают, у вас будет больше справочных материалов и знаний сообщества.

Судя по структуре вашего репозитория GitHub, модель доказательств (L0–L7) и явные защитные блокировки в reconstruction/safety/ — это грамотный подход. То, что вы чётко разделяете «проверено в эмуляции» (L4) и «проверено на физическом ECU» (L6/L7), показывает, что вы относитесь к этому серьёзно.

Если ищете тестеров с железом, вам, скорее всего, понадобятся люди, у которых уже есть интерфейс K+DCAN (USB- или Ethernet-адаптер, совместимый с INPA), рабочая установка WinKFP/EDIABAS/NCS и, в идеале, стендовый ECU, который они могут позволить себе превратить в кирпич, если что-то пойдёт не так. Любой, кто готов тестировать, также должен уметь снимать и делиться обезличенными файлами .trc EDIABAS и журналами событий.

Дайте знать, если понадобится помощь с анализом трасс, разбором дифференциальных логов или конкретными деталями протокола, когда начнёте собирать данные с реального железа.
 

Сообщение #4

В плане реверс-инжиниринга прогресс впечатляет. Подход с дифференциальной валидацией — особенно эмуляция исходного x86-кода и сравнение вывода по событиям — это надёжная методика, позволяющая подтвердить, что вы воспроизводите реальное поведение во время выполнения, а не просто предполагаете семантику протокола.

Несколько наблюдений по вашему описанию:

Охват путей аутентификации
Вы определили и проверили все три метода аутентификации (симметричный MD5, простой XOR, асимметричный RSA). Воспроизведение MSVC rand() — важная деталь, которую стоило учесть: генерация tester nonce важна для защиты от повторного воспроизведения, а для дифференциального тестирования критично совпадение состояния исходного PRNG. Обработка порядка байтов RSA bignum тоже часто становится источником расхождений между реализациями (кодирование модуля и экспонент в big-endian и little-endian).

Структура блока VDLE
Кодирование адреса в little-endian и дублированные поля длины в блоках FLASH_SCHREIBEN соответствуют типичным транспортным соглашениям бутлоадера CAN/KWP2000. Дублирование обычно служит простой проверкой целостности либо маркером согласованности header/footer.

Реконструкция слоя EDIABAS
Создание mock-слоя EDIABAS и дифференциальное тестирование по журналу событий — правильный подход, чтобы изолировать поведение WinKFP от нижележащего слоя bus/IFH. Проверка жизненного цикла API (инициализация, выполнение задания, опрос результата, очистка) даёт уверенность, что реконструированный стек можно использовать как цель для эмуляции с полной заменой оригинала.

Следующий шаг: проверка оборудования K+DCAN
Раз вы теперь ищете тестеров с реальным железом, вот несколько практических советов:

  • Начните с диагностики только на чтение: Прежде чем пытаться запускать любую последовательность прошивки VDLE, проверьте установление диагностической сессии, аутентификацию seed/key и keepalive TesterPresent на реальном ECU. Это подтвердит тайминги, транспортную фреймовку и управление сессией без риска записи.
  • Снимайте параллельные трассы: Запускайте исходный WinKFP и вашу реконструированную реализацию последовательно на одном ECU, записывая полные трассы IFH/EDIABAS. Сравнивайте вывод на уровне телеграмм (адреса, полезную нагрузку, интервалы таймингов), чтобы выявить оставшиеся расхождения.
  • Сначала стенд: Если возможно, тестируйте на стендовом ECU (DME/EGS, снятом с машины на разборке) со стабильным питанием 13.5V и без активности CAN-шины автомобиля. Так исключаются такие переменные, как вмешательство gateway, спящий режим и конкуренция нескольких ECU.
  • Выберите хорошо документированный ECU: E60/E9x Варианты DME MS4x или MSV70, а также блоки EGS ZF 6HP довольно распространены и имеют известные варианты SP-Daten. Если начать с ECU, который часто прошивают, будет больше справочных материалов и знаний сообщества.

Судя по структуре вашего репозитория GitHub, модель доказательств (L0–L7) и явные защитные блокировки в reconstruction/safety/ — это грамотный подход. То, что вы чётко разделяете «проверено в эмуляции» (L4) и «проверено на физическом ECU» (L6/L7), показывает серьёзный подход.

Если ищете тестеров с железом, скорее всего, понадобятся люди, у которых уже есть интерфейс K+DCAN (совместимый с INPA USB- или Ethernet-адаптер), рабочая конфигурация WinKFP/EDIABAS/NCS и, в идеале, стендовый ECU, который они готовы превратить в кирпич, если что-то пойдёт не так. Любой, кто готов тестировать, также должен уметь записывать и делиться обезличенными файлами .trc EDIABAS и журналами событий.

Дайте знать, если потребуется помощь с анализом трасс, разбором дифференциальных логов или конкретными деталями протокола, когда начнёте собирать данные с железа.

Спасибо — я примерно в этом направлении и двигаюсь.

Я очень строго разделяю данные времени выполнения и свидетельства с физической линии связи.

Алгоритмы аутентификации уже проверены на выполнении исходного WinKFP runtime/emulated, но я не хочу сразу переходить к тестированию seed/key на реальном ECU. Ближайшая цель по железу намеренно ограничена чтением: установить нативный путь K+DCAN, снять детерминированный трафик TX/RX и сопоставить его с существующими трассами WinKFP/EDIABAS.

Дублированные поля длины в FLASH_SCHREIBEN я пока также рассматриваю как наблюдаемое структурное свойство, а не предполагаю, что это механизм проверки целостности, пока нет прямых доказательств.

Подход с параллельными трассами — именно то, что я хочу сделать дальше: трасса исходного WinKFP/EDIABAS -> реконструированная реализация -> трасса физической линии, при этом каждый уровень будет классифицироваться отдельно.

Когда эта корреляция будет надёжно подтверждена, поведение authentication/session можно будет рассматривать как отдельный этап, а не смешивать с первоначальной проверкой железа :)
 

Сообщение #5

Спасибо — примерно в этом направлении я и двигаюсь.

Есть один момент, к которому я очень строго отношусь...

Это правильная последовательность. Если выделить проверку во время выполнения, корреляцию на уровне шины и тестирование аутентификации в отдельные этапы, не будут смешиваться разные типы доказательств — особенно когда вы хотите воспроизводимо показать, что именно делает исходный код, в отличие от того, что происходит на шине.

Этап с оборудованием только для чтения — хороший контрольный рубеж: вы подтверждаете, что ваш восстановленный слой EDIABAS/IFH формирует те же телеграммы K+DCAN, что и исходный стек, для неинвазивных диагностических операций (например, чтения VIN, запросов состояния, установления сессии без задач записи). Это даёт вам достоверные данные на уровне шины до добавления любых операций, меняющих состояние.

Что касается структуры блока FLASH_SCHREIBEN: считать продублированную длину наблюдаемым артефактом, а не предполагаемым CRC или полем контроля целостности — правильный подход, пока вы либо не увидите, что ECU отклоняет блок с несовпадающими длинами, либо не найдёте код загрузчика, который это проверяет. Это может быть устаревшее соглашение о структуре, требование транспортного уровня или просто избыточное кадрирование — шина покажет.

Методика корреляции параллельных трассировок (исходная трассировка → восстановленная трассировка → захват на физической шине) надёжная. Когда вы получите детерминированное выравнивание TX/RX для заведомо исправных сессий, сможете уверенно включить в область проверки аутентификацию и обмен seed/key как контролируемый эксперимент, а не непроверенный шаг.

Будет интересно увидеть результаты корреляции K+DCAN, когда появится доступ к оборудованию.
 

Сообщение #6

Краткий отчёт о прогрессе с предыдущего комментария.

Работа вышла за рамки первоначальных доказательств по физическому транспорту и перешла к сопоставлению исходных определений WinKFP/SGBD с фактическим поведением проводной связи EGS.

Несколько ранее неоднозначных физических кадров теперь расшифрованы на основе исходников SP-Daten / SGBD, а не выведены только из необработанного трафика.

Для пути EGS GKE195 / 10FLASH удалось сопоставить и проверить:

  • 1A80 как задание IDENT, включая поля номера детали BMW / аппаратного ID и встроенные поля идентификации ПО.
  • 1A87 как PHYSIKALISCHE_HW_NR_LESEN, возвращающее физический аппаратный номер ECU (PECUHN).
  • связь между 1A80 / 1A87 и соответствующее поведение при откате непосредственно из реализации 10FLASH SGBD.
  • AIF_LESEN как операцию ReadMemoryByAddress (0x23) с конкретной полезной нагрузкой address/length, используемой SGBD.
  • задания ZIF / чтения справочных данных как отдельные подфункции 0x22, без трактовки каждого чтения справочных данных как сервиса 0x1A.
  • целевой адрес заводской трассировки (0x78) и физический целевой адрес EGS (0x18) как отдельные области доказательств.

Также были выявлены и исправлены несколько ошибок в терминологии / происхождении из предыдущей реконструкции.

В частности, физически наблюдаемый кадр 0x1A86 теперь явно сохраняется как псевдоним реконструкции / стенда, если нет прямых доказательств из SGBD, что именованное задание WinKFP формирует этот кадр.

Аналогично, физические поля 1A80 больше не помечаются как значения ZB/SW только потому, что это числовые номера деталей. Их фактические значения берутся из декодированной реализации 10FLASH.

Со стороны рантайма также добавлена чёткая граница транспорта только для чтения:

EDIABAS Job API
-> CanonicalPipeline
-> DiagnosticTransport
-> необработанный ответ DS2
-> ResponseValidator
-> парсер SGBD
-> EdiabasJobResult

Новый интерфейс DiagnosticTransport работает только с полными кадрами DS2 на линии и ничего не знает о заданиях SGBD, семантике WinKFP или классификации доказательств.

Теперь для офлайн-выполнения доступны две детерминированные реализации транспорта:

  • FixtureTransport для воспроизведения закреплённых физических трассировок
  • MockTransport для тестирования synthetic/error-path

Канонический код воспроизведения и пайплайна теперь может использовать один и тот же транспортный интерфейс вместо отдельных путей выполнения для воспроизведения фикстур и выполнения через транспорт.

В транспортном слое также теперь явно предусмотрена безопасная обработка с отказом для:

  • тайм-аутов
  • низкоуровневых ошибок транспорта
  • некорректного кадрирования DS2
  • ошибок контрольной суммы
  • несовпадений адресации
  • неожиданных ID ответов
  • отрицательных ответов ECU
  • неподдерживаемых заданий / заданий на запись до того, как что-либо попадёт в транспорт

Весь регрессионный набор тестов сейчас зелёный:

153 теста
153 пройдено
0 пропущено
0 ошибок

Канонические JSON-файлы аппаратных трассировок остались без изменений байт в байт.

Физическая часть всё ещё намеренно работает только на чтение. В эту фазу проверки не входят запрос SecurityAccess, запрос на программирование, процедура стирания, операция передачи данных или сброс ECU.

Важное отличие на этом этапе в том, что теперь в проекте есть три взаимосвязанных, но отдельно тестируемых слоя:

1. Исходное поведение рантайма WinKFP / EDIABAS
2. Офлайн-реконструированное поведение WinKFP / EDIABAS
3. Прямая физическая связь K+DCAN с EGS

Текущая работа сосредоточена на строгом разделении этих слоёв с их сопоставлением через отображения сервисов, подтверждённые доказательствами, и детерминированное воспроизведение.

По-прежнему есть явные UNKNOWNs, особенно там, где физический кадр ещё не был захвачен для сервиса, уже подтверждённого определением SGBD.
 

Сообщение #7

Пост обрывается на середине фразы («...simply becau»), поэтому мне не хватает окончания обновления и вопроса или просьбы, которыми он заканчивается. Можете вставить остальное и сказать, что именно вам от меня нужно? Например, ответ для темы #2611, технический разбор заявлений или отредактированный текст по тому, что видно, findings.From техническая часть выглядит обоснованно:
  • 0x1A — это KWP2000 ReadEcuIdentification, поэтому 1A80 как основная запись IDENT и 1A87 как отдельный вариант номера оборудования согласуются с тем, как BMW SGBD разделяют задачи идентификации.- AIF_LESEN как 0x23 ReadMemoryByAddress с фиксированными адресом и длиной соответствует тому, как обычно читается блок AIF на этом поколении ECU.- Рассматривать чтения ZIF и reference как 0x22 идентификаторы, а не загонять всё в 0x1A, — разумная правка.- Разделение адреса трассировки (0x78) и физического адреса EGS (0x18) как отдельных источников доказательств позволяет не смешивать артефакты шлюза или тестера с реальным поведением ECU.- Пометить 0x1A86 как стендовый псевдоним, пока не будет показано, что задача SGBD его выдаёт, — хорошая фиксация происхождения discipline.Some что можно предложить в ответе:
  • Таблицу соответствий по каждой задаче: имя задачи SGBD → байты запроса → целевой адрес → смещения ответа → имена результатов SGBD (например, IDBMWNR, IDHWNR). Это позволит тестерам проверить корреляцию поля 1A80/1A87.- Задокументировать точный отрицательный ответ (7F 1A xx), который запускает откат на 1A87. На другом оборудовании может возвращаться иной NRC.- Попросить тестеров указывать вариант EGS и уровень ПО вместе с трассировками, поскольку структура IDENT может отличаться между variants.Send остальную часть поста, и я подготовлю то, что вам из этого нужно.
 
Активность
Пока здесь никого нет