Soweit ich weiß, besteht jedes Programm aus einem Paket von Prozessoranweisungen mit einigen spezifischen Datenvariablen (float, int, char ...), um an den Prozessorregistern zu arbeiten .
Das erste, worüber ich (vor langer Zeit) nachgedacht habe, ist, dass, wenn Sie wissen, dass der ASCII-Wert von %¨#$¨#
(nur ein zufälliges Beispiel) als die Adresse des Stapelzeigerregisters (nur als Beispiel) eines x86 interpretiert werden kann Prozessor. Wenn dies zutrifft, können Sie jedes Mal, wenn Sie diesen "unlesbaren" Wert beim Lesen des Inhalts einer Binärdatei finden, interpretieren, dass das Stapelzeigerregister zum Verwalten einer Datenvariablen verwendet wird.
Das passiert leider nicht. Unten finden Sie ein Beispiel für den Inhalt des ping.exe
Programms unter Windows, das geöffnet wurde mit notepad.exe
:
Es ist eine Binärdatei und ihre Daten sind für uns Menschen unverständlich (sie sind für Maschinen verständlich). Sie ergeben für niemanden einen Sinn, selbst wenn sie den Assembler-Code kennen (die niedrigste Ebene der Maschinensprache).
Also, wenn ich alles richtig verstanden habe, könnte jemand erklären
- Warum kann ein Binärcode nicht zum Assembly-Code zurückkehren, solange er tief im Inneren dasselbe ist?
- Wenn man Assembler-Code verstehen kann, warum ist die kompilierte Binärdatei, die sich aus diesem Code ergibt, nicht mehr "lesbar"?
quelle
Antworten:
Erstens haben Register keine Adressen. Jede Anweisung in einer beliebigen Assemblersprache wird in einen Opcode übersetzt. Opcodes in x86 können ein, zwei, drei oder sogar mehr Bytes sein (in einigen anderen Prozessoren haben sie eine "feste Breite"). Normalerweise identifiziert der Opcode den Befehl, den Adressierungsmodus und die beteiligten Register. Der "Adressierungsmodus" bestimmt, ob mehr als der Opcode von der CPU benötigt wird, dh "sofortiger" Adressierungsmodus bedeutet, dass zusätzliche Daten direkt nach (oder "unmittelbar nach") der Anweisung für diese Anweisung vorhanden sind - "absolute" Adressierungsmodi bedeuten, dass a Die Speicheradresse folgt der Anweisung und wird von dieser Anweisung verwendet.
Sie können den Opcode von etwas ähnlichem
MOV AL,SP
oder ähnlichem herausfinden und dann danach suchen. x86 verfügt über viele Anweisungen, die auf dem Stapelzeiger ausgeführt werden.Aber bitte, bitte beenden Sie die Verwendung von Notepad und verwenden Sie stattdessen einen Hex-Editor. Ich würde HxD empfehlen, obwohl es viele andere gibt.
Und @ David Schwartz ist richtig. Ein Disassembler durchläuft eine Datei und übersetzt Opcodes zurück in lesbaren Text. Was Sie tun möchten, ist absolut möglich.
Allerdings müssen Sie wissen , wo in der Datei der Anweisungen beginnen , denn wenn man an der falschen Adresse beginnen, einige Daten, die die „Operanden“ auf Opcodes sein sollten (wie Anweisungen , die eine Adresse für einen Operanden oder „Argument“ nehmen) Macht als Opcodes falsch interpretiert werden. Um dies zu wissen, muss das Format der ausführbaren Datei bekannt sein, das für Windows das Format "Portable Executable" oder PE ist (und häufig Linux für Linux-Systeme ist). Ich bin mir sicher, dass es Disassembler gibt, die PE usw. verstehen, aber ich kenne keine Nebenhand.
quelle
%¨#$¨#
nicht unbedingt ein Verweis auf den Stapelzeiger. Es könnte nur die Mitte von zwei verschiedenen Befehlen sein :_3p%¨#
und$¨#b5F
(_3p %¨#
$¨# b5F
).Nicht ganz.
Normalerweise ist eine Binärdatei für Mensch und Maschine unverständlich, insbesondere wenn der Zweck der Datei unbekannt ist. Beachten Sie, dass nicht alle Binärdateien ausführbare Dateien sind. Viele Binärdateien sind Datendateien, die keine Maschinenanweisungen enthalten. Aus diesem Grund werden beim Benennen von Dateien (in einigen Betriebssystemen) Dateierweiterungen verwendet. Das . Die com- Erweiterung wurde von CP / M verwendet, um eine ausführbare Datei zu kennzeichnen. Das . Die Erweiterung exe wurde von MS-DOS hinzugefügt, um ein anderes ausführbares Dateiformat zu kennzeichnen. * nixes verwenden das execute-Attribut, um anzugeben, welche Dateien ausgeführt werden können, obwohl es sich sowohl um ein Skript als auch um Code handeln kann.
Wie bereits von anderen erwähnt, sollten Binärdateien, die Zahlen enthalten, von einem Hex-Dump-Programm oder Hex-Editor und nicht von einem Text-Viewer angezeigt werden.
Diese Datei ist tatsächlich ein verschiebbares Programm, und nicht alle Daten in dieser Datei repräsentieren Maschinencode. Es gibt Informationen über das Programm, z. B. welche dynamischen Bibliotheken es benötigt, welche Routinen verknüpft werden müssen, Anforderungen an Stapel und Programm- und Datenspeicher sowie den Einstiegspunkt des Programms. Adressoperanden in der Datei können relative Werte sein, die zu absoluten Werten berechnet werden müssen, oder Referenzen, die aufgelöst werden müssen.
Die "Programmdatei", an die Sie wahrscheinlich denken, wird als Binärbilddatei oder Speicherauszug des Programmspeichers bezeichnet. Eine solche Datei würde nur Maschinencode und Daten enthalten, wobei alle Adressreferenzen ordnungsgemäß für die Ausführung festgelegt sind.
Assemblersprache ist nicht dasselbe wie Maschinensprache . Die typische CPU (um Hochsprachencomputer auszuschließen) akzeptiert Maschinencode als Eingabe, eine Anweisung nach der anderen. Die Operanden sind entweder Register oder numerische Speicheradressen. Assemblersprache ist eine übergeordnete Sprache, die symbolische Bezeichnungen für Anweisungspositionen und Variablen verwenden und numerische Op-Codes durch Mnemonik ersetzen kann. Ein Assembler-Programm muss in Maschinensprache / Code konvertiert werden, bevor es tatsächlich ausgeführt werden kann (normalerweise von Dienstprogrammen namens Assembler, Linker und Loader).
Die umgekehrte Operation, Disassemby, kann für Programmdateien mit einigem Erfolg und Verlust symbolischer Informationen ausgeführt werden. Die Demontage eines Speicherauszugs oder einer Programmabbilddatei ist eher ein Versuch und Irrtum, da Code- und Datenpositionen manuell identifiziert werden müssen.
Übrigens gibt es Personen, die den (numerischen) Maschinencode lesen und codieren können. Natürlich ist dies auf einer 8-Bit-CPU oder einem Mikrocontroller viel einfacher als auf einem 32-Bit-CISC-Prozessor mit einem Dutzend Speicheradressenmodi.
quelle
Sie können die richtige, beabsichtigte Codierung einer Binärdatei nicht über Notepad sehen. Bitte überprüfen Sie dies für zukünftige Referenz. Die meisten Textbearbeitungsprogramme analysieren keine binären Codierungsformate und es wird erwartet, dass sie die ASCII-Zeichencode-Formatierung analysieren.
Wenn Sie also eine Binärdatei in einem Texteditor öffnen, erhalten Sie äquivalente ASCII-Zeichen, die für das vom Texteditor analysierte Originalformat der Binärdaten keinen Sinn ergeben. Wie bereits erwähnt, verfügen Hex-Editoren und einige über Binärfunktionen, um den Inhalt im reinen Binärformat anzuzeigen.
Sie sind falsch, dass der Inhalt einer Binärdatei nicht verstanden werden kann. Während sie schwierig sein werden und in modernen Computerarchitekturen extrem schwer von der Binärdatei allein in die richtigen Anweisungen zu zerlegen sind, die von der CPU zur Ausführung (oder emulierten / virtuellen CPU) usw. erkannt werden, kann dies durchgeführt werden.
Wie sind Emulatoren Ihrer Meinung nach programmiert? Der Entwickler müsste Opcodes kennen, um das fiktive System so programmieren zu können, dass es die reale Hardware in irgendeiner Weise erkennt und sich so verhält. Dokumentationen erklären viele Architekturen von CPUs, und sogar GPUs haben sie (wenn auch geheimnisvoller).
Eine andere Sache, die zu beachten ist, ist, dass in der niedrigsten Ebene, obwohl korrelativ, die "Binärdaten" nicht wirklich eine Reihe von Nullen und Einsen sind, sondern hohe und niedrige Spannungen, die durch einen Stromkreis als Strom verstärkt / geschaltet werden.
Binär ist dabei normalerweise 1: 1, daher ist es sehr sinnvoll, das Zahlensystem dafür zu verwenden.
quelle