Hallo, kann man an einem Hexcode erkennen, in welcher Programiersprache das Programm geschrieben wurde und wenn ja, an was? Gruß wilials
Kannst Du knicken. Das ist Maschinencode und der kann aus sämtlichen Sprachen generiert worden sein. Du könntest mit verschiedenen Hex-Files Geschwindigkeitsmessungen am Controller machen. Der am schnellsten laufende Code könnte mal von einem guten Programmierer in Assembler geschrieben worden sein. Muss aber nicht...
> kann man an einem Hexcode erkennen, in welcher Programiersprache das > Programm geschrieben wurde und wenn ja, an was? Das geht nur bedingt, und zwar dann, wenn du detailiert weisst, wie ein Compiler übersetzt. Man kann evtl. daran, wie Parameter gehandhabt werden schon rausfinden, welcher Compiler es war, der Startup-Code dürfte ebenfalls ein guter Ansatzpunkt sein. Aber dazu müsstest du eben die entsprechenden Compiler zur Hand haben, um vergleichen zu können. Ralf
mit etwas erfahrung geht das recht aufwendig. zuerst schaut man ob strings vorkommen. (enden diese mit 0x00 würde ich sofort auf c als sprache tippen.) dann schaut man ob man erkennt ob 8, 16, oder 32bit architektur. prozessor herrausfinden kann man mit suche nach JMP, RET, PUSH und POP, das könnte zeitaufwendig sein. wenn man den prozessor weiss, kann man den hex-code relativ einfach in assembler umwandeln. an den PUSH und POP erkennt man dann später eventuell die programmiersprache - gcc hat da zB eine eigene signatur.
>prozessor herrausfinden kann man mit suche nach JMP, RET, PUSH und POP,
In einer HEX Datei stehen keine JMP, RET,...
Das steht 05890AEF67BC oder sowas.
Hexadezimale Zahlen eben.
Ralf schrieb: > der Startup-Code > dürfte ebenfalls ein guter Ansatzpunkt sein. Danke, das war ein Tipp, mit dem ich etwas anfangen kann. Ursprünglich dachte ich an ein paar charakteristische Bits am Anfang oder am Ende des Codes, die Auskunft darüber geben. Der Startup-Code zeigt einen Weg. Gruß wilials
incocknito schrieb: > zuerst schaut man ob strings vorkommen. (enden diese mit 0x00 würde ich > sofort auf c als sprache tippen.) ??? Wenn ich Assembler programmiere enden meine Strings auch mit 0 und das mache nicht nur ich so...
holger schrieb: > In einer HEX Datei stehen keine JMP, RET,... > Das steht 05890AEF67BC oder sowas. > Hexadezimale Zahlen eben. Der Ansatz ist schon richtig. Man sucht halt nach dessen Opcodes und nach sinnvollen Konstruktionen. Zwei ijmp oder 2 gleiche Vergleiche hintereinander sind beispielsweise Unsinn. push sollte ähnlich oft wie pop vorkommen.
incocknito schrieb: > zuerst schaut man ob strings vorkommen. (enden diese mit 0x00 würde ich > sofort auf c als sprache tippen.) > > dann schaut man ob man erkennt ob 8, 16, oder 32bit architektur. > > prozessor herrausfinden kann man mit suche nach JMP, RET, PUSH und POP, > das könnte zeitaufwendig sein. > > wenn man den prozessor weiss, kann man den hex-code relativ einfach in > assembler umwandeln. > > an den PUSH und POP erkennt man dann später eventuell die > programmiersprache - gcc hat da zB eine eigene signatur. Danke, auch das ist eine wertvolle Hilfe für mich Gruß wilials
>Unser Holgi mal wieder. Lol.
Wieso Lol? Ich hab noch nie ein JMP im Klartext in
einer HEX Datei gesehen. Weder J, noch M noch P
sind hexadezimale Zahlen;) ROFL.
>Der Ansatz ist schon richtig. Man sucht halt nach dessen Opcodes und >nach sinnvollen Konstruktionen. Dazu muss man aber schon wissen um welchen Controller es geht. Und solche Opcodes kommen auch in Bitmaps oder Fonts vor die das Programm evtl. benutzt. Und wenn der TO denkt das er aus einer Hex Datei wieder ein Programm in C oder Bascom oder sonstwas bekommen kann, dann liegt er falsch. Das einzige was man bekommen kann ist ein wertloses undokumentiertes Assemblerlisting.
holger schrieb: > Dazu muss man aber schon wissen um welchen Controller es geht. Man kann den Controller damit finden. Ein Arm-Programm in Avr-Assembler disassembliert sieht sicher überhaupt nicht sinnvoll aus. Einfach ist das ganze nicht - aber auch Datenblöcke kann man erkennen (viele aufeinanderfolge unsinnige Instruktionen, abschließende 0...). Am Ende scheint für das Programm eine Architektur am sinnvollsten zu sein.
holger schrieb: > Und wenn der TO denkt das er aus einer Hex Datei wieder ein > Programm in C oder Bascom oder sonstwas bekommen kann, dann > liegt er falsch. Das einzige was man bekommen kann ist ein > wertloses undokumentiertes Assemblerlisting. Sehr schöne Verallgemeinerung, also haben alle Leute die reverse-engineering von Programmen machen ein schönes Hobby? Weil bezahlen wird ja keiner für das produzieren und auswerten von wertlosen Listings?
holger schrieb: > Dazu muss man aber schon wissen um welchen Controller es geht. Da kann man das Pferd auch andersrum aufzäumen und der Reihe nach gucken, ob die OP-Codes des verdächtigen µC an passender Stelle vorkommen.
>Sehr schöne Verallgemeinerung, also haben alle Leute die >reverse-engineering von Programmen machen ein schönes Hobby? Oder zu viel Zeit? Vieleicht verrät uns der TO ja noch mal warum er wissen will womit seine HEX Datei erzeugt wurde.
Willi Lich schrieb: > kann man an einem Hexcode erkennen, in welcher Programiersprache das > Programm geschrieben wurde Um es am Hexcode selber zu erkennen, wird wohl zumindest etwas Übung erforderlich sein. Das würde ich mir im Moment nicht zutrauen. Aber ich würde es mir zutrauen, auch das zu lernen. Wenn ich es für nützlich halten würde. Was allerdings ziemlich sicher geht, ist (nach ReAssemblierung des Codes) die Unterscheidung am generierten Asm-Quelltext, ob es sich um liebevoll und kompetent handoptimierten Assemblercode oder das maschinelle, trostlose, phantasielose und ineffiziente Produkt eines Compilers handelt. In aller Regel kann man sogar auch noch recht problemlos herausfinden, welcher Compiler diesen ineffezienten Mist verbrochen hat und sogar, mit welchen "Optimierungsoptionen" dieses Machwerk seinen Mist produziert hat. Man findet sogar die längeren Asm-Inlines aus den Libs mit einem Blick, weil sie sich so wohltuend von ihrer Umgebung unterscheiden... Nunja, nachdem der Compiler enttarnt ist, fällt der Rückschluß auf die für diesen Müll verwendete Sprache dann nicht sehr schwer... > wenn ja, an was? An den Mustern, die die Compiler produzieren. Der Mensch ist ein wahres Wunder bei der Mustererkennung. Man braucht bloß ein wenig Training. Man muß dabei noch nichtmal unbedingt die zur Darstellung der Muster verwendete Sprache verstehen. Man könnte den Kram genausogut auch als bunte Klötzchen darstellen. Für die Musterkennung ist das sogar günstiger als z.B. ein Disassemblat. Übrigens: Allein die Tatsache, daß überhaupt so reichlich einfach erkennbare Muster vorhanden sind, zeigt schon, daß die Compiler massiv suboptimale Encoder sein müssen. Aber mit so einem Stück Informatik-Weisheit darfst du natürlich keinem C-Fetischisten kommen. Da vergißt der natürlich sofort sein gesamtes Studium zugunsten seines geliebten Kauderwelschs, nur um nicht in Argumentationsnotstand zu geraten...
Welche Programmiersprache der Ausgang war ist kaum sicher zu erkennen, jemand könnte UML genommen habe und das dann automatisch in EIFFEL übersetzen lassen welches dann vom EIFFEL-Compiler in reinen C-Code übersetzt wurde der dann vom extra optimierenden VLIW Compiler des Herstellers XYZ in den Opcode = HEX-File übersetzt wurde. Die genannten Ansätze funktionieren daher nur bedingt und lassen viel Spielraum. Daher gibt es auch keine mir bekannten "Disscler" oder "DisEIFFELler" :-P (Ausnahme bildet JAVA aber da weiß man ja gleich was so eine .class Datei erstellt hat)
c-hater schrieb: > Übrigens: Allein die Tatsache, daß überhaupt so reichlich einfach > erkennbare Muster vorhanden sind, zeigt schon, daß die Compiler massiv > suboptimale Encoder sein müssen. Aber mit so einem Stück > Informatik-Weisheit darfst du natürlich keinem C-Fetischisten kommen. Mit deinem Scheiss brauchst du dafür industriell nicht auftricksen. Da hast du dir noch gar keine Registerbelegung überlegt, bin ich in C schon wieder fertig. Mit einem Hochsprachenoverhead, der sich im kleinen einstelligen Prozentbereich bewegt und völlig uninteressant ist. Industrielles Entwickeln ist eine Geldfrage. Deine paar Prozent, die dein Assemblerprogramm (abgesehen von Ausnahmefällen, wenn eine ISR wirklich taktgenau schnell sein muss) schneller ist, interessieren keinen. Aber es interessiert ob du an einem Vormittag oder in einer Woche fertig bist. Denn das wirkt sich für den Kunden in Geldeinheiten aus.
c-hater schrieb: > Allein die Tatsache, daß überhaupt so reichlich einfach > erkennbare Muster vorhanden sind, zeigt schon … dass du schon lange keinen compilergenerierten Code mehr angesehen hast. Vermutlich das letzte Mal zu Zeiten der PDP-11. So ziemlich das einzige, woran man den Compiler sehr sicher erkennt, ist das Durchziehen gleichmäßiger Aufrufkonventionen von Funktionen bzw. Unterprogrammen. Allerdings könnte es passieren, dass geübte Assemblerprogrammierer diese Technik ebenfalls beherrschen. ;-)
Jörg Wunsch schrieb: > So ziemlich das einzige, woran man den Compiler sehr sicher erkennt, > ist das Durchziehen gleichmäßiger Aufrufkonventionen von Funktionen > bzw. Unterprogrammen. Mir würde bei x86-Familie noch das ziemlich "zufällige" verwenden von SSE-Erweiterungen oder so einfallen. Ein Mensch findet selten in einem Programm ein paar wenige Stellen wo die irgendwie nützlich sind, sondern verwendet sie entweder gezielt oder garnicht.
>Um es am Hexcode selber zu erkennen, wird wohl zumindest etwas Übung >erforderlich sein. Das würde ich mir im Moment nicht zutrauen. Aber ich >würde es mir zutrauen, auch das zu lernen. Wenn ich es für nützlich >halten würde. Dann bist du der letzte der hier Tips geben kann. >Nunja, nachdem der Compiler enttarnt ist, fällt der Rückschluß auf die >für diesen Müll verwendete Sprache dann nicht sehr schwer... Dieser Rückschluss nützt aber niemandem. Aus einem Hamburger kann man keine lebende Kuh mehr machen. Ich nehme den vom Compiler erzeugten Müll gerne in Kauf. Wenn ich ein C Projekt auf eine andere uC Architektur umsetzen muss kann ich bestimmt 80% mitnehmen und muss nur 20% neu machen. Der Assemblerprogrammierer muss 100% neu machen. Falls er sich überhaupt mal aus seinem Nest rauswagt.
Ein Disassembly des Codes gibt schon recht gut Aufschluss über die verwendete Sprache und den Compiler. Ist der Prozessortyp nicht bekannt, probiert man einfach mehrere Disassembler aus und schaut nach, wo zumindest streckenweise sinnvoller Coder herauskommt. Hier sind ein paar (teilweise schon genannte) Kriterien, die entsprechende Hinweise geben: Startup- und Exit-Code: Bspw. wird in einem C++-Programm eine aufwendigere Initialisierung statischer Variablen durchgeführt (wegen der Konstruktoren) als in einem C-Programm. Formate bestimmter Datentypen: Bspw. sehen Strings in C anders als in Basic oder Pascal aus. Unterprogrammaufrufkonventionen: Bspw. unterscheiden sich C, Pascal und Basic recht deutlich in der Argumentübergabe (verwendete Register, Stacknutzung), dem Anlegen von lokalen Variablen auf dem Stack (z.B. Frame-Pointer in C) und dem Aufräumen des Stacks nach der Rückkehr aus dem Unterprogramm. Verwendete Untermenge des Prozessorbefehlssatzes: Die meisten Compiler verwenden nicht alle zur Verfügung stehenden Befehle. Dadurch kann die Suche etwas eingeschränkt werden. Speziell genutzte Register: Bspw. ist beim AVR-GCC das R1-Register für den Wert 0 reserviert und wird nach jeder Multiplikation (die dieses Register überschreibt) mit 0 nachgeladen. Bibliotheksfunktionen: Man kann versuchen, einfache Funktionen, wie bspw. die _delay_[um]s-Funktion der AVR-Libc wiederzuerkennen. Auch arithmetische Funktionen wie die Integerdivision werden je nach verwendeter Tool-Chain unterschiedlich aussehen. Besonders bei nichtimperativen Sprachen sieht der compilierte Code meist sehr charakteristisch aus, da sie ein ganz anderes Ablaufschema haben: Bspw. generiert ein Haskell-Compiler einen riesengroßen Spaghetti-Code, der kaum Unterprogrammaufrufe enthält. Ein Prolog-Programm sieht nochmals ganz anders aus. Generell kann gesagt werden: Je höher die verwendete Programmiersprache, umso mehr weicht der erzeugte Code von einem in Assembler programmierten Programm ab. Theoretisch kann natürlich jedes Assemblerprogramm so aussehen, als wäre es von einem Compiler generiert worden. Wenn aber gleich mehrere der o.g. Kriterien auf die gleiche Programmiersprache oder gar den gleichen bestimmten Compiler hinweisen, ist der Wahrscheinlichkeit schon sehr groß, dass man damit einen Treffer gelandet hat. Bei der Analyse muss man aber immer auch berücksichtigen, dass Teile des Programms (insbesondere Bibliotheksfunktionen) unabhängig von der sonst verwendeten Programmiersprache in Assembler geschrieben sein können. Auf diese Teile sind natürlich die meisten der genannten Kriterien nicht anwendbar. Eine große Hilfe ist es, wenn man möglichst alle der in Frage kommenden Compiler verfügbar hat, um im Zweifelsfall mittels kleiner Testprogramme nachschauen zu können, was deren Charakteristika bei der Übersetzung sind.
Hi Also ich kann mich noch erinnern, das sich einige Compiler bei PC-Programmen im Klartext in der .exe verewigt haben. MfG Spess
holger schrieb: > Dieser Rückschluss nützt aber niemandem. > Aus einem Hamburger kann man keine lebende Kuh mehr machen. Ist richtig, aber es hat ja auch keiner behauptet, dass man irgendwas mit der Information anfangen kann, oder?
Hallo, bevor man sich da lange alles mögliche abbricht: bei mir steht im Binärcode normalerweise ein Copyright-Vermerk drin, das machen auch viele andere programmierer so - weniger aus Eitelkeit sondern weil man beim Programmieren oder EPROM-Tauschen gleich sieht, welches Programm und welche Version. Und wenn man den Programmierer weiss kann man den ja fragen. Auch Libraries sind oft gekennzeichnet, und bei PC-Programmen stehen soviel DLL-Aufrufe drin, dass man leicht feststellen kann womit sie erzeugt wurden, z.B. wenn VBRUN oder MSVC files angefordert werden. Gruss Reinhard
>> Dieser Rückschluss nützt aber niemandem. >> Aus einem Hamburger kann man keine lebende Kuh mehr machen. >Ist richtig, aber es hat ja auch keiner behauptet, dass man irgendwas >mit der Information anfangen kann, oder? Auch richtig, dann ist es aber auch sinnlos hier weiter zu posten. Wozu braucht man das dann? Es ist nicht verwertbar. Zeitverschwendung. Ich könnte mal ein paar Hex Dateien posten und ihr ratet wo die herkommen. Dabei werde ich natürlich schummeln;) Der TO meldet sich nicht mehr. Wahrscheinlich hab ich ihn verjagt.
Jörg Wunsch schrieb: > … dass du schon lange keinen compilergenerierten Code mehr > angesehen hast. Vermutlich das letzte Mal zu Zeiten der PDP-11. Achja? Dann scheint avrgcc 4.7.2 auch aus der Zeit zu stammen. Jedenfalls finden ich viel zu oft einfache Optimierungsmöglichkeiten, die in meinem Assemblercode enthalten wären. avrgcc gegen asm dürfte ich zu 99%+ erkennen (sofern der Assemblerprogrammierer es nicht darauf anlegt, den C-Compiler zu imitieren). Selbst viele einfache Optimierungen sind teilweise nicht enthalten (Ob sie inzwischen implementiert sind, kann ich nicht garantieren): -subi+sbci durch sbiw/adiw ersetzen -rcall+ret durch rjmp ersetzen -dauerndes überschreiben des Pointerregisters mit der selben Variable, statt einmal kopieren und st Z+ nutzen -1<<x mit Schleife, statt 14 Takte Funktion oder 7 Takte inline (wäre eine Option für O2; ja das geht wirklich in nur 7 Takten). Und der Overhead ist nicht klein, wenn man ein bisschen Assembler programmieren kann. Wenn ich in C programmiere, sollte ich gar nicht mehr ins listing schauen, sonst rege ich mich wieder unnötig über den Compiler auf.
Interessant, wie breitbandig das Fachwissen bzw Unkenntnis sich hier reflektiert... Ich habe hier Tools, welche genau sowas machen, nämlich Architektur eines Binaries erkennen (Format, CPU-Architektur, Programmstruktur, Einsprungsanalyse), zudem können für einige Architekturen Compiler ermittelt werden (von GCC über Keil bis exotische Pascal-Compiler). Bevor nun wer fragt, wo man diese Software kriegen kann: Sind in-house-Tools für Reverse-Engineering, und werden auch in-house bleiben. Kurze Antwort also: Ja, man kann.
Spess53 (Gast) schrieb: > Hi > Also ich kann mich noch erinnern, das sich einige Compiler bei > PC-Programmen im Klartext in der .exe verewigt haben. > MfG Spess Teilweise ist das so, je nach dem ob Exe-Packer oder Protecter SW eingesetzt wurde und man nicht vorsätzlich eine falsche Fährte legen wollte. Beispiele: eagle v6: Microsoft Visual C++ 8; QT als Framework Sprint Layout 6: Borland Delphi 4.0 Diptrace: Delphi (Delphi 5) LTSpice: MS Visual C++ 6, Framework MFC DosBOX v0.74: MingWin32 C++ 4.x 7-zip: MS Visual C++ XnView: Microsoft Visual C++ 6; kaum Hinweise auf MFC PDFCreator: MS Visual BASIC 5/6
Vielen Dank an alle, die sich an diesem Thema beteiligt haben. Ich empfand die Beiträge als sehr informativ, womit auch mein Grund für das Thema definiert ist. Es war nicht meine Absicht, Codes zu "knacken". Weiterhin bin ich der Ansicht, daß Wissen nicht schadet, auch wenn man damit kein direktes Ziel verfolgt. Nochmals vielen Dank für die Beiträge. Mein Ergebnis lautet: Man kann! Gruß wilials
>Mein Ergebnis lautet: Man kann!
Hmmm, ja gut; schön.
Mein Glückwunsch.
Aber was willste mit der Erkenntnis jetzt anfrangen?
Für'n Nobelpreis wird's nicht reichen.
Gruss
BöserFisch schrieb: > Sind in-house-Tools für Reverse-Engineering, Jetzt wüßte ich schon gerne, was für ein house das ist...
avr schrieb: [Thema was der avr-gcc 4.7.2 alles nicht kann] > -rcall+ret durch rjmp ersetzen Na, dachte ich mir, probier ich das gleich mal mit dem avr-gcc 4.7.2 aus:
1 | int ext_f(int x); |
2 | |
3 | int f(int x) |
4 | {
|
5 | return ext_f(x * 2); |
6 | }
|
Ergebnis mit -Os:
1 | Disassembly of section .text: |
2 | |
3 | 00000000 <f>: |
4 | 0: 88 0f add r24, r24 |
5 | 2: 99 1f adc r25, r25 |
6 | 4: 00 c0 rjmp .+0 ; 0x6 <__zero_reg__+0x5> |
Die anderen Sachen habe ich jetzt auf die Schnelle nicht getestet.
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.