Wie man eine teure Kamera knackt, damit deine Frau dich nicht umbringt

Haftungsausschluss: Die Studie begann im Jahr 2013. Wenn Sie also einige Methoden für dumm und gefährlich halten, haben Sie Recht, das war es. Dabei habe ich jedoch viel gelernt.

Eintrag
Alles begann einige Monate vor der Geburt meines ersten Kindes. Meine Frau und ich wollten immer eine coole Leica-Kamera kaufen und stellten plötzlich fest, dass wir es lange Zeit nicht tun konnten, wenn wir es jetzt nicht kauften. Deshalb haben wir die M240 Kamera bestellt und ... Boom, wir wurden für sechs Monate in die Schlange gestellt. Bald hatte ich es satt zu warten und fing an, ihre Seite zu studieren. Meine Aufmerksamkeit wurde sofort auf den Dateibereich gelenkt. Nun, Sie können sich vorstellen, warum ... Firmware!

Ich habe eine unverschlüsselte und unkomprimierte Datei ( m8-2_005.upd ) gesehen, die mit PWAD Magic beginnt. Erkennst du Ja, das stimmt, das ist das Doom Patch WAD-Format. Jungs scheinen die Klassiker zu lieben. Das Format ist sehr gut dokumentiert , so dass es nicht schwierig war, es zu analysieren.

Leica Firmware-Dateien


Firmware Leica M8


Das ist eigentlich sehr lustig, denn als ich später die komprimierte Leica T-Firmware-Datei studierte, beschloss ich zunächst, die Komprimierungsmethoden zu testen, die id Software in der Vergangenheit verwendet hat.

Wikipedia sagt, dass sie das LHA-Format verwendet haben , das im Wesentlichen LZW ist. Da gängige LZW-Dekompressoren jedoch nicht passten, suchte ich nach einer bestimmten Implementierung der ID-Software - und voila fand ich Catacomb Armageddon in der Quelle . Ich muss zugeben, glücklich.

Auf jeden Fall zurück zum M8. Hier ist die Firmware-Struktur:

  REGELN: 0x0000008C (3036: 0x00000BDC) - XML-Beschreibung
 LUTS: 0x00000C68 (183274: 0x0002CBEA)
  GAMMA: 0x0000007C (31760: 0x00007C10)
  GEWINN: 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) - Blackfin-Prozessorfamilie für analoge Geräte
 GUI: 0x0011FEE0 (3574180: 0x003689A4)
  TRANS: 0x0000005C (59988: 0x0000EA54) - Lokalisierung
  BILDER: 0x0000EAB0 (267433: 0x000414A9)
   21_1PRT: 0x000000CC (18411: 0x000047EB) - Bild von JFIF
   21_2GRP: 0x000048B8 (23172: 0x00005A84) - Bild von JFIF
   21_3PAN: 0x0000A33C (23034: 0x000059FA) - Bild von JFIF
   24_1PRT: 0x0000FD38 (18489: 0x00004839) - Bild von JFIF
   24_2GRP: 0x00014574 (23230: 0x00005ABE) - Bild von JFIF
   24_3PAN: 0x0001A034 (22998: 0x000059D6) - Bild von JFIF
   28_1PRT: 0x0001FA0C (22605: 0x0000584D) - Bild von JFIF
   28_2GRP: 0x0002525C (23081: 0x00005A29) - Bild von JFIF
   28_3PAN: 0x0002AC88 (23282: 0x00005AF2) - Bild von JFIF
   35_1PRT: 0x0003077C (22496: 0x000057E0) - Bild von JFIF
   35_2GRP: 0x00035F5C (23532: 0x00005BEC) - Bild von JFIF
   35_3PAN: 0x0003BB48 (22881: 0x00005961) - Bild von JFIF
  FONT1: 0x0004FF5C (1522988: 0x00173D2C)
  FONT2: 0x001C3C88 (1723676: 0x001A4D1C)
  VERSION: 0x003689A4 (0: 0x00000000)
 M16C: 0x00488884 (130406: 0x0001FD66) - Renesas M16C-Familie (Motorola S-Record)
 FPGA: 0x004A85EC (131604: 0x00020214) - Xilinx Spartan 3
 FSL: 0x004C8800 (814: 0x0000032E) - der Bootloader der ersten Stufe 

Der sofort einsatzbereite IDA unterstützt keine Blackfin-Prozessoren, es gibt jedoch ein Plugin eines Drittanbieters .

Firmware Leica M9


Die Leica M9-Firmware-Datei ( m9-1_196.upd ) sieht verschlüsselt aus: Das Histogramm zeigt eine Verteilung von ca. 0,45%.



Das Ende der Geschichte? Vielleicht nicht. Tatsache ist, dass Leica eher schwache Prozessoren in den Kameras verwendete und zu dieser Zeit häufig XOR-Verschlüsselung in der Unterhaltungselektronik verwendet wurde. Deshalb habe ich beschlossen, ein einfaches Tool für den XOR-Vorgang zu schreiben, um die Firmware mit mir selbst zu vergleichen und einige Statistiken zu berechnen.

Die Schlüssellänge wurde durch Suchen nach dem längsten sich wiederholenden Muster bestimmt. Dies ist sinnvoll, da jede Firmware normalerweise große Blöcke sich wiederholender Daten enthält, z. B. ein 0x00 / 0xFF-Pad oder Grafiken mit LUT-Pixeln. Der Schlüssel selbst wird durch die Häufigkeit von Bytes innerhalb der Länge des Schlüssels berechnet, wobei das häufigste Byte an den Schlüsselpuffer geht. Das Ergebnis des Programms zeigte deutlich die XOR-Verschlüsselung. Dann musste ich das Tool ein wenig modifizieren , um den potenziellen Schlüssel zu erhalten und den Code zu entschlüsseln. Dies stellte sich erneut als PWAD-Datei heraus.

