Ich versuche mich am "Hacken" einer Firmware (ARM Cortex-M3) und habe mir IDA (7.0 Free kann kein ARM), radare2/Cutter (komplex, muss erstmal richtig konfiguiert werden), Binary Ninja Demo (schon ganz gut), Ghidra (naja) mal angesehen. Es schwankt zwischen "erkennt Funktionen nicht richtig" und "[Oberfläche] unbedienbar". Ich hatte gehofft, man könne den Programm- und Datenfluss (erfordert Simulation?) einigermaßen einfach verfolgen um die für einen interessanten Stellen zu finden und ggf. zu "hacken". Mit komplettem Call-Graph und erklärten Instruktionen, sowie eine Kern- und Peripherie-Register-Map (gibt es eigentlich standardisierte Daten vom Hersteller oder köchelt da jeder seine eigene Suppe für die eigene IDE?). Ein Simulator wäre auch nett.. Kurzum: der Einstieg erfordert viel low-level Wissen (Memory Map im Kopf, Assembler fließend lesen, ggf. Ergebnis der automatischen Analyse prüfen) zu erfordern, die Tools nehmen mehr oder weniger gut einen kleinen Teil der Arbeit ab, und die Analyse erfordert sehr, sehr viel Handarbeit. Es ist aber wohl auch ein eher spezielles Beschäftigungsfeld. Wie sind eure Erfahrungen?
Geht es immer noch darum, diesen Lime Roller zu hacken?
Noob schrieb: > die Analyse erfordert sehr, sehr viel > Handarbeit. So ist es. Manchmal erkennt man, welcher Compiler verwendet wurde und welche Libs. Das hilft mächtig. Aber ansonsten ist Hirn angesagt (und Geduld).
Mit einem Assembler/Disassembler hackt man nichts, sondern man wandelt Code nur in eine andere Darstellungsform um, also Binärsprache in Assenmbersprache. Seit wann sind das denn Code-Analysatoren? Um einen Algorytmus zu "hacken" wäre ein Debugger das passendere Werkzeug, denke ich. Die haben aber ihre Grenzen, weil größere Programme damit praktisch nicht mehr zu handeln wären. Dafür gibts ausgefeiltere Software die hier erst vor ein paar Wochen mal erwähnt wurden. Leider habe ich mir da nichts markiert und weiß auch nicht nach welchem Begriff ich da suchen müsste.
Da bleibt immer sehr viel Handarbeit über. Schaut man sich beliebigen Code "von der Seite" an, so ist oft noch nicht mal ersichtlich, ob überhaupt etwas ausführbares vorliegt, oder ob es sich um Daten handelt. Die Daten eines Textstrings oder einer Konstantenliste lassen sich oft auch als ausführbarer Code darstellen und umgekehrt. Ob eine (oft verwendet) Sprungtabelle vorliegt ist bis zu dem Zeitpunkt unklar, indem Du die Registerbelegung kennst. Ein schöner Gruß an den guten, alten Sisyphos.
So gut, das manche Leute damit schon alte N64 Spiele soweit zerlegt haben, damit man sie hinterher wieder binärkompatibel compilieren konnte....
bei alten 8-bittern war man ja noch mit fast jedem Byte per DU. Ich habe nach 20 Jahren auch meinen alten PC1500 Code wieder disassembliert zu Fuss, mein Vorteil es war MEIN Programm und so ungefähr wusste ich noch wie und warum ich das so geschrieben hatte, ich wollte den Code relokatibel machen und direkten Zugriff auf den PC hatte ich nicht nur indirekt. Ich habe mich aber auch nie in die vielbenutzten ROM Routinen begeben, das wäre dann komplizierter geworden. Ich denke auch manche ROM Routinen sind deswegen so unübersichtlich wegen Mehrfachnutzung (durch optimnierende Assembler/Compiler)und um Platz zu sparen, da wird mit Sicherheit nichts linear gerade runter programmiert sein.
Noob schrieb: > Es ist aber wohl auch ein eher spezielles Beschäftigungsfeld. Es kommt drauf an, was man erreichen will. Um die Funktionen einer Steuerung zu erfassen, muss man u.U. garnicht disassemblieren oder hacken, da kann man phänomenologisch vorgehen - drückt man Button X, bewegt sich die X-Achse usw. Das setzt funktionierende Hard- und Software voraus. So entsteht praktisch ein Pflichtenheft. Das identische Programm wieder übersetzen zu können ist auch trivial, dafür reichen Define Bytes mit dem ROM-Inhalt. Ist nur ziemlich sinnlos. Programmideen zu klauen ist für jemanden, der die Qualifikation zur Code-Analyse hat, auch uninteressant, da schreibt man den nötigen Code schneller selber. Sinnvoll ist es nur, einen Sourcecode zu erzeugen und zu verstehen, um das vorliegende Programm an entscheidenden Stellen ändern und neu übersetzen zu können, das ist die Königsdisziplin. Leider setzt das viel Erfahrung voraus und artet trotzdem in harte Arbeit aus. Georg
Sebastian S. schrieb: > Schaut man sich beliebigen Code "von der Seite" an, so ist oft noch > nicht mal ersichtlich, ob überhaupt etwas ausführbares vorliegt Also bei ARM sieht man das ziemlich schnell. Wenn man irgendwelche Daten disassembliert, stellt man schnell fest dass das ziemlicher Blödsinn ist, z.B. wenn da 10x hintereinander die gleiche Instruktion steht. Vielleicht ist es ja sogar typisch RISC, dass man öfters bestimmte Muster hat, die man schnell erkennt. Der Klassiker sind ja Funktions-Anfang und -Ende. Bei ARM A32 Code sieht man eine Menge "E" in der hexadezimalen Darstellung - der Condition Code "Always".
Wie schon öfter erwähnt, muss man sowieso noch einen Plan des Portmappings erstellen - am besten ausgedruckt mit den Alternate Functions des MC, um den es geht. Das hat mir hier sehr gut geholfen, obwohl es nie in meiner Absicht lag, die Firmware zu disassemblieren, sondern neue Firmware für die vorhandene Hardware zu entwickeln. Auf dem Ausdruck kann man dann die Funktionen abhaken, die schon erkannt sind und sich dann gezielt um die noch fehlenden kümmern. - bis alle 176 Pins zugeordnet sind... Zusätzlich braucht man natürlich die Datenblätter etwaiger Peripheriechips.
:
Bearbeitet durch User
Ich denke mal, es ist einfacher, mit einem LA an den IO-Pins mitzusniffen, was der MC macht und es dann neu zu programmieren.
Rote T. schrieb: > So gut, das manche Leute damit schon alte N64 Spiele soweit > zerlegt haben, damit man sie hinterher wieder binärkompatibel > compilieren konnte.... Da wusste man aber auch, welcher Compiler benutzt wurde, welche Bibliotheken verwendet wurden und was für Code da hinten rausgefallen ist. Für eine unbekannte Cortex M3-Firmware gilt das nicht. Noob schrieb: > Ich hatte gehofft, man könne den Programm- und Datenfluss > (erfordert Simulation?) einigermaßen einfach verfolgen um > die für einen interessanten Stellen zu finden und ggf. zu "hacken". Das geht einigermaßen gut, je nachdem, was den Code ursprünglich erzeugt hat (Compiler oder handgeklöppeltes Assembler), wie der Decompiler das versucht zu verarbeiten (welche Plugins für welche Compiler-Entry/Exit-Sequenzen er kennt), und welche Register bekannt sind. Der Cortex M3-Kern ist gut standardisiert, daher kennst du den Einstiegspunkt und kannst du dich vom Reset_Handler aus durch den Code hangeln. Der Anfang ist normalerweise auch handgeschriebener Assemblercode, d.h. der ist auch im Disassembler recht einfach lesbar. Was danach kommt, hängt vom Inhalt ab.
Danke für's Feedback, da lag ich ja nicht so falsch mit meiner Einschätzung. Zum Resethandler bin ich schon gekommen, da wird der SP explizit nochmal per Software gesetzt (=schlechter Compiler bzw. Startup Code?), ansonsten geht es dann los mit der fehlerhaften disassembly und Analyse - und vielen undurchschaubaren Verzweigungen. Mein erstes Ziel wäre, zumindest die Zugriffe auf Peripherieregister zu finden und Schleifen aufzuspüren. Den Befehlssatz werde ich mir also mal durchlesen müssen... Tipp: Cutter kann offenbar nur lokale Funktionen graphisch darstellen, für die Funktionszusammenhänge muss es dann radare2 sein (Download für Windows von appveyor, die offiziellen Downloads sind veraltet). Ebenso sollte man Cutter gleich in der Kommandozeile starten, sonst ist die Konsole nicht wirklich nutzbar. Und zum Vergleich lässt sich Binary Ninja immer mal wieder für 15 Minuten oder so nutzen (zeitbeschränkt). georg schrieb: > Sinnvoll ist es nur, einen Sourcecode zu erzeugen und zu verstehen, um > das vorliegende Programm an entscheidenden Stellen ändern und neu > übersetzen zu können, das ist die Königsdisziplin. Leider setzt das viel > Erfahrung voraus und artet trotzdem in harte Arbeit aus. Genau, "ein bisschen anpassen" wäre schön.
Noob schrieb: > Zum Resethandler bin ich schon gekommen, da wird der SP explizit > nochmal per Software gesetzt (=schlechter Compiler bzw. Startup Code?), Das machen einige Startup-Codes so, weil man dort mit #ifdef arbeiten und so ein gemeinsames Linkerscript für mehrere Chips nutzen kann. > ansonsten geht es dann los mit der fehlerhaften disassembly > und Analyse - und vielen undurchschaubaren Verzweigungen. Um was für einen Chip geht es denn? Wenn es was halbwegs bekanntes ist, dann schau dir einfach mal den Startup-Code vom Hersteller als Vergleich an. Bist du dir sicher, dass dein Decompiler die korrekte Architektur decompiliert? Weil "Cortex-M3" ist nicht dasselbe wie "ARM", und wenn da eine unbekannte Instruktion steht, dann fliegt der Decompiler aus der Bahn. Bedenke, dass der Startup-Code in aller Regel handgeklöppelter Assemblercode ist. Da kann man wunderschöne Tricks benutzen, wie z.B. mehrere sich überlappende Schleifen und sowas. Ein linearer Decompiler kommt mit sowas absolut nicht klar. ;-) Achso, viele Sprünge sind relativ, auch zu PC oder SP. Wenn du die Basisadresse der Firmware nicht korrekt angegeben hast, dann kann der Disassembler die Zieladressen nicht korrekt berechnen und du bekommst Müll. Üblicherweise kannst du dem Disassembler bestimmte Registerwerte zu bestimmten Zeiten vorgeben, damit das funktioniert. Auf einem Cortex-M3 gilt allgemein: Flash@0x08000000, SRAM@0x20000000 und oft irgendein Alias oder Boot-ROM oder sowas bei 0x00000000. > Mein erstes Ziel wäre, zumindest die Zugriffe auf > Peripherieregister zu finden und Schleifen aufzuspüren. Ich würde an deiner Stelle erstmal den Befehlsverlauf vom Startup-Code verfolgen. Der muss logisch aufgebaut sein. Ich hänge mal einen von mir (in C für LM3S811 im Qemu) geklöppelten Startup-Code an. Mindestens diese Funktionalität solltest du finden, wenn die Firmware in C oder C++ geschrieben wurde. Noob schrieb: > Den Befehlssatz werde ich mir also mal durchlesen müssen... Das sowieso. Du musst den Assemblercode schon einigermaßen lesen können, sonst wird das nix. Datenblatt vom Controller ist immer gut bei der Hand zu haben, und wenn du das nicht hast, zumindest das Datenblatt vom Cortex-M3. Nachtrag: Praktische Erfahrung hab ich maximal mit IDA Free, da hab ich mal angefangen, ein 80186-BIOS zu zerlegen. Also nicht unbedingt ARM Cortex-M3, wobei ich da auch öfter mit objdump mal Hex-Dateien zerlegt habe.
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.