Code einer EXE-Datei auslesen?


30.08.2020, 22:46

*einer

Das Ergebnis basiert auf 14 Abstimmungen

Jain 50%
Nein es geht nicht 29%
Ja es geht 21%

6 Antworten

Vom Fragesteller als hilfreich ausgezeichnet
Jain

Eine "EXE" enthält den reinen Maschinencode, also die Zahlenfolgen die die CPU steuert.

Das kann man sich mit einem Assembler angucken, da werden die Maschinenbefehle in Kürzel übersetzt die ein Mensch besser lesen kann. Außerdem werden Befehle und deren Parameter getrennt sowie Sprungziele markiert. Damit kann man das Programm als Mensch lesen und nachvollziehen. Die originalsprache bzw. deren Befehle sind aber unbekannt. Variablen sind hier nur als Speicheradressen dargestellt oder höchstens "Durchnummeriert".

Ein De-Compiler versucht Code zu erzeugen der wieder zum Maschinencode führt. Früher, also vor etwa 20 jahren ging das auch ganz gut. Ein C Compiler hat die Befehle einfach nach einer Datenbank stur in Maschinensprachebefehle übersetzt. Anhand dieser Datenbank konnte man leicht die original Befehle rekonstruieren. Heutzutage wird aber sehr komplex optimiert, unnötige Befehle werden weggelassen bzw. viele Befehle werden je nachdem was die bewirken durch weniger Befehle ersetzt die in genau diesem Szenario zum gleichen Ergebnis führen.

Variablennamen können nicht "überleben", aus

Fläche = Länge * Breite;

wird höchstens

A1 = A2 * A3

Noch schlimmer, auch Formeln werden vom Compiler optimiert. Der kann zum Beispiel den Wertebereich den eine Variable annehmen kann feststellen und dann eine ganz neue Formel erfinden die mit dem begrenzten Wertebereich zum gleichen Ergebnis kommt, nur schneller. Wird das Programm geändert so dass der Wertebereich der Variablen anders ist, kommt diese Formel zu falschen Ergebnissen, der Compiler würde dann eine neue Formel erfinden. Die alte allgemein gültige Formel die der Programmierer da vor dem compilieren eingegeben hatte ist verloren, die kann man nicht mehr rekonstruieren.

Auch werden ganze Programmteile vom Compiler weg gelassen wenn die nicht ausgelöst werden. Solche Programmteile werden vor allem zum debugging benutzt. In der "Final Version" legt man mit einem #define fest, dass diese debugging Programmteile ignoriert werden als wären die gar nicht da. Das kann aber auch "aus versehen" passieren, eben wenn Wertebereiche bestimmter Variablen dazu führen, dass bestimmte Programmteile nie ausgeführt werden können und wenn der Compiler das merkt, lässt der diese Teile weg. Durch winzige Änderungen im programm können diese Programmteile später wieder mit eingebaut werden.

So erhält man vom De-Compiler immer nur "Spaghetticode" der auch noch nicht mal vollständig ist was das original Programm angeht und alle Variablen sind nur durchnummeriert.

alfredo153  31.08.2020, 07:19
Früher, also vor etwa 20 jahren ging das auch ganz gut. Ein C Compiler hat die Befehle einfach nach einer Datenbank stur in Maschinensprachebefehle übersetzt.

Vielleicht bist du so jung dass dir "vor 20 Jahren" wie die frühe Bronzezeit der Informatik erscheint, aber ernsthaft optimierende Compiler gab es schon ein paar Jahrzehnte davor...eine derartige Karikatur eines Compilers gab es in den 2000ern allenfalls in Studentenübungen.

0
Commodore64  06.09.2020, 12:55
@alfredo153

Da bin ich definitiv viel älter.

Klar gab es optimierende Compiler schon viel länger. Ich habe vor etwa 30 Jahren auch damit gearbeitet. Nur waren diese Compiler extrem teuer, konnten sich also nur Profis leisten. Die Mehrheit der Compiler, vor allem diejenigen, die man privat bzw. in der Ausbildung nutzt waren dagegen sehr simpel gestrickt.