Der Inhalt von PWAD ergab die folgende Struktur:

  REGELN: 0x0000007C (2788: 0x00000AE4) - XML-Beschreibung
 LUTS: 0x00000B60 (4060616: 0x003DF5C8)
  PROZESS: 0x0000004C (3900572: 0x003B849C)
   CREATE: 0x0000004C (20: 0x00000014) - Zeitstempel
   LUTS: 0x00000060 (427744: 0x000686E0)
   GAINMAP: 0x00068740 (20008: 0x00004E28)
   LENS: 0x0006D568 (3452724: 0x0034AF34)
  CCD: 0x003B84E8 (148662: 0x000244B6)
   CREATE: 0x0000004C (20: 0x00000014) - Zeitstempel
   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) - Blackfin-Prozessorfamilie für analoge Geräte
  bf0: 0x0000004C (117846: 0x0001CC56) - Hauptprozessor
  bf1: 0x0001CCA4 (117826: 0x0001CC42) - Firmware des Subprozessors
  bf0.map: 0x000398E8 (27072: 0x000069C0) - Firmware-Karte des Hauptprozessors mit den folgenden Zeichen: D.
  bf1.map: 0x000402A8 (26304: 0x000066C0) - Subprozessor-Firmware-Karte mit den folgenden Zeichen: D.
 KÖRPER: 0x00426A90 (143280: 0x00022FB0) - Renesas M16C-Familie (Motorola S-Record)
 GUI: 0x00449A40 (3647624: 0x0037A888)
  TRANS: 0x0000005C (131656: 0x00020248) - Lokalisierung
  BILDER: 0x000202A4 (267433: 0x000414A9)
   21_1PRT: 0x000000CC (18411: 0x000047EB) - Bild von JFIF
   21_2GRP: 0x000048B8 (23172: 0x00005A84) - Bild von JFIF
   21_3PAN: 0x0000A33C (23034: 0x000059FA) - Bild von JFIF
   24_1PRT: 0x0000FD38 (18489: 0x00004839) - Bild von JFIF
   24_2GRP: 0x00014574 (23230: 0x00005ABE) - Bild von JFIF
   24_3PAN: 0x0001A034 (22998: 0x000059D6) - Bild von JFIF
   28_1PRT: 0x0001FA0C (22605: 0x0000584D) - Bild von JFIF
   28_2GRP: 0x0002525C (23081: 0x00005A29) - Bild von JFIF
   28_3PAN: 0x0002AC88 (23282: 0x00005AF2) - Bild von JFIF
   35_1PRT: 0x0003077C (22496: 0x000057E0) - Bild von JFIF
   35_2GRP: 0x00035F5C (23532: 0x00005BEC) - Bild von JFIF
   35_3PAN: 0x0003BB48 (22881: 0x00005961) - Bild von JFIF
  FONT1: 0x00061750 (1522988: 0x00173D2C)
  USBLOGO: 0x001D547C (1775: 0x000006EF) - Bild von JFIF
  FONT2: 0x001D5B6C (1723676: 0x001A4D1C)
 FPGA: 0x007C42C8 (150176: 0x00024AA0) - Xilinx Spartan 3A
 BF547: 0x007E8D68 (937576: 0x000E4E68) - Blackfin-Prozessorfamilie für analoge Geräte (FSL?) 


Firmware Leica M240


Ich habe mir angewöhnt, jeden Morgen die Download-Seite mit der Leica-Firmware zu überprüfen. Bald erschien eine neue Datei: FW_M240_1_1_0_2.FW .

Es sah nicht verschlüsselt aus, wurde aber komprimiert ...

Komprimierung


Das Histogramm zeigt einen großen Burst bei 0x9D.



Vielleicht ist dies eine Art Kompressionsmagie. Eine Suche im Internet [9D + Komprimierung] ergab nichts, außer dass 0x1F9D als Signatur für die LZW-Komprimierung verwendet wird . Wenn überhaupt, verstehe ich die LZ-Komprimierungstypen und habe beschlossen, die Bytes nach 0x9D zu betrachten. Und ich sah vier Optionen:

  1. 9D 70 C4
  2. 9D 00
  3. 9D XX YY
  4. 9D XX 8Y YY

Was haben Sie sonst noch bemerkt:

  • Die erste Option wird nur einmal unter der Adresse 0x30 angezeigt: Sie wird wahrscheinlich als Indikator für komprimierte Daten verwendet.
  • XX überschreitet niemals 0x7F;
  • Das letzte Byte von YY im dritten und vierten Fall überschreitet niemals 0x7F

Soweit ich über LZ weiß, ist dies LZ77 oder LZSS sehr ähnlich, wobei YY der Einrückungsschritt und XX die Anzahl der zu kopierenden Bytes ist. Und die zweite Option ist ein Sonderfall der Ausgabe von 0x9D. Ich habe eine einfache C-Funktion geschrieben, die diese Logik implementiert. Sie bestätigte, dass wir uns in die richtige Richtung bewegen, aber die vierte Option passt immer noch nicht in das Schema.

Ich habe in jeder Hinsicht versucht, es zu interpretieren, aber es wurde nichts daraus. Deshalb habe ich mich an meine Kameraden gewandt, um Rat zu bekommen. Einer bemerkte, dass nach meinen eigenen Beobachtungen das vierte Byte von YY nur erscheint, wenn das höchste Bit 0x8Y gesetzt ist: Dies ist nur ein zusätzlicher Abstand für den Einrückungsschritt. Ich schämte mich, alles stellte sich als so offensichtlich heraus ...

Schließlich begann der Dekomprimierer, einen gültigen Stream auszugeben ... bis er in der Mitte der Datei stecken blieb. Dies geschah aufgrund der unbekannten Länge des Schiebefensters. Zusätzliches Debugging und Tests haben die Situation behoben.

Es gab also ein Tool zum Parsen der Firmware M240 .

Firmware-Struktur


Um mit einem unbekannten Format zu arbeiten, habe ich mir nichts Besseres ausgedacht, als einige Offsets und Größen von Codeabschnitten zu messen - und zu versuchen, die nächstgelegenen Werte im Dateikopf zu finden. Zum Beispiel dieser Block:

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


verwandelte sich schließlich in:

1E1CAF2E — "LEICA FILE"
01010002 - 1.1.0.2
005C1AB1 — (big endian)
01291A7E — (big endian)
AE3873659C3D75B4342F446E13178E6B — MD5
00000001 —
00000030 —


Als ich die Struktur der Firmware verstand, verbesserte ich mein Tool und am Ende produzierte es Folgendes:

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!


Die M240-Firmware enthält einen Container mit neun Elementen:

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 -


Wie Sie sehen können, gibt es in einer Firmware zwei Sätze von Dateien. Später erfuhr ich, dass 212 eine Version der Bildverarbeitungs-Mikroschaltung ist und zwei Versionen der Leica M240 in Produktion gingen. Diese Studie basiert auf Version 212.

Systemverwaltung: CTRL_SYS-11.bin


Der einzige gemeinsame Teil ist die Firmware für den Systemsteuerchip. Dies ist eine wirklich große Binärdatei, und der Code kann leicht erraten, wofür er bestimmt ist.

$ 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


Daher haben wir den Renesas SH7216-Prozessor (SH-2A), der für die frühe Phase des Ladens, der E / A-Tests und der Firmware-Updates verantwortlich ist. Standardmäßig unterstützt IDA diesen Prozessortyp. Es blieb nur die richtige Grundlastadresse zu finden, die aus der Beschreibung der Firmware-Abschnitte bekannt ist: Dies ist 0x0 .

Section Name: "[A]CTRL_SYS-11"
Section offset: 14680064 | 0x00E00000
Section size: 917277 | 0x000DFF1D
Section base: 0 | 0x00000000


Ich habe es in die IDA geladen und alle Funktionen erkannt, aber ich habe mich nicht besonders damit befasst, da die Firmware des Hauptprozessors viel interessanter ist.

Hier kann auch angemerkt werden, dass der UART dieses Chips zum Service-Port geöffnet wird, wo er das Download-Protokoll anzeigt. Wir werden später darauf zurückkommen.

