» » » Как взломать дорогую камеру, чтобы вас не убила жена

 

Как взломать дорогую камеру, чтобы вас не убила жена

Автор: admin от 30-01-2019, 19:35, посмотрело: 52

Дисклеймер: исследование началось в 2013 году, так что если считаете некоторые методы глупыми и опасными — вы правы, так и было. Тем не менее, я многому научился в процессе.



Вступление

Всё началось за несколько месяцев до рождения моего первого ребенка. Мы с женой всегда хотели купить крутой фотоаппарат Leica и вдруг поняли, что если не купим его сейчас, то уже долго не сможем это сделать. Поэтому мы заказали камеру M240 и… бум, нас поставили в очередь на полгода. Вскоре мне надоело ждать, и я начал изучать их сайт. Моё внимание сразу привлёк раздел с файлами. Ну, вы можете догадаться, почему… Прошивки!



Я увидел незашифрованный и несжатый файл (m8-2_005.upd), который начинается с магии PWAD. Узнаёте? Да, всё правильно, это формат Doom Patch WAD. Кажется, ребята любят классику. Формат очень хорошо документирован, так что распарсить его оказалось совсем несложно.

формат LHA, который по сути представляет собой LZW. Но распространённые декомпрессоры LZW не подошли, поэтому я начал искать конкретную реализацию программного обеспечения id — и вуаля, нашёл в исходниках Catacomb Armageddon. Должен признать, повезло.



В любом случае, вернёмся к M8. Вот структура прошивки:





RULES: 0x0000008C ( 3036:0x00000BDC) - описание XML
LUTS: 0x00000C68 ( 183274:0x0002CBEA)
GAMMA: 0x0000007C ( 31760:0x00007C10)
GAIN: 0x00007C8C ( 50344:0x0000C4A8)
LEICA: 0x00014134 ( 7000:0x00001B58)
BLEMISH: 0x00015C8C ( 250:0x000000FA)
WREF: 0x00015D88 ( 82480:0x00014230)
OBJ: 0x00029FB8 ( 11268:0x00002C04)
VERSION: 0x0002CBBC ( 46:0x0000002E)
PXA: 0x0002D854 ( 858384:0x000D1910)
BF: 0x000FF164 ( 134522:0x00020D7A) - семейство процессоров Analog Devices Blackfin
GUI: 0x0011FEE0 ( 3574180:0x003689A4)
TRANS: 0x0000005C ( 59988:0x0000EA54) - локализация
IMAGES: 0x0000EAB0 ( 267433:0x000414A9)
21_1PRT: 0x000000CC ( 18411:0x000047EB) - изображение JFIF
21_2GRP: 0x000048B8 ( 23172:0x00005A84) - изображение JFIF
21_3PAN: 0x0000A33C ( 23034:0x000059FA) - изображение JFIF
24_1PRT: 0x0000FD38 ( 18489:0x00004839) - изображение JFIF
24_2GRP: 0x00014574 ( 23230:0x00005ABE) - изображение JFIF
24_3PAN: 0x0001A034 ( 22998:0x000059D6) - изображение JFIF
28_1PRT: 0x0001FA0C ( 22605:0x0000584D) - изображение JFIF
28_2GRP: 0x0002525C ( 23081:0x00005A29) - изображение JFIF
28_3PAN: 0x0002AC88 ( 23282:0x00005AF2) - изображение JFIF
35_1PRT: 0x0003077C ( 22496:0x000057E0) - изображение JFIF
35_2GRP: 0x00035F5C ( 23532:0x00005BEC) - изображение JFIF
35_3PAN: 0x0003BB48 ( 22881:0x00005961) - изображение JFIF
FONT1: 0x0004FF5C ( 1522988:0x00173D2C)
FONT2: 0x001C3C88 ( 1723676:0x001A4D1C)
VERSION: 0x003689A4 ( 0:0x00000000)
M16C: 0x00488884 ( 130406:0x0001FD66) - семейство Renesas M16C (Motorola S-record)
FPGA: 0x004A85EC ( 131604:0x00020214) - Xilinx Spartan 3
FSL: 0x004C8800 ( 814:0x0000032E) - загрузчик первой стадии



IDA из коробки не поддерживает процессоры Blackfin, но есть сторонний плагин.



Прошивка Leica M9



Файл прошивки Leica M9 (m9-1_196.upd) выглядит зашифрованным: гистограмма показывает распределение около 0,45%.



Как взломать дорогую камеру, чтобы вас не убила жена


Конец истории? Может и нет. Дело в том, что Leica использовала довольно слабые процессоры в камерах, а в то время в бытовой электронике часто применялось шифрование XOR, поэтому я решил написать простой инструмент для операции XOR, чтобы сравнить прошивку с собой и посчитать некоторую статистику.



Длина ключа определялась путём поиска самого длинного повторяющегося шаблона. Это имеет смысл, так как любая прошивка обычно включает в себя большие блоки повторяющихся данных, таких как набивка 0x00/0xFF или графики с пикселями LUT. Сам ключ вычисляется по частотности байтов в пределах длины ключа, где наиболее часто встречающийся байт идёт в буфер ключа. Результат работы программы явно указывал на шифрование XOR. Затем пришлось немного модифицировать инструмент, чтобы получить потенциальный ключ и расшифровать код. Это опять оказался файл PWAD.



Содержание PWAD выявило следующую структуру:





