Статья Взлом ЭБУ гидроусилителя руля VW Golf - #1

timeshout

RAID-массив
Пользователь
Регистрация
29.06.2022
Сообщения
62
Реакции
83
В этой серии статей я опишу свои попытки модификации прошивки ЭБУ электронного усилителя руля (EPS) от Volkswagen Golf Mk6 2010 года. Эта рулевая рейка, вероятно, присутствует на всех автомобилях платформы VW PQ, начиная с 2008 года и по настоящее время. Автомобили с платформы PQ46 производятся до сих пор (например, Pasat NMS 2022 года). Это, вероятно, означает, что это один из самых производимых модулей EPS в этой области.

Несмотря на то, что стойка была представлена еще в 2008 году, поддержка Lane Keep Assist (LKAS) или Heading Control Assist (HCA) в терминологии VW уже присутствует. Это позволяет использовать этот автомобиль с openpilot, системой помощи водителю с открытым исходным кодом. К сожалению, команды рулевого управления не принимаются после 6 минут непрерывной работы или на скорости ниже 50 км/ч. В этот момент необходимо отключить руль на целую секунду. Я считаю, что эти меры контрпродуктивны и ставят под угрозу безопасность, когда уже имеется надлежащая система контроля водителя на основе камер. Поэтому я хотел внести некоторые изменения в прошивку, работающую на этом EPS, чтобы отключить их.


весь код, написанный для связи с ECU и, в конечном итоге, его перепрошивки, является открытым исходным кодом и может быть найден здесь: https://github.com/pd0wm/pq-flasher .


Получение деталей
Первым шагом к взлому ЭБУ будет получение одного (или нескольких) данного ЭБУ. Для этого нам необходимо получить номер детали. Если ЭБУ находится в доступном месте, номер детали обычно можно считать с модуля. Если ЭБУ находится глубоко внутри автомобиля, возможно, вы сможете найти его на сайте производителя запчастей или на Ebay.

В качестве альтернативы, если вы хотите быть уверенным на 100%, вы можете использовать диагностический прибор для опроса ЭБУ по CAN. Обычно он может напрямую сообщить вам номер детали. В данном случае был использован последний способ, и номер детали: 1K0909144E.

Имея на руках номер детали, мы можем искать запчасти из вторых рук. Чем старше и проданнее автомобиль, тем проще и дешевле это будет сделать. В зависимости от вашего местоположения вам, возможно, придется искать на нескольких сайтах. В США мне больше всего повезло с Ebay и LKQ Online. В Европе доставка может сделать Ebay дороже, чем поиск на местном рынке. Просто набрав в Гугле номер детали, можно найти несколько результатов. Для этого проекта я нашел одну деталь на сайте onderdelenlijn.nl и забрал ее в нескольких минутах езды от моего дома. Я заплатил всего 100 евро за всю стойку, поскольку это такая распространенная деталь. Для более современных автомобилей вы можете заплатить до $200-$500 в зависимости от типа ЭБУ.

1656834230702.png


Разборка
Теперь, когда у нас есть дубликат интересующего нас ЭБУ, мы можем рассмотреть его поближе. Наша первая цель - запустить его и поговорить с ним по CAN, чтобы убедиться, что он все еще работает. Во-вторых, мы хотим подключить отладчик к микроконтроллеру внутри, чтобы посмотреть, сможем ли мы извлечь прошивку в случае, если доступ к отладке не был отключен.

Для подключения к ЭБУ нам необходимо найти распиновку разъема. Обычно это можно получить с помощью оригинальной схемы. Большинство производителей автомобилей предлагают подписку на все свои руководства и схемы, обычно с дешевым вариантом на 1 день (например, Toyota TIS, Honda Techinfo и VW Erwin). Премиум-подписки обычно также поставляются с оригинальным диагностическим программным обеспечением, которое можно использовать с любым J2534-ключом, таким как panda или Tactrix.


В данном случае, после подключения к панде и запуска простого инструмента дампа, мы получили хороший CAN-трафик. Мы можем сопоставить его с соответствующим файлом Golf DBC и подтвердить, что это действительно сообщения, отправленные EPS (Lenkwinkel_1, Lenkhilfe_3, Lenkhilfe_1 и Lenkhilfe_2).
DBC: https://github.com/commaai/opendbc/blob/master/vw_golf_mk4.dbc

Код:
hex  ( dec) data
0x0C2( 194) b'0000000080224bdd'
0x0D0( 208) b'44b0002004d0'
0x3D0( 976) b'00a10028005d'
0x3D2( 978) b'52411200010000'

Похоже, что электроника изготовлена с использованием голых матриц, прикрепленных к какой-то подложке, вероятно, для снижения стоимости и повышения надежности при высоких температурах. Плата состоит из двух частей, маломощной части с процессором и приемопередатчиками CAN, и высокомощной части с 6 МОП-транзисторами, образующими трехфазный H-мост.