Hauptchip: IMG_LOKI-212.bin


Um mit dem Reverse Engineering dieser Firmware zu beginnen, müssen Sie zunächst einige Fragen beantworten:

  1. welche Art von Prozessor
  2. Was ist die Grundlastadresse?
  3. Auf welchem ​​Betriebssystem basiert es, falls vorhanden?

Dank unseres Tools kennen wir bereits die Adresse der Grundlast: Dies ist 0x100000 .

Section Name: "[A]IMG_LOKI-212"
Section offset: 0 | 0x00000000
Section size: 7340032 | 0x00700000
Section base: 1048576 | 0x00100000


Die Firmware speichert die verbleibenden Antworten in lesbarer Form. Zum Beispiel diese Zeile:

$ 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
...


Es handelt sich also um einen benutzerdefinierten Prozessor Fujitsu FR (Leica nennt ihn Maestro ) und das Betriebssystem Softune REALOS . In der Tat ist dies viel besser als Blackfin, da die IDA sofort FR unterstützt.

FR-Prozessormodul


Die Realität sah nicht so gut aus, da das IDA-Programm nach dem Herunterladen der Firmware-Datei keine Anweisungen, externen Links usw. zeigte.

Ich habe beschlossen, das Problem zu beheben, musste aber am Ende einige Teile der Firmware komplett neu schreiben . Hier ist das Ergebnis:





Zusätzlich zu den Korrekturen in ana , ins und out kann ein völlig neuer emu Code:

  • verschiedene Arten von Code und externe Links zu Daten erkennen;
  • Switch-Anweisungen erkennen
  • Stack-Tracing durchführen;
  • Separate Stapelargumente und lokale Variablen
  • Funktionen richtig erkennen.

Aber die größte Änderung, wie Sie bemerkt haben, sind Großbuchstaben für Anweisungen :)

Möchten Sie die vollständige Anleitung sehen? Da ist er:

  ADD ODER 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   
 UND BEORL DIV4S ST BNE DMOV ADDSP VERLASSEN   
 ANDH BEORH LSL STH BC DMOVH EXTSB XCHB    
 ANDB BTSTL LSL2 STB BNC DMOVB EXTUB 

Also einfach und schön.

Übrigens haben Sie vielleicht bemerkt, dass einige Anweisungen nicht ausgerichtet sind:

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

Dies ist kein Fehler im Prozessormodul, sondern ein Merkmal der Fujitsu FR-Familie. Es wird als Verzögerungssteckplatz bezeichnet und ist für RISC-Prozessoren recht typisch.

Aus dem FR80-Prozessorhandbuch (Hinweis: Der Link funktioniert nicht mehr):

Der Befehl, der sich unmittelbar nach dem Verzweigungsbefehl befindet (sein Ort wird als "Verzögerungsschlitz" bezeichnet), wird vor der Verzweigung ausgeführt, und der Befehl an der Zieladresse wird nach der Verzweigung ausgeführt. Da der Befehl im Verzögerungsschlitz vor der Verzweigungsoperation ausgeführt wird, beträgt die scheinbare Ausführungsgeschwindigkeit 1 Zyklus.

Dies ist im Wesentlichen eine Optimierung der Pipeline, und es ist besser, sich daran zu erinnern, da sie überall in der Leica-Firmware verwendet wird.

Softune REALOS


Aus dem Wiki :

Softune ist die integrierte Entwicklungsumgebung von Fujitsu für die Prozessorfamilien Fujitsu FR, FR-V und F2MC. Unterstützt von REALOS µITRON Echtzeit-Kernel. Beispielsweise wird es in Nikon DSLR-Kameras (siehe Nikon EXPEED) und einigen Pentax-Kameras mit K verwendet.

Dies ist also ein ziemlich beliebtes anständiges RTOS mit Aufgaben, Semaphoren und anderen Extras. Ich habe mich gefragt, ob es möglich ist, einige Standardbibliotheksfunktionen in der Leica-Firmware zu erkennen.

Ich muss den ersten Teil der Studie als große Zeitverschwendung bezeichnen, und hier ist der Grund dafür.

Die Softune-IDE erwies sich als sehr schwer zu finden, aber am Ende gelang es mir, etwas zu bekommen. Wie erwartet enthielt die IDE Bibliotheken. Es gab vier Binärdateien:

  • lib911.lib
  • lib911e.lib
  • lib911if.lib
  • lib911p.lib

Ich weiß nicht, warum ich, vielleicht durch Trägheit, als ich alles gehackt habe, was mit Leica zu tun hat, wieder mit dem Reverse Engineering des Formats begonnen habe. Ja, ein sehr gut dokumentiertes Objektmodulformat . Und ja, natürlich habe ich dafür ein spezielles Tool geschrieben :

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


Mithilfe dieser Funktion können Sie *.pat Dateien erstellen und diese als Eingabe in IDA FLAIR verwenden , um Signaturdateien zu generieren.

$ 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


Nachdem ich diese Unterschrift angewendet hatte, sah ich endlich glücklich die Korrespondenz in IMG_LOKI-212.idb .



Layout


Die Anzahl der Zeilen in der Firmware fällt sofort auf. Viele Funktionen sind nach ihrer Funktionalität benannt. Dies ist im Reverse Engineering-Prozess sehr nützlich, um das allgemeine Muster zu verstehen.

Es ist auch wichtig zu beachten, dass einige Teile der Firmware-Datei im Reset-Handler an eine andere Adresse kopiert werden. Beispielsweise wird der integrierte Loader zur Laufzeit im RAM höher verschoben.

Ich musste manuell zusätzliche Abschnitte erstellen, wodurch ich das folgende Layout erhielt:



Unterbrechungen


Die Tabelle der Interruptvektoren kann durch Zugriff auf TBR (Table Base Register) gefunden werden:

LDI:32 #int_table, R0
MOV R0, TBR


Normalerweise tritt es im Vektor-Reset-Handler ganz am Anfang der Firmware auf.

Die Adressen der Handler in der Tabelle werden in umgekehrter Reihenfolge gemäß der Formel TBR + (0x3FC - 4 × inum) gespeichert, sodass der Rücksetzvektor am Ende der Tabelle um 0x3FC versetzt 0x3FC .

Ich fand die meisten Unterbrechungen im FR-Handbuch und schlug vor, dass Leica Maestro ein ähnliches Layout hat. Dann nahm er jeden Handler und versuchte, eine Zeichenfolge oder einen anderen Hinweis zu finden, der den Zweck des Interrupts enthüllt.

Als Ergebnis habe ich diese Liste erstellt:



Viele Interrupts wie AUDIO / SDIO / VIDEO / JPEG / RAW werden erwartet, aber versuchen Sie, die mysteriösesten von ihnen zu identifizieren? Ich spreche über die Unterbrechung von int_uart_in . Es scheint, dass die Kamera eine Art UART CLI im Konsolenmodus unterstützt.

Systemaufrufe