Zum Beispiel bekam man bei Microichip beim Kauf eines PIC "Brenners"einen kostenlosen Compiler dazu. Schrieb man da so was wie

float a = b * c;

dann war die hälfte aller PIC Mikrocontroller auf dem Markt zu mindestens 40% ROM gefüllt, nur durch diese eine Zeile. Denn der PIC kann nicht multiplizieren, das musste mit Schleifen und Additionen abgebildet werden. Viele "low cost" chips waren dann gleich gar nicht mehr zu gebrauchen da deren ROM kleiner war als der Code den diese Zeile erzeugte.

Aber man konnte damals für "nur" DM 5000,- einen Compiler kaufen der optimierte, der Code der da raus kam war im Schnitt weniger als 20% des Codes vom Gratis-Compiler. Man konnte damit also viel komplexere Programme schreiben die dann auch noch ein vielfaches schneller liefen. Oder eben einen viel billigeren PIC kaufen und damit dann genau das selbe machen wie bei den teuren Varianten die viel ROM hatten.

Das war die Zeit als man dann lieber direkt selber in Assembler programmierte wenn man nicht gerade sehr reich war oder kommerziell Code für PIC schrieb.

Angefangen habe ich mit C als Turbo C 2.0 noch das Maß der Dinge war und 3.0 zwar bereits auf dem Markt, aber viel zu teuer war um auch nur an den Kauf zu denken. Das war vor fast 30 Jahren.

Zwar hat Turbo C 3.0 "kräftig optimiert", aber noch lange nicht so stark wie heute üblich. Man konnte auch noch bei TC 3.0 Fingerabdrücke des Originalcodes finden und so per Decompiler den Originalcode zwar bei weiten nicht vollständig wiederherstellen aber bekam zumindest die Original Struktur wieder heraus.

Unterprogramme und Befehle aus der C Bibliothek waren immer durch einen CALL erkennbar, heutzutage ist das völlig anders, hier erfindet der Compiller eigene Unterprogramme in denen viele C-Befehle aber auch Unterprogramme des Programmierers zusammengefasst werden.

0
Commodore64  06.09.2020, 13:02
@Commodore64

Als Analogie ist das als wenn man sagt, dass in den 1960ern und 70ern alle Autos über 200km/h schnell waren. Klar gab es Maseratis und andere zu kaufen, aber die Mehrheit der Autofahrer hatte damals aber einen Käfer der nur 120 konnte.

0
Nein es geht nicht

Ja, man kann mit nem Decompiler nen Source kriegen der das selbe macht wie das programm aber den originalen source zu kriegen ist nicht möglich

Ja es geht

Hey MESPREAE,

das geht mit einem De-Compiler.

Aber ohne Symbol-File wirst Du nicht so viel Spaß haben, da Variablen, Methoden und co. alle kryptische Namen haben werden.

Man kann natürlich durch den Code gehen und gucken was der macht und sich dann passende Namen überlegen.

Man hat am Ende dann doch Arbeit und wenn das Programm umfangreich ist, dann wird es sehr aufwändig - aber nicht unmöglich.

Ich empfehle mit kleinen Programmen anzufangen. Evtl. mit selbst geschriebenen, dass Du siehst was passiert.

Der Code der beim Decompiler raus kommt wird auch nicht so aussehen wie der Original-Code.

Gruß

Jain

Ich mache das täglich auf der Arbeit.

Allerdings ist "lesbarer Code" Assembler, was vermutlich nicht das ist, was du erwartet hast.

Code in einer Hochsprache wie C++ kannst du komplett vergessen. Es gibt zwar selbsternannte Decompiler, aber die haben noch nie richtig in freier Wildbahn funktioniert.

Fazit: Wenn du Assembler lesen kannst, ist das kein Problem. Alles andere ist unmöglich.

Nachtrag: Gerade C++ enthält so viel Template-Code, dass zich Seiten an Quelltext gerne mal vom Compiler auf eine Hand voll einzelner CPU-Instruktionen eingestampft werden.

Da wieder etwas C++-artiges raus lesen zu wollen, ist per Defintiion unmöglich!

Jain

Direkt den Code auslesen nicht, aber du kannst es mal mit Ghidra versuchen