Habe mal wieder was zum tüfteln (vielleicht ließt Dieter ja wieder mit!
:-)
Und zwar beschäftige ich mich schon länger mit den Blaupunkt
Navigationssystemen und habe doch so einiges darüber in Erfahrung
gebracht. U.a. weiss ich wie man das Mainboard-Flash (ein Spansion
S29GL256 mit 32MB) via JTAG ausliest und programmiert.
Der Pin-Algo des Gerätes ist mir aber noch ein Rätsel. Durch Experimente
habe ich herausgefunden das sich in Sektor #251 ab Adresse 0x1F60000
Daten befinden die zur Berechnung verwendet werden. Dabei ist der Sektor
nur am Anfang mit 0x5C9 Bytes gefüllt, der Rest ist 0xFF:
Hier mal exemplarisch der Bindump von "FX_PIN_8367.bin":
Ich kann einem Gerät einen Sektor eines anderen übertragen und somit die
PIN "vererben".
In dem Sektor stecken lesbare Infos wie:
die Ford-Nummer des Gerätes: "8S7T-18K931-AD"
die Ford-Nummer der Firmware: "8S7T-14C260-AC"
die BOSCH-Teilenummer: "7612300524"
die Seriennummer "9032145"
Der Algo könnte(!) in dem beigefügten Firmware-Dump liegen, es könnte
aber auch sein das dieser in der Firmware des Display-Boards steckt.
Auf dem Mainboard werkelt ein OMAP5948, welcher im Grunde ein
ARM9-Prozessor mit DSP auf einem Chip ist und eine Sonderanfertigung des
OMAP5912 darstellt.
Habe noch vergessen zu erwähnen das sich der PIN-Code wohl über die
Typen/Seriennummer des Gerätes berechnen lässt. In der Typennummer
steckt ein Verweis auf dem Algorithmus, es gibt wohl mind. 3
verschiedene:
https://mk4-wiki.denkdose.de/_media/artikel/audio_navigation/algo_a05_fx_side.jpghttps://mk4-wiki.denkdose.de/_media/artikel/audio_navigation/algo_f07_mca_side.jpghttps://mk4-wiki.denkdose.de/_media/artikel/audio_navigation/algo_f09_mca_side.jpg
Aber das ist mehr "Hörensagen" muss ich gestehen.
Die im o.g. Sektor befindliche Seriennummer kann ich ändern wie ich
will, das hat erstmal keinen Einfluß auf PIN-Code. Vermutlich wird nicht
die als ASCII kodierte Nummer zur Codevalidierung genutzt, sondern
andere Bytes des Sektors. Ich werde mal versuchen mich da ran zu tasten
um wenigstens die Speicherstellen zu identifizieren. Dann kann man ggf.
mittels Disassemblierung eine Referenz darauf finden.
Was ich nicht 100% weiss ist, ob die Software aus dem Flash ausgeführt
wird, oder ob diese beim Systemstart ins ebenfalls am OMAP
angeschlossene SDRAM (128MB) kopiert wird und dort läuft. Das könnte
natürlich dann Einfluß auf die Adressen haben.
Wer eine IDA zuhause hat, kann die Firmware als ARM Little Endian laden
und in den Processor-options ARMv5TEJ als Befehlsebene einstellen. Die
erste Instruction in (C)ode wandeln und schon baut sich der gesamte Baum
auf.
Hey Dieter mein Freund! Na klar hab ich den, hängt anbei und ums Rund zu
machen einer von nem NX gleich mit :-)
Ich habe es inzwischen auch endlich mal geschafft einen QEMU an IDA zu
kopplen, sodass ich Code ausführen kann... aber ich lerne noch. Obwohl
ARM(Thumb) relativ wenige Befehle hat ist es halt nicht so einfach
daraus schlau zu werden. Selbst aus dem Decompilat von IDA in C nicht.
Mir ist es heute gelungen das interne Boot-ROM des OMAP5948 via JTAG
auszulesen. Ich habe ein Dump beigefügt.
Dafür habe ich die Stromversorgung des Flash-Speichers unterbrochen
(hier war dankenswerter Weise ein 0 Ohm Widerstand auf dem Board
vorgesehen) und mit J-Flash die Bytes ab Adresse 0x0000 ausgelesen.
Eigentlich ganz einfach :-)
Evtl. nutzt das ja im weiteren Verlauf der Analyse etwas...
Gibt es Blaupunkt Autoradios überhaupt noch?
Früher gab es in der Hackerszene Tools mit denen sich der Code berechnen
lies. Keine Ahnung ob diese Tools noch im Netz auffindbar sind.
Sicherheitstechnisch waren sie heutigen Passworteingaben weit voraus.
Nach der dritten Fehleingabe wurde die Zeit bis der Code neu eingegeben
werden konnte, stufenweise erhöht.
Petra schrieb:> Gibt es Blaupunkt Autoradios überhaupt noch?> Früher gab es in der Hackerszene Tools mit denen sich der Code berechnen> lies. Keine Ahnung ob diese Tools noch im Netz auffindbar sind.
Das Gerät um das es geht ist Baujahr 2008. Hackertools mag es geben,
interessieren mich aber nicht, dafür würde ich auch kein Geld ausgeben.
Mir geht es darum das selbst herauszufinden, also mehr so ne Art Rätsel
:-) und natürlich dabei was zu lernen.
Olli Z. schrieb:> und natürlich dabei was zu lernen
Dann mal ein paar Tipps für das weitere Vorgehen: Das gesamte Flash
Image zu disassemblieren macht in diesem Fall keinen Sinn da im Flash
verschiedene Dinge gespeichert sind (u.a. ein Filesystem). Auch der
Bootloader ist für den PIN-Algorithmus ohne Bedeutung. Ein Blick auf den
Inhalt der Software-Update CD gibt dabei ein paar Hinweise was so alles
im Flash stehen könnte.
Dabei wird man feststellen dass bestimmte Teil komprimiert sind, die
muss man vor einer weiteren Analyse also erst entpacken.
Und noch was zu dem PIN-Algorithmus: wie aus der Seriennummer des Geräts
die dazugehörige PIN bestimmt wird wird man in der Firmware mit großer
Wahrscheinlichkeit nicht finden sondern nur wie die eigentliche PIN
obfuskiert wird und dann in dem von Dir schon entdeckten Flash-Bereich
abgelegt wird.
Ich vermute dass die Berechnung der PIN aus der Geräte-Seriennummer, wie
es diverse Tools machen, auf einem eventuell geleakten Tool von
Ford/Blaupunkt basieren, mit dem die Geräte bei der Produktion mit einer
PIN versehen werden. Dafür spricht auch die entsprechende
UDS-Funktionalität, mit der man eine neue PIN setzen kann (wenn man die
alte kennt). Wenn die PIN schon in der Software aus der
Geräte-Seriennummer berechnet werden würde bräuchte man sie nicht
obfuskiert im Flash speichern.
Dieter schrieb:> Olli Z. schrieb:>> und natürlich dabei was zu lernen>> Dann mal ein paar Tipps für das weitere Vorgehen: Das gesamte Flash
Danke für die Hinweise. Das macht Sinn was Du sagst. Zum Vergleich der
Eingabe und dem Hash-Wert im Flash muss ja eine Berechnung stattfinden.
Dieser Algorithmus wäre mein Ansatz zu prüfen ob er reversibel ist,
ähnlich wie beim KM-Stand im Tacho. Gut möglich das er das nicht ist.
Aber Du kennst mich ja, mir geht es nicht darum Radios in großem Stil zu
knacken, sondern mehr über den inneren Aufbau und die Funktion des
Gerätes zu erforschen und da wäre Bootprozess und eben auch die
Pin-Abfrage einfach ein praktisches Beispiel. Im Endeffekt könnte man,
wenn man weiss wo die Pin-Abfrage stattfindet, diese Routine patchen
sodass jeder Pin zum Erfolg führt oder die Abfrage garnicht erst
erscheint. Zumindest für letzteres gibt es im Radio sogar eine
Einstellung (Diebstahlschutz deaktivieren).
> Ein Blick auf den Inhalt der Software-Update CD gibt dabei ein paar Hinweise was
so alles im Flash stehen könnte.
> Dabei wird man feststellen dass bestimmte Teil komprimiert sind, die> muss man vor einer weiteren Analyse also erst entpacken.
Meinst Du? Ich denke da diese Updates keine Vollversionen sondern
wirklich nur Patches sind und daher keine echten zusammenhängenden
Blöcke darstellen und man schon garnicht ein "leeres" Radio damit
grundbetanken könnte. Die App welche das Update durchführt wird dann
wissen wo welche Bereiche überschrieben werden sollen. Und ja, das kann
gut sein das die Daten dort gepackt vielleicht sogar verschlüsselt
vorliegen, aber im Gerät selbst wird das eher nicht der Fall sein. Daher
hatte ich mich eher an die per JTAG gelesenen Images gehalten...
Olli Z. schrieb:> Meinst Du?
Wenn ich etwas nur vermute schreibe ich das explizit. Schau Dir halt den
Flash-Inhalt und die Update-CD an, dann siehst Du es selber. Auf den
Update-CDs ist die fast vollständige Software (bis auf den Bootloader
und teilweise DSP Software) und alles was man braucht um den Algorithmus
für das Obfuskieren der PIN im Flash herauszufinden.
Ben B. schrieb:> Gibts für den Hauptprozessor keinen Simulator, in den man den> Flash-Inhalt laden könnte?
Der Hauptprozessor, also die CPU (ARM926) ist ja garnicht das Problem
dabei. Dafür gibts genug Emulatoren (theoretisch ginge das sogar mit
QEMU), das Problem ist der "Rest" vom OMAP und damit meine ich noch
nichtmal den DSP, sondern die ganzen Peripheriebausteine und deren
Memory-Mapped-IO Addressen.
Das Boot-ROM (PBL) und auch der Boot-Loader (SBL) werden reichlich auf
diese Hardware zugreifen und entsprechende Rückmeldungen davon erwarten,
ohne die das Programm nicht weiterlaufen wird. Das fängt mit so
Kleinigkeiten wie der OMAP_ID an und geht weiter über eine Board-ID die
über den Adress-Bus ermittelt wird und die Kommunikation mit den
externen Komponenten wie z.B. dem V850 Radioprozessor.
Eine Sache beschäftigt mich auch noch: Wäre es nicht denkbar in den
Flash des Gerätes einen U-Boot SBL hochzuladen und damit das System mit
einem Linux-Kernel zu booten? Zumindest um sowas wie eine serielle
Konsole zu erhalten und mit der Hardware zu experimentieren?
Inzwischen weiss ich ja wie ich auch den ersten Sektor löschen und
beschreiben kann...
Vielleicht gibt es sogar eine Möglichkeit über das Boot-ROM von einem
externen USB-Medium zu booten, oder von der SD-Card.
Dieter schrieb:> Olli Z. schrieb:>> Meinst Du?>> Wenn ich etwas nur vermute schreibe ich das explizit. Schau Dir halt den> Flash-Inhalt und die Update-CD an, dann siehst Du es selber. Auf den> Update-CDs ist die fast vollständige Software (bis auf den Bootloader> und teilweise DSP Software) und alles was man braucht um den Algorithmus> für das Obfuskieren der PIN im Flash herauszufinden.
Ok. Der Inhalt teilt sich und ich denke das
dnl/bin/system/arion/ford_hsr der richtige Ordner für mein NX ist. Darin
finde ich die im Bild angegebenen Dateien.
Zuerst ins Auge springen einem dabei natürlich die boot.bin und
bootload.bin, welche exakt gleich sind. Vermutlich hat man irgendwann
mal den Dateinamen geändert und den alten/zweiten aus
Kompatibilitätsgründen drin gelassen.
Der ist auf jeden Fall unkomprimiert und kann direkt mit IDA
disassembliert werden. Das Array am Ende finde ich interessant, auch
wenn ich noch keine Idee hab was das sein könnte:
Schaut Inhaltlich so aus wie der erste Sektor vom Flash (Bootloader).
Die Datei "replace.btl" mit dem Inhalt "replace" sorgt dafür das der
Bootloader im Flash des Gerätes ausgetauscht wird.
Die Dateien "fgs.dnl" und "radio.dnl" sind wohl die Images die vom OMAP
aus in Richtung Graphicsboard (FGS) und Radioprozessor (V850) gesendet
werden. Somit könnte dann die "system.elf" die Main-Software vom OMAP
enthalten?!
Was es mit den *.uli Dateien auf sich hat erschließt sich mir noch
nicht.
Lustig der Text vom Entwickler der am Ende von sdsapp.uli steht (SDS ist
das Spracherkennungsmodul in der Software):
1
das ist ein text den ich`...gefügt habe um zu testen ob es mit..m packP...besser geht wenn mehr initialisierte da|..vorliegen "|M.tatsächlt...stimmte meine vermutung:|..gibt k€..fehler¤..beim erzeu`..des .uli-files!!!9¼?...DI_SBN_8.1V2
Hier ist die Rede von "mpack"? Wikipedia sagt darüber "mpack and munpack
are utilities used to encode and decode binaries for use in mail
messages following the MIME standard."
Aber was könnte ULI für ein Packformat sein? Da man große Teile des
Textes lesen kann spricht das eher gegen LZW oder RLE. Hmm....
In der gleichen Datei findet man diesen String
"X:\di_sbn\products\boot\sdsapp\source.._¬....cpp" der die Vermutung
nahe legt das es in C++ geschrieben wurde, also kein Java Byte-Code oder
sowas ist.
Die "system.elf" ist auch nicht komprimiert, die kann IDA öffnen und
disassemblieren.
Olli Z. schrieb:> Die "system.elf" ist auch nicht komprimiert, die kann IDA öffnen und> disassemblieren.
Das muss nichts heissen. Du kannst auch ein JPEG durch den duisasembler
jagen und sagen, das sei 8086 code. Rauskommen wird dabei natürlich nur
Müll, aber wenn der User es so will...
Olli Z. schrieb:> Das Array am Ende finde ich interessant, auch> wenn ich noch keine Idee hab was das sein könnte
Warum lädst Du die Datei in einen Disassembler wenn Du dann diese Frage
stellst? Schau Dir halt den Code an, dann siehst Du es. Der Bootloader
ist wirklich einfach, und der ARM Code nicht sehr schwierig zu
verstehen, an solchen Beispielen kann man gut üben. Wobei das zwar
nichts dazu beiträgt den PIN Algorithmus zu finden aber man kann an
einem einfachen Beispiel mal ausprobieren wie Reverse-Engineering
funktioniert.
Und wenn es immer noch zu kompliziert ist: Der Bootloader lädt im Großen
und Ganzen lediglich "system.elf" und ist im Prinzip ein einfacher ELF
Loader, der erste Teil dieser 32-Bit Werte ist ein Marker der in dem
Image gesucht wird.
Ben B. schrieb:> 0xCAFEAFFE, 0xAFFEAFFE, 0xAFFECAFE, 0xCAFECAFE
Cafe Affe, Affe Affe, Affe Cafe, Cafe Cafe :-)
Accent aigu muss man sich halt denken ...
Johann J. schrieb:> Ben B. schrieb:>> 0xCAFEAFFE, 0xAFFEAFFE, 0xAFFECAFE, 0xCAFECAFE> Cafe Affe, Affe Affe, Affe Cafe, Cafe Cafe :-)
Ja, man könnte es für einen Gag der Entwickler halten, aber es ist wohl
eher so wie Dieter gesagt hat, denn diese Kombi findet man auch im
"system.elf" wieder.
Dieter schrieb:> Schau Dir halt den Code an, dann siehst Du es. Der Bootloader> ist wirklich einfach, und der ARM Code nicht sehr schwierig zu> verstehen, an solchen Beispielen kann man gut üben. Wobei das zwar
Einfach... für jemand Deines Kalibers vielleicht. Ich hock schon zwei
Tage vor dem Code und weiss praktisch noch garnichts darüber.
Vielleicht gehe ich es auch falsch an, Vom RESET-Vector aus durchlaufen
zu wollen? Grundsätzlich sind es ja nur Nebeneffekte die etwas ausmachen
und die sind für mich aktuell nicht immer leicht zu finden. Daher hatte
ich ja gehofft etwas zu begreifen wenn man mal ein paar Subs mit mir
zusammen durchackert. Aber vermutlich hätte ich besser 2-3 Jahre
Assemblererfahrung haben sollen und überhaupt rückwärts denken zu können
:-)
Olli Z. schrieb:> Ja, man könnte es für einen Gag der Entwickler halten, aber es ist wohl> eher so wie Dieter gesagt hat, denn diese Kombi findet man auch im> "system.elf" wieder.
Sowas nimmt man zum Initialisieren von Speicherbereichen, um dann z.B.
die maximale Stackgröße bestimmen zu können. 0xDEAD BEEF ist auch
beliebt, oder klassisch 0x5AA5 A55A.
soul e. schrieb:> Sowas nimmt man zum Initialisieren von Speicherbereichen, um dann z.B.> die maximale Stackgröße bestimmen zu können. 0xDEAD BEEF ist auch> beliebt, oder klassisch 0x5AA5 A55A.
Du scheinst das zu kennen. Magst Du mir das Prinzip dahinter erklären?
Ich kapiers noch nicht.
Du schreibst ein markantes Muster ins RAM, dann lässt Du Deins Software
eine Weile rödeln, und dann guckst Du nach welche Bereiche überschrieben
wurden und ob das Deinen Erwartungen entspricht.
Aufwendigere Betriebssysteme bringen Funktionen zum Speicherschutz und
Stack Monitoring mit, da braucht man solche einfachen Tricks nicht mehr.
soul e. schrieb:> Du schreibst ein markantes Muster ins RAM, dann lässt Du Deins Software> eine Weile rödeln, und dann guckst Du nach welche Bereiche überschrieben> wurden und ob das Deinen Erwartungen entspricht.
Ah, ich glaube ich verstehe was Du meinst. Um vielleicht zu erkennen
wenn eine Funktion sich selbst rekursiv aufruft, oder unerwartet tiefe
Schachtelungen auftreten und dadurch der verfügbare Speicher immer
kleiner wird durch den anwachsenden Stack.
Also nehmen wir mal an das würde hier so gemacht werden, dann müsste ja
irgendwas in dem Bootloader auch darauf prüfen, also sowas in der Art
wie "if(*(SP-8)==0xCAFEAFFE) { error("Stack overflow"); }" ?
> Du kannst auch ein JPEG durch den duisasembler jagen und sagen,> das sei 8086 code.
Das wird jede Menge illegaler OpCodes erzeugen und daran sollte man
recht schnell merken, daß man probiert, Daten zu disassemblieren.
Also, ich sauge gerad an ARM disassembler-tutorials ein was geht. Ein
paar Konzepte sind mir inzwischen schon geläufig. Z.B.:
Das zum laden von Speicheradressen häufig referenzierte Konstanten zum
Einsatz kommen, welche sich "in der Nähe" des nutzenden Codes befinden
müssen.
Oder das mit BX und einer ungeraden Ziehladresse in Thumb und mit einer
geraden in den ARM Status gewechselt wird.
Oder das Subroutinen mit BL ausgeführt und mit BX LR zurück.
usw.
Aber, auch die Arbeit mit IDA Pro will gelernt sein ;-)
Sehr schick ist ja die graphische Anzeige, da erkennt man auf einen
Blick switch-Konditionen. Auch die C Pseudo-Code Generierung ist
interessant, wenn auch nicht immer so verständlich wie man sich das
wünschen würde ;-)
Komisch finde ich allerdings das IDA beides nur für Subroutinen
(Functions) macht und nicht auch für den Linearen Code.
Man darf aber ja auch nicht vergessen das den Assemblercode ein C++
Compiler erzeugt hat und kein Mensch. Daher wird man sicher häufiger auf
komische Dinge stossen, aber es sollten sich auch Muster erkennen
lassen.
Ich habe mal was über eine Methode gelesen wie man so verwendete
Bibliotheken ermitteln können soll. Irgendwie logisch, wenn ein ARM
Executeable statisch gelinkte Libs enthält, müsste man die fast mit
einer einfachen Bytesuche aufstöbern können!?
Das von Dieter genannte SYSTEM.ELF könnte sowas enthalten, denn die
Entwickler haben sicher nicht alles neu erfunden. Ich vermute auch das
hier der Kernel drin steckt, welcher ggf. auch wieder was
standardmäßiges wie ein RTOS ist.
Olli Z. schrieb:> Man darf aber ja auch nicht vergessen das den Assemblercode ein C++> Compiler erzeugt hat
Gibt es nur C++-Compiler? Merkwürdig, ich dachte, es gäbe da viel mehr
...
Wenn Du Dich mit der Thematik und angewandten Techniken (der
"Verschleierung") nicht auskennst - vergiss es.
Dieter, eine Frage an Dich als Vollblutprofi: Ich weiss das beim Booten
der Zustand der EMIFS-Adressleitungen einmal eingelesen wird und anhand
des Musters verschiedene Images gestartet werden können. Das sieht man
auch im Bootloader anhand der Strings. Auch wird die Board-ID so
übermittelt wodurch die Software weiss welche Hardware für welches
Fahrzeug sie darstellt.
Jedoch finde ich diesen Zugriff nicht im SBL. Kan das sein das der im
PBL des OMAP steckt?
An die EMIFS_A1-A25 Adressleitungen wird mit teils fest verdrahteten,
teils über PNP-Transistoren geschaltete 4,7k Widerstände gegen Vcc ein
Muster generiert. Der Widerstand ist so groß das die am Adressbus
hängenen Chips störungsfrei eine 0 (GND) erzeugen können und dieser
Umstand nicht weiter ins Gewicht fällt. Die Widerstände wirken eher wie
Pullups.
Für den normalen Start müsste es so ein Muster sein:
A25..A0
*****100000000001000010**
('*' bedeutet, beliebig)
Olli Z. schrieb:> Das sieht man> auch im Bootloader anhand der Strings
Welche Strings meinst Du, die in "bootload.bin"? Da stehen zum großen
Teil Namen von Sections des ELF-Image ("system.elf"), die der Loader
besonders behandelt.
Dieter schrieb:> Olli Z. schrieb:>> Das sieht man>> auch im Bootloader anhand der Strings>> Welche Strings meinst Du, die in "bootload.bin"? Da stehen zum großen> Teil Namen von Sections des ELF-Image ("system.elf"), die der Loader> besonders behandelt.
Genau, da gibt es TEST und andere Dinge.
Olli Z. schrieb:> Die hier behandelten Info sind von einem NX, aber grundsätzlich ist das> beim FX und beim MCA genauso.
Mein FX liegt hier bestimmt noch 10 Tage rum bis die Ram Riegel da
sind.. zum Flash/Rom auslesen etc hab ich eigentlich alles da wenn ich
nicht großartig dran rumbraten muss könnte ich da was auslesen..
allerdings sind im moment die RAMs ausgelötet.
Olli Z. schrieb:> Genau, da gibt es TEST und andere Dinge.
Diesen Namen haben, wie schon geschrieben, nichts mit irgendwelchen
unterschiedlichen Images zu tun, die in Abhängigkeit der
Hardware-Konfiguration geladen werden sondern es sind Sections in dem
ELF Image.
Das sieht man ganz einfach wenn man sich den Bootloader-Code ansieht
(die Strings werden per memcmp() verglichen) oder man schaut sich die
Struktur des ELF Image an (dazu muss man noch nicht einmal Assembler
Code lesen).
Philipp K. schrieb:> Mein FX liegt hier bestimmt noch 10 Tage rum bis die Ram Riegel da> sind.. zum Flash/Rom auslesen etc ha
Flash auslesen geht auch ohne RAM, aber da brauchen wir nichts, wär
alles verfügbar. FXe hab ich alle Varianten hier rumliegen, mehrfach ;-)
Damit kann man PIN codes des "A05" Algorithmus errechnen. Das Array mit
den Hash-Werten habe ich im Firmwareimage leider nicht finden können.
Habe mir zum testen mal ein kleines Tool in mein Wiki integriert:
https://mk4-wiki.denkdose.de/artikel/nav_fx/pin_code_decryptor
Olli Z. schrieb:> Das Array mit> den Hash-Werten habe ich im Firmwareimage leider nicht finden können.
Die Voraussetzung für eine Suche ist dass die gepackten Teile der
Firmware vorher entpackt wurden. Aber wie schon früher geschrieben, der
Algorithmus für die Berechnung des PIN Code aus der Geräte-Seriennummer
steckt mit ziemlicher Sicherheit nicht in der Firmware. Dort gibt es nur
den Algorithmus wie die PIN obfuskiert wird um sie im Flash zu
speichern. Man kann ja auch die PIN im Gerät ändern, dann passt die
Berechnung aus der Geräte-Seriennummer nicht mehr.
Dieter schrieb:> Die Voraussetzung für eine Suche ist dass die gepackten Teile der> Firmware vorher entpackt wurden.
Hieran bin ich bislang gescheitert. Ich wüsste nicht was komprimiert ist
und womit. Und kommt da am Ende was anderes raus als im Firmwareimage
steht?
Auch den Bootloader hab ich nur zum Teil verstanden.
> den Algorithmus wie die PIN obfuskiert wird um sie im Flash zu> speichern. Man kann ja auch die PIN im Gerät ändern,
Davon habe ich beim FX (NX und MCA) noch nie gehört. Auch kenne ich
keine UDS Prozedur (via CAN) dafür. Woher hast Du diese Info?
Olli Z. schrieb:> Ich wüsste nicht was komprimiert ist> und womit. Und kommt da am Ende was anderes raus als im Firmwareimage> steht?
Die ".ULI" Dateien sind komprimiert. Diese Dateien werden auch
komprimiert im Flash abgelegt und bei Gebrauch in den RAM ausgepackt.
Olli Z. schrieb:> Davon habe ich beim FX (NX und MCA) noch nie gehört. Auch kenne ich> keine UDS Prozedur (via CAN) dafür. Woher hast Du diese Info?
Entsprechende UDS Funktionen sind im Code. Sehr wahrscheinlich werden
die in der Produktion genutzt, eventuell sind die in einer normalen
Diagnose-Session nicht zu erreichen.
Lukasz schrieb:> code
Es stimmt das der jeweilige PIN im Image des Flash (mehrfach) im
Klartext abgelegt wird. ABER....
a) man muss wissen WO das ist (ich habe in mehr als 10 Images
nachgeschaut und er liegt jedesmal an anderen Speicherstellen) oder man
ein eindeutiges Prefix/Kontext hat.
b) wird er dort sicher nur hineinkopiert aber nicht abgeprüft. Die
Prüfung geschieht über den genannten Sector im Flash und die darin
enthaltene Seriennummer
c) man muss das Image auslesen können (wer das kann, kann den Sector
auch mit einer Wunsch-Pin umprogrammieren)
Dennoch interessant fürs Reverse Engineering, denn der ist dort nicht
von Hause aus, sondern wir von der software dort hingeschrieben. Diesen
Schreibzugriff müsste man zurückverfolgen um auf die Routine zu gelangen
die dies macht und da wäre man schon im richtigen Bereich für die Suche
nach dem Algo.
Dieter schrieb:> Die ".ULI" Dateien sind komprimiert. Diese Dateien werden auch> komprimiert im Flash abgelegt und bei Gebrauch in den RAM ausgepackt.
Nachdem was ich so finden konnte, könnte das eine LZO-Kompression sein
(Lempel-Ziv-Oberhumer). Ein Kompressionsverfahren auf Wörterbuch-Basis
wie z.B. das gute alte GIF. Das wäre dann auch eine Erklärung warum man
Teile lesen kann.
Leider ist der Header komplett anders als es der LZO-Standard vorsieht,
wodurch die Packprogramme (habe jetzt mal lzop auf Linux getestet) das
Format nicht erkennen. Ein Fake-Header hat auch nicht geklappt weil
darin div. Parameter zur Kompression/Dekompression enthalten sind und
u.a. auch noch eine Prüfsumme über die gesamte Datei.
> Entsprechende UDS Funktionen sind im Code. Sehr wahrscheinlich werden> die in der Produktion genutzt, eventuell sind die in einer normalen> Diagnose-Session nicht zu erreichen.
Sowas konnte ich noch nicht finden weil ich noch keine Idee habe wie ich
das erkenne. Womöglich müsste man erst die CAN-Handling Routine finden.
Die wird aber schwer zu finden sein, da vom OMAP kein CAN-Controller
genutzt wird. Es wird vielmehr der im Radioprozessor (V850) integrierte
CAN-Controller genutzt (hierhin laufen auch die CAN-Leitungen vom
Transceiver auf dem Board) und der V850 wiederum ist via SPI mit dem
OMAP verbunden.
Ich bin wieder einen Schritt weiter, aber stehe nun wieder vor diversen
Rätseln.
Olli Z. schrieb:> Leider ist der Header komplett anders als es der LZO-Standard vorsieht,> wodurch die Packprogramme (habe jetzt mal lzop auf Linux getestet) das> Format nicht erkennen.
Stimmt so nicht ganz. Die kleinen ".ULI" Dateien (< 20 kByte) lassen
sich durch eine triviale Änderung (Tipp: die ersten vier Bytes) mit
"lzopack" auspacken. Mit diesem Wissen kommt man dann auch bei den
größeren Dateien mit etwas Kreativität weiter (Tipp: es sind mehrere
Teile, die getrennt ausgepackt und am Schluss wieder zusammengesetzt
werden, entsprechend sind mehrere Einträge für die einzelnen Teile im
Header).
Olli Z. schrieb:> Sowas konnte ich noch nicht finden weil ich noch keine Idee habe wie ich> das erkenne.
Man erkennt das ziemlich schnell wenn man den Code für die zuständigen
Funktionen ausgepackt hat.
Danke für Deine Hilfe Dieter! Bin grad nicht einsatzfähig, aber teste
das sobald ich kann. Ich denke Du meinst den Magic header im File. Werde
mal was ausprobieren... aber das hatte ich mir eigentlich schon alles
angesehen. In der offiziellen Formatbeschreibung ist ein 7 Byte header
vorgesehen und in der Source hier
https://github.com/nemequ/lzo/blob/master/examples/lzopack.c
habe ich in Funktion do_decompress() auch gelesen das dieser explizit in
Länge und Bytefolge abgefragt wird. Der Start der plattapp.uli ist
jedoch nicht nur in den ersten 4 Bytes unterschiedlich. Womöglich ist
der Header dieser Datei nicht der Start eines LZO-Archives, sondern
mehrerer in einem ULI-Container gesammelter (ähnlich tar)..
Aber ich knobel nochmal etwas, zumindest gut zu wissen auf der richtigen
Spur zu sein...
Ich hab jetzt einiges mit LZO rumprobiert, komme aber zu keinen rechten
Ergebnis. Zunächst habe ich mit ein lzop.exe heruntergeladen und damit
eine Minimaldatei erzeugt um ein funktionierendes, echtes Archiv zu
untersuchen. Dies hier ist der Hexdump aus einer nur mit drei Zeichen
("LZO") bestehenden Textdatei welche ich comprimiert habe:
000003A0 00 00 01 00 CE DE AD CE 31 21 52 31 B4 03 00 00 ....ÎÞ.Î1!R1´...
13
000003B0 61 1C 56 EC a.Vì
Jetzt gehe ich mal einfach her und nemhe die 4 Byte Magic und pumpe dort
den 9 Byte Magic von LZO rein, wohlwissen das damit jegliche CRC
vermutlich zum Teufel sein wird:
00000020 00 42 03 00 00 93 E4 44 C8 00 0B AC BB B9 BB BA .B...“äDÈ..¬»¹»º
Wenn ich das mit der obigen Beschreibung vergleiche passt da fast nichts
zusammen. Daher vermute ich das dies entweder eine modifizierte oder
eine sehr frühe Version von LZO ist. Oder ein Teil der
Header-Information ist ans Ende der Datei geschrieben worden.
Olli Z. schrieb:> Wenn ich das mit der obigen Beschreibung vergleiche passt da fast nichts> zusammen.
Und warum nimmst Du nicht "lzopack", wie ich es geschrieben habe?
Dieter schrieb:> Olli Z. schrieb:>> Wenn ich das mit der obigen Beschreibung vergleiche passt da fast nichts>> zusammen.>> Und warum nimmst Du nicht "lzopack", wie ich es geschrieben habe?
Ähm, ja, natürlich. Ist unter "examples" im code. Klappt aber leider
auch nicht.
Habe den Header der basereg.uli so modifiziert das das im Source
geforderte Magic (7 bytes) vorn dran steht. Da in der Originaldatei nur
4 Byte magic drin stehen habe ich den Anfang der Datei um 3 Bytes
vergrößert:
00000020 03 00 00 93 E4 44 C8 00 0B AC BB B9 BB BA B7 AA ...“äDÈ..¬»¹»º·ª
Dabei bricht dann der "lzopack -d basereg.uli basereg.bin" mit der
Meldung ab: "header error - invalid blocksize 512". Im Source erkennt
man warum: an der Speicherstelle der Blockgröße steht in der Datei der
Long "00 00 02 00", also 512 Byte, aber laut Source müssen es mindestens
1024 Byte sein.
Den Wert in der Datei einfach zu erhöhen brachte keine Besserung, zwar
ging der Test dann durch aber es kam keine Datei heraus (0 byte).
Es sieht im Source so aus als wäre der Header bei diesem Format nur 17
Bytes lang:
7 Magic (00 E9 4C 5A 4F FF 1A)
4 Flags (00 00 00 00)
1 Method (01 => das ist gut, denn im Source wird nur diese zugelassen
:-)
1 Compression level (00 => hmm)
4 Block size (00 00 02 00 = 512 Bytes)
Olli Z. schrieb:> Klappt aber leider> auch nicht.
Sorry, mein Fehler. Ich sehe hier gerade dass der Header im Vergleich
zum original "lzopack" doch länger ist: nach den 4 Byte Magic kommen
acht 32-Bit Werte (Little Endian), gebraucht werden davon die letzten
drei (Block Größe, gepackte Größe, CRC). Die ausgepackte Größe gibt es
nicht im Header und kann auf die Block Größe gesetzt werden. Die CRC ist
nicht Adler32 sondern CRC32, die entsprechende Funktion gibt es in der
LZO Library. Die ursprünglich von "lzopack" gelesenen Werte "flags",
"method" und "compression_level" setzt man auf 1.
Für die größeren .ULI Dateien enthält der Header dann Angaben zu mehr
als einem mit LZO gepackten Datenblock.
Dieter schrieb:> Olli Z. schrieb:>> Klappt aber leider>> auch nicht.>> Sorry, mein Fehler. Ich sehe hier gerade dass der Header im Vergleich> zum original "lzopack" doch länger ist: nach den 4 Byte Magic kommen> acht 32-Bit Werte (Little Endian), gebraucht werden davon die letzten> drei (Block Größe, gepackte Größe, CRC). Die ausgepackte Größe gibt es> nicht im Header und kann auf die Block Größe gesetzt werden. Die CRC ist> nicht Adler32 sondern CRC32, die entsprechende Funktion gibt es in der> LZO Library. Die ursprünglich von "lzopack" gelesenen Werte "flags",> "method" und "compression_level" setzt man auf 1.>> Für die größeren .ULI Dateien enthält der Header dann Angaben zu mehr> als einem mit LZO gepackten Datenblock.
Also verstehe ich Dich richtig? ...
00000020 93 E4 44 C8 00 0B AC BB B9 BB BA B7 AA CA F4 A5 “äDÈ..¬»¹»º·ªÊô¥
4 Byte magic = "ULI "
Nun folgen acht 4-Byte (32-Bit) Werte im Little Endian Format:
1.) 00 00 00 00
2.) 01 00 00 00
3.) 02 00 00 00
4.) 00 00 00 00
5.) 24 00 00 00
6.) BB 0A 00 00 = Block Größe = 0xABB
7.) 42 03 00 00 = Gpackte Größe = 0x342
8.) 93 E4 44 C8 = CRC32 = 0xC844E493
Dann folgen die Daten:
00 0B AC BB B9 BB BA B7 AA CA F4 A5 ...
Ich habe nun den Code von examples/lzopack.c aus dem Paket
http://www.oberhumer.com/opensource/lzo/#download etwas modifiziert:
[code c]
/* magic file header for lzopack-compressed files */
static const unsigned char magic[4] =
{ 0x55, 0x4C, 0x49, 0x20 }; // "ULI "
/* read Little Endian 32-bit integer */
static lzo_uint32_t xread32_le(FILE *fp)
{
unsigned char b[4];
lzo_uint32_t v;
xread(fp, b, 4, 0);
v = (lzo_uint32_t) b[0] << 0;
v |= (lzo_uint32_t) b[1] << 8;
v |= (lzo_uint32_t) b[2] << 16;
v |= (lzo_uint32_t) b[3] << 24;
return v;
}
static int do_decompress(FILE *fi, FILE *fo)
{
int r = 0;
lzo_bytep buf = NULL;
lzo_uint buf_len;
unsigned char m [ sizeof(magic) ];
lzo_uint32_t flags;
int method;
int compression_level;
lzo_uint block_size;
lzo_uint32_t checksum;
lzo_uint32_t dummy;
total_in = total_out = 0;
/*
* Step 1: check magic header, read flags & block size, init checksum
*/
if (xread(fi, m, sizeof(magic), 1) != sizeof(magic) ||
memcmp(m, magic, sizeof(magic)) != 0)
{
printf("%s: header error - this file is not compressed by
lzopack\n", progname);
r = 1;
goto err;
}
dummy = xread32(fi); // ??? (00 00 00 00)
dummy = xread32(fi); // ??? (01 00 00 00)
dummy = xread32(fi); // ??? (02 00 00 00)
dummy = xread32(fi); // ??? (00 00 00 00)
dummy = xread32(fi); // ??? (24 00 00 00)
block_size = 0x2000; // DUMMY
flags = 1; // fixed
method = 1; // fixed
compression_level = 1; // fixed
checksum = lzo_crc32(0, NULL, 0);
/*
* Step 2: allocate buffer for in-place decompression
*/
buf_len = block_size + block_size / 16 + 64 + 3;
buf = (lzo_bytep) xmalloc(buf_len);
if (buf == NULL)
{
printf("%s: out of memory\n", progname);
r = 4;
goto err;
}
/*
* Step 3: process blocks
*/
for (;;)
{
lzo_bytep in;
lzo_bytep out;
lzo_uint in_len;
lzo_uint out_len;
/* read uncompressed size */
out_len = xread32_le(fi); // UNCOMPR SIZE (BB 0A 00 00)
printf("Uncompressed size: %d (0x%X) bytes\n", out_len, out_len);
/* exit if last block (EOF marker) */
if (out_len == 0)
break;
/* read compressed size */
in_len = xread32_le(fi); // COMPR SIZE (42 03 00 00)
printf("Compressed size: %d (0x%X) bytes\n", in_len, in_len);
/* sanity check of the size values */
if (in_len > block_size || out_len > block_size ||
in_len == 0 || in_len > out_len)
{
printf("%s: block size error - data corrupted\n", progname);
r = 5;
goto err;
}
/* place compressed block at the top of the buffer */
in = buf + buf_len - in_len;
out = buf;
/* read compressed block data */
xread(fi, in, in_len, 0);
if (in_len < out_len)
{
/* decompress - use safe decompressor as data might be
corrupted
* during a file transfer */
lzo_uint new_len = out_len;
r = lzo1x_decompress_safe(in, in_len, out, &new_len, NULL);
if (r != LZO_E_OK || new_len != out_len)
{
printf("%s: compressed data violation\n", progname);
r = 6;
goto err;
}
/* write decompressed block */
xwrite(fo, out, out_len);
/* update checksum */
if (flags & 1)
checksum = lzo_crc32(checksum, out, out_len);
}
else
{
/* write original (incompressible) block */
xwrite(fo, in, in_len);
/* update checksum */
if (flags & 1)
checksum = lzo_crc32(checksum, in, in_len);
}
}
/* read and verify checksum */
if (flags & 1)
{
lzo_uint32_t c = xread32_le(fi); // CRC32
if (c != checksum)
{
printf("%s: checksum error - data corrupted\n", progname);
r = 7;
goto err;
}
}
r = 0;
err:
lzo_free(buf);
return r;
}
[/code]
Wie man erkennt ist die Checksum die hier normalerweise genutzr wird
nicht im Header sondern im Trailer des komprimierten Files zu finden.
Was auch daher zu erklären ist, das die Prüfsumme auf den
dekomprimierten Teil der Daten berechnet ist. Die Methoden zur
Berechnung habe ich, wie von Dir vorgeschlagen von "adler32" auf "crc32"
geändert.
Das mit Blocksize kommt mir komisch vor. Wenn ich das so nehme wie Du
sagst, dann wäre die Blocksize im 6. 32-Bit Wert des Headers, also
0xABB. Warum aber wird eine solch "krumme" Blockgröße verwendet? So wie
ich die Blocks verstanden habe sind das in erster Linie Buffer die in
der Lage sind den unkomprimierten Teil zzgl. ein paar Zwischenzustände
aufnehmen zu können. Da hätte man doch eigentlich eher 0x1000 genommen
oder sowas?! Für mich sieht das ja doch eher nach der unkomprimierten
Größe aus. Im Sourcecode kann man erkennen das diese durchaus benötigt
wird, um z.B. den output-Buffer zu initiieren.
Dann noch die Frage zur IN-Size (Länge der komprimierten Daten): Die ist
mit 0x342 grundsätzlich plausibel. Nehme ich nun als Start der Daten den
Offset 0x0020 dann lande ich bei 0x0361 als letztes Byte. Das sieht so
irgendwie auch stimmig aus vom Bytemuster her, denn danach kommen noch
etliche Daten mit vielen 0x00ern drin und am Ende könnte das wieder eine
Checksum sein:
000003A0 00 00 01 00 CE DE AD CE 31 21 52 31 B4 03 00 00 ....ÎÞ.Î1!R1´...
9
000003B0 61 1C 56 EC a.Vì
Aber egal, habe es kompiliert und erhalte nur den Fehler:
1
Uncompressed size: 2747 (0xABB) bytes
2
Compressed size: 834 (0x342) bytes
3
lzopack.exe: compressed data violation
was wohl soviel bedeutet das die dekomprimierung nicht erfolgreich war
:-(
Dann habe ich nochmal etwas gehackt und doch wie von Dir angenommen das
der 8. 32-Bit Header-Wert die CRC ist und diese "überlesen" bevor ich
den decoder gefüttert habe. Heraus kam das er das Dateiende nicht so
richtig erkannt hat, aber er hat mir eine BIN Datei erstellt ohne
"violation" und mit der richtigen CRC (Datei angehangen). Ob jetzt diese
"basereg" (Registry?) nun irgendwas sinnvolles enthält... weiss noch
nicht, werde mich mal an den anderen Dateien versuchen.
Olli Z. schrieb:> Ob jetzt diese "basereg" (Registry?) nun irgendwas sinnvolles enthält... > >
weiss noch nicht, werde mich mal an den anderen Dateien versuchen.
Die ausgepackte Datei stimmt so, in den kleinen Dateien steht aber
nichts direkt lesbares. Interessant wird es erst bein den größeren
Code-Dateien.
Noch eine Korrektur: Die Blockgröße ist die Größe der ausgepackten
Daten, das Ergebnis ändert sich dadurch aber nicht (LZO packt nur soviel
aus wie tatsächlich da ist).
Dieter schrieb:> Noch eine Korrektur: Die Blockgröße ist die Größe der ausgepackten> Daten, das Ergebnis ändert sich dadurch aber nicht (LZO packt nur soviel> aus wie tatsächlich da ist).
Ja, das war mir schon klar :-) Die Blockgröße ist das was ein Reader
mindestens bereitstellen muss, damit LZO einen zusammenhängenden,
komprimierten Datenbereich im RAM auspacken kann. Auf diesen Block
scheint es dann jeweils eine Prüfsumme zu geben, welche am Anfang der
komprimierten Daten steht. Also lag ich schon garnicht so falsch mit
meiner Annahme das die Prüfsumme garnicht Bestandteil des Headers
sondern eher Bestandteil des komprimierten Datenblocks ist. Besteht also
eine Datei aus mehreren Blöcken, dann hätte jeder dieser Blöcke eine
Prüfsumme vorweg. Die Größe der entpackten Daten im Header wäre dann
aber vermutlich die der gesamten Datei und nicht des Blocks.
Dieter schrieb:> Olli Z. schrieb:>> Ob jetzt diese "basereg" (Registry?) nun irgendwas sinnvolles enthält... > >> weiss noch nicht, werde mich mal an den anderen Dateien versuchen.>> Die ausgepackte Datei stimmt so, in den kleinen Dateien steht aber> nichts direkt lesbares. Interessant wird es erst bein den größeren> Code-Dateien.
Ich frag mich noch warum meine Version des lzopack (werde ich am besten
mal in ulipack umbenennen ;-) das Ende der komprimierten Daten nicht
erkennt und denkt das da noch ein Block folgen würde. Das ich ein
korrektes Ergebnis habe liegt eher an meinem Hack. Das muss ich noch
bereinigen. Ich frage mich aber was denn da hinter den komprimierten
Daten noch für ein Zeug hängt?
Nach ein wenig Brute-Force habe ich folgendes herausgefunden:
- Die komprimierten Daten starten erst nach der 0xFFFF FFFF Signatur,
also ab Offset 0x54. Die Prüfsumme (CRC32) steckt wie gewohnt in Offset
0x20 (0xE9B76913). Extrahiere ich den Block (komprimiert 0x35E6B9 Bytes,
entpackt 0x4B7908 Bytes) und rechne die Prüfsumme nach, passt diese. Das
resultierende Binary (hier im ZIP zusammen mit dem Original ULI) enthält
dann auch Code welchen man mit IDA debuggen kann (naja, sofern man ihn
versteht ;-) sowie lesbaren Text.
Soweit so gut. Aber da fehlt hinten noch was. Es gibt also wenigstens
noch einen weiteren gepackten Teil in dem ULI. Aufgrund der
Größenangaben endet der erste gepackte Teil an Offset 0x35E70C:
Ab 0x35E70D müsste dann der nächste Teil weiter gehen. Sicher sind hier
auch wieder Headerinformationen enthalten, denn der Algo muss ja
wenigstens wissen wieviele komprimierten Bytes nun folgen und wie die
Prüfsumme des dekomprimierten Bereichs lautet. So richtig finde ich den
nächsten Anfang aber nicht...
Olli Z. schrieb:> So richtig finde ich den> nächsten Anfang aber nicht...
Warum sind da wohl noch Daten vor dem 0xFFFFFFFF am Anfang der Datei,
diese enthalten alle nötigen Informationen. Von der navfx001.uli hast Du
aber sowieso schon fast alles, der fehlende Teil ist ausgepackt nur
knapp 25 kByte groß.
Das meiste erkennt man, wenn man die Header-Daten etwas anders
formatiert (siehe Bild).
Unklar ist mir noch was in den Bytes 4-7 drin steht, sowie dem sich
wiederholenden Teil in jedem Header-Block der mit "????" gekennzeichnet
ist.
Auch komisch ist bei den Dateien mit mehreren Blöcken das dort beim
letzten Teil eigentlich keine wirklich sinnvollen Infos drin zu stehen
scheinen (Sizes mit 0 und startpos mit 0, sowie Checksum mit FF)
Der Packer schreibt imho am Schluss einen leeren Block folglich ergibt
sich das crc auf ff.
Der Entpacker erkennt daran den letzen Block des files und somit die
zahl der Blöcke und das im Anschluss die komprimierten Daten beginnen.
Namaste
Winfried J. schrieb:> Der Packer schreibt imho am Schluss einen leeren Block folglich ergibt> sich das crc auf ff.> Der Entpacker erkennt daran den letzen Block des files und somit die> zahl der Blöcke und das im Anschluss die komprimierten Daten beginnen.
Dann müsste er das ja beim Single-Block File genauso machen. Das klingt
irgendwie nicht schlüssig für mich.
Interessant ist, das alle Dateien den gleichen Footer/Trailer zu haben
scheinen. Dieser gehört definitiv nicht zum LZO-Teil und ist 0x4B Bytes
(evtl. auch nur 0x48 Bytes) groß. Es ändern sich, bis auf bootload.bin,
navreg.uli und navfx001.uli, nur die letzten 8 Bytes. Hierin sind
definitiv zwei Informationen enthalten:
Der vorletzte 4-Byte Wert enthält die Gesamt-Dateilänge
Der letzte 4-Byte Wert enthält die CRC32 Prüfsumme der gesamten Datei,
exlusive der Prüfsumme selbst (versteht sich von selbst ;-)
(In den nachfolgenden Anzeigen habe ich die Blöcke immer an Offset
0x0000 kopiert damit es besser lesbar und vergleichbar ist)
main_ver.bin:
00000030 12 1B 09 0A 00 00 01 00 CE DE AD CE 31 21 52 31 ........ÎÞ.Î1!R1
5
00000040 C8 26 00 00 10 2F 8C 58 È&.../ŒX
Das "CE DE AD CE" ist wohl eine Signatur. Ich vermute das der Updater im
Radio diese Daten benötigt um die Datei als gültige Updatedatei zu
erkennen. Darüber lässt sich sicher eine Routine im Code (flashdump oder
system.elf) finden die das behandelt!
Auch sollte man doch irgendwo eine CRC32 Funktion im Disassembler-Code
finden können, so häufig wie davon Gebrauch gemacht wird. Auf jeden Fall
finde ich schonmal die Entropy-Tabelle wie man sie im Quellcode von
LZOP, aber auch frei im Internet findet (z.B.:
http://web.mit.edu/freebsd/head/sys/libkern/crc32.c)
Olli Z. schrieb:> Darüber lässt sich sicher eine Routine im Code (flashdump oder> system.elf) finden die das behandelt!
Warum einfach wenn es auch kompliziert geht? Man könnte z.B. nach "ULI "
(mit dem Leerzeichen) in der "system.elf" suchen. Ganz nebenbei steht
dann auch noch "LZO" in der Nähe...
Dieter schrieb:> Warum einfach wenn es auch kompliziert geht? Man könnte z.B. nach "ULI "> (mit dem Leerzeichen) in der "system.elf" suchen. Ganz nebenbei steht> dann auch noch "LZO" in der Nähe...
Ja, darüber bin ich ja zum LZO gekommen ;-) Das wird/sollte alles
irgendwie zusammenhängen. Über die Handler müsste man dann auch zum
Aufruf gelangen. Aktuell weiss ich nur noch nicht wo und wie ich da
ansetzen soll, dafür kenne ich IDA noch zuwenig.
Noch ein Tipp zu den "XXXreg.uli" Dateien: Ausgepackt sind die ja nicht
direkt lesbar. Wenn man genau hinschaut erkennt man dass man das mit
einem XOR beheben kann (trivial mit einem konstanten Byte).
Dieter schrieb:> Noch ein Tipp zu den "XXXreg.uli" Dateien: Ausgepackt sind die ja nicht> direkt lesbar
Vielen Dank! Irgendwie finde ich das richtig klasse mit Deinen
Hinweisen, das ist fast wie ein Krimirätsel :-)
Momentan arbeite ich daran mir aus dem lzopack.c einen ulipack.c zu
bauen, mit all den Erkenntnissen von oben. Da werde ich dann eine Option
für die reg-Dateien mit integrieren.
Zuerstmal musste ich merken das die block_size beim uncompress-alog
nicht beliebig sein kann, sprich bei großen Datenmengen muss man hier in
kleineren Schritten vorgehen, sonst erhält man nen
LZO_E_INPUT_NOT_CONSUMED, was laut API der Fall ist "if 'src_len' is too
large". Naja, Lehrgeld halt...
> Wenn man genau hinschaut erkennt man dass man das mit> einem XOR beheben kann (trivial mit einem konstanten Byte).
Wie kommt man denn darauf? Ich kann noch so lange drauf gucken, ich sehe
nur Bytes. Woran "siehst" Du nur das da mit XOR gearbeitet wurde?
Olli Z. schrieb:> Wie kommt man denn darauf? Ich kann noch so lange drauf gucken, ich sehe> nur Bytes. Woran "siehst" Du nur das da mit XOR gearbeitet wurde?
Man sieht dass es nicht komplett zufällig ist (z.B. an den
Wiederholungen),
außerdem ist Bit 8 in fast allen Bytes gesetzt (abgesehen vom dem
letzten Byte). Das könnte also ASCII Text sein, nur halt mit XOR, damit
man es nicht sofort erkennt. Und ein konstantes Bytes als XOR wegen der
Wiederholungen.
Eine "akademische" Lösung wäre z.B. die Entropie ansehen oder die
Häufigkeit der Byte-Werte berechnen, aber in diesem Fall ist es so
einfach dass man mit ausprobieren schneller ans Ziel kommt.
Noch etwas wofür man keinen Disassembler braucht: Man kann etwas
Struktur in die Daten aus dem Flash bringen (der Hexdump hier ganz am
Anfang) wenn man genau hinsieht. Es gibt einen Header, dann kommen die
Datensätze, die jeweils aus CRC, ID, Länge und den eigentlichen Daten
bestehen. Etwas erschwert wird das Ganze durch ein Alignment der Daten,
dafür werden Füllbytes verwendet. Der Header hat ebenfalls eine CRC,
außerdem gibt es eine spezielle ID für gelöschte Datensätze.
Dieter schrieb:> Noch ein Tipp zu den "XXXreg.uli" Dateien: Ausgepackt sind die ja nicht> direkt lesbar. Wenn man genau hinschaut erkennt man dass man das mit> einem XOR beheben kann (trivial mit einem konstanten Byte).
Ich denke das Cipher für die in "basereg.uli" enthaltenen Daten lautet
0xFE.
Hab mir die Daten, wie Du gesagt hast nochmal auf mich wirken lassen.
Zunächst mal sehe ich das dort nur hohe Werte enthalten sind und damit
der Cipher wenigstens 0x80 (0b1000 0000) sein muss um gültige
ASCII-Zeichen zu produzieren.
Dann habe ich mir in C schnell ein Tool geschrieben welches die ersten
80 Zeichen (einfach nur um genug für eine Aussage zu haben) einer Datei
einliest und dann über alle möglichen XOR-Werte (1 Byte) iteriert
ausgibt. Dabei ersetze ich nicht ASCII-Zeichen durch "." damit es kein
Wirrwarr im output gibt.
Das Ergebnis betrachte ich dann einfach und suche nach etwas "lesbarem":
1
PS C:\temp\crack_xor.exe basereg.bin
2
using cipher 0x80: ,;9;:7*Jt%65;'!21=?2!3?=670;#t%65;'!21=?2!3?=670;"-18*)?,;#t%65;'!21=?2!3?=670;"
3
using cipher 0x81: -:8:;6+Ku$74:& 30<>3 2><761:"u$74:& 30<>3 2><761:#,09+(>-:"u$74:& 30<>3 2><761:#
4
using cipher 0x82: .9;985(Hv'479%#03?=0#1=?4529!v'479%#03?=0#1=?4529 /3:(+=.9!v'479%#03?=0#1=?4529
5
using cipher 0x83: /8:894)Iw&568$"12><1"0<>5438 w&568$"12><1"0<>5438!.2;)*</8 w&568$"12><1"0<>5438!
6
using cipher 0x84: (?=?>3.Np!21?#%659;6%7;9234?'p!21?#%659;6%7;9234?&)5<.-;(?'p!21?#%659;6%7;9234?&
7
using cipher 0x85: )><>?2/Oq 30>"$748:7$6:8325>&q 30>"$748:7$6:8325>'(4=/,:)>&q 30>"$748:7$6:8325>'
8
using cipher 0x86: *=?=<1,Lr#03=!'47;94'59;016=%r#03=!'47;94'59;016=$+7>,/9*=%r#03=!'47;94'59;016=$
9
using cipher 0x87: +<><=0-Ms"12< &56:85&48:107<$s"12< &56:85&48:107<%*6?-.8+<$s"12< &56:85&48:107<%
10
using cipher 0x88: $3132?"B|->=3/):957:);75>?83+|->=3/):957:);75>?83*%90"!7$3+|->=3/):957:);75>?83*
11
using cipher 0x89: %2023>#C},?<2.(;846;(:64?>92*},?<2.(;846;(:64?>92+$81# 6%2*},?<2.(;846;(:64?>92+
12
using cipher 0x8A: &1310= @~/<?1-+8;758+957<=:1)~/<?1-+8;758+957<=:1(';2 #5&1)~/<?1-+8;758+957<=:1(
13
using cipher 0x8B: '0201<!A.=>0,*9:649*846=<;0(.=>0,*9:649*846=<;0)&:3!"4'0(.=>0,*9:649*846=<;0)
14
using cipher 0x8C: 7576;&Fx):97+->=13>-?31:;<7/x):97+->=13>-?31:;<7.!=4&%3 7/x):97+->=13>-?31:;<7.
15
using cipher 0x8D: !6467:'Gy(;86*,?<02?,>20;:=6.y(;86*,?<02?,>20;:=6/ <5'$2!6.y(;86*,?<02?,>20;:=6/
16
using cipher 0x8E: "57549$Dz+8;5)/<?31</=1389>5-z+8;5)/<?31</=1389>5,#?6$'1"5-z+8;5)/<?31</=1389>5,
17
using cipher 0x8F: #46458%E{*9:4(.=>20=.<0298?4,{*9:4(.=>20=.<0298?4-">7%&0#4,{*9:4(.=>20=.<0298?4-
18
using cipher 0x90: <+)+*':Zd5&%+71"!-/"1#/-&' +3d5&%+71"!-/"1#/-&' +2=!(:9/<+3d5&%+71"!-/"1#/-&' +2
19
using cipher 0x91: =*(*+&;[e4'$*60# ,.#0".,'&!*2e4'$*60# ,.#0".,'&!*3< );8.=*2e4'$*60# ,.#0".,'&!*3
20
using cipher 0x92: >)+)(%8Xf7$')53 #/- 3!-/$%")1f7$')53 #/- 3!-/$%")0?#*8;->)1f7$')53 #/- 3!-/$%")0
21
using cipher 0x93: ?(*()$9Yg6%&(42!".,!2 ,.%$#(0g6%&(42!".,!2 ,.%$#(1>"+9:,?(0g6%&(42!".,!2 ,.%$#(1
22
using cipher 0x94: 8/-/.#>^`1"!/35&%)+&5'+)"#$/7`1"!/35&%)+&5'+)"#$/69%,>=+8/7`1"!/35&%)+&5'+)"#$/6
23
using cipher 0x95: 9.,./"?_a0# .24'$(*'4&*(#"%.6a0# .24'$(*'4&*(#"%.78$-?<*9.6a0# .24'$(*'4&*(#"%.7
24
using cipher 0x96: :-/-,!<\b3 #-17$'+)$7%)+ !&-5b3 #-17$'+)$7%)+ !&-4;'.<?):-5b3 #-17$'+)$7%)+ !&-4
25
using cipher 0x97: ;,.,- =]c2!",06%&*(%6$(*! ',4c2!",06%&*(%6$(*! ',5:&/=>(;,4c2!",06%&*(%6$(*! ',5
26
using cipher 0x98: 4#!#"/2Rl=.-#?9*)%'*9+'%./(#;l=.-#?9*)%'*9+'%./(#:5) 21'4#;l=.-#?9*)%'*9+'%./(#:
27
using cipher 0x99: 5" "#.3Sm</,">8+($&+8*&$/.)":m</,">8+($&+8*&$/.)";4(!30&5":m</,">8+($&+8*&$/.)";
28
using cipher 0x9A: 6!#! -0Pn?,/!=;(+'%(;)%',-*!9n?,/!=;(+'%(;)%',-*!87+"03%6!9n?,/!=;(+'%(;)%',-*!8
using cipher 0xA0: .......jT....................T.............................T....................
35
using cipher 0xA1: .......kU....................U.............................U....................
36
using cipher 0xA2: .......hV....................V.............................V....................
37
using cipher 0xA3: .......iW....................W.............................W....................
38
using cipher 0xA4: .......nP....................P.............................P....................
39
using cipher 0xA5: .......oQ....................Q.............................Q....................
40
using cipher 0xA6: .......lR....................R.............................R....................
41
using cipher 0xA7: .......mS....................S.............................S....................
42
using cipher 0xA8: .......b\....................\.............................\....................
43
using cipher 0xA9: .......c]....................].............................]....................
44
using cipher 0xAA: .......`^....................^.............................^....................
45
using cipher 0xAB: .......a_...................._............................._....................
46
using cipher 0xAC: .......fX....................X.............................X....................
47
using cipher 0xAD: .......gY....................Y.............................Y....................
48
using cipher 0xAE: .......dZ....................Z.............................Z....................
49
using cipher 0xAF: .......e[....................[.............................[....................
50
using cipher 0xB0: .......zD....................D.............................D....................
51
using cipher 0xB1: .......{E....................E.............................E....................
52
using cipher 0xB2: .......xF....................F.............................F....................
53
using cipher 0xB3: .......yG....................G.............................G....................
54
using cipher 0xB4: .......~@....................@.............................@....................
55
using cipher 0xB5: .......A....................A.............................A....................
56
using cipher 0xB6: .......|B....................B.............................B....................
57
using cipher 0xB7: .......}C....................C.............................C....................
58
using cipher 0xB8: .......rL....................L.............................L....................
59
using cipher 0xB9: .......sM....................M.............................M....................
60
using cipher 0xBA: .......pN....................N.............................N....................
61
using cipher 0xBB: .......qO....................O.............................O....................
62
using cipher 0xBC: .......vH....................H.............................H....................
63
using cipher 0xBD: .......wI....................I.............................I....................
64
using cipher 0xBE: .......tJ....................J.............................J....................
65
using cipher 0xBF: .......uK....................K.............................K....................
66
using cipher 0xC0: l{y{zwj.4evu{garq}ras}vwp{c4evu{garq}ras}vwp{bmqxjil{c4evu{garq}ras}vwp{b
67
using cipher 0xC1: mzxz{vk.5dwtzf`sp|~s`r~|wvqzb5dwtzf`sp|~s`r~|wvqzclpykh~mzb5dwtzf`sp|~s`r~|wvqzc
68
using cipher 0xC2: ny{yxuh.6gtwyecps}pcq}turya6gtwyecps}pcq}tury`oszhk}nya6gtwyecps}pcq}tury`
69
using cipher 0xC3: oxzxyti.7fuvxdbqr~|qbp|~utsx`7fuvxdbqr~|qbp|~utsxanr{ij|ox`7fuvxdbqr~|qbp|~utsxa
70
using cipher 0xC4: h}~sn.0arqcevuy{vew{yrstg0arqcevuy{vew{yrstfiu|nm{hg0arqcevuy{vew{yrstf
71
using cipher 0xC5: i~|~ro.1`sp~bdwtxzwdvzxsru~f1`sp~bdwtxzwdvzxsru~ght}olzi~f1`sp~bdwtxzwdvzxsru~g
72
using cipher 0xC6: j}}|ql.2cps}agtw{ytguy{pqv}e2cps}agtw{ytguy{pqv}dkw~loyj}e2cps}agtw{ytguy{pqv}d
73
using cipher 0xC7: k|~|}pm.3bqr|`fuvzxuftxzqpw|d3bqr|`fuvzxuftxzqpw|ejvmnxk|d3bqr|`fuvzxuftxzqpw|e
74
using cipher 0xC8: dsqsrb.<m~}soizyuwzi{wu~xsk<m~}soizyuwzi{wu~xsjeypbawdsk<m~}soizyuwzi{wu~xsj
75
using cipher 0xC9: erprs~c.=l|rnh{xtv{hzvt~yrj=l|rnh{xtv{hzvt~yrkdxqc`verj=l|rnh{xtv{hzvt~yrk
76
using cipher 0xCA: fqsqp}`.>o|qmkx{wuxkyuw|}zqi>o|qmkx{wuxkyuw|}zqhg{r`cufqi>o|qmkx{wuxkyuw|}zqh
77
using cipher 0xCB: gprpq|a.?n}~pljyzvtyjxtv}|{ph?n}~pljyzvtyjxtv}|{pifzsabtgph?n}~pljyzvtyjxtv}|{pi
78
using cipher 0xCC: `wuwv{f.8izywkm~}qs~msqz{|wo8izywkm~}qs~msqz{|wna}tfes`wo8izywkm~}qs~msqz{|wn
79
using cipher 0xCD: avtvwzg.9h{xvjl|prl~rp{z}vn9h{xvjl|prl~rp{z}vo`|ugdravn9h{xvjl|prl~rp{z}vo
80
using cipher 0xCE: buwutyd.:kx{uio|sq|o}qsxy~um:kx{uio|sq|o}qsxy~ulcvdgqbum:kx{uio|sq|o}qsxy~ul
81
using cipher 0xCF: ctvtuxe.;jyzthn}~rp}n|pryxtl;jyzthn}~rp}n|pryxtmb~wefpctl;jyzthn}~rp}n|pryxtm
82
using cipher 0xD0: |kikjgz.$ufekwqbamobqcomfg`ks$ufekwqbamobqcomfg`kr}ahzyo|ks$ufekwqbamobqcomfg`kr
83
using cipher 0xD1: }jhjkf{.%tgdjvpc`lncpbnlgfajr%tgdjvpc`lncpbnlgfajs|`i{xn}jr%tgdjvpc`lncpbnlgfajs
84
using cipher 0xD2: ~ikihex.&wdgius`com`samodebiq&wdgius`com`samodebipcjx{m~iq&wdgius`com`samodebip
85
using cipher 0xD3: hjhidy.'vefhtrabnlar`lnedchp'vefhtrabnlar`lnedchq~bkyzlhp'vefhtrabnlar`lnedchq
86
using cipher 0xD4: xomonc~. qbaosufeikfugkibcdow qbaosufeikfugkibcdovyel~}kxow qbaosufeikfugkibcdov
87
using cipher 0xD5: ynlnob.!pc`nrtgdhjgtfjhcbenv!pc`nrtgdhjgtfjhcbenwxdm|jynv!pc`nrtgdhjgtfjhcbenw
88
using cipher 0xD6: zmomla|."s`cmqwdgkidweik`afmu"s`cmqwdgkidweik`afmt{gn|izmu"s`cmqwdgkidweik`afmt
89
using cipher 0xD7: {lnlm`}.#rablpvefjhevdhja`glt#rablpvefjhevdhja`gluzfo}~h{lt#rablpvefjhevdhja`glu
90
using cipher 0xD8: tcacbor.,}nmcyjiegjykgenohc{,}nmcyjiegjykgenohczui`rqgtc{,}nmcyjiegjykgenohcz
91
using cipher 0xD9: ub`bcns.-|olb~xkhdfkxjfdonibz-|olb~xkhdfkxjfdonib{thaspfubz-|olb~xkhdfkxjfdonib{
92
using cipher 0xDA: vaca`mp..loa}{hkgeh{ieglmjay.loa}{hkgeh{ieglmjaxwkbpsevay.loa}{hkgeh{ieglmjax
93
using cipher 0xDB: w`b`alq./~mn`|zijfdizhdfmlk`x/~mn`|zijfdizhdfmlk`yvjcqrdw`x/~mn`|zijfdizhdfmlk`y
94
using cipher 0xDC: pgegfkv.(yjig{}nmacn}ocajklg(yjig{}nmacn}ocajklg~qmdvucpg(yjig{}nmacn}ocajklg~
95
using cipher 0xDD: qfdfgjw.)xkhfz|ol`bo|nb`kjmf~)xkhfz|ol`bo|nb`kjmfplewtbqf~)xkhfz|ol`bo|nb`kjmf
96
using cipher 0xDE: regedit.*{hkeylocalmachine}*{hkeylocalmachine|software}*{hkeylocalmachine|
97
using cipher 0xDF: sdfdehu.+zijdx~mnb`m~l`bihod|+zijdx~mnb`m~l`bihod}rnguv`sd|+zijdx~mnb`m~l`bihod}
98
using cipher 0xE0: L[Y[ZWJ*.EVU[GARQ]_RAS_]VWP[C.EVU[GARQ]_RAS_]VWP[BMQXJI_L[C.EVU[GARQ]_RAS_]VWP[B
99
using cipher 0xE1: MZXZ[VK+.DWTZF@SP\^S@R^\WVQZB.DWTZF@SP\^S@R^\WVQZCLPYKH^MZB.DWTZF@SP\^S@R^\WVQZC
100
using cipher 0xE2: NY[YXUH(.GTWYECPS_]PCQ]_TURYA.GTWYECPS_]PCQ]_TURY@OSZHK]NYA.GTWYECPS_]PCQ]_TURY@
101
using cipher 0xE3: OXZXYTI).FUVXDBQR^\QBP\^UTSX@.FUVXDBQR^\QBP\^UTSXANR[IJ\OX@.FUVXDBQR^\QBP\^UTSXA
102
using cipher 0xE4: H_]_^SN..ARQ_CEVUY[VEW[YRST_G.ARQ_CEVUY[VEW[YRST_FIU\NM[H_G.ARQ_CEVUY[VEW[YRST_F
103
using cipher 0xE5: I^\^_RO/.@SP^BDWTXZWDVZXSRU^F.@SP^BDWTXZWDVZXSRU^GHT]OLZI^F.@SP^BDWTXZWDVZXSRU^G
104
using cipher 0xE6: J]_]\QL,.CPS]AGTW[YTGUY[PQV]E.CPS]AGTW[YTGUY[PQV]DKW^LOYJ]E.CPS]AGTW[YTGUY[PQV]D
105
using cipher 0xE7: K\^\]PM-.BQR\@FUVZXUFTXZQPW\D.BQR\@FUVZXUFTXZQPW\EJV_MNXK\D.BQR\@FUVZXUFTXZQPW\E
106
using cipher 0xE8: DSQSR_B".M^]SOIZYUWZI[WU^_XSK.M^]SOIZYUWZI[WU^_XSJEYPBAWDSK.M^]SOIZYUWZI[WU^_XSJ
107
using cipher 0xE9: ERPRS^C#.L_\RNH[XTV[HZVT_^YRJ.L_\RNH[XTV[HZVT_^YRKDXQC@VERJ.L_\RNH[XTV[HZVT_^YRK
108
using cipher 0xEA: FQSQP]@ .O\_QMKX[WUXKYUW\]ZQI.O\_QMKX[WUXKYUW\]ZQHG[R@CUFQI.O\_QMKX[WUXKYUW\]ZQH
109
using cipher 0xEB: GPRPQ\A!.N]^PLJYZVTYJXTV]\[PH.N]^PLJYZVTYJXTV]\[PIFZSABTGPH.N]^PLJYZVTYJXTV]\[PI
110
using cipher 0xEC: @WUWV[F&.IZYWKM^]QS^M_SQZ[\WO.IZYWKM^]QS^M_SQZ[\WNA]TFES@WO.IZYWKM^]QS^M_SQZ[\WN
111
using cipher 0xED: AVTVWZG'.H[XVJL_\PR_L^RP[Z]VN.H[XVJL_\PR_L^RP[Z]VO@\UGDRAVN.H[XVJL_\PR_L^RP[Z]VO
112
using cipher 0xEE: BUWUTYD$.KX[UIO\_SQ\O]QSXY^UM.KX[UIO\_SQ\O]QSXY^ULC_VDGQBUM.KX[UIO\_SQ\O]QSXY^UL
113
using cipher 0xEF: CTVTUXE%.JYZTHN]^RP]N\PRYX_TL.JYZTHN]^RP]N\PRYX_TMB^WEFPCTL.JYZTHN]^RP]N\PRYX_TM
114
using cipher 0xF0: \KIKJGZ:.UFEKWQBAMOBQCOMFG@KS.UFEKWQBAMOBQCOMFG@KR]AHZYO\KS.UFEKWQBAMOBQCOMFG@KR
115
using cipher 0xF1: ]JHJKF[;.TGDJVPC@LNCPBNLGFAJR.TGDJVPC@LNCPBNLGFAJS\@I[XN]JR.TGDJVPC@LNCPBNLGFAJS
116
using cipher 0xF2: ^IKIHEX8.WDGIUS@COM@SAMODEBIQ.WDGIUS@COM@SAMODEBIP_CJX[M^IQ.WDGIUS@COM@SAMODEBIP
117
using cipher 0xF3: _HJHIDY9.VEFHTRABNLAR@LNEDCHP.VEFHTRABNLAR@LNEDCHQ^BKYZL_HP.VEFHTRABNLAR@LNEDCHQ
118
using cipher 0xF4: XOMONC^>.QBAOSUFEIKFUGKIBCDOW.QBAOSUFEIKFUGKIBCDOVYEL^]KXOW.QBAOSUFEIKFUGKIBCDOV
119
using cipher 0xF5: YNLNOB_?.PC@NRTGDHJGTFJHCBENV.PC@NRTGDHJGTFJHCBENWXDM_\JYNV.PC@NRTGDHJGTFJHCBENW
120
using cipher 0xF6: ZMOMLA\<.S@CMQWDGKIDWEIK@AFMU.S@CMQWDGKIDWEIK@AFMT[GN\_IZMU.S@CMQWDGKIDWEIK@AFMT
121
using cipher 0xF7: [LNLM@]=.RABLPVEFJHEVDHJA@GLT.RABLPVEFJHEVDHJA@GLUZFO]^H[LT.RABLPVEFJHEVDHJA@GLU
122
using cipher 0xF8: TCACBOR2.]NMC_YJIEGJYKGENOHC[.]NMC_YJIEGJYKGENOHCZUI@RQGTC[.]NMC_YJIEGJYKGENOHCZ
123
using cipher 0xF9: UB@BCNS3.\OLB^XKHDFKXJFDONIBZ.\OLB^XKHDFKXJFDONIB[THASPFUBZ.\OLB^XKHDFKXJFDONIB[
124
using cipher 0xFA: VACA@MP0._LOA][HKGEH[IEGLMJAY._LOA][HKGEH[IEGLMJAXWKBPSEVAY._LOA][HKGEH[IEGLMJAX
125
using cipher 0xFB: W@B@ALQ1.^MN@\ZIJFDIZHDFMLK@X.^MN@\ZIJFDIZHDFMLK@YVJCQRDW@X.^MN@\ZIJFDIZHDFMLK@Y
126
using cipher 0xFC: PGEGFKV6.YJIG[]NMACN]OCAJKLG_.YJIG[]NMACN]OCAJKLG^QMDVUCPG_.YJIG[]NMACN]OCAJKLG^
127
using cipher 0xFD: QFDFGJW7.XKHFZ\OL@BO\NB@KJMF^.XKHFZ\OL@BO\NB@KJMF_PLEWTBQF^.XKHFZ\OL@BO\NB@KJMF_
128
using cipher 0xFE: REGEDIT4.[HKEY_LOCAL_MACHINE].[HKEY_LOCAL_MACHINE\SOFTWARE].[HKEY_LOCAL_MACHINE\
129
using cipher 0xFF: SDFDEHU5.ZIJDX^MNB@M^L@BIHOD\.ZIJDX^MNB@M^L@BIHOD]RNGUV@SD\.ZIJDX^MNB@M^L@BIHOD]
Die einzig sinnvollen Zeilen sind dann nur diese:
1
using cipher 0xDE: regedit.*{hkeylocalmachine}*{hkeylocalmachine|software}*{hkeylocalmachine|
2
using cipher 0xFE: REGEDIT4.[HKEY_LOCAL_MACHINE].[HKEY_LOCAL_MACHINE\SOFTWARE].[HKEY_LOCAL_MACHINE\
wobei ganz klar die letztere die gesuchte sein dürfte :-)
Wow, wer hätte gedacht das die Bosch-Bubens wirklich nen Windows Regedit
für ihre Softwarekonfiguration nutzen...
Automatisiert könnte ich das XOR cipher nur dann finden wenn ich die
resultierenden Zeichen auf den ASCII-Zeichensatz pro Cipher
quantifizieren würde. Aber den Aufwand habe ich mir jetzt nicht gemacht
;-)
Die "entschlüsselte" Registry-Datei (hier im Beispiel aus "basereg.uli")
entspricht weitestgehend dem was man von einem REGEDIT.EXE Export eines
Hive unter Windows erkennt, ausser das ein Zeilenende nur mit LF (0x0A)
markiert ist.
Zudem ist am Ende der Datei noch ein 2-Byte Wert welcher nicht
standardmäßig zu einer Registrydatei gehört. Der ist auch bei
verschiedenen Registry-Dateien gleich, also eher keine Prüfsumme sondern
vielleicht nur eine Signatur?!
Dieter schrieb:> Noch etwas wofür man keinen Disassembler braucht: Man kann etwas> Struktur in die Daten aus dem Flash bringen (der Hexdump hier ganz am> Anfang) wenn man genau hinsieht. Es gibt einen Header, dann kommen die> Datensätze, die jeweils aus CRC, ID, Länge und den eigentlichen Daten
Schau ich mal rein. Strukturen dieser Art habe ich schon gesehen
(teilweise mit dem Keyword "INODE" versehen). Was genau könnte denn ein
solchen "Datensatz" enthalten?
Mir scheint als verfüge das vermutlich zugrunde liegende RTOS
Betriebssystem über ein Filesystem. Man erkennt ja auch sowas wie
errorlogs. Daran wäre ich natürlich besonders interessiert weil sie
evtl. Aufschluß über Hardwareprobleme geben.
Spannend finde ich auch diesen Code in der system.elf:
Olli Z. schrieb:> Was genau könnte denn ein> solchen "Datensatz" enthalten?
Welchen Datensatz meinst Du? Die Datensätze in dem Hexdump sind alle
möglichen Dinge wie Geräte-Seriennummer, das sieht man ja. Ich vermute
dass das ursprünglich für einen EEPROM gedacht war (dafür spricht das
Alignment, das könnte für EEPROM Pages gedacht sein).
Dass es im Flash auch noch ein Filesystem gibt hatte ich ja schon
erwähnt. Dieses Filesystem hat aber nichts mit den Datensätzen in dem
Hexdump zu tun. Es ist auch nicht so schwierig herauszufinden was das
für ein Filesystem ist, allerdings ist es ein "Exot" und man findet nur
ein wenig zu einer älteren Version, die nicht kompatibel ist (aber
genügend Hinweise über die Internas enthält).
Olli Z. schrieb:> Spannend finde ich auch diesen Code in der system.elf:
Das ist eine von vielen möglichen Ausgaben des Loggings über die
seriellen Schnittstelle, zumindest wen das Logging aktiviert ist.
Das ist jetzt schon etwas weiter weg vom Topic, aber irgendwie dann doch
dazugehörig:
Es gibt in der Firmware eine Funktion die bei erkennen des
Rückwärtsganges (CAN-ID 433, Data 00 00 00 02 00 A0 00 00) den
Bildschirm auf Video-In umschaltet um das Signal der Rückfahrkamera
anzuzeigen. Wie könnte man herausbekommen ob es für diese Funktion noch
eine Alternative gibt? Einer meiner vielen, verwegenen Pläne ist es
nämlich über diesen Eingang eine Front-Kamera anzuschließen. Das Bild
müsste aber beim aktivieren des PDC und eben ohne eingelegten
Rückwärtsgang zu sehen sein...
Dieter schrieb:> Olli Z. schrieb:>> Spannend finde ich auch diesen Code in der system.elf:>> Das ist eine von vielen möglichen Ausgaben des Loggings über die> seriellen Schnittstelle, zumindest wen das Logging aktiviert ist.
Genau, das wäre eine tolle Sache wenn man wüsste wie man das aktiviert.
An den Service-Ports des Gerätes befinden sich zwei serielle
Schnittstellen.
Olli Z. schrieb:> Wie könnte man herausbekommen ob es für diese Funktion noch> eine Alternative gibt?
Denkbar wäre vielleicht dass es die Möglichkeit gibt diese Funktion per
UDS auszulösen um das z.B. in der Werkstatt oder bei der Produktion zu
testen.
Ansonsten wird es schwierig wenn das nicht schon in der Software
vorgesehen ist. "Schwierig" in dem Sinn dass man eine neue
Funktionalität in das Binary einbauen muss, Du willst ja vermutlich
nicht dauerhaft das Kamerabild sehen, also muss man das auch irgendwie
ein-/ausschalten können.
Ohne Änderung am Code könnte man "Man-in-the-Middle" auf dem CAN-Bus
spielen und die entsprechende CAN-Message bei Bedarf so manipulieren
dass das Gerät denkt der Rückwärtsgang ist drinnen. Das wäre nicht so
schwierig, entsprechende Hardware und Software gibt es. Ob man so einen
Eingriff bei einem Fahrzeug tatsächlich machen will ist eine andere
Frage, beim Infotainment könnte man das vielleicht noch akzeptieren.
Dieter schrieb:> Ohne Änderung am Code könnte man "Man-in-the-Middle" auf dem CAN-Bus> spielen und die entsprechende CAN-Message bei Bedarf so manipulieren> dass das Gerät denkt der Rückwärtsgang ist drinnen.
Das ist aber umständlich. Einfacher wäre imho das Bit dafür im
Schattenregister zu setzen und zu löschen als täte es der CAN-Busparser.
Schließlich ist das kein staatisch anliegendes Signal sondern ein
ereignisgesteuertes Bit in irgendeiner Variable
mit dem warscheinlichen Namen "video-suorce".
Namaste
Winfried J. schrieb:> Das ist aber umständlich. Einfacher wäre imho das Bit dafür im> Schattenregister zu setzen und zu löschen als täte es der CAN-Busparser.
Du meinst im Gerät? Dann muss aber diese Funktion "hineingepatcht"
werden, einschließlich einer Möglichkeit das ein- und auszuschalten. Und
das wollte ich ja mit dem "Man-in-the-Middle" vermeiden. Wie gesagt,
entsprechenden Code und Hardware gibt es, siehe z.B. ältere BlackHat
Vorträge, wo das für Security Untersuchungen vorgestellt wurde.
Nur zur Info: Wie man das über CAN macht weiss ich und hab das auch
schon realisiert. Aber es ist recht umständlich, denn man muss einen
CAN-Filter bauen der auf der einen Seite mit dem Sender (in meinem Fall
ist es der Tacho der den Bus speist) und auf der anderen Seite mit dem
Radio "redet". Der Filter muss überwiegend alles bidirektional
durchschleifen, nur unter bestimmten Bedingungen simuliert er auf der
Radioseite das Bit in dem Byte der CAN-ID welches den eingelegten
Rückwärtsgang reflektiert und damit sorgt das das Navi auf Video-IN
umschaltet. Heraus kommt man da mit Bordmitteln indem man irgend eine
Taste am Navi drückt, z.B. Radio oder Menu, oder man den Rückwärtsgang
wieder rausmacht. Bei letzterem allerdings mit einigen Sekunden
Verzögerung.
Das war aber wirklich nur eine Nebenanfrage zu der ich zu gegebener Zeit
lieber einen eigenen Thread eröffne. Denn hier geht es ja um was
anderes...