Warum können wir den Inhalt einer Binärdatei nach dem Kompilieren nicht verstehen?

5095
Diogo

Soweit ich weiß, besteht jedes Programm aus einem Paket von Prozessoranweisungen mit bestimmten Datenvariablen (float, int, char ...), die in den Prozessorregistern bearbeitet werden können .

Das erste, worüber ich nachgedacht habe (vor langer Zeit): Wenn Sie wissen, dass der ASCII-Wert von %¨#$¨#(nur ein zufälliges Beispiel) als Adresse des Stack-Pointer-Registers (nur beispielhaft) eines x86 interpretiert werden kann Prozessor. Wenn dies der Fall ist, könnten Sie jedes Mal, wenn Sie beim Lesen des Inhalts einer Binärdatei diesen "unlesbaren" Wert finden, feststellen, dass das Stack-Pointer-Register zur Verwaltung einiger Datenvariablen verwendet wird.

Leider passiert das nicht. Unten sehen Sie ein Beispiel für den Inhalt des ping.exeProgramms von Windows, das mit geöffnet wurde notepad.exe:

Ping.exe wie in MS Notepad angezeigt

Es ist eine binäre Datei und ihre Daten sind für uns Menschen unverständlich (für Maschinen verständlich). Es macht für niemanden Sinn, selbst wenn sie Assembler-Code kennen (die niedrigste Maschinensprache).

Wenn ich also alles richtig verstanden habe, könnte jemand erklären

  1. Warum kann ein Binärcode nicht so weit zum Assembly-Code zurückkehren, wie er tief unten dasselbe ist?
  2. Wenn man Assembler-Code verstehen kann, warum ist die aus diesem Code resultierende kompilierte Binärdatei nicht mehr "lesbar"?