Wie fast jedes Betriebssystem verwendet Softline REALOS Systemaufrufe. Im Assembler sehen sie folgendermaßen aus:



Die tatsächliche Adresse des Systemaufruf-Handlers wird wie folgt berechnet. Beginnen wir mit der Suche nach dem Interrupt-Handler INT #0x40 . Wie oben beschrieben, dies

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

Im Handler ist es einfach, einen Link zum Ende der Systemaufruftabelle mit 16-Bit-Wörtern zu finden. Der spezifische Datensatz in dieser Tabelle wird mit der Formel syscall_table_bottom + (num * 2) berechnet:

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

Dies sieht nicht wie eine Adresse aus, da die tatsächliche Adresse des Systemaufruf- syscall_table_bottom + offset als syscall_table_bottom + offset berechnet wird. Der gesamte Vorgang ist im Diagramm dargestellt.



Alle Systemaufrufe und ihre Funktionalität sind im Softline REALOS / FR-Kernelhandbuch angegeben. Daher konnte ich alle in der Tabelle implementierten Handler wiederherstellen und die IDB ein wenig verbessern.



Natürlich können Sie den Code noch schöner machen, indem Sie die Arten von Systemaufrufen in der IDA definieren.



Ich habe ein Python-Skript geschrieben, um automatisch nach diesen Systemaufrufen und mehr zu suchen.

Die Aufgaben


Beim sta_tsk ich festgestellt, dass nicht die Hauptfunktion als Parameter übergeben wird, sondern pid. Dies bedeutet, dass es Zeit ist, nach einer Vielzahl von Aufgabendeskriptoren zu suchen. Und es ist sinnvoll, mit sta_tsk selbst zu beginnen.

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

Ganz am Anfang sehen wir einige Links. Ich musste ein bisschen an Datentypen basteln, aber am Ende kamen die Teile zusammen:

  ROM: 100B80 word_100B80: .word 0xF;  Anzahl der Aufgaben
 ROM: 100B82 .word 0x1C;  Taskdeskriptorgröße

 ROM: 100B84 .long 0x82A09F5C;  Aufgabe 1 Deskriptor
 ROM: 100B88 .long 0x1000D
 ROM: 100B8C .lang 0
 ROM: 100B90 .long 0x40000000
 ROM: 100B94 .long sub_1A7DB2;  Hauptaufgabe
 ROM: 100B98 .long 0x8286EEC0
 ROM: 100B9C .long 0

 ROM: 100BA0 .long 0x82A09F88;  Aufgabe 2 Deskriptor
 ROM: 100BA4 .long 0x20010
 ROM: 100BA8 .long 0
 ROM: 100BAC .long 0x40000000
 ROM: 100BB0 .long sub_1A6BD2;  Hauptaufgabe
 ROM: 100BB4 .long 0x8287EEC0
 ROM: 100BB8 .lang 0
 ... 

usw. Nur 15 Aufgaben. Es war eine Frage der Zeit, jede Hauptfunktion zu untersuchen, den Namen und den Zweck der Aufgabe zu bestimmen (mit Ausnahme der letzten). Hier ist die vollständige Liste:

  1. SubCPU
    Diese Aufgabe ist anscheinend für Erfassungsvorgänge wie Belichtung, Sichtung auf dem Bildschirm usw. verantwortlich.
  2. Keymanager
    Diese Aufgabe ist höchstwahrscheinlich mit Hardwaretasten verbunden.
  3. Guimanager
    Eine ziemlich große Aufgabe, bei der die UI-Zustandsmaschine und das Interface-Rendering implementiert werden.
  4. Debugmanager
    Ja, es gibt etwas zu debuggen. Yum Yum.
  5. Filemanager
    Bei dieser Aufgabe dreht sich alles um Dateivorgänge.
  6. Fammanager
    Ich würde sagen, dass die Aufgabe für die Dateien und den Speicher verantwortlich ist, da dies von den Aufgaben des Dateimanagers und des Speichermanagers abhängt.
  7. Memorymanager
    Keine Überraschungen: Speicheroperationen, Poolverwaltung usw.
  8. Imagemanager
    Diese Aufgabe verwaltet die Codierungs- / Decodierungsprozesse und andere Bildverarbeitungsprozesse.
  9. Usbmanager
    Die aktuelle Herausforderung ist die USB-Kommunikationsverarbeitung, die MassStorage, PTP und Leicas eigenes Protokoll umfasst.
  10. IOManager
    Diese Aufgabe scheint darin zu bestehen, Speichergeräte wie SD- und CF-Karten zu verwalten (was? Welche anderen CFs? Vielleicht stammt sie vom Modell 213).
  11. Systemmanager
    Verschiedene Aufgaben wie allgemeiner Systembetrieb, Energieverwaltung usw.
  12. SettingsManager
    Behandelt den Kamerastatus und die Einstellungen.
  13. Monitormanager
    Verfolgt Änderungen des Kamerastatus und informiert andere Aufgaben.
  14. Peripheralmanager
    Diese Aufgabe steuert GPS, Helligkeit und einige andere Sensoren.
  15. Unbekannt
    Leider fand ich nichts Bedeutendes für sie.

Es ist interessant festzustellen, dass es nach dem Hauptarray einen weiteren herausragenden Deskriptor gibt.

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


Und die Funktion der Aufgabe verzweigt sich einfach von selbst.

ROM:101494 sub_101494:
ROM:101494 BRA sub_101494 ; CODE XREF: sub_101494


Auf diesen Deskriptor wird am Ende der start verwiesen, die für das Erstellen anderer Aufgaben und das Einrichten der Firmware verantwortlich ist. Dies ist also höchstwahrscheinlich die Aufgabe der Systeminaktion.

Module und Nachrichten


Zusätzlich zu Aufgaben können Sie einige logische Objekte definieren, z. B. E / A- und Peripheriemodule. Module werden als Teil einer der Aufgaben als Gruppe von Nachrichtenhandlern dargestellt.

Die IO-Gruppe scheint Folgendes zu umfassen:

  • IO-Manager
  • Subprozessor
  • USB-Manager
  • USB PTP
  • USB Leica-Protokoll
  • USB-Massenspeicher
  • Button Manager
  • Debug-Manager
  • Objektivmanager

Und in der peripheren Gruppe:

  • Peripherie-Manager
  • Lichtsensor
  • LEDs
  • Sprecher
  • Neigungssensor
  • Kappenverschlusserkennung
  • GPS-Modul
  • 3DAxis-Modul

Das Nachrichtensystem selbst verwendet die Standard-SOFTUNE-Strukturen:

 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 } 