RULES: 0x0000007C ( 2788:0x00000AE4) - описание XML
LUTS: 0x00000B60 ( 4060616:0x003DF5C8)
PROCESS: 0x0000004C ( 3900572:0x003B849C)
CREATE: 0x0000004C ( 20:0x00000014) - метка времени
LUTS: 0x00000060 ( 427744:0x000686E0)
GAINMAP: 0x00068740 ( 20008:0x00004E28)
LENS: 0x0006D568 ( 3452724:0x0034AF34)
CCD: 0x003B84E8 ( 148662:0x000244B6)
CREATE: 0x0000004C ( 20:0x00000014) - метка времени
BLEMISH: 0x00000060 ( 1092:0x00000444)
WREF: 0x000004A4 ( 147452:0x00023FFC)
LIN: 0x000244A0 ( 22:0x00000016)
ICCPROF: 0x003DC9A0 ( 4304:0x000010D0)
ECI-RGB: 0x0000003C ( 540:0x0000021C)
sRGB: 0x00000258 ( 3144:0x00000C48)
A-RGB: 0x00000EA0 ( 560:0x00000230)
WBPARAM: 0x003DDA70 ( 7000:0x00001B58)
BF561: 0x003E0128 ( 289128:0x00046968) - Analog Devices Blackfin Processor family
bf0: 0x0000004C ( 117846:0x0001CC56) - основной процессор
bf1: 0x0001CCA4 ( 117826:0x0001CC42) - прошивка подпроцессора
bf0.map: 0x000398E8 ( 27072:0x000069C0) - карта прошивки основного процессора с символами :D
bf1.map: 0x000402A8 ( 26304:0x000066C0) - карта прошивки подпроцессора с символами :D
BODY: 0x00426A90 ( 143280:0x00022FB0) - семейство Renesas M16C (Motorola S-record)
GUI: 0x00449A40 ( 3647624:0x0037A888)
TRANS: 0x0000005C ( 131656:0x00020248) - локализация
IMAGES: 0x000202A4 ( 267433:0x000414A9)
21_1PRT: 0x000000CC ( 18411:0x000047EB) - изображение JFIF
21_2GRP: 0x000048B8 ( 23172:0x00005A84) - изображение JFIF
21_3PAN: 0x0000A33C ( 23034:0x000059FA) - изображение JFIF
24_1PRT: 0x0000FD38 ( 18489:0x00004839) - изображение JFIF
24_2GRP: 0x00014574 ( 23230:0x00005ABE) - изображение JFIF
24_3PAN: 0x0001A034 ( 22998:0x000059D6) - изображение JFIF
28_1PRT: 0x0001FA0C ( 22605:0x0000584D) - изображение JFIF
28_2GRP: 0x0002525C ( 23081:0x00005A29) - изображение JFIF
28_3PAN: 0x0002AC88 ( 23282:0x00005AF2) - изображение JFIF
35_1PRT: 0x0003077C ( 22496:0x000057E0) - изображение JFIF
35_2GRP: 0x00035F5C ( 23532:0x00005BEC) - изображение JFIF
35_3PAN: 0x0003BB48 ( 22881:0x00005961) - изображение JFIF
FONT1: 0x00061750 ( 1522988:0x00173D2C)
USBLOGO: 0x001D547C ( 1775:0x000006EF) - изображение JFIF
FONT2: 0x001D5B6C ( 1723676:0x001A4D1C)
FPGA: 0x007C42C8 ( 150176:0x00024AA0) - Xilinx Spartan 3A
BF547: 0x007E8D68 ( 937576:0x000E4E68) - семейство процессоров Analog Devices Blackfin (FSL?)





Прошивка Leica M240



У меня вошло в привычку каждое утро проверять страницу загрузки с прошивками Leica. Скоро там появился новый файл: FW_M240_1_1_0_2.FW.



Он не выглядел зашифрованным, но был сжат…



Сжатие



Гистограмма показывает огромный всплеск на 0x9D.



Как взломать дорогую камеру, чтобы вас не убила жена