10
Sie können, Sie brauchen nur einen [Disassembler] (http://en.wikibooks.org/wiki/X86_Disassembly/Disassemblers_and_Decompilers#Free_Windows_Disassemblers). David Schwartz vor 12 Jahren 12
So kann ich jede .exe-Datei zerlegen ??? Ich wusste nur, dass es mit verwaltetem Code funktioniert ... Diogo vor 12 Jahren 0
Sie können jede ausführbare Datei zerlegen. Ob Sie die disassemblierte Ausgabe verstehen können, ist eine andere Geschichte. David Schwartz vor 12 Jahren 13
Hmm, ich habe darüber nachgedacht, den ursprünglichen Code wiederherzustellen. Ich meine, wenn Sie den disassemblierten Code erneut zusammenbauen, würde er genauso funktionieren wie zuvor ... Allerdings ist dies eine neue Information für mich. Diogo vor 12 Jahren 0
Sicher, wenn Sie es wieder zusammenbauen, wird es genauso funktionieren. Das bedeutet aber nicht, dass * Sie * es verstehen können. Ein Großteil des Materials, das es für den Menschen verständlich machte, ist weg. David Schwartz vor 12 Jahren 0
Beim Kompilieren oder Assemblieren werden viele menschenwichtige Informationen wie Variablennamen, Beschriftungen von Verzweigungen usw. entfernt. Durch die Demontage wird der Befehlsstrom abgerufen. mpez0 vor 12 Jahren 5
Durch die Optimierung können die Operationen und die Reihenfolge der Operationen erheblich von den ursprünglichen Schreibvorgängen abweichen. Dies ändert die Funktionalität selten, macht es jedoch unmöglich, den ursprünglichen, nicht optimierten Code zu generieren. Außerdem werden alle lokalen Variablennamen gelöscht, da sie nicht benötigt werden. BillThor vor 12 Jahren 0
[Code-Verschleierung] (http://en.wikibooks.org/wiki/X86_Disassembly/Code_Obfuscation) kann die Demontage behindern. math vor 12 Jahren 1
Das Demontieren von Programmen ist eine Kunst. Abgesehen von den anderen sehr realen Problemen, die in den anderen Antworten erwähnt wurden, steht einem Programmierer oder Compiler nichts dagegen, Daten irgendwo in der Mitte eines Programms einzubetten. Das bedeutet, dass Sie herausfinden müssen, welche Teile zu zerlegender Code sind und welche nur Daten sind. Joe vor 12 Jahren 0
Die meisten Programme verwenden außerdem Bibliotheksfunktionen wie DLLs in Windows oder .so-Dateien in Linux. Alles, was Sie im Code sehen, ist eine Art Aufruf- oder Sprunganweisung für ein Stück Code, das nicht vorhanden ist, und ohne den Namen und die Parameterübergabereihenfolge ist es sehr schwierig zu wissen, wozu dieser Code existiert und was auch immer Elemente Ihres Programms, auf dem das Programm ausgeführt wird oder zurückgegeben wird. Joe vor 12 Jahren 0
Ich finde es sehr interessant und amüsant, dass die Antwort auf diese Frage nur durch Ultraschallmesser und Sägemehl gegeben wird. "oO" Synetech vor 11 Jahren 0

3 Antworten auf die Frage

12
LawrenceC

Erstens haben Register keine Adressen. Jede Anweisung in einer beliebigen Assembler-Sprache wird in einen Opcode übersetzt. Opcodes in x86 können ein, zwei, drei oder sogar mehr Bytes sein (in einigen anderen Prozessoren sind sie "Festbreite"). 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 der "unmittelbare" Adressierungsmodus bedeutet, dass unmittelbar nach (oder "unmittelbar nach") der Anweisung für diese Anweisung zusätzliche Daten 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 herausfinden MOV AL,SPund danach suchen. x86 hat viele Anweisungen, die den Stapelzeiger bearbeiten.

Aber bitte, bitte beenden Sie den Editor verwenden und ein Hex - Editor stattdessen verwenden. 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 OP - Codes (wie Anweisungen, die eine Adresse für einen Operanden oder „Argument“ nehmen) sein sollten, könnten als Opcodes falsch interpretiert werden. Um dies zu wissen, muss das Format der ausführbaren Datei bekannt sein. Dies ist für Windows das "Portable Executable" - oder PE-Format (und für Linux-Systeme häufig ELF). Ich bin sicher, dass es Disassembler gibt, die PE usw. verstehen, aber ich kenne keine Nebenprodukte.

[IDA] (http://en.wikipedia.org/wiki/Interactive_Disassembler) ist einer der gebräuchlichsten PE-Dissembler. Funktioniert auch mit Linux- und Mac-Dateien. Version 5.0 ist [noch verfügbar] (http://www.hex-rays.com/products/ida/support/download_freeware.shtml) als Freeware verfügbar Scott Chamberlain vor 12 Jahren 1
*> Wenn Sie an der falschen Adresse beginnen, wird… möglicherweise falsch interpretiert. * Deshalb sind alle Vorkommen von% ¨ # $ ¨ # nicht unbedingt ein Verweis auf den Stackzeiger. Es kann nur die Mitte von * zwei verschiedenen Befehlen * sein: `_3p% ¨ #` und `$ ¨ # b5F` (` _3p% ¨ # `` $ ¨ # b5F`). Synetech vor 11 Jahren 1
11
sawdust

So, if I have understood everything correctly

Not quite.

It is a binary file and its data is incomprehensible for us humans

Typically a binary file is incomprehensible to human and machine, especially when the purpose of the file is unknown. Note that not all binary files are executable files. A lot of binary files are data files that do not contain any machine instructions. That is why file extensions are used when naming files (in some OSes). The .com extension was used by CP/M to denote an executable file. The .exe extension was added by MS-DOS to denote another executable file format. *nixes use the execute attribute to denote which files can be executed, although it could be script as well as code.

As already mentioned by others, binary files, which contain numbers, should be viewed by a hex dump program or hex editor and not by a text viewer.

there is a example of the content of the ping.exe program

That file is actually a relocatable program, and not all of the data in that file represents machine code. There is information about the program such as which dynamic libraries it needs, which routines have to be linked, requirements for stack and program & data memory, and the program's entry point. Address operands in the file could be relative values that need to be calculated to absolute values, or references that need to be resolved.

The "program file" that you're probably thinking of is called a binary image file or a dump of program memory. Such a file would contain only machine code and data, with all address references properly set for execution.

even if they know Assembly code(the lowest level of machine language.)

Assembly language is not the same as machine language. The typical (as to exclude high-level language computers) CPU accepts machine code as input, one instruction at a time. The operands are either registers or numeric memory addresses. Assembly language is a higher-level language that can use symbolic labels for instruction locations and variables, as well as replacing numeric op-codes with mnemonics. An assembly language program has to converted to machine language/code before it can actually be executed (typically by utilities called assembler, linker and loader).

The reverse operation, disassemby, can be performed on program files with some success and loss of symbolic information. Disassembly of a memory dump or program image file is more trial & error, as code and data locations need to be identified manually.

BTW there are persons that can read and code the (numeric) machine code. Of course this is a lot easier on an 8-bit CPU or microcontroller than a 32-bit CISC processor with a dozen memory address modes.

2

Sie können die richtige, beabsichtigte Kodierung einer Binärdatei nicht über den Editor anzeigen. Bitte überprüfen Sie dies für zukünftige Referenz. Die meisten Textbearbeitungsprogramme analysieren keine binären Codierungsformate und müssen ASCII-Zeichencode-Formatierungen analysieren.

Wenn Sie also eine Binärdatei in einem Texteditor öffnen, erhalten Sie gleichwertige ASCII-Zeichen, die keinen Sinn für das ursprüngliche Format der Binärdaten ergeben, das vom Texteditor analysiert wird. Wie bereits erwähnt, verfügen Hex-Editoren und einige über binäre Funktionen, um den Inhalt im reinen Binärformat anzuzeigen.

Sie sind falsch, dass der Inhalt einer Binärdatei nicht verstanden werden kann. Während sie hart sein werden und in modernen Computerarchitekturen extrem schwer von Hand zu zerlegen sind, in richtige Anweisungen, die von der CPU zur Ausführung (oder emulierten / virtuellen CPU) usw. erkannt werden, ist dies möglich.

Wie denkst du, sind Emulatoren programmiert? Der Entwickler müsste Opcodes kennen, um das fiktive System so programmieren zu können, dass es in gewisser Weise wie die reale Hardware erkennt und sich verhält. Dokumentationen erklären viele Architekturen von CPUs, und sogar GPUs haben sie (wenn auch geheimer).

Zu beachten ist auch, dass in der untersten Ebene, obwohl korrelativ, die "binären Daten" nicht wirklich ein Bündel von Nullen und Einsen sind, sondern Hoch-und-Nieder-Spannungen, die durch einen elektrischen Stromkreis als Strom verstärkt / durchgeschaltet werden.

Binär ist in der Regel 1: 1, daher ist es sinnvoll, das Zahlensystem dafür zu verwenden.