Собираем здесь информацию о структурах системных файлов моторолы и о способах чтения инфы из них. Описание парсеров, декодеров и способов решения возникающих проблем.
Начнём с описания структуры файла DL_DMH_File, отвечающего за хранение телефонной книги и календаря.
Я выделил два поколения DL_DMH_File файлов. Первое – файлы без каких-либо заголовков, второе – со следующим заголовком в начале: "DMH_FILE_HEADER_00.00.02".
В начале идёт служебная информация о содержании и/или структуре самого файла, далее идут записи телефонной книжки и в конце - записи календаря. Начальные смещения для календаря и телефонной книжки различны для разных моделей телефона и небыли обнаружены в служебной информации из начала файла. По этой причине предлагается блочное сканирование всего файла, начиная с некоторого смещения.
Размер одной записи телефонной книжки кратен 0x20 байтам, например: 0x20, 0x40, 0x80 и 0x240 байт (эти размеры блоков были встречены в изучаемых файлах). Начинать чтение блоков необходимо с некоторого начального смещения, которое различно для разных моделей. Для решения этой проблемы предлагается следующий алгоритм получения начального смещения:
dwStartPos = dwFileSize % 0x100 - (для файлов первого поколения)
или
dwStartPos = dwFileSize % 0x100 + длинна заголовка (=0x18) - (для файлов второго поколения).
Таким образом, предлагается чтение, начиная с вычисленного смещения, блоков размером большим, чем 0x240 байт и кратным 0x20 байтам. Но при этом блоки читать со смещением в 0x20 байт. Таким образом, не будут пропущены маленькие записи, но в случае, когда записи длиннее 0x20 байт, буфер будет периодически содержать куски данных из разных записей. Эта ситуация должна контролироваться на уровне парсеров, т.е. парсеры не должны пропускать некорректные данные, которых будет намного больше чем корректных записей по причине сканирования всего файла.
Для файлов первого поколения были расшифрованы записи шесть типов, по этой причине один буфер прогоняется через шесть декодировщика и ответ каждого из них необходимо рассматривать как верный, т.е. для одного блока может быть до трёх расшифровок.
Первый тип записи:
03 FE 81 0D 08 90 BB B5 BA C1 B5 B9 20 97 B0 B8
BA B0 07 81 08 79 79 83 91 F3 FF FF FF FF FF FF
FF FF FF FF FF 00 00 01 FF 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 FF FE EF FF FE
Первый байт записи должен быть меньше 0xEE, третий байт должен быть равен 0x81, пятый - 0x08. Имя начинается с шестого байта, четвёртый байт – длина имени в байтах. Имя храниться в моторола-кодировке, которая представляет собой «обрезанную» версию UTF8 – храниться лишь последний байт символа, стальные байты отбрасываются и для их восстановления необходима информация о ленг-паке телефона. Далее следует байт длинны номера телефона (в байтах), и за ним следует сам номер в BCD с перевернутыми байтами. Если первый байт номера равен 0x91, то в начале номера идёт символ «+», иначе (обычно 0x81) он просто пропускается.
Второй тип записи:
81 05 08 90 BB 20 98 B2 07 91 97 01 09 62 64 F5
FF FF 04 FE FF FF FF FF FF FF FF FF FF 00 00 28
FF FF FF 00 00 04 FF FF FE EF FF FE EF FF FE EF
FF FE EF FF FE EF FF FE EF FF FE EF FF FE EF FF
Структура второго типа полностью совпадает со структурой первого типа, без первых двух байт.
Третий тип записи:
03 FE 80 22 04 15 04 21 04 22 04 FF FF 07 81 08
79 79 83 91 F3 FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF 00 00 01 FF 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 FF FE EF FF FE
Первый байт записи должен быть меньше 0xEE, третий байт должен быть равен 0x80. Имя начинается с четвёртого байта, длина имени не храниться – если имя короче 0x30 байт, то оно заканчивается словом 0xFFFF, иначе оно занимает ровно 0x30 байт (возможно в разных телефонах эта длина окажется различной) и завершающего слова нет. Имя храниться в LITLEENDIAN UNICODE. Далее (аналогично) следует байт длинны номера телефона (в байтах), и за ним следует сам номер в BCD с перевернутыми байтами. Если первый байт номера равен 0x91, то в начале номера идёт символ «+», иначе (обычно 0x81) он просто пропускается.
Четвёртый тип записи:
00 FE 54 65 73 74 2E FF 05 81 21 45 55 45 FF FF
FF 00 02 00 00 4E 46 45 E2 DF 01 00 0D FF 04 10
04 34 04 38 04 3C 04 40 00 00 00 55 00 6C 00 69
00 63 00 61 00 00 00 55 00 6C 00 69 00 63 00 61
00 32 00 00 00 43 00 69 00 74 00 69 00 00 00 50
00 49 00 6E 00 64 00 65 00 78 00 00 00 4F 00 62
00 6C 00 61 00 73 00 74 00 00 00 43 00 6F 00 75
00 6E 00 74 00 72 00 69 00 00 15 05 07 D6 14 EF
46 DF EB C0 46 E0 90 6F 00 00 00 00 00 03 C0 80
00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00
04 22 04 35 04 41 04 42 00 31 00 00 00 FF FE EF
FF FE EF FF FE EF FF FE EF FF FE EF FF FE EF FF
46 E0 15 F0 46 E0 90 89 00 00 00 00 00 03 C0 80
00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00
04 22 04 35 04 41 04 42 00 32 00 00 00 FE EF FF
FE EF FF FE EF FF FE EF FF FE EF FF FE EF FF FE
Имя начинается с третьего байта, длина имени не храниться – оно заканчивается байтом 0xFF. Имя храниться в ANSI. Далее (аналогично) следует байт длинны номера телефона (в байтах), и за ним следует сам номер в BCD с перевернутыми байтами. Если первый байт номера равен 0x91, то в начале номера идёт символ «+», иначе (обычно 0x81) он просто пропускается.
Пятый тип записи:
54 65 73 74 2E FF 05 81 21 45 55 45 FF FF FF FF
FF 00 02 00 00 4E 46 45 E2 DF 01 00 0D FF 04 10
04 34 04 38 04 3C 04 40 00 00 00 55 00 6C 00 69
00 63 00 61 00 00 00 55 00 6C 00 69 00 63 00 61
00 32 00 00 00 43 00 69 00 74 00 69 00 00 00 50
00 49 00 6E 00 64 00 65 00 78 00 00 00 4F 00 62
00 6C 00 61 00 73 00 74 00 00 00 43 00 6F 00 75
00 6E 00 74 00 72 00 69 00 00 15 05 07 D6 14 EF
46 DF EB C0 46 E0 90 6F 00 00 00 00 00 03 C0 80
00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00
04 22 04 35 04 41 04 42 00 31 00 00 00 FF FE EF
FF FE EF FF FE EF FF FE EF FF FE EF FF FE EF FF
46 E0 15 F0 46 E0 90 89 00 00 00 00 00 03 C0 80
00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00
04 22 04 35 04 41 04 42 00 32 00 00 00 FE EF FF
FE EF FF FE EF FF FE EF FF FE EF FF FE EF FF FE
Структура пятого типа полностью совпадает со структурой четвёртого типа, без первых двух байт.
Шестой тип записи:
80 1C 04 30 04 40 04 38 04 3D 04 30 04 FF FF 07
81 08 66 63 19 93 F3 FF FF 03 FE 3F 58 CC F3 46
CC 00 00 00 00 00 01 FF EF FF FE EF FF FE EF FF
FE EF FF FE EF FF FE EF FF FE EF FF FE EF FF FE
80 1C 04 30 04 40 04 38 04 3D 04 30 04 FF FF 6D
61 72 75 73 79 61 40 61 70 72 69 6F 72 69 74 2E
63 6F 6D 00 06 FE 51 FF FF FF FF FF FF FF FF 00
00 01 FF EF FF FE EF FF FE EF FF FE EF FF FE EF
Первый байт должен быть равен 0x80. Имя начинается со второго байта, длина имени не храниться – если имя короче 0x30 байт, то оно заканчивается словом 0xFFFF, иначе оно занимает ровно 0x30 байт (возможно в разных телефонах эта длина окажется различной) и завершающего слова нет. Имя храниться в BIGENDIAN UNICODE. Далее (аналогично) следует байт длинны номера телефона (в байтах), и за ним следует сам номер в BCD с перевернутыми байтами. Если первый байт номера равен 0x91, то в начале номера идёт символ «+», иначе (обычно 0x81) он просто пропускается. Этот тип похож на третий и отличается от него отсутствием первых двух байт и типом хранения текста.
Файлы второго поколения более универсальны и имеют следующую структуру:
01 81 09 04 1C 30 40 38 3D 3E 47 3A 30 81 00 00
81 00 00 07 81 08 92 85 86 79 F2 FF FF FF FF FF
FF 00 00 00 00 00 00 00 81 00 00 00 00 00 00 00
16 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 81 00 00 81 00 00 03 FF FF FF FF FF FF FF FF
FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 81 00 00 81 00 00 81 00
00 81 00 00 81 00 00 81 00 00 81 00 00 81 00 00
81 00 00 81 00 00 81 00 00 81 00 00 81 00 00 81
00 00 81 00 00 81 00 00 00 00 00 00 00 81 00 00
00 00 00 00 00 00 00 00 00 01 03 00 0D 00 00 00
B3 FF FF FF FF FF FF FF FF FE FE FE FE FE FE FE
Первый байт записи должен быть равен 0x01, второй байт должен быть равен 0x81. Имя начинается с пятого байта, длина имени храниться в третьем байте (в байтах). Имя храниться в «упакованном» UNICODE – первый байт, если он одинаков для всего имени, вырезан и храниться в байте перед байтом длинны (четвёртом) имени. Далее снова идёт 0x81, длинна, вырезанный общий байт, имя в такой же кодировке. Далее снова идёт 0x81, длинна, вырезанный общий байт, имя в такой же кодировке. Далее (аналогично) следует байт длинны номера телефона (в байтах), и за ним следует сам номер в BCD с перевернутыми байтами. Если первый байт номера равен 0x91, то в начале номера идёт символ «+», иначе (обычно 0x81) он просто пропускается.
Сообщение отредактировал Ailinor - 20.10.2007, 21:00
Начнём с описания структуры файла DL_DMH_File, отвечающего за хранение телефонной книги и календаря.
Я выделил два поколения DL_DMH_File файлов. Первое – файлы без каких-либо заголовков, второе – со следующим заголовком в начале: "DMH_FILE_HEADER_00.00.02".
В начале идёт служебная информация о содержании и/или структуре самого файла, далее идут записи телефонной книжки и в конце - записи календаря. Начальные смещения для календаря и телефонной книжки различны для разных моделей телефона и небыли обнаружены в служебной информации из начала файла. По этой причине предлагается блочное сканирование всего файла, начиная с некоторого смещения.
Размер одной записи телефонной книжки кратен 0x20 байтам, например: 0x20, 0x40, 0x80 и 0x240 байт (эти размеры блоков были встречены в изучаемых файлах). Начинать чтение блоков необходимо с некоторого начального смещения, которое различно для разных моделей. Для решения этой проблемы предлагается следующий алгоритм получения начального смещения:
dwStartPos = dwFileSize % 0x100 - (для файлов первого поколения)
или
dwStartPos = dwFileSize % 0x100 + длинна заголовка (=0x18) - (для файлов второго поколения).
Таким образом, предлагается чтение, начиная с вычисленного смещения, блоков размером большим, чем 0x240 байт и кратным 0x20 байтам. Но при этом блоки читать со смещением в 0x20 байт. Таким образом, не будут пропущены маленькие записи, но в случае, когда записи длиннее 0x20 байт, буфер будет периодически содержать куски данных из разных записей. Эта ситуация должна контролироваться на уровне парсеров, т.е. парсеры не должны пропускать некорректные данные, которых будет намного больше чем корректных записей по причине сканирования всего файла.
Для файлов первого поколения были расшифрованы записи шесть типов, по этой причине один буфер прогоняется через шесть декодировщика и ответ каждого из них необходимо рассматривать как верный, т.е. для одного блока может быть до трёх расшифровок.
Первый тип записи:
Код
03 FE 81 0D 08 90 BB B5 BA C1 B5 B9 20 97 B0 B8
BA B0 07 81 08 79 79 83 91 F3 FF FF FF FF FF FF
FF FF FF FF FF 00 00 01 FF 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 FF FE EF FF FE
Первый байт записи должен быть меньше 0xEE, третий байт должен быть равен 0x81, пятый - 0x08. Имя начинается с шестого байта, четвёртый байт – длина имени в байтах. Имя храниться в моторола-кодировке, которая представляет собой «обрезанную» версию UTF8 – храниться лишь последний байт символа, стальные байты отбрасываются и для их восстановления необходима информация о ленг-паке телефона. Далее следует байт длинны номера телефона (в байтах), и за ним следует сам номер в BCD с перевернутыми байтами. Если первый байт номера равен 0x91, то в начале номера идёт символ «+», иначе (обычно 0x81) он просто пропускается.
Второй тип записи:
Код
81 05 08 90 BB 20 98 B2 07 91 97 01 09 62 64 F5
FF FF 04 FE FF FF FF FF FF FF FF FF FF 00 00 28
FF FF FF 00 00 04 FF FF FE EF FF FE EF FF FE EF
FF FE EF FF FE EF FF FE EF FF FE EF FF FE EF FF
Структура второго типа полностью совпадает со структурой первого типа, без первых двух байт.
Третий тип записи:
Код
03 FE 80 22 04 15 04 21 04 22 04 FF FF 07 81 08
79 79 83 91 F3 FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF 00 00 01 FF 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 FF FE EF FF FE
Первый байт записи должен быть меньше 0xEE, третий байт должен быть равен 0x80. Имя начинается с четвёртого байта, длина имени не храниться – если имя короче 0x30 байт, то оно заканчивается словом 0xFFFF, иначе оно занимает ровно 0x30 байт (возможно в разных телефонах эта длина окажется различной) и завершающего слова нет. Имя храниться в LITLEENDIAN UNICODE. Далее (аналогично) следует байт длинны номера телефона (в байтах), и за ним следует сам номер в BCD с перевернутыми байтами. Если первый байт номера равен 0x91, то в начале номера идёт символ «+», иначе (обычно 0x81) он просто пропускается.
Четвёртый тип записи:
Код
00 FE 54 65 73 74 2E FF 05 81 21 45 55 45 FF FF
FF 00 02 00 00 4E 46 45 E2 DF 01 00 0D FF 04 10
04 34 04 38 04 3C 04 40 00 00 00 55 00 6C 00 69
00 63 00 61 00 00 00 55 00 6C 00 69 00 63 00 61
00 32 00 00 00 43 00 69 00 74 00 69 00 00 00 50
00 49 00 6E 00 64 00 65 00 78 00 00 00 4F 00 62
00 6C 00 61 00 73 00 74 00 00 00 43 00 6F 00 75
00 6E 00 74 00 72 00 69 00 00 15 05 07 D6 14 EF
46 DF EB C0 46 E0 90 6F 00 00 00 00 00 03 C0 80
00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00
04 22 04 35 04 41 04 42 00 31 00 00 00 FF FE EF
FF FE EF FF FE EF FF FE EF FF FE EF FF FE EF FF
46 E0 15 F0 46 E0 90 89 00 00 00 00 00 03 C0 80
00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00
04 22 04 35 04 41 04 42 00 32 00 00 00 FE EF FF
FE EF FF FE EF FF FE EF FF FE EF FF FE EF FF FE
Имя начинается с третьего байта, длина имени не храниться – оно заканчивается байтом 0xFF. Имя храниться в ANSI. Далее (аналогично) следует байт длинны номера телефона (в байтах), и за ним следует сам номер в BCD с перевернутыми байтами. Если первый байт номера равен 0x91, то в начале номера идёт символ «+», иначе (обычно 0x81) он просто пропускается.
Пятый тип записи:
Код
54 65 73 74 2E FF 05 81 21 45 55 45 FF FF FF FF
FF 00 02 00 00 4E 46 45 E2 DF 01 00 0D FF 04 10
04 34 04 38 04 3C 04 40 00 00 00 55 00 6C 00 69
00 63 00 61 00 00 00 55 00 6C 00 69 00 63 00 61
00 32 00 00 00 43 00 69 00 74 00 69 00 00 00 50
00 49 00 6E 00 64 00 65 00 78 00 00 00 4F 00 62
00 6C 00 61 00 73 00 74 00 00 00 43 00 6F 00 75
00 6E 00 74 00 72 00 69 00 00 15 05 07 D6 14 EF
46 DF EB C0 46 E0 90 6F 00 00 00 00 00 03 C0 80
00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00
04 22 04 35 04 41 04 42 00 31 00 00 00 FF FE EF
FF FE EF FF FE EF FF FE EF FF FE EF FF FE EF FF
46 E0 15 F0 46 E0 90 89 00 00 00 00 00 03 C0 80
00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00
04 22 04 35 04 41 04 42 00 32 00 00 00 FE EF FF
FE EF FF FE EF FF FE EF FF FE EF FF FE EF FF FE
Структура пятого типа полностью совпадает со структурой четвёртого типа, без первых двух байт.
Шестой тип записи:
Код
80 1C 04 30 04 40 04 38 04 3D 04 30 04 FF FF 07
81 08 66 63 19 93 F3 FF FF 03 FE 3F 58 CC F3 46
CC 00 00 00 00 00 01 FF EF FF FE EF FF FE EF FF
FE EF FF FE EF FF FE EF FF FE EF FF FE EF FF FE
80 1C 04 30 04 40 04 38 04 3D 04 30 04 FF FF 6D
61 72 75 73 79 61 40 61 70 72 69 6F 72 69 74 2E
63 6F 6D 00 06 FE 51 FF FF FF FF FF FF FF FF 00
00 01 FF EF FF FE EF FF FE EF FF FE EF FF FE EF
Первый байт должен быть равен 0x80. Имя начинается со второго байта, длина имени не храниться – если имя короче 0x30 байт, то оно заканчивается словом 0xFFFF, иначе оно занимает ровно 0x30 байт (возможно в разных телефонах эта длина окажется различной) и завершающего слова нет. Имя храниться в BIGENDIAN UNICODE. Далее (аналогично) следует байт длинны номера телефона (в байтах), и за ним следует сам номер в BCD с перевернутыми байтами. Если первый байт номера равен 0x91, то в начале номера идёт символ «+», иначе (обычно 0x81) он просто пропускается. Этот тип похож на третий и отличается от него отсутствием первых двух байт и типом хранения текста.
Файлы второго поколения более универсальны и имеют следующую структуру:
Код
01 81 09 04 1C 30 40 38 3D 3E 47 3A 30 81 00 00
81 00 00 07 81 08 92 85 86 79 F2 FF FF FF FF FF
FF 00 00 00 00 00 00 00 81 00 00 00 00 00 00 00
16 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 81 00 00 81 00 00 03 FF FF FF FF FF FF FF FF
FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 81 00 00 81 00 00 81 00
00 81 00 00 81 00 00 81 00 00 81 00 00 81 00 00
81 00 00 81 00 00 81 00 00 81 00 00 81 00 00 81
00 00 81 00 00 81 00 00 00 00 00 00 00 81 00 00
00 00 00 00 00 00 00 00 00 01 03 00 0D 00 00 00
B3 FF FF FF FF FF FF FF FF FE FE FE FE FE FE FE
Первый байт записи должен быть равен 0x01, второй байт должен быть равен 0x81. Имя начинается с пятого байта, длина имени храниться в третьем байте (в байтах). Имя храниться в «упакованном» UNICODE – первый байт, если он одинаков для всего имени, вырезан и храниться в байте перед байтом длинны (четвёртом) имени. Далее снова идёт 0x81, длинна, вырезанный общий байт, имя в такой же кодировке. Далее снова идёт 0x81, длинна, вырезанный общий байт, имя в такой же кодировке. Далее (аналогично) следует байт длинны номера телефона (в байтах), и за ним следует сам номер в BCD с перевернутыми байтами. Если первый байт номера равен 0x91, то в начале номера идёт символ «+», иначе (обычно 0x81) он просто пропускается.
Сообщение отредактировал Ailinor - 20.10.2007, 21:00