Возможно, это какая-то магия сжатия. Поиск в интернете [9D+compression] ничего не дал, кроме того, что 0x1F9D используется в качестве подписи сжатия LZW. Если что, я разбираюсь в типах сжатия LZ и решил посмотреть на байты после 0x9D. И увидел четыре варианта:




  • 9D 70 C4


  • 9D 00


  • 9D XX YY


  • 9D XX 8Y YY



  • Что ещё удалось подметить:




    • первый вариант всплывает лишь однажды по адресу 0x30: вероятно, используется в качестве индикатора сжатых данных;


    • XX никогда не превышает 0x7F;


    • последний байт YY в третьем и четвёртом случаях никогда не превышает 0x7F



    Из того, что я знаю о LZ, это очень похоже на LZ77 или LZSS, где YY — шаг отступа, а XX — количество байтов для копирования. И второй вариант — частный случай выдачи 0x9D. Я написал простую функцию на C, которая реализует эту логику. Она подтвердила, что мы движемся в правильном направлении, но четвёртый вариант всё равно не вписывается в схему.



    Я всячески пытался его интерпретировать, но ничего не получилось. Поэтому я обратился за советом к товарищам. Один парень заметил, что согласно моим собственным наблюдениям, четвёртый байт YY появляется только тогда, когда установлен самый высокий бит 0x8Y: это просто дополнительное расстояние для шага отступа. Мне было стыдно, всё оказалось настолько очевидно…



    Наконец, декомпрессор начал выдавать валидный поток… пока не застрял посередине файла. Это произошло из-за неизвестной длины скользящего окна. Дополнительная отладка и тесты исправили ситуацию.



    Так появился инструмент для парсинга прошивки M240.



    Структура прошивки



    Для работы с неизвестным форматом я не придумал ничего лучше, чем измерить некоторые смещения и размеры участков кода — и попытаться найти самые близкие значения в заголовке файла. Например, этот блок:



    0x00: 1E 1C AF 2E 01 01 00 02 07 E1 EA 5E 00 5C 1A B1

    0x10: 01 29 1A 7E AE 38 73 65 9C 3D 75 B4 34 2F 44 6E

    0x20: 13 17 8E 6B 00 00 00 01 00 00 00 30 E1 E3 50 D1



    в итоге превратился в:



    1E1CAF2E — выглядит как "LEICA FILE"

    01010002 - 1.1.0.2

    005C1AB1 — размер сжатого файла (big endian)

    01291A7E — размер несжатого файла (big endian)

    AE3873659C3D75B4342F446E13178E6B — хэш MD5

    00000001 — количество полезных нагрузок

    00000030 — смещение первой полезной нагрузки



    По мере понимания структур прошивки я улучшал свой инструмент, и в конечном итоге он выдавал такое:



    Running with options:

    + firmware folder: M240_FIRMWARE

    + verbose enabled



    Open firmware file: FW_M240_1_1_0_2.FW

    File size: 6036193 | 0x005C1AE1



    Parse container header:

    version: 1.1.0.2

    packed size: 6036145 | 0x005C1AB1

    unpacked size: 19470974 | 0x01291A7E

    body blocks: 1 | 0x00000001

    body offset: 48 | 0x00000030

    MD5: AE387365 9C3D75B4 342F446E 13178E6B

    MD5 check: PASSED



    Uncompress container body:

    6036145 19470974

    Uncompression: DONE



    Split container:

    Number of sections: 9 | 0x00000009

    Section table size: 612 | 0x00000264

    Section table offset: 36 | 0x00000024

    Section 1

    Section Name: "[A]IMG_LOKI-212"

    Section offset: 0 | 0x00000000

    Section size: 7340032 | 0x00700000

    Section base: 1048576 | 0x00100000

    MD5: A8D55AA2 B0ACDB14 0673AD79 707674F3

    MD5 check: PASSED

    Create file: M240_FIRMWARE/IMG_LOKI-212.bin



    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~



    Section 9

    Section Name: "[A]IMG-LENSDATA-213"

    Section offset: 19214844 | 0x012531FC

    Section size: 255478 | 0x0003E5F6

    Section base: 16252928 | 0x00F80000

    MD5: 39C2BEC0 27ED23F6 2C1C8513 EEE697B9

    MD5 check: PASSED

    Create file: M240_FIRMWARE/IMG-LENSDATA-213.bin

    Splitting container: DONE

    Extraction COMPLETE!



    Прошивка М240 включает один контейнер с девятью элементами:



    IMG_LOKI-212.bin - прошивка прикладного процессора

    IMG_LOKI-213.bin - прошивка прикладного процессора

    CTRL_SYS-11.bin - прошивка процессора ввода-вывода

    IMG-FPGA-212.bin - прошивка для обработки изображений (сенсор)

    IMG-FPGA-213.bin - прошивка для обработки изображений (сенсор)

    IMG-DSP-212.bin - прошивка DSP

    IMG-DSP-213.bin - прошивка DSP

    IMG-LENSDATA-212.bin - данные по оптике

    IMG-LENSDATA-213.bin - данные по оптике



    Как видим, в одной прошивке два набора файлов. Позже я узнал, что 212 — это версия микрсхемы для обработки изображений, а в производство пошло два варианта Leica M240. Данное исследование основано на версии 212.



    Управление системой: CTRL_SYS-11.bin



    Единственная общая часть — прошивка для чипа управления системой. Это реально большой бинарник, и по коду нетрудно догадаться, для чего он предназначен.



    $ strings CTRL_SYS-11.bin | rg SH

    Test SH7216 data flash driver

    Test SH7216 SCI driver

    Test SH7216 I2C driver

    Test SH7216 MTU2 driver

    Test SH7216 ADC functions

    Test SH7216 CMT driver



    Таким образом, перед нами процессор Renesas SH7216 (SH-2A), который отвечает за раннюю стадию загрузки, тесты ввода-вывода и обновление прошивки. IDA из коробки поддерживает этот тип процессора. Оставалось лишь найти правильный адрес базовой загрузки, известный по описанию разделов прошивки: это 0x0.



    Section Name: "[A]CTRL_SYS-11"

    Section offset: 14680064 | 0x00E00000

    Section size: 917277 | 0x000DFF1D

    Section base: 0 | 0x00000000



    Я загрузил его в IDA и распознал все функции, но не особенно в нём не копался, потому что намного интереснее прошивка основного процессора.



    Здесь можно ещё отметить, что UART этого чипа открывается на сервисный порт, куда выдаёт журнал загрузки. Мы вернёмся к этому позже.



    Основной чип: IMG_LOKI-212.bin



    Чтобы начать реверс-инжиниринг данной прошивки, необходимо сначала ответить на несколько вопросов:




  • какой тип процессора


  • каков адрес базовой загрузки


  • на какой ОС он основан, если таковая имеется



  • Благодаря нашему инструменту мы уже знаем адрес базовой загрузки: это 0x100000.



    Section Name: "[A]IMG_LOKI-212"

    Section offset: 0 | 0x00000000

    Section size: 7340032 | 0x00700000

    Section base: 1048576 | 0x00100000



    Остальные ответы прошивка хранит в удобочитаемом виде. Например, эта строка:



    $ strings ./IMG_LOKI-212.bin | rg Softune

    6Softune REALOS/FR is Realtime OS for FR Family, based on micro-ITRON COPYRIGHT(C) FUJITSU LIMITED 1994-1999

    ...



    Таким образом, мы имеем дело с кастомным процессором Fujitsu FR (Leica называет его Maestro) и операционкой Softune REALOS. На самом деле, это намного лучше, чем Blackfin, потому что IDA из коробки поддерживает FR.



    Модуль процессора FR



    Реальность оказалась не такой яркой, потому что после загрузки файла прошивки программа IDA не показала никаких инструкций, внешних ссылок и т. д.



    Я решил исправить это, но в итоге пришлось полностью переписать некоторые части прошивки. Вот результат:



    Как взломать дорогую камеру, чтобы вас не убила жена


    Как взломать дорогую камеру, чтобы вас не убила жена


    Кроме исправлений в ana, ins и out, совершенно новый код emu умеет:




    • распознавать различные типы кода и внешние ссылки на данные;


    • распознавать операторы switch;


    • выполнять трассировку стека;


    • разделять аргументы стека и локальные переменные;


    • правильно распознавать функции.



    Но самое большое изменение, как вы заметили, — это прописные буквы для инструкций :)



    Хотите увидеть полный набор инструкций? Вот он:





    ADD OR BTSTH LSR MOV BN LDRES EXTSH
    ADD2 ORH MUL LSR2 JMP BP STRES EXTUH
    ADDC ORB MULU ASR CALL BV COPOP SRCH0
    ADDN EOR MULH ASR2 RET BNV COPLD SRCH1
    ADDN2 EORH MULUH LDI INT BLT COPST SRCHC
    SUB EORB DIV0S LDI INTE BGE COPSV LDM0
    SUBC BANDL DIV0U LDI RETI BLE NOP LDM1
    SUBN BANDH DIV1 LD BRA BGT ANDCCR STM0
    CMP BORL DIV2 LDUH BNO BLS ORCCR STM1
    CMP2 BORH DIV3 LDUB BEQ BHI STILM ENTER
    AND BEORL DIV4S ST BNE DMOV ADDSP LEAVE
    ANDH BEORH LSL STH BC DMOVH EXTSB XCHB
    ANDB BTSTL LSL2 STB BNC DMOVB EXTUB



    Вот так, просто и красиво.



    Кстати, вы могли заметить, что некоторые инструкции не выровнены:





    BRA:D loc_xxx
    LDI:8 #0x64, R5



    Это не ошибка в процессорном модуле, а фактически особенность семейства Fujitsu FR. Она называется слот задержки и довольно типична для RISC-процессоров.



    Из руководства по процессору FR80 (примечание: ссылка больше не работает):



    Инструкция, которая находится сразу после инструкции ветвления (её расположение называется «слотом задержки»), выполняется перед ветвлением, а инструкция по целевому адресу выполняется после ветвления. Поскольку инструкция в слоте задержки выполняется перед операцией ветвления, видимая скорость выполнения составляет 1 цикл.


    Таким образом, это, по сути, оптимизация конвейера, и лучше помнить о ней, потому что она применяется повсюду в прошивке Leica.



    Softune REALOS



    Из вики:



    Softune — это интегрированная среда разработки Fujitsu для семейств процессоров Fujitsu FR, FR-V и F2MC. Работает на ядре реального времени REALOS µITRON. Например, используется в цифровых зеркальных камерах Nikon (см. Nikon EXPEED) и некоторых камерах Pentax с байонетом K.


    Так что это довольно популярная приличная RTOS с задачами, семафорами и другими вкусностями. Мне было интересно, можно ли распознать в прошивке Leica некоторые стандартные функции библиотеки.



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



    Softune IDE оказалось очень трудно найти, но в конце концов мне удалось кое-что достать. Как и ожидалось, IDE включала в себя библиотеки. Там было четыре двоичных файла:




    • lib911.lib


    • lib911e.lib


    • lib911if.lib


    • lib911p.lib



    Не знаю почему, может по инерции, как я взламывал всё связанное с Leica, я опять начал реверс-инжиниринг формата. Да, очень хорошо документированного формата Object Module Format. И да, конечно, я написал для этого специальный инструмент:



    Fujitsu RISC Library Tool v1.0

    Usage: FRLibTool [-s start] [-i imagebase] [-o output] [-f index] [-dv] FIRMWARE.BIN LIBRARY.LIB



    This tool will help you to find Softune REALOS library functions in FR (Fujitsu RISC) firmware.

    Use following arguments:

    -f Specify firmware image file

    -s Specify firmware image scan offset

    -b Specify firmware imagebase

    -o Specify output type (exclusively)

    list - list of functions

    idc - IDC script

    py - IDA python script

    pat - FLAIR pattern file

    -i xxx Specify index of particular function

    -d Dump library

    -v Be verbose



    С его помощью можно создавать файлы *.pat и использовать их в качестве входных данных в IDA FLAIR для генерации файлов сигнатур.



    $ FRLibTool -o pat lib911.lib

    $ FRLibTool -o pat lib911e.lib

    $ FRLibTool -o pat lib911if.lib

    $ FRLibTool -o pat lib911p.lib

    ...

    $ sigmake -n "SOFTUNE C/C++ Library" lib911.pat lib911e.pat lib911if.pat lib911p.pat softune.sig



    После применения этой сигнатуры я наконец-то с радостью увидел соответствия в IMG_LOKI-212.idb.



    Как взломать дорогую камеру, чтобы вас не убила жена


    Макет



    Сразу обращает на себя внимание количество строк в прошивке. Многие функции именуются по своей функциональности. Это очень полезно в процессе обратной разработки, чтобы понять общий шаблон.



    Также важно отметить, что некоторые части файла прошивки копируются на другой адрес в обработчике сброса (reset handler). Например, встроенный загрузчик во время выполнения перемещается выше по оперативной памяти.



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



    Как взломать дорогую камеру, чтобы вас не убила жена


    Прерывания



    Таблицу векторов прерываний можно найти по доступу к TBR (Table Base Register):



    LDI:32 #int_table, R0

    MOV R0, TBR



    Обычно он происходит в обработчике сброса вектора в самом начале прошивки.



    Адреса обработчиков в таблице хранятся в обратном порядке по формуле TBR + (0x3FC - 4 x inum), так что вектор сброса в конце таблицы со смещением 0x3FC.



    Я нашёл большинство прерываний из руководства по FR и предположил, что у Leica Maestro аналогичная компоновка. Затем взял каждый обработчик и попытался найти строку или любой другой намёк, раскрывающий цель прерывания.



    В итоге составил такой список:



    Как взломать дорогую камеру, чтобы вас не убила жена


    Многие прерывания вполне ожидаемы, такие как AUDIO/SDIO/VIDEO/JPEG/RAW, но попробуйте определить самое загадочное из них? Я говорю о прерывании int_uart_in. Похоже, что камера поддерживает какой-то консольный режим UART CLI.



    Системные вызовы



    Как почти любая ОС, Softline REALOS использует системные вызовы. В ассемблере они выглядят так:



    Как взломать дорогую камеру, чтобы вас не убила жена


    Фактический адрес обработчика системных вызовов вычисляется следующим образом. Начнём с поиска обработчика прерывания INT #0x40. В соответствии с описанием выше это



    (0x3FC - 4 x inum) = (0x3FC - 4 x 0x40) = 0x2FC = int_realos_syscall



    В обработчике легко найти ссылку на нижнюю часть таблицы системных вызовов с 16-битными словами. Конкретная запись в этой таблице вычисляется по формуле syscall_table_bottom + (num * 2):



    [syscall_table_bottom + (-23 * 2)] = [syscall_table_bottom - 0x2E] = [0x1012EA] = 0xE68



    Это не похоже на адрес, потому что фактический адрес обработчика системных вызовов вычисляется как syscall_table_bottom + offset. Весь процесс показан на диаграмме.



    Как взломать дорогую камеру, чтобы вас не убила жена


    Все системные вызовы и их функциональность указаны в Руководстве по ядру Softline REALOS/FR, поэтому мне удалось восстановить все реализованные обработчики в таблице и ещё немного улучшить IDB.



    Как взломать дорогую камеру, чтобы вас не убила жена


    Конечно, можно сделать код ещё красивее, определив типы системных вызовов в IDA.



    Как взломать дорогую камеру, чтобы вас не убила жена


    Я написал скрипт на Python для автоматического поиска этих системных вызовов и прочего.



    Задачи



    В системном вызове sta_tsk я заметил, что в качестве параметра передаётся не основная функция, а pid. Это означает, что пришло время искать большой массив дескрипторов задач. И имеет смысл начать с самого sta_tsk.





    ROM:102180 sys_sta_tsk:
    ROM:102180 ST RP, @-R15
    ROM:102182 LDUB @(R14, 0x4F), R3
    ROM:102184 LDI:32 #word_100B80, R14



    В самом начале мы видим какие-то ссылки. Пришлось немного повозиться с типами данных, но в итоге части собрались вместе:





    ROM:100B80 word_100B80: .word 0xF ; number of tasks
    ROM:100B82 .word 0x1C ; task descriptor size

    ROM:100B84 .long 0x82A09F5C ; task 1 descriptor
    ROM:100B88 .long 0x1000D
    ROM:100B8C .long 0
    ROM:100B90 .long 0x40000000
    ROM:100B94 .long sub_1A7DB2 ; task main
    ROM:100B98 .long 0x8286EEC0
    ROM:100B9C .long 0

    ROM:100BA0 .long 0x82A09F88 ; task 2 descriptor
    ROM:100BA4 .long 0x20010
    ROM:100BA8 .long 0
    ROM:100BAC .long 0x40000000
    ROM:100BB0 .long sub_1A6BD2 ; task main
    ROM:100BB4 .long 0x8287EEC0
    ROM:100BB8 .long 0
    ...



    и так далее. Всего 15 задач. Было вопросом времени заглянуть в каждую основную функцию, определить имя и цель задачи (кроме последней). Вот полный список:




  • SubCPU

    Эта задача, по-видимому, отвечает за операции захвата, такие как экспозиция, визирование по экрану и т. д.


  • KeyManager

    Скорее всего, эта задача связана с аппаратными кнопками.


  • GuiManager

    Довольно большая задача, в которой реализована машина состояний UI и отрисовка интерфейса.


  • DebugManager

    Да, есть кое-что для отладки. Ням-ням.


  • FileManager

    Эта задача — всё о файловых операциях.


  • FamManager

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


  • MemoryManager

    Никаких сюрпризов: операции с памятью, управление пулом и т. д.


  • ImageManager

    Эта задача управляет процессами кодирования/декодирования и другими процессами обработки изображений.


  • UsbManager

    Текущая задача — обработка коммуникаций по USB, которая включает в себя MassStorage, PTP и собственный протокол Leica.


  • IOManager

    Похоже, эта задача управляет устройствами хранения данных, такими как SD и CF-карты (что? какие ещё CF? может, это из модели 213).


  • Systemmanager

    Разные задачи вроде общих системных операций, управления питанием и т. д.


  • SettingsManager

    Обрабатывает состояние камеры и настройки.


  • MonitorManager

    Отслеживает изменения состояния камеры и информирует другие задачи.


  • PeripheralManager

    Эта задача контролирует GPS, яркость и некоторые другие сенсоры.


  • Неизвестно

    К сожалению, для неё я не нашел ничего существенного.



  • Интересно отметить, что после основного массива есть ещё один выдающийся дескриптор.



    ROM:100D28 dword_100D28: .long 0x82A0A1F0

    ROM:100D2C .long 0x21

    ROM:100D30 .long 0

    ROM:100D34 .long 0x80000000

    ROM:100D38 .long tid16_task

    ROM:100D3C .long 0x8285EEC0

    ROM:100D40 .long 0



    А функция задачи — просто ветвление самой себя.



    ROM:101494 sub_101494:

    ROM:101494 BRA sub_101494 ; CODE XREF: sub_101494



    На этот дескриптор стоит ссылка в конце функции start, которая отвечает за создание других задач и настройку встроенного ПО. Так что это, скорее всего, задача бездействия системы.



    Модули и сообщения



    Помимо задач, можно определить некоторые логические объекты, такие как IO и периферийные модули. Модули представлены в виде группы обработчиков сообщений в рамках одной из задач.



    Группа IO, кажется, включает:




    • Менеджер IO

    • Подпроцессор

    • Менеджер USB

    • USB PTP

    • Протокол USB Leica

    • USB Mass Storage

    • Менеджер управления кнопками

    • Менеджер отладки

    • Менеджер объектива



    А в периферийной группе:




    • Менеджер периферии

    • Датчик освещённости

    • Светодиоды

    • Динамик

    • Датчик угла наклона

    • Распознавание закрытия крышки

    • Модуль GPS

    • Модуль 3DAxis



    Сама система обмена сообщениями использует стандартные структуры SOFTUNE:



    struct RealOS_MsgPayload
    {
      uint32_t msgID;   // +0x0
      uint32_t data[];  // +0x4
    }
    
    struct RealOS_Message
    {
      uint32_t            os_reserved1; // +0x0
      uint32_t            os_reserved2; // +0x4
      
      uint32_t            to;           // +0x8
      uint32_t            from;         // +0xC
      RealOS_MsgPayload*  payload;      // +0x10
    }


    Как и ожидалось, в IPC тоже есть несколько групп сообщений. Поскольку много сообщений обрабатывается в задачах и модулях, я смог восстановить только некоторые из этих групп:



    0x1101xxxx - глобальные системные сообщения:
    0x11010002 = SYS_UPDATE_BOOTLOADER или
    0x11010005 = SYS_ERASE_SETTINGS
    0x1102xxxx - сообщения, связанные с захватом изображения:
    0x11020001 = CMD_CAP_CAPTURE или
    0x11020008 = IMAGE_STATUS_CHANGED
    0x1104xxxx - сообщения о событиях, связанных с воспроизведением:
    0x11040002 = PLY_DISABLE_PLAY_MODE или
    0x11040004 = PLY_IMAGE_READY
    0x1108xxxx - различные сообщения для отладки PTP и др.:
    0x11080002 = DBG_CHANGE_LEVEL или
    0x11080012 = DBG_WRITE_ROM_DUMP_SD
    0x2201xxxx - сообщения USB PTP
    0x22010108 = изменение настроек камеры или
    0x22010118 = запрос DebugObject
    0x2202xxxx - довольно большая группа сообщений SUBCPU:
    0x22020002 = E_SUBCPU_REQUEST_M_EXPOSURE_REQUEST
    0x22020015 = E_IO_SUBCPU_COMMAND_CLEANING_SENSOR
    0x2203xxxx - некоторые другие сообщения отладки:
    0x22030001 = команда отладочной строки
    0x2204xxxx - различные сообщения IO:
    0x2204000C = включение/отключение Mass Storage или
    0x22040012 = перезагрузка устройства
    0x330000xx - другая группа сообщений для UI:
    0x33000001 = нажатие клавиш
    0x33000007 = подключение объектива
    0x440000xx - здесь мало информации, но похоже на обработку изображений
    0x44000013 = E_IMG_CMD_CHANGE_PINFO
    0x55xxxxxx — группы сообщений FAM:
    0x558800xx = файл-менеджер FAM или
    0x558888xx = первая группа настройки меню FAM
    0x6602xxxx — похоже на управляющие сообщения LED, например:
    0x66020001 - переключение LED с X Гц
    0x66020002 = включение непрерывного LED
    0x6604xxxx - управление бипером:
    0x66040001 = установка бипера
    0x66040007 = писк о заполненной карте
    0x6611xxxx - сообщения отладки, связанные с памятью
    0x6622xxxx - сообщения обработки сообщений, связанные с памятью
    0x6660xxxx - некоторые другие сообщения, связанные с памяьтю:
    0x66600006 = HISTOGRAM
    0x66600011 = RAWCOMP
    0x771100xx and 0x77AA00xx - сообщения, связанные с переключением режимов камеры


    К сожалению, много других сообщений остаются неизвестными.



    GUI



    В файле прошивки посмотрим ещё на следующие разделы: CTRL_SYS-11, IMG-LOKI-212, IMG-DSP-212, IMG-FPGA-212 и IMG-LENSDATA-212.



    Что меня удивило, так это полное отсутствие ресурсов GUI. Но они где-то должны быть и, скорее всего, встроены в IMG-LOKI-212.



    Один из моих обычных подходов к обратной разработке прошивки — восстановить все возможные перекрёстные ссылки. Не только в коде, но и в разделе данных. Затем я просматриваю их, пытаясь найти некоторые шаблоны или ссылки на известные части кода.



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



    Например, я нашёл структуру данных без каких-либо ссылок:



    g_data = { ... }


    К ней обращалась другая структуры:



    g_data_struct1 = { ... , &g_data }


    К которой в свою очередь обращается ещё одна структура:



    g_data_struct2 = { &g_data, ... }


    На эту структуру данных есть ссылка из кода, и её передают в качестве параметра другой функции:



    func1()
    ? func2(..., &g_data_struct2, ...)


    Однако func1() не вызывается напрямую из другой функции, а хранится в некотором массиве:



    g_func_list1[] = { ..., func1(), ... }


    Посмотрев выше, я нашел в коде вызов g_func_list1:



    func3() {
        g_func_list1[x]
    }


    И снова эта функция сохранена в массиве:



    g_func_list2[] = { ..., func3(), ... }


    К самому массиву обращается какой-то другой код:



    func4() {
        g_func_list2[x]
    }


    К счастью, на этот раз функция вызвана из другой функции, и так до gui_MADE_ApplicationRun.



    gui_Statemachine_DoStateChange()
    ? gui_MADE_ApplicationRun()
      ? func5()
        ? func4()


    В некоторых строках указано, что подсистема GUI называется “MADE”, а переходы страниц обрабатываются с помощью MADE_GetSysTri, что бы это ни значило. Машина состояний GUI, в основном, реализована в функции gui_Statemachine_DoStateChange. После сбора информации о GUI сложилась общая картина:



    Как взломать дорогую камеру, чтобы вас не убила жена


    Как видите, основная функция для ресурсов GUI — gui_CopyImageDesc (хотя это не настоящее имя). У неё следующие аргументы:



    gui_CopyImageDesc(
        uint32_t			dstAddress;		// R4 - destination address
        UIDescType			type;			// R5 - description type
        UITarget			target;			// R6 - rendering target
        uint32_t			descAddress;	    	// R7 - description address
        uint8_t			always0;        	// (SP + 0x0) - always 0
        uint8_t			index1;			// (SP + 0x4) - index 1
        uint8_t			index2;			// (SP + 0x8) - index 2
        uint16_t			x_offset;		// (SP + 0xC) - x offset
        uint16_t			y_offset;		// (SP + 0x10) - y offset
        uint16_t			unknown2;		// (SP + 0x14) -
        uint32_t			language1;		// (SP + 0x18) - language id 1
        uint32_t			language2;		// (SP + 0x1C) - language id 2
        uint32_t			funcAddress;		// (SP + 0x20) - function address
    )


    Есть четыре типа описаний ресурсов:



    struct UIDescType0Header         struct UIDescType1Header         struct UIDescType2                struct UIDescType3       
    {                                {                                {                                 {                        
        uint32_t    address;             uint32_t    address;             uint32_t    reg;                  uint16_t    x_offset;
        uint16_t    entries;             uint16_t    entries;             uint32_t    address;              uint16_t    y_offset;
        uint16_t    unknown;             uint16_t    unknown;             uint16_t    unknown1;             uint32_t    address; 
    }                                }                                    uint16_t    unknown2;         }                        
                                                                          uint16_t    unknown3;                                        
    struct UIDescType0Entry          struct UIDescType1Entry              uint16_t    tableoff;                                        
    {                                {                                }                                                                
        uint16_t    x_offset;            uint16_t    x_offset;                   
        uint16_t    y_offset;            uint16_t    y_offset;                   
        uint32_t    address;             uint32_t    address;                    
    }                                    uint16_t    objects;                    
                                         uint16_t    total_w; 
                                         uint16_t    total_h;                    
                                         uint16_t    unknown;                    
                                     }    


    У первого типа заголовок со ссылкой на массив записей. Каждая запись имеет координаты и адрес пиксельных данных. Текущий тип, похоже, описывает зависимые от состояния элементы, такие как значки, которые могут быть серыми или исчезать из UI.



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



    Третий тип описывает карты символов для разных языков.



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



    Теперь взглянем на сами данные для изображений.



    +0x00: 00 08 00 14 00 01 A2 FF 0A 04 05 FF 0C 04 03 FF

    +0x10: 0D 04 03 FF 0E 04 02 FF 0E 04 02 FF 04 04 06 FF

    +0x20: 04 04 02 FF 04 04 06 FF 04 04 02 FF 04 04 06 FF

    +0x30: 04 04 02 FF 04 04 06 FF 04 04 02 FF 04 04 06 FF

    +0x40: 04 04 02 FF 04 04 06 FF 04 04 02 FF 04 04 06 FF

    +0x50: 04 04 02 FF 04 04 06 FF 04 04 02 FF 0E 04 02 FF

    +0x60: 0E 04 02 FF 0D 04 03 FF 0D 04 03 FF 0C 04 04 FF

    +0x70: 04 04 0C FF 04 04 0C FF 04 04 0C FF 04 04 0C FF

    +0x80: 04 04 0C FF 04 04 0C FF 04 04 0C FF 04 04 0C FF

    +0x90: 04 04 0D FF 02 04 2D FF 00 06 00 14 00 01 79 FF




    Первые шесть байт выглядят как маленький заголовок, за которым следует какой-то повторяющийся шаблон, где каждый второй байт является либо 0xFF, либо 0x04. Логично предположить, что 0x0008 и 0x0014 — ширина и высота в представлении с прямым порядком байтов (big endian). В конце этого дампа мы видим начало другой последовательности 00 06 00 14 00 01. Скорее всего, это следующий ресурс (что подтверждается ссылкой на него). Таким образом, размер фактических данных изображения составляет 146 байт. Но размер изображения должен быть 0x8 * 0x14 = 0xA0 = 160. Ясно, что в данных не чисто пиксели и даже не 8-битная LUT, потому что она на 14 байт меньше. Тогда что? Вероятно, какое-то сжатие.



    Глядя на этот шестнадцатеричный дамп, трудно поверить, что используется какая-то сложная схема. GUI у Leica не очень красочный, так что по моему опыту здесь лучше всего использовать таблицу LUT. В этом случае ресурсы UI будут полностью повторять индексы LUT вроде 03 03 03 или А1 А1 А1. Обычно компрессор пытается избавиться от дублирования данных, заменяя их ссылкой. Эти массивы индексов идеальны для сжатия даже простым методом вроде RLE [data][number]. Простая команда записать data (значение) number раз.



    С учётом всего этого я предположил, что перед нами, скорее всего, простое изображение с двумя цветами LUT (0xFF и 0x04), а байт перед цветом — количество пикселей для рисования.



    «А потом ты написал ещё один инструмент», — подумаете вы. Но нет, я взял ручку и бумагу и начал заполнять клетки. Забавно, что у меня до сих пор сохранился тот рисунок.



    Как взломать дорогую камеру, чтобы вас не убила жена


    Где-то по пути я понял, что для этого изображения недостаточно 160 пикселей, так что 0x8 и 0x14 нужно умножить на два. Третье слово 0x0001 указывает, является ли изображение символом ASCII, так что окончательная структура ImageAsset выглядит следующим образом:



    struct ImageAsset
    {
        uint16_t    width;        // ширина/2 (big endian)
        uint16_t    height;       // высота/2 (big endian)
        uint16_t    ascii;        // 1, если символ ASCII
        struct      image_data {
            uint8_t number;       // количество пикселей для рендеринга
            uint8_t color;        // индекс цвета пикселя в LUT
        } data[];
    }


    Но одна часть всё ещё отсутствует: LUT.



    Её было не так сложно найти, потому что многие ссылки и структуры уже восстановлены вручную, так что я медленно прокручивал разделы данных, ища массив на 256 элементов из 16-битных или 32-битных значений, пока не натолкнулся на это:



    .long 0x7008080, 0x72D8080, 0x73C8080, 0x75A8080, 0x79B8080, 0x71DFF6B, 0x7BE8080, 0x7FF8080

    .long 0x77BBD27, 0x75B60E7, 0x7835F4A, 0x7D3089F, 0x7018080, 0x7028080, 0x7038080, 0x7048080

    .long 0x7058080, 0x7068080, 0x7078080, 0x7088080, 0x7098080, 0x70A8080, 0x70B8080, 0x70C8080

    .long 0x70D8080, 0x70E8080, 0x70F8080, 0x7108080, 0x7118080, 0x7128080, 0x7952B15, 0x7138080

    .long 0x7148080, 0x7158080, 0x7168080, 0x7178080, 0x7188080, 0x7198080, 0x71A8080, 0x71C8080

    .long 0x71D8080, 0x71E8080, 0x71F8080, 0x7338080, 0x7208080, 0x7218080, 0x7228080, 0x7238080

    .long 0x7248080, 0x7248080, 0x7268080, 0x7278080, 0x7288080, 0x7298080, 0x72A8080, 0x72B8080

    .long 0x72C8080, 0x75E8080, 0x7608080, 0x7628080, 0x7648080, 0x7678080, 0x7688080, 0x7698080

    .long 0x76B8080, 0x76E8080, 0x7708080, 0x7728080, 0x7758080, 0x7778080, 0x7798080, 0x77C8080

    .long 0x77E8080, 0x7818080, 0x7838080, 0x7868080, 0x7888080, 0x78B8080, 0x78D8080, 0x7908080

    .long 0x7928080, 0x7958080, 0x7978080, 0x7998080, 0x79C8080, 0x79D8080, 0x7668080, 0x79E8080

    .long 0x7A18080, 0x7A28080, 0x7A38080, 0x7A68080, 0x7A78080, 0x7A88080, 0x7AB8080, 0x7AC8080

    .long 0x7AD8080, 0x7B08080, 0x7B28080, 0x7B58080, 0x7B88080, 0x7B98080, 0x7BC8080, 0x7CC8080

    .long 0x7AB3BBB, 0x7E10094, 0x7E4556E, 0x4008080, 0x2922D17, 0x7B2AB00, 0x7C2A262, 0x71DFF6B

    .long 0x768D4A2, 0x769D4EA, 0x7BD88AE, 0x705997B, 0x70BB377, 0x711CC73, 0x717E66F, 0x7238866

    .long 0x729A262, 0x72FBB5E, 0x735D55A, 0x7417751, 0x747914D, 0x74DAA48, 0x753C444, 0x75F663B

    .long 0x76B9933, 0x7998080, 0x771B32F, 0x77D5526, 0x7836F22, 0x789881E, 0x78FA21A, 0x7159095

    .long 0x71AAA91, 0x720C38D, 0x726DD88, 0x7506F6A, 0x7568866, 0x75CA262, 0x762BB5E, 0x76E5E55

    .long 0x7747751, 0x77A914D, 0x780AA48, 0x78C4D3F, 0x792663B, 0x7988037, 0x79E9933, 0x7AA3C2A

    .long 0x7B05526, 0x7B66F22, 0x7BC881E, 0x72488AE, 0x72AA1AA, 0x72FBBA6, 0x735D4A2, 0x7427799

    .long 0x7489095, 0x74DAA91, 0x753C38D, 0x77E556E, 0x7836F6A, 0x7898866, 0x78FA262, 0x79C4459

    .long 0x7A15E55, 0x7A77751, 0x7AD914D, 0x7BF4D3F, 0x7CC8080, 0x7C5663B, 0x7CB8037, 0x7337FC8

    .long 0x73999C4, 0x73FB2C0, 0x745CCBB, 0x7757799, 0x74C54FF, 0x77B9095, 0x780AA91, 0x7AB3C72

    .long 0x7B1556E, 0x7B66F6A, 0x7BC8866, 0x74277E1, 0x74890DD, 0x74EAAD9, 0x754C3D5, 0x76066CC

    .long 0x7667FC8, 0x76C99C4, 0x772B2C0, 0x77E55B7, 0x7846EB3, 0x78A88AE, 0x790A1AA, 0x7526EFB

    .long 0x75787F7, 0x75DA1F3, 0x763BAEE, 0x76F5DE6, 0x77577E1, 0x77B90DD, 0x781AAD9, 0x78D4CD0

    .long 0x79366CC, 0x79F99C4, 0x7E10094, 0x7CF44A1, 0x7DB7799, 0x7E71A90, 0x7ED338C, 0x7FF8080

    .long 0x7328080, 0x7DC8080, 0x7C88080, 0x7508080, 0x775CD2C, 0x76944EA, 0x7808080, 0x71A61FF

    .long 0x7244D40, 0x7242C15, 0xFFF8080, 0xF338080, 0xF668080, 0xF998080, 0xFCC8080, 0xF008080

    .long 0xF4C54FF, 0xFAB3BBB, 0xFE10094, 0xFE4556E, 0xF952B15, 0xFDA7751, 0xFB2AB00, 0xFC2A262

    .long 0xF1DFF6B, 0xF68D4A2, 0xF69D4EA, 0xFBD88AE, 0xA922D17, 0xC6E4130, 0xE286963, 0x74C55FF

    .long 0x768D536, 0x7FF8080, 0x7FF8080, 0x7FF8080, 0x2922D17, 0x46E4130, 0x6286963, 0x8080




    Опять же, благодаря моей работе с Blackmagic Design я сразу распознал пиксели YUV (например, все значения с цифрами 8080).



    Я не дурак, чтобы опять рисовать весь пользовательский интерфейс вручную на бумаге, так что да, я написал ещё один инструмент — M240UITool.



    Leica M (typ 240) UI Tool v1.0

    Usage: ./M240UITool [-a address] [-i imagebase] [-s script] [-d dump] [-f folder] [-l LUT] [-rbv] FIRMWARE.BIN



    This tool will help you to find UI resources in firmware.

    Use following arguments:

    -a Specify address of the gui_CopyImageDesc function (ex. 0x2F95E0)

    -i Specify firmware imagebase

    -s Specify IDC file name

    -c Specify container file name

    -d Specify dump image format

    png - PNG format

    bmp - BMP (ARGB) format

    -f Specify folder for dumped images

    -l Specify LUT for images (filename of address)

    -b Specify number of bytes to display in verbose mode

    -r Try to recover string characters

    -v Be verbose




    Кроме сброса всех ресурсов изображений из файла микропрограммы в BMP/PNG, этот инструмент умеет создавать IDC-скрипты в IDA для определения всех ресурсов UI.



    Мы уже знаем, что из функции, которую создаёт одну страницу UI, несколько раз вызывается gui_CopyImageDesc. Я подумал, что будет здорово сделать браузер ресурсов UI и определить все функции рендеринга страниц. Для этого предназначена опция -c — она сооздаёт специальный контейнер для просмотра ресурсов.



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



    Как взломать дорогую камеру, чтобы вас не убила жена


    Будучи интерактивным (полупрозрачные кнопки на скриншоте), этот инструмент позволяет не только прокручивать страницы меню EVF/LCD, но просматривать этапы рендеринга в пределах одной страницы.



    К сожалению, исходники этого шедевра где-то потерялись, но заголовочные файлы всё ещё в коде M240UITool, поэтому технически можно воссоздать его с нуля.



    Меню отладки



    Какую строку мы ищем в первую очередь при реверс-инжиниринге? По-моему, это слово debug и производные от него.



    В прошивке было много интересных строк, но эти особенные:



    $ strings ./IMG_LOKI-212_1.1.0.2.bin | grep "Debug Mode"

    GUI: State: %d! Scanning for Debug Mode successful

    GUI: Scanning for Debug Mode: State: %d, Ignore long DEL

    GUI: Scanning for Debug Mode: State: %d

    GUI: Scanning for Debug Mode: State: %d, Ignore long DEL

    GUI: Scanning for Debug Mode: State: %d

    GUI: Scanning for Debug Mode: State: %d, Ignore long DEL

    GUI: Scanning for Debug Mode: State: %d

    GUI: Scanning for Debug Mode: State: %d, Ignore long DEL

    GUI: Scanning for Debug Mode: State: %d

    GUI: Scanning for Debug Mode: State: %d, Ignore long DEL

    GUI: Scanning for Debug Mode: State: %d

    ...

    GUI: ScanningForDebugWithKeyAndJoyStick(): g_GUI_CheckForDebugWithKeyAndJoyStick = %d




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



    Как взломать дорогую камеру, чтобы вас не убила жена


    Не буду врать, потребовалось некоторое время, чтобы понять, как в прошивке обрабатываются аппаратные кнопки, а затем восстановить перечисляемые типы для кнопок и джойстика. Но когда я получил комбинацию, то с огорчением выяснил, что она ничего не делает. Вероятно, она работает только с какой-то конкретной страницы GUI. Еще пара вечеров ручной трассировки машины состояний GUI — и проблема решена, а также удалось найти страницу меню Reset.



    Наконец, добро пожаловать в режим отладки.



    Как взломать дорогую камеру, чтобы вас не убила жена


    Я много думал, огласить ли эту комбинацию, но решил воздержаться. Я уважаю тяжёлую работу, которую делает Leica, выпуская свои уникальные аппараты, и не хочу отвечать за то, что их сервисные центры заполнят сломанные тушки камер в результате некоторого бездумного любопытства.



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



    enum ControlActionType {
        kControlAction_Idle,        // 0
        kControlAction_Push,        // 1
        kControlAction_Release,     // 2
        kControlAction_LongPush     // 3
    };
    
    enum ControlBtnType {
        kControlBtn_LV,             // 0
        kControlBtn_PLAY,           // 1
        kControlBtn_DEL,            // 2
        kControlBtn_ISO,            // 3
        kControlBtn_MENU,           // 4
        kControlBtn_SET             // 5
    };
    
    enum ControlJoystickType {
        kControlJoy_INFO,           // 0
        kControlJoy_Up,             // 1
        kControlJoy_Down,           // 2
        kControlJoy_Left,           // 3
        kControlJoy_Right           // 4
    };


    PTP



    Думая над задачей USB, я определил три режима (что также подтверждается в меню отладки):




    • PTP


    • MSC (Mass Storage Class)


    • Leica Custom



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



    В прошивке довольно легко найти обработчики PTP, потому что из этого кода много вызовов. Все вызовы PTP делятся на три группы: Legacy, Leica Extended (LE) и Production.



    Отладочные сообщения помогли установить названия почти для всего кода.





    Legacy: Leica Extented: Production:
    0x1001 - GetDeviceInfo 0x9001 - Set Camera Settings 0x9100 - Open Production Session
    0x1002 - OpenSession 0x9002 - Get Camera Settings 0x9101 - Close Production Session
    0x1003 - CloseSession 0x9003 - Get Lens Parameter 0x9102 - UpdateFirmware
    0x1004 - Get Storage ID 0x9004 - Release Stage 0x9103 - Open OSD Session
    0x1005 - Get Storage Info 0x9005 - Open LE Session 0x9104 - Close OSD Session
    0x1006 - GetNumObjects 0x9006 - Close LE Session 0x9105 - Get OSD Data
    0x1007 - GetObjectHandles 0x9007 - RequestObjectTransferReady 0x9106 - GetFirmwareStruct
    0x1008 - GetObjectInfo 0x9008 - GetGeoTackingData 0x910B - GetDebugMenu
    0x1009 - GetObject 0x900A - Open Debug Session 0x910C - SetDebugMenu
    0x100A - Get Thumb 0x900B - Close Debug Session 0x910D - ODIN Message
    0x100B - Delete Object 0x900C - Get Debug Buffer 0x910E - GetDebugObjectHandles
    0x100E - Initiate Capture 0x900D - Debug Command String 0x910F - GetDebugObject
    0x1014 - GetDevicePropDesc 0x900E - Get Debug Route 0x9110 - DeleteDebugObject
    0x1015 - GetDevicePropV 0x900F - SetIPTCData 0x9111 - GetDebugObjectInfo
    0x101C - Initiate Open Capture 0x9010 - GetIPTCData 0x9112 - WriteDebugObject
    0x9020 - Get3DAxisData 0x9113 - CreateDebugObject
    0x9030 - OpenLiveViewSession 0x9114 - Calibrate 3Daxis
    0x9031 - CloseLiveViewSession 0x9115 - Magnetic calibration
    0x9033 - Unknown 0x9116 - Get Viewfinder Data



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



    В любом случае, всё вышесказанное довольно увлекательно. Вы можете подумать: «Давайте просто подключим камеру по USB и начнём зондировать с помощью libptp». Всё верно.



    Только блин…



    У Leica M240 нет USB-порта.



    Порт для рукоятки



    Leica предлагает немного аксессуаров для этой камеры, но есть один особенно интересный. Речь идет о многофункциональной рукоятке Leica M (14495). Он заменяет нижнее металлическую часть корпуса, обеспечивает встроенный GPS и несколько разъёмов вроде USB, терминал вспышки SCA, DIN/ISO-X и гнездо для питания.



    Как взломать дорогую камеру, чтобы вас не убила жена<

    Источник: Хабр / Интересные публикации

    Категория: Веб-разработка

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

    Добавление комментария

    Имя:*
    E-Mail:
    Комментарий:
    Полужирный Наклонный текст Подчеркнутый текст Зачеркнутый текст | Выравнивание по левому краю По центру Выравнивание по правому краю | Вставка смайликов Выбор цвета | Скрытый текст Вставка цитаты Преобразовать выбранный текст из транслитерации в кириллицу Вставка спойлера
    Введите два слова, показанных на изображении: *