Wie erwartet verfügt IPC auch über mehrere Nachrichtengruppen. Da viele Nachrichten in Aufgaben und Modulen verarbeitet werden, konnte ich nur einige dieser Gruppen wiederherstellen:

  0x1101xxxx - globale Systemmeldungen:
              0x11010002 = SYS_UPDATE_BOOTLOADER oder
              0x11010005 = SYS_ERASE_SETTINGS
 0x1102xxxx - Meldungen zur Bilderfassung:
              0x11020001 = CMD_CAP_CAPTURE oder
              0x11020008 = IMAGE_STATUS_CHANGED  
 0x1104xxxx - Meldungen zu Ereignissen im Zusammenhang mit der Wiedergabe:  
              0x11040002 = PLY_DISABLE_PLAY_MODE oder
             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 und 0x77AA00xx - Meldungen zum Wechseln des Kameramodus 

Leider sind viele andere Beiträge unbekannt.

GUI


In der Firmware-Datei werden auch die folgenden Abschnitte behandelt: CTRL_SYS-11 , IMG-LOKI-212 , IMG-DSP-212 , IMG-FPGA-212 und IMG-LENSDATA-212 .

Was mich überraschte, war der völlige Mangel an GUI-Ressourcen. Aber sie sollten irgendwo sein und sind höchstwahrscheinlich in IMG-LOKI-212 eingebaut .

Einer meiner üblichen Ansätze zur Umkehrung der Firmware-Entwicklung besteht darin, alle möglichen Querverweise wiederherzustellen. Nicht nur im Code, sondern auch im Datenbereich. Dann schaue ich sie durch und versuche, einige Muster oder Links zu bekannten Teilen des Codes zu finden.

Leica Firmware war keine Ausnahme. Es gibt viele ähnliche Datensequenzen mit Adressen zu anderen Datensequenzen, die weiter gehen usw. Als ich die Hierarchie der Links erklomm, sah ich endlich eine vertraute Funktion.

Zum Beispiel habe ich eine Datenstruktur ohne Links gefunden:

 g_data = { ... } 

Eine andere Struktur ging darauf ein:

 g_data_struct1 = { ... , &g_data } 

Worauf wiederum von einer anderen Struktur Bezug genommen wird:

 g_data_struct2 = { &g_data, ... } 

Diese Datenstruktur hat eine Verknüpfung vom Code und wird als Parameter an eine andere Funktion übergeben:

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

Aber func1()es heißt nicht direkt von einer anderen Funktion, und wird in einem Array gespeichert:

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

Oben habe ich einen Anruf im Code gefunden g_func_list1:

 func3() { g_func_list1[x] } 

Und wieder ist diese Funktion in einem Array gespeichert:

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

Ein anderer Code greift auf das Array selbst zu:

 func4() { g_func_list2[x] } 

Glücklicherweise wird diesmal die Funktion von einer anderen Funktion aufgerufen und so weiter gui_MADE_ApplicationRun.

 gui_Statemachine_DoStateChange() ╰ gui_MADE_ApplicationRun() ╰ func5() ╰ func4() 

Einige Zeilen weisen darauf hin, dass das GUI-Subsystem "MADE" heißt und Seitenübergänge mit MADE_GetSysTriallen Mitteln behandelt werden. Die GUI-Zustandsmaschine ist grundsätzlich in einer Funktion implementiert gui_Statemachine_DoStateChange. Nach dem Sammeln von Informationen über die GUI ergab sich ein allgemeines Bild:



Wie Sie sehen können, ist die Hauptfunktion für GUI-Ressourcen gui_CopyImageDesc(obwohl dies kein richtiger Name ist). Sie hat folgende Argumente:

 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 ) 

Es gibt vier Arten von Ressourcenbeschreibungen:

 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; } 

Der erste Typ hat einen Header mit einem Verweis auf ein Array von Datensätzen. Jeder Datensatz hat Koordinaten und eine Adresse für Pixeldaten. Der aktuelle Typ scheint zustandsabhängige Elemente wie Symbole zu beschreiben, die möglicherweise ausgegraut sind oder in der Benutzeroberfläche verschwinden.

Der zweite Typ beginnt ebenfalls mit einer Überschrift und wird zum Lokalisieren, Beschreiben von Zeilen oder Textblöcken verwendet.

Der dritte Typ beschreibt Zeichentabellen für verschiedene Sprachen.

Der letztere Typ ist für alle anderen statischen Ressourcen wie Bilder, Hintergründe usw. verantwortlich.

Schauen wir uns nun die Daten für die Bilder selbst an. Die ersten sechs Bytes sehen aus wie ein kleiner Header, gefolgt von einem sich wiederholenden Muster, bei dem jedes zweite Byte entweder oder ist . Es ist logisch , anzunehmen , dass und

+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


0xFF0x040x00080x0014- Breite und Höhe in einer Ansicht mit direkter Bytereihenfolge (Big Endian). Am Ende dieses Dumps sehen wir den Beginn einer anderen Sequenz 00 06 00 14 00 01. Dies ist höchstwahrscheinlich die nächste Ressource (wie durch einen Link dazu bestätigt). Somit beträgt die Größe der tatsächlichen Bilddaten 146 Bytes. Die Bildgröße sollte jedoch 0x8 * 0x14 = 0xA0 = 160 sein. Es ist klar, dass die Daten keine reinen Pixel und nicht einmal eine 8-Bit-LUT sind, da sie 14 Bytes kleiner sind. Was dann? Wahrscheinlich eine Art Komprimierung.

Wenn man sich diesen hexadezimalen Speicherauszug ansieht, ist es kaum zu glauben, dass ein komplexes Schema verwendet wird. Die Benutzeroberfläche von Leica ist nicht sehr farbenfroh. Nach meiner Erfahrung ist es daher am besten, die LUT-Tabelle hier zu verwenden. In diesem Fall wiederholen die UI-Ressourcen die LUT-Indizes wie 03 03 03oder vollständig1 1 1. In der Regel versucht der Kompressor, Datenverdopplungen zu beseitigen und sie durch einen Link zu ersetzen. Diese Index-Arrays sind auch mit einer einfachen Methode wie RLE ideal für die Komprimierung [data][number]. Ein einfacher Befehl zum Schreiben data(Wert) numbermal. Vor

diesem Hintergrund schlug ich vor, dass wir höchstwahrscheinlich ein einfaches Bild mit zwei LUT-Farben ( 0xFFund 0x04) betrachten und das Byte vor der Farbe die Anzahl der zu zeichnenden Pixel ist.

„Und dann hast du ein anderes Instrument geschrieben“, denkst du. Aber nein, ich nahm einen Stift und Papier und fing an, die Zellen auszufüllen. Es ist lustig, dass ich das Bild noch habe.



Irgendwann auf dem Weg wurde mir klar, dass 160 Pixel für dieses Bild nicht ausreichen, daher müssen 0x8 und 0x14 mit zwei multipliziert werden. Das dritte Wort 0x0001 gibt an, ob das Bild ein ASCII-Zeichen ist. Die endgültige ImageAsset-Struktur lautet also wie folgt:

 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[]; } 

Aber ein Teil fehlt noch: LUT.

