Чтобы предотвратить снижение IQ во время самоизоляции, возникло желание сделать что-то полезное для себя, а если повезет — не только. Нарезая n-ый круг по квартире, мой взгляд зацепился за автомобильный сканер, который я брал у знакомого для дальнейшего изучения, а именно Lexia 3, он же Actia XS Evolution. Вот такой:
Его огромным минусом было то, что работать с ним может только софт DiagBox, предназначенный для диагностики автомобилей марки Peugeout/Citroen. С последним мириться было нельзя (с), поэтому возникла мысль, а что если этот сканер заставить отправлять и получать произвольные сообщения в CAN-шину автомобиля, тем самым превратив его в универсальный адаптер.
Итак, план действий:
Программный комплекс DiagBox свободно гуляет по интернету, поэтому трудностей с пунктом 1 не возникло, тем более в комплекте с ним идет небольшая утилита для идентификации адаптера, что несколько упростило задачу из пункта 2. При получении обмена по шине USB помогла пробная версия программы USBLyzer.
Идем к успеху. На картинке отправленный пакет данных, вид устройства в диспетчере и та самая утилитка.
Глядя на IRP'ы при открытии устройства и обмене с ним можно сделать вывод, что работа производится через штатный механизм ввода-вывода Windows, а именно, для открытия виртуального файла устройства функция CreateFile и для обмена — DeviceIOControl.
Данные собраны, IOCTL ID и флаги получены, осталось дело за малым, открыть файл-устройство и отправить туда пачку байт. Вот только что открывать? Поиск через WinObj результатов не дал, при подключении адаптер не имеет точного имени, лишь неявную ссылку с постоянно меняющимся ID, то есть просто открыть устройство наподобие COM-порта не получится
Изучение файлов программы внесло ясность, оказалось все довольно просто — адаптер имеет свой уникальный GUID, с помощью которого у операционной системы запрашивается список всех устройств с таким GUID и если они присутствуют, мы получим ссылку на устройство, вида
Функция, возвращающая путь взамен GUID:
«файл» успешно открывается, не забываем про флаги, которые добыли через USBLyzer
Отправляем пакет байт, а в ответ — тишина…
Долго я сидел и смотрел в монитор, вот тот самый обмен, вот приходят ответы от устройства, вот они флаги, в точности такие, как я повторил, но ничего не выходит.
Окончательно потеряв всякую надежду на успех, у меня оставалось последнее — тяжелая артиллерия в виде диска от журнала «Хакер» с программой OllyDbg. Запускаем, аттачимся к процессу, ставим брякпоинт на функции DeviceIoControl и что же мы видим.
Царь-то не настоящий. Абсолютно другой IOCTL код, данные совсем не похожи на те, что видно через USBLyzer.
То, что было отправлено в устройство:
А это ушло по USB:
Подсказка крылась в названии устройства, видимом в диспетчере задач. На сайте Microsoft'а нашел статью о том, что такое UMDF USB драйвер. Наглядная блок-схема:
Выходит, то, что мы видим в USBLyzer'е это транспортный уровень передачи клиентских данных, который реализован в UMDF драйвере (направление 7 на картинке), в то время как мы передаем данные устройству (направление 2 на картинке), которые дойдут сначала в драйвер, а потом уйдут в шину USB. Надеюсь понятно объяснил.
Теперь все стало ясно, откуда другие IOCTL ID и данные. Чтож, так даже проще, не нужно ломать голову над тем, как реализовать транспорт, у нас простейший интерфейс запрос-ответ. Также в файлах программы случайно завалялось описание протокола обмена (частичное), жаль только на французском.
Согласно ему, в сообщении выше была запрошена версия прошивки (00 FA), на что был получен ответ со строкой APPLI_XS_Fuji_ P106138A V4.3.0 @ACTIA 02.01.12.
ВСЕ. Настраиваем CAN, отправляем адреса запрос-ответ для общения по протоколу ISO-TP и получаем полноценно работающий адаптер с автомобилем. Для удобства пользования была написана обертка, которая насколько это возможно соответствует стандарту PassThru J2534, для того, чтобы этот адаптер можно было использовать с различным автомобильным софтом, в том числе собственной разработки.
Видео работы (stdout выведен в консоль для удобства отладки):
Исходники можно посмотреть тут
Его огромным минусом было то, что работать с ним может только софт DiagBox, предназначенный для диагностики автомобилей марки Peugeout/Citroen. С последним мириться было нельзя (с), поэтому возникла мысль, а что если этот сканер заставить отправлять и получать произвольные сообщения в CAN-шину автомобиля, тем самым превратив его в универсальный адаптер.
Итак, план действий:
- Собрать обмен по шине USB между ПК и нашим пациентом.
- Разобраться как происходит общение между драйвером адаптера и программным обеспечением.
- Повторить обмен и почувствовать себя молодцом (спойлер: вышло все несколько сложнее).
1. Обмен
Программный комплекс DiagBox свободно гуляет по интернету, поэтому трудностей с пунктом 1 не возникло, тем более в комплекте с ним идет небольшая утилита для идентификации адаптера, что несколько упростило задачу из пункта 2. При получении обмена по шине USB помогла пробная версия программы USBLyzer.
Идем к успеху. На картинке отправленный пакет данных, вид устройства в диспетчере и та самая утилитка.
Глядя на IRP'ы при открытии устройства и обмене с ним можно сделать вывод, что работа производится через штатный механизм ввода-вывода Windows, а именно, для открытия виртуального файла устройства функция CreateFile и для обмена — DeviceIOControl.
2. Разбор полетов
Данные собраны, IOCTL ID и флаги получены, осталось дело за малым, открыть файл-устройство и отправить туда пачку байт. Вот только что открывать? Поиск через WinObj результатов не дал, при подключении адаптер не имеет точного имени, лишь неявную ссылку с постоянно меняющимся ID, то есть просто открыть устройство наподобие COM-порта не получится
CreateFile("\\\\.\\COM1", ...)
Изучение файлов программы внесло ясность, оказалось все довольно просто — адаптер имеет свой уникальный GUID, с помощью которого у операционной системы запрашивается список всех устройств с таким GUID и если они присутствуют, мы получим ссылку на устройство, вида
\\?\USB#VID_103A&PID_F000#6&268bff9b&0&7#{75a835f4-d77d-4402-8585-c42247f25b76}\vcommusb0
открытие которой будет успешным. Функция, возвращающая путь взамен GUID:
CM_Get_Device_Interface_List(InterfaceClassGuid, pDeviceID, Buffer, BufferLen, ulFlags);
«файл» успешно открывается, не забываем про флаги, которые добыли через USBLyzer
Device = CreateFile(DeviceName, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
3. Финал
Отправляем пакет байт, а в ответ — тишина…
bStatus = DeviceIoControl(Device, 0x220003, send_buf, send_len, out_buf, max_out_len, &returned_len, NULL);
Долго я сидел и смотрел в монитор, вот тот самый обмен, вот приходят ответы от устройства, вот они флаги, в точности такие, как я повторил, но ничего не выходит.
Окончательно потеряв всякую надежду на успех, у меня оставалось последнее — тяжелая артиллерия в виде диска от журнала «Хакер» с программой OllyDbg. Запускаем, аттачимся к процессу, ставим брякпоинт на функции DeviceIoControl и что же мы видим.
Царь-то не настоящий. Абсолютно другой IOCTL код, данные совсем не похожи на те, что видно через USBLyzer.
То, что было отправлено в устройство:
<b>00 FA</b> <i>AA</i> BA 7C 15 00 00 00 00 00 00
А это ушло по USB:
40 05 15 C0 <b>00 FA</b> 00 00 <i>AA</i> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 41
Подсказка крылась в названии устройства, видимом в диспетчере задач. На сайте Microsoft'а нашел статью о том, что такое UMDF USB драйвер. Наглядная блок-схема:
Выходит, то, что мы видим в USBLyzer'е это транспортный уровень передачи клиентских данных, который реализован в UMDF драйвере (направление 7 на картинке), в то время как мы передаем данные устройству (направление 2 на картинке), которые дойдут сначала в драйвер, а потом уйдут в шину USB. Надеюсь понятно объяснил.
Теперь все стало ясно, откуда другие IOCTL ID и данные. Чтож, так даже проще, не нужно ломать голову над тем, как реализовать транспорт, у нас простейший интерфейс запрос-ответ. Также в файлах программы случайно завалялось описание протокола обмена (частичное), жаль только на французском.
Согласно ему, в сообщении выше была запрошена версия прошивки (00 FA), на что был получен ответ со строкой APPLI_XS_Fuji_ P106138A V4.3.0 @ACTIA 02.01.12.
ВСЕ. Настраиваем CAN, отправляем адреса запрос-ответ для общения по протоколу ISO-TP и получаем полноценно работающий адаптер с автомобилем. Для удобства пользования была написана обертка, которая насколько это возможно соответствует стандарту PassThru J2534, для того, чтобы этот адаптер можно было использовать с различным автомобильным софтом, в том числе собственной разработки.
Видео работы (stdout выведен в консоль для удобства отладки):
Исходники можно посмотреть тут
kolu4iy
А обратная задача? Произвольный J2534 (диалинк, например) в качестве lexia — получится? :)
kolyandex Автор
Думаю да, но только CAN составляющая, ибо у французов помимо него свой проприетарный интерфейс, который J2534 не поддерживает.
Denuo
Dialink не получится. DiagBox® видит его как J2534 интерфейс, но при попытке связаться с машиной при тестировании интерфейса по всем блоком показывает ошибку. Я связывался с разработчиком Dialink, отсылал ему логи, он сказал что их адаптер не поддерживает один из запрашиваемых протоколов, обещал посмотреть что можно сделать, на этом общение прекратилось.
Простое гугление показало что французы тестировали DiagBox с адаптерами Bosch KTS и DrewTech CarDAQ?M и могут их рекомендовать для использования. Адаптеры попроще скорее всего просто не умеют мультиплицировать (работать с несколькими протоколами одновременно). В теории, из дешевых адаптеров с ДиагБоксом сможет работать Сhipsoft j2534 Pro, потому что умеет мультиплицировать K-Line и Can на определённых пинах, ЕМНИП 3-8.
kolyandex Автор
Тут я ничего не могу сказать, с французами не знаком абсолютно. Только япошки.
Denuo
Добавлю, что переделка Actia psa xs evolution в Actia Passthru+ XS 2G (то есть в VCI c полноценной поддержкой стандарта J2534-1/2) и обратно — это чуть ли не штатный функционал, по крайней мере я встречал статьи на эту тему. У меня не получилось это проделать из-за того, что был только китайский клон адаптера.