1656834483251.png



Чтобы узнать больше об этом ЭБУ, мы должны провести дополнительные исследования с помощью доступного интерфейса CAN.

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

Если микроконтроллер выполнен в корпусе BGA и контакты не оголены, можно использовать JTAGULATOR для "перебора" распиновки отладчика. Если это не принесет результатов, можно пожертвовать другим ЭБУ, выпаяв компонент BGA.

Поскольку у нас уже есть ЭБУ, подключенный к компьютеру с помощью панды, мы можем попытаться выяснить, можем ли мы общаться с ним по одному из стандартных диагностических протоколов, таких как UDS или его предшественник KWP2000. UDS/KWP2000 имеют много полезных "конечных точек", включая чтение памяти, так что это будет хорошим местом для начала.

Мы можем начать с запуска небольшого скрипта сканирования. Он отправит команду UDS "Tester Present" на наиболее часто используемые адреса диагностики (0x700 - 0x7ff, 0x18da00f1 - 0x18dafff1). Однако это не принесло никаких результатов. Это означает, что UDS/KWP2000 не используется, по крайней мере, не используется стандартный транспорт ISO-TP.

Код:
#!/usr/bin/env python3
import argparse
from tqdm import tqdm
from panda import Panda
from panda.python.uds import UdsClient, MessageTimeoutError, NegativeResponseError, SESSION_TYPE, DATA_IDENTIFIER_TYPE

if __name__ == "__main__":
  parser = argparse.ArgumentParser()
  parser.add_argument('--rxoffset', default="")
  parser.add_argument('--nonstandard', action='store_true')
  parser.add_argument('--debug', action='store_true')
  parser.add_argument('--addr')
  args = parser.parse_args()

  if args.addr:
    addrs = [int(args.addr, base=16)]
  else:
    addrs = [0x700 + i for i in range(256)]
    addrs += [0x18da0000 + (i << 8) + 0xf1 for i in range(256)]
  results = {}

  uds_data_ids = {}
  for std_id in DATA_IDENTIFIER_TYPE:
    uds_data_ids[std_id.value] = std_id.name
  if args.nonstandard:
    for uds_id in range(0xf100,0xf180):
      uds_data_ids[uds_id] = "IDENTIFICATION_OPTION_VEHICLE_MANUFACTURER_SPECIFIC_DATA_IDENTIFIER"
    for uds_id in range(0xf1a0,0xf1f0):
      uds_data_ids[uds_id] = "IDENTIFICATION_OPTION_VEHICLE_MANUFACTURER_SPECIFIC"
    for uds_id in range(0xf1f0,0xf200):
      uds_data_ids[uds_id] = "IDENTIFICATION_OPTION_SYSTEM_SUPPLIER_SPECIFIC"

  panda = Panda()
  panda.set_safety_mode(Panda.SAFETY_ELM327)
  print("querying addresses ...")
  with tqdm(addrs) as t:
    for addr in t:
      # skip functional broadcast addrs
      if addr == 0x7df or addr == 0x18db33f1:
        continue
      t.set_description(hex(addr))
      panda.send_heartbeat()

      bus = 1 if panda.has_obd() else 0
      rx_addr = addr + int(args.rxoffset, base=16) if args.rxoffset else None
      uds_client = UdsClient(panda, addr, rx_addr, bus, timeout=0.2, debug=args.debug)
      # Check for anything alive at this address, and switch to the highest
      # available diagnostic session without security access
      try:
        uds_client.tester_present()
        uds_client.diagnostic_session_control(SESSION_TYPE.DEFAULT)
        uds_client.diagnostic_session_control(SESSION_TYPE.EXTENDED_DIAGNOSTIC)
      except NegativeResponseError:
        pass
      except MessageTimeoutError:
        continue

      # Run queries against all standard UDS data identifiers, plus selected
      # non-standardized identifier ranges if requested
      resp = {}
      for uds_data_id in sorted(uds_data_ids):
        try:
          data = uds_client.read_data_by_identifier(uds_data_id)  # type: ignore
          if data:
            resp[uds_data_id] = data
        except (NegativeResponseError, MessageTimeoutError):
          pass

      if resp.keys():
        results[addr] = resp

    if len(results.items()):
      for addr, resp in results.items():
        print(f"\n\n*** Results for address 0x{addr:X} ***\n\n")
        for rid, dat in resp.items():
          print(f"0x{rid:02X} {uds_data_ids[rid]}: {dat}")
    else:
      print("no fw versions found!")