Es war nicht so schwer zu finden, da viele Links und Strukturen bereits manuell wiederhergestellt wurden. Ich blätterte langsam durch die Datenabschnitte und suchte nach einem Array von 256 Elementen aus 16-Bit- oder 32-Bit-Werten, bis ich darauf stieß: Nochmals vielen Dank Bei meiner Arbeit mit Blackmagic Design habe ich sofort YUV-Pixel erkannt (zum Beispiel alle Werte mit den Zahlen 8080). Ich bin kein Dummkopf, die gesamte Benutzeroberfläche erneut manuell auf Papier zu zeichnen, also habe ich ein anderes Tool geschrieben - M240UITool . Dieses Tool kann nicht nur alle Image-Ressourcen aus der Firmware-Datei auf BMP / PNG zurücksetzen, sondern auch IDC-Skripte in IDA erstellen, um alle UI-Ressourcen zu ermitteln.

.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






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




Wir wissen bereits, dass die Funktion, die eine UI-Seite erstellt, mehrmals aufgerufen wird gui_CopyImageDesc. Ich dachte, es wäre großartig, einen UI-Ressourcenbrowser zu erstellen und alle Funktionen zum Rendern von Seiten zu definieren. Die Option -cist dafür vorgesehen - sie erstellt einen speziellen Container zum Anzeigen von Ressourcen.

Und wer hat gesagt, dass ein UI-Ressourcenbrowser möglicherweise nicht ungewöhnlich aussieht?



Dieses Tool ist interaktiv (durchscheinende Schaltflächen auf dem Screenshot) und ermöglicht es Ihnen, nicht nur durch die Seiten des EVF / LCD-Menüs zu scrollen, sondern auch die Rendering-Schritte innerhalb einer Seite anzuzeigen.

Leider ist der Quellcode für dieses Meisterwerk irgendwo verloren gegangen, aber die Header-Dateien befinden sich immer noch im M240UITool-Code, sodass Sie ihn technisch von Grund auf neu erstellen können.

Debug-Menü


Welche Linie suchen wir vor allem beim Reverse Engineering? Meiner Meinung nach dieses Wort debugund seine Ableitungen.

Es gab viele interessante Zeilen in der Firmware, aber diese sind etwas Besonderes: Es scheint, dass Sie mit einer Tastenkombination in den Debug-Modus wechseln können. Alle diese Zeilen werden von einer riesigen Funktion aufgerufen , die eine Knopfscan-Zustandsmaschine implementiert. So sieht es in der IDA aus:

$ 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



Ich werde nicht lügen, es hat einige Zeit gedauert, um zu verstehen, wie die Hardwaretasten in der Firmware verarbeitet werden, und dann die aufgezählten Typen für die Tasten und den Joystick wiederherzustellen. Aber als ich die Kombination bekam, stellte ich mit Ärger fest, dass sie nichts tat. Es funktioniert wahrscheinlich nur von einer bestimmten GUI-Seite. Noch ein paar Abende mit der manuellen Verfolgung der GUI-Zustandsmaschine - und das Problem ist gelöst, und wir haben es auch geschafft, die Menüseite Zurücksetzen zu finden.

Willkommen im Debug-Modus.



Ich dachte viel darüber nach, ob ich diese Kombination ankündigen sollte, entschied mich aber, mich zu enthalten. Ich respektiere die harte Arbeit, die Leica leistet, indem sie ihre einzigartigen Geräte herausbringt, und ich möchte nicht dafür verantwortlich sein, dass ihre Service-Center die kaputten Kadaver der Kameras aufgrund einer gedankenlosen Neugier füllen.

Dennoch werde ich einige aufgezählte Typen bereitstellen, um das Reverse Engineering für diejenigen zu vereinfachen, die bereit sind, diesen Weg zu gehen.

 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


Beim Nachdenken über die USB-Aufgabe habe ich drei Modi definiert (die auch im Debug-Menü bestätigt werden):

  • Ptp
  • MSC (Massenspeicherklasse)
  • Leica Brauch

PTP ist am interessantesten, weil es gut dokumentiert ist und es Ihnen ermöglicht, die Kamera zu steuern.

Es ist ziemlich einfach, PTP-Handler in der Firmware zu finden, da dieser Code viele Aufrufe enthält. Alle PTP-Anrufe sind in drei Gruppen unterteilt: Legacy , Leica Extended (LE) und Production .

Durch das Debuggen von Nachrichten konnten Namen für fast den gesamten Code festgelegt werden.

 Vermächtnis: Leica Umfang: Produktion:                           
0x1001 - GetDeviceInfo 0x9001 - Kameraeinstellungen festlegen 0x9100 - Produktionssitzung öffnen      
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 

Die Implementierung der PTP-Schnittstelle selbst scheint Standard zu sein, aber einige Befehle weisen Einschränkungen auf, die ich hier absichtlich weglasse.

In jedem Fall ist all das ziemlich aufregend. Sie könnten denken: "Schließen Sie einfach die Kamera über USB an und beginnen Sie mit libptp zu testen." Alles ist richtig.

Verdammt ...

Leica M240 hat keinen USB-Anschluss.

Griffanschluss


Leica bietet nur wenige Zubehörteile für diese Kamera an, aber es gibt eines, das besonders interessant ist. Wir sprechen über den Multifunktionsgriff Leica M (14495) . Es ersetzt den unteren Metallteil des Gehäuses, bietet integriertes GPS und mehrere Anschlüsse wie USB, einen SCA-Flash-Anschluss, DIN / ISO-X und eine Steckdose.



Und Sie sagen noch einmal: "Großartig, jetzt kaufen Sie es einfach, schließen Sie es an die Kamera an, schließen Sie die Kamera über USB an und beginnen Sie mit libptp zu testen." Alles ist richtig.

Nur verdammt ...

Es kostet fast 900 Dollar.

Dies sind fast neunhundert Gründe, einen eigenen Adapter zu erstellen. Für alle Fälle habe ich jedoch eBay-Benachrichtigungen für dieses Zubehör eingerichtet.

Anschluss


Der Anschluss an der Kamera lautet wie folgt:



Ich habe versucht, ihn im Internet zu finden, aber im Ernst, wie würden Sie ihn bei Google beschreiben?

Verzweifelt begann ich über einige verrückte Dinge nachzudenken, wie das Aufkleben von Folie oder Nadeln auf einen Radiergummi. Als ich bei Blackmagic Design auf die Kamera-Platine schaute, bemerkte ich, dass einer der Anschlüsse eine sehr vertraute Form hatte. Am nächsten Tag brachte ich meine Leica M240 zur Arbeit - und ja, es sah ähnlich aus, nur viel länger mit vielen Pads.

Es bleibt, die Teilenummer unseres Komponentenmanagers zu erfragen und sie dann im Samtec-Katalog zu finden: ERM8-013-05.0-L-DV-TR .



Wir haben Samtec auch gefragt, ob es möglich ist, eine Probe zu bekommen, und sie haben freundlicherweise zugestimmt.



Ein wenig Arbeit mit Lötkolben, Pappe und Klebeband - und mein eigener Stecker ist fertig (Muster von 2013).



Fünf Jahre später, im Jahr 2018, beschloss ich, Samtec persönlich zu bitten, eine weitere Probe zu senden. Ich wollte etwas besser machen.

ERCD-013-05.00-TTR-TTR-1-D


Wieder viel Arbeit mit einem Lötkolben, Fluchen, Drahtschneiden, Fluchen, wieder Arbeiten mit einem Lötkolben, um eine neue, attraktivere Option zu schaffen:



Pinbelegung


Der Stecker enthält 26 Kontakte: 13 auf jeder Seite. Noch bevor ich mein Teil verlötete, untersuchte ich den Kameraanschluss mit einem Multimeter und einem Logikanalysator. Übrigens müssen Sie einen Magneten am Sensor der unteren Abdeckung anbringen, damit die Kamera berücksichtigt, dass die Abdeckung angebracht ist.

Erde (Kamera aus, keine Batterie)

Ich beginne immer vom Boden aus, weil es sicher und sehr leicht zu finden ist.



Wir haben also acht Grundlinien (dunkelgrau).

Potential (Kamera ein)

Wenn die Kamera eingeschaltet ist, können Sie das Potential an jedem Pin messen und sich ein Bild von der Logik und den Leistungspegeln machen.

alexhude.imtqy.com/assets/2019/2019-01-24-hacking-leica-m240/probe2_potential.png

Die Leistung an den Pins 8–9 und 11–13 ist für Logik-Pins zu hoch, daher habe ich sie als Leistung (rot) definiert.

Widerstand (Kamera ausgeschaltet, kein Akku)

Es ist nützlich, den Widerstand zu messen. In einigen Fällen hilft dies, die Eingaben zu identifizieren und einige Zeilen zu gruppieren.



Angeschlossene Ausgänge (Kamera ausgeschaltet, kein Akku)

Dann habe ich beschlossen, alle externen Pads am Kameragehäuse zu überprüfen, um festzustellen, ob sie mit dem Service-Port verbunden sind.



Der Blitzsynchronisationskontakt wurde direkt mit Leitung 10 verbunden.

Logikanalysator (Kamera eingeschaltet) Die

Daten für jede Leitung wurden in der folgenden Reihenfolge aufgezeichnet: Einschalten, die Kamera sollte sich im LV-Modus befinden, ein Bild aufnehmen, Videoaufnahme starten.



Zwei Zeilen zeigen die Übertragung einiger Daten: 01 und 21.

01 - 115200, Übertragung von 8 Bits, 1 Stoppbit, Paritätsbit, LSB zuerst.



Alle 500 ms sendet es einen Zähler C3 3C 02 81 00 01 00 82, C3 3C 02 81 01 01 00 83, C3 3C 02 81 02 01 00 80...

21 - 115200, Übertragung von 8 Bits, 1 Stoppbit, kein Paritätsprüfbit, LSB zuerst.



Es sendet das Bootloader-Protokoll an SH7216 („Leica Camera AG“ im obigen Screenshot).

Markieren wir sie dunkelblau. Es ist ziemlich traurig, dass das Maestro-Protokoll auch bei den maximalen Debugging-Einstellungen im Debug-Menü nicht gelöscht wird.



Bei diesen Kontakten beträgt der Widerstand ca. 310 kOhm.

Ich weiß nicht warum, aber ich schlug vor, dass andere Datenleitungen einen ähnlichen Widerstand haben oder geschlossen werden. Daher habe ich die Linien ~ 300 kOhm, ~ 200 kOhm und ~ 100 kOhm als Datenleitungen definiert (Blautöne im Bild).

Im Allgemeinen wurde das folgende Bild gezeichnet.



12 Kandidaten auf der Datenleitung. Aber wie kann man sie überprüfen? Nach einem kurzen Gespräch mit den Eisenexperten über den elektrischen Schutz integrierter Schaltkreise fing ich an, Kontakte über einen 4-kOhm-Widerstand zu stechen, wodurch der Strom auf einen Wert reduziert wird, den die Eingänge nicht verbrennen sollten.

UART


Ich ging erneut davon aus, dass sich die RX-Leitung in der Nähe des TX befinden sollte. Die Leitungen 02, 03 und 20 sehen aus wie gute Kandidaten, da beide wie TX eine Spannung von 3,3 V haben.

Anfangs habe ich versucht, diese Linien mit Bus Pirate zu erkunden. Leider war das Ergebnis eher schmutzig. Dann habe ich SiLabs-basierte Kabel als zuverlässiger und konfliktfreier unter macOS angesehen.

Zuerst habe ich das TX-Kabel an Pin 20 angeschlossen und helpnach dem Bootloader mit der Eingabe begonnen . Wie erwartet wiederholte die Kamera nach einer kurzen Verzögerung die Zeichen.



Die Kontakte 02 und 03 waren die nächsten Kandidaten für UART. Leider gab es keine Anzeichen dafür, dass diese Leitungen abgehört wurden.

In der Abbildung sind die bekannten UARTs durch einen dunkleren Grünton gekennzeichnet.



USB


Alles begann damit, ein USB-Kabel mit einem Header in der Mitte und 4 kOhm-Widerständen zur Erfassung in zwei Hälften zu schneiden. Signalintegrität eines Differentialpaares? Nein, dann war es mir eigentlich egal. :) :)



Dann habe ich zu Hause mehrere USB-Heimgeräte untersucht, um eine Vorstellung davon zu bekommen, wie die Kommunikation an diesem Port aussieht.

Canon


Kamera Blackmagic Pocket


Camcorder Canon


Camcorder JVC Camcorder


Schlüsselbund


KidiZoom Kamera


Sie sind alle etwas unterschiedlich, aber der anfängliche D-D + Status ist niedrig. Nun, wir werden es wissen und jetzt werden wir überprüfen, ob wir Folgendes haben:

  • 22 - unwahrscheinlich, da D-D + ein Differentialpaar sind und ziemlich nahe beieinander liegen sollten;
  • 04/05 - es ist unwahrscheinlich, weil sie unterschiedliche Widerstände haben;
  • 14/15 — , ;
  • 15/16 — , .

Also habe ich den USB D-D + an die 15/16 Pins angeschlossen und an den iMac angeschlossen ...



Auf dem USB PTP-Bildschirm wurde die Kamera jedoch nicht auf dem Host angezeigt. Ich habe versucht, verschiedene Optionen für das Layout der elektronischen Schaltung zu konfigurieren, aber nichts hat funktioniert. Beagle zeigte viele beschädigte Pakete und andere Fehler. Am Ende gab ich auf und kehrte zum Reverse Engineering der Firmware zurück.

Dies ist die letzte Pinbelegung. USB ist dunkelgrün markiert.



Wer hätte gedacht, dass ein paar Jahre später dieselbe eBay-Benachrichtigung bei mir eintrifft und ich das gewünschte Zubehör ziemlich günstig kaufe?

Schließlich kann ich meine Annahmen über PTP testen. Aber zuerst war es sehr merkwürdig, wie der USB-PHY im Gadget aussieht.



Im Inneren befand sich der SMSC 2512b Hubdirekt auf der Straße von der Griffbuchse zum Mini-USB-Anschluss. Der Chip arbeitet im Standardmodus, da keine EEPROM- oder SCL / SDA-Pins vorhanden sind. Der erste Downstream-Port ist an eine Buchse am Kameragehäuse angeschlossen, der zweite ist jedoch an nichts angeschlossen.

Ich habe wahrscheinlich etwas verpasst, aber für mich macht eine solche Lösung nicht viel Sinn. Der technische Pass besagt, dass der Chip "voll integrierte USB-Pins sowie Widerstände zum Erhöhen und Verringern der Spannung" hat. Vielleicht haben die Leica-Ingenieure beschlossen, kein eigenes USB-PHY zu implementieren, sondern das im Hub, das gut getestet ist und sofort funktioniert. Tatsächlich kann ich ihnen keine Vorwürfe machen, denn bevor ich dies versuchte, stellte sich heraus, dass es eine schwierige Aufgabe war. Vielleicht ist dies eine Funktion zum Schutz vor Fälschungen, wer weiß.

Wenn Sie USB PHY verstehen und bereit sind zu helfen, zögern Sie nicht, mir zu schreiben: Es sollte möglich sein, über einen USB-Anschluss ohne dieses Markenzubehör zu arbeiten :)

Wieder PTP


Wie gesagt, es ist Zeit, mit der Leica PTP-Erweiterung herumzuspielen.

Glücklicherweise habe ich anstelle von libptp eine ziemlich coole C ++ - Bibliothek gefunden - es ist libEasyPTP . Das Schreiben eines auf dieser Bibliothek basierenden Tools dauerte ebenfalls nicht lange: Ich kannte bereits einige Einschränkungen in der Leica PTP-Oberfläche.

Und obwohl M240PTPTool ziemlich fehlerhaft ist, eignet es sich gut für die Rolle des Proof of Concept ( Programmcode ).

Nur zwei Anforderungen werden über PTP gesendet : GetDebugBuffer (0x900C) und DebugCommandString (0x900D) . Damit die Module das Debug-Protokoll ausfüllen können, müssen Sie im Menü die Debug-Stufe als "Debug" oder "Debug RAW" festlegen.

In der M240PTPTool-Oberfläche gibt es mehrere Optionen:

  • beenden - Werkzeug schließen;
  • Flush - Debug-Puffer von Kamera zusammenführen:

M240> flush
I:[00:11:468]|01| DATE/TIME CORRECTED by 5921 sec
D:[00:12:079]|00| Send message from TID 0 to TID 1 over MBX 3 - length: 4 - MesgID: 0x22020103
D:[00:12:179]|00| Send message from TID 0 to TID 1 over MBX 3 - length: 4 - MesgID: 0x22020103
D:[00:12:282]|11| Message received from TID 0 for TID 1 over MBX 3
D:[00:12:283]|11| Message received from TID 0 for TID 1 over MBX 3
D:[00:12:301]|00| Send message from TID 0 to TID 1 over MBX 3 - length: 4 - MesgID: 0x22020103
D:[00:12:402]|00| Send message from TID 0 to TID 1 over MBX 3 - length: 4 - MesgID: 0x22020103
D:[00:12:502]|00| Send message from TID 0 to TID 1 over MBX 3 - length: 4 - MesgID: 0x22020103
...


Jeder andere Text wird als Debugging-Befehl an die Kamera gesendet. Zum Beispiel helpwerden alle möglichen Befehle mit Argumenten angezeigt: Die vollständige Liste ist ziemlich groß, aber Sie können für jede Aufgabe direkte Nachrichten an Softune senden! Was wäre so interessant, dorthin zu senden ... Eine andere beliebte Zeile, nach der in der Firmware häufig gesucht wird, ist . Mal sehen, ob wir eine haben. Anscheinend können Sie die Firmware auf die SD-Karte kopieren. Über den Link zur Zeile "Dateien auf Karte ausgeben" können Sie den dafür verantwortlichen Code leicht finden. Es befindet sich im riesigen System Task-Block (PID 11, wie wir bereits wissen) und wird von der Nachricht ohne Argumente aufgerufen . Dial in M240PTPTool , drücken Sie die Eingabetaste und Blick auf den Bildschirm.

M240> help
********* debug command description ********

exposure request
Description: requests a release from Sub CPU
Parameter 1: Exposure Time TV

still request
Description: simulates the -still request- command flow of Sub CPU
Parameter: no

...

send Message;[Parameter1];[Parameter2];[Parameter2];...;...
Description: Sending Message to Task
Parameter 1: Receiver Task ID
Parameter 2: Command ID
Parameter 3: Command Data[0] (32 Bit)
Parameter 4: Command Data[1] (32 Bit)
Parameter 5: .
Parameter 6: .
use maximum 10 Parameter

...




dump

$ strings IMG_LOKI-212_1.1.0.2.bin | rg -i dump
GUI: HEX DUMP: Address: %x, Length: %d
HSK: DBG_WRITE_ROM_DUMP_SD: File was properly opened, but it seems to be empty.
ROM_DUMP
HSK: DBG_WRITE_ROM_DUMP_SD: Flushing Dump to ROM. Size %d
SD:\ROM_DUMP.bin
HSK: DBG_WRITE_ROM_DUMP_SD Command received!
ROM_DUMP.bin
HSK: DUMP failed, no cards inserted!
HSK: DUMP FlashROM to SD card.
HSK: DUMP FlashROM to CF card.
Dumping files to card


0x11080006

send Message;11;0x11080006



Entfernen Sie dann die SD-Karte und überprüfen Sie, was sich darauf befindet.



Hier ist es ein kompletter Dump, einschließlich Firmware.

Dies eröffnet endlose Möglichkeiten. Zum Beispiel können Sie ein winziges Gerät mit einer MCU, Unterstützung für einen USB-Host und Schaltflächen zum Starten komplexer Nachrichtensequenzen herstellen ...

Und dann hatten wir ein zweites Kind. :) :)

Nachwort


Wenn Sie das Gerät nicht beschädigen möchten, können Sie es normalerweise untersuchen, ohne das Gehäuse zu öffnen oder Drähte an die Leiterplatte zu löten. Unten sind meine Tipps, wenn Sie interessiert sind:

  • Hier finden Sie alle öffentlichen Informationen zum Gerät: technische Daten, Daten zu den Komponenten, Fotos der Innenseiten, Video ab Werk ;)
  • Wenn Sie über Firmware verfügen, lesen Sie diese und suchen Sie nach Tipps für externe Ausgänge.
  • , ;
  • GND// , ;
  • ;
  • , ;
  • , (, );
  • , Google (USB/UART/SPI/I2C/1Wire);
  • , ;
  • , ;
  • , .



github.com/alexhude

!

Source: https://habr.com/ru/post/de438168/


All Articles