Реверс-инжениринг софта из мафона, часть 1

Исследование внутреннего устройства ГУ от лохуса

Место моего старого верного зеленого друга занял новый белый друг (тоже gs450h), от того и перерыв в блогопостинге.

Так уж вышло что меня заинтересовало устройство головы (он же мафон, он же магнитола, он же головное устроство). Так оно выглядит :

minipic minipic

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

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

minipic

Обновление скачано и лежит передо мной. Сам апдейт сделан довольно лаконично. Всего два файла - бинарник с данными и бинарник с контрольными суммами.

HASHLIST.DAT  размер 32 байт
LOADING.KWI   размер 166 533 120 байт

KWI файл это большой контейнер в котором запаковано все что нужно, плюс щедро разбавлено информацией о версиях, обновляемых системах, производителе и прочем. Но беда в том, что формат недокументирован. На лексусклубе ( http://club-lexus.ru/forum/viewtopic.php?t=76273 ) есть большая тема где пара парней разбирали формат и писали какието утилиты для парсинга. Но попробовав ими воспользоваться, ничего не вышло. Может быть потому что формат изменился с тех пор (врядли), а может потому что для карт навигации формат данных немного другой чем для файлов обновления прошивки (скорее всего именно так). Вооружившись тем что есть, принялся разбирать формат файла. Документация на него если и существует, то, скорее всего, только в тесном кругу программистов, придумавших это чудо. Немного не ясно почему не используется какойто открытый формат хранения подобных контейнеров, наверное чтоб было более "секретно".

Заголовок файла мне удалось выявить используя какойто обрубок скрипта на питоне. Копирайт и заголовок файла :

#!/usr/bin/env python
#
#       kiwi
# http://biot.com/blog/navigation-dvd-hacking
#       Copyright 2009 Bert Vermeulen <bert@biot.com>
#
#       This program is free software; you can redistribute it and/or modify
#       it under the terms of the GNU General Public License as published by
#       the Free Software Foundation; either version 2 of the License, or
#       (at your option) any later version.
#
#       This program is distributed in the hope that it will be useful,
#       but WITHOUT ANY WARRANTY; without even the implied warranty of
#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#       GNU General Public License for more details.
#
#       You should have received a copy of the GNU General Public License
#       along with this program; if not, write to the Free Software
#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#       MA 02110-1301, USA.
#
#
# REV. 1.2 fixed small bug in the extraction section. this still follows 
# GPL v2 and will be distrubuted maintaining current and past info.

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

Структуры заголовка (синтаксис для 101Editor):

typedef struct KWI_FILE_SYSTEMHEADER {
    USHORT  SystemCount;
    USHORT  SystemPadding_1 <hidden=true>;
    BYTE    ManufacturerID[12] <format=hex>;
    USHORT  ModulesCount;
    USHORT  Unknown;
} kwifilesystemheader <bgcolor=cLtGray, optimize=false>;


typedef struct SYSTEM_MODULE_HEADER {
    ModuleCategories Category;
 BYTE             Padding[3];
 CHAR             ModuleName[52];
 CHAR             ModuleVersion[8];
} SYSTEM_MODULE_HEADER;

typedef struct SYSTEM_MODULE_ATTR {
    USHORT StartDate;
 USHORT EndDate;
 CHAR Title[64];
 CHAR Info[182];
 DWORD Address;


    if(AddressMultiplier == 0){
        if(Address < 0x100) AddressMultiplier = 2048;
        else if((Address >> 8) < 0x100) AddressMultiplier = 8;
        else AddressMultiplier = 1;
    }

    USHORT Size;
    //Size = Size * AddressMultiplier;
}SYSTEM_MODULE_ATTR <bgcolor=cLtYellow>;


struct KWI_FIRMWARE_FILE {
    KWI_FILE_SYSTEMHEADER SystemHeader;
    SYSTEM_MODULE_HEADER SystemModules[SystemHeader.ModulesCount];
    SYSTEM_MODULE_ATTR SystemModulesAttr[SystemHeader.ModulesCount] <optimize=false>;

    Printf("AddressMultiplier : %d\r\n", AddressMultiplier);
    Printf("SizeMultipler : %d\r\n", SizeMultipler);

    // 
}kwifile <optimize=false>;

А вот как это выглядит на физщическом файле :

minipic

Что там дальше, уже находилось путем имперических изысканий. Говоря в кратце, киви файл это иерархическое хранилище. Первым делом указывается сколько в нем сущностей, названных автором питоновского скрипта "система". У меня оно одно, я думаю подобный файл можно собрать таким образом, что он будет большой и будет включать в себя несколько паков обновления под разные авто. А авто в свою очередь выберет то, что ему подходит. Далее некая сигнатура, однозначно обозначающая что это именно киви контейнер (сигнатура такая же и для контейнера с картами) и количество включенных модулей. У каждого модуля есть основные атрибуты и расширенные. Основные это имя, версия, тип (программа, данные, еще что-то). Расширенные - дата применимости (?) (от и до какой даты, предположительно, работает модуль), полное название и расширенная информация (текстовая, предположительно это некое описание) о модуле, его размер и стартовое смещение. И смещение и размер может указыватся как в секторах так и в байтах. Думаю, что для киви-файлов выпускаемых изначально на DVD-дисках (обновление карт навигатора тойот), адреса секторные. Сектор 2048 байт, но адрес секторный динамический. Он вычисляется в зависимости от того как он вписан. Математика несложная, вот так вычисляетяс множитель адреса :

if(Address < 0x100) AddressMultiplier = 2048;
else if((Address >> 8) < 0x100) AddressMultiplier = 8;
else AddressMultiplier = 1;

Далее адрес, извлеченный из файла умножается на множитель и получается смещение в байтах. По вычесленному смещению я наткнулся на еще какоето гавно какуюто структуру данных, которая, видимо, характерна только для обновлений прошивки (firmware). Под нее (видимо на всякий случай) выделено аж 2 килобайта, но во моем случае она зполнена лишь частично. Все что ниже этой границы состояит из заголовка и блока данных. Заголовок это набор 4х-байтовых переменных, в каждой из которых вписана длина блока, за каоторый ответственна переменная. То есть берем блок данных, отмеряем Block1Size байт и это переменная Block1. От конца Block1 отмеряем Block2Size байт и это Block2 и так далее. Получается что у нас просто набор разделителей. Имена блоков даны наобум.

struct KWI_MODULE {
    DWORD Block1Size; // Тут картинка, непонятно какая.
    DWORD Block2Size; // Тут картинка, непонятно какая тоже
    DWORD Block3Size; // Тут какаято слабоструктурированная часть, одни нули
    DWORD shit4;      // unused here
    DWORD shit5;      // unused here
    DWORD shit6;      // unused here
    DWORD FirmwareBlockSize; //тут интересное - непосредственно блок обновления.
    DWORD shit8;
}kwimodule <optimize=false, size=2048>;

Я вырезал каждый фрагмент, который заполнен в этой структуре. Касательно первых двух блоков - это изображения. Формат их мне не ясен и пока не интересен. Вот выдержка из поста на форуме

Ок. Это модуль системы denso. Это GraphicDB V0564. Это графический файл. Система читает словами (16 битами), и байты в парах нужно менять местами. Перед этим что то пожее на алфавит, но это палитра из 256 цветов, каждый цвет 8 байт, 3 последних из них это RGB, а через некое кол-во байт после магического слова представление палитры в виде рисунка. Это предположения - кто готов, графический файл в студию. Дальше русифицируем если там что то не русское... Более того после магического слова указано разрешение рисунка/экрана - 400 x 234...

цитата из http://clublex.ru/p3053204

В каких-то случаях используются и другие блоки, но у меня там пустота.

minipic

Самое интересно дальше, в блоке FirmwareBlock, об этом завтра