Поскольку сообщения CAN могут содержать только 8 байт, обычно между протоколом диагностики и необработанными сообщениями CAN используется транспортный уровень для передачи больших кусков данных. Большинство ЭБУ используют протокол ISO-TP, который использует первый байт в каждом сообщении для указания счетчика последовательности и того, последуют ли еще сообщения. Он также содержит некоторое управление потоком для случаев, когда принимающий ЭБУ еще не готов к приему. Для диагностики в диапазоне 0x7XX ответы обычно отправляются по адресу TX + 0x8, для сообщений в диапазоне 0x18daXXf1 последние два байта адреса меняются местами.

В этот момент я решил подключить коммерческий диагностический донгл VW, который использует приложение Android для общения с ЭБУ, чтобы посмотреть, что это даст. После того, как я убедил донгл подключиться (несмотря на то, что большая часть автомобиля не присутствовала на шине CAN), он смог показать некоторую диагностическую информацию об ЭБУ.


1656834747095.png


Volkswagen Transport Protocol 2.0 (TP 2.0)

Теперь, когда есть некоторая связь, я использовал панду для прослушивания трафика CAN. Это дало нам следующий трафик:

Код:
time     address  data
0.339    0x200    b'09c00010000301'   # dongle - Request channel open
0.342    0x209    b'00d00003a80701'   # ECU    - Channel open response
0.343    0x7a8    b'a00f8aff0aff'     # dongle - Parameter request
0.352    0x300    b'a10f8aff4aff'     # ECU.   - Parameter response
0.407    0x7a8    b'1000021089'       # dongle - 0x10 0x89 - Enter diagnostics mode 0x89
0.412    0x300    b'b1'               # ECU    - ACK
0.422    0x300    b'1000025089'       # ECU    - 0x50 0x89 - Mode 0x89 entered
0.425    0x7a8    b'b1'               # dongle - ACK
0.587    0x7a8    b'1100021089'       # dongle - 0x10 0x89 - Enter diagnostics mode 0x89
0.592    0x300    b'b2'               # ECU    - ACK
0.602    0x300    b'1100025089'       # ECU    - 0x50 0x89 - Mode 0x89 entered
0.605    0x7a8    b'b2'               # dongle - ACK
0.643    0x7a8    b'1200021a9b'       # dongle - 0x1a 0x9b - Ecu identification
0.652    0x300    b'b3'               # ECU - ACK
0.662    0x300    b'2200305a9b314b30' # ECU - "Z.1K0"
0.672    0x300    b'2339303931343445' # ECU - "909144E"
0.682    0x300    b'2420203235303100' # ECU - "  2501."
0.692    0x300    b'2500000000064016' # ECU - ".....@."
0.702    0x300    b'26054d4550535f5a' # ECU - ".MEPS_Z"
0.712    0x300    b'27464c53204b6c2e' # ECU - "FLS Kl."
0.722    0x300    b'2820313834202020' # ECU - " 184.  "
0.732    0x300    b'1920'             # ECU - " "
0.735    0x7a8    b'ba'               # dongle - ACK

Вы можете увидеть обмен одним сообщением на парах 0x200-0x209, затем связь возобновляется на 0x7a8 и 0x300. Беглый поиск в Google показывает, что это должен быть транспортный протокол Volkswagen Transport Protocol 2.0 (TP 2.0). Информации не так много, но достаточно, чтобы понять, что происходит, и расшифровать приведенный выше фрагмент.

Мы видим, как открывается канал с модулем 0x9. Затем мы видим 0x10 0x89, который входит в диагностическую сессию с помощью KWP2000. Затем приложение запрашивает идентификацию ecu, используя 0x1a 0x9b, с Z.1K0909144E 2501......@..MEPS_ZFLS Kl. 184 в качестве ответа (что соответствует тому, что мы видим в приложении на предыдущем рисунке).

Теперь, когда мы знаем, какой протокол используется, я могу написать свою собственную реализацию на Python. Этот репозиторий GitHub содержит весь код, использованный в этом проекте, на случай, если у вас на столе тоже есть ecu и вы хотите поиграть с ним дома. Я реализовал транспортный уровень TP 2.0 и некоторые полезные сервисы KWP2000. Это будет использовано в последующих частях для проведения дополнительной диагностики и, в конечном итоге, перепрошивки ЭБУ.


Пожалуйста, дождитесь следующей части!

Hacking a VW Golf Power Steering ECU - Part 1

 
Эта рулевая рейка, вероятно, присутствует на всех автомобилях платформы VW PQ, начиная с 2008 года и по настоящее время. Автомобили с платформы PQ46 производятся до сих пор (например, Pasat NMS 2022 года).
то о котором поколении ты говоришь, это поколение pq35, после pq35 пошло поколение mqb, помоему ты втираешь какую то дичь
но в целом лайк
 
это довольно неплохой перевод буржевской статьи
возникает вопрос, а никто не видел готовой/полуготовой реализации управления ЭБУ усилителя руля с возможностью его дистанционного управления через сеть?
не совсем то, что в комма.ио только функционал подруливания (изменения оборотоа руля на х градусов) без полноценной нейронки и лидаров.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх