Connect with us

Wie man

So können Sie über die Linux-Befehlszeile in Binärdateien einsehen

Everything You Ever Wanted to Know About inodes on Linux

fatmawati achmad zaenuri/Shutterstock

Haben Sie eine mysteriöse Datei? Das Linux file Befehl wird Ihnen schnell sagen, um welchen Dateityp es sich handelt. Wenn es sich jedoch um eine Binärdatei handelt, können Sie noch mehr darüber erfahren. file hat eine ganze Reihe von Stallgefährten, die Ihnen bei der Analyse helfen. Wir zeigen Ihnen, wie Sie einige dieser Tools verwenden.

Identifizieren von Dateitypen

Dateien weisen normalerweise Merkmale auf, die es Softwarepaketen ermöglichen, zu erkennen, um welchen Dateityp es sich handelt und was die darin enthaltenen Daten darstellen. Es würde keinen Sinn machen, eine PNG-Datei in einem MP3-Musikplayer zu öffnen, daher ist es sowohl nützlich als auch pragmatisch, dass eine Datei eine Form von ID mit sich führt.

Dies können einige Signaturbytes ganz am Anfang der Datei sein. Dies ermöglicht es einer Datei, ihr Format und ihren Inhalt eindeutig anzugeben. Manchmal wird der Dateityp aus einem bestimmten Aspekt der internen Organisation der Daten selbst abgeleitet, der als Dateiarchitektur bekannt ist.

Einige Betriebssysteme, wie Windows, richten sich vollständig nach der Erweiterung einer Datei. Sie können es leichtgläubig oder vertrauensvoll nennen, aber Windows geht davon aus, dass jede Datei mit der DOCX-Erweiterung wirklich eine DOCX-Textverarbeitungsdatei ist. Linux ist nicht so, wie Sie gleich sehen werden. Es will Beweise und sucht in der Datei, um es zu finden.

Die hier beschriebenen Tools wurden bereits auf den Distributionen Manjaro 20, Fedora 21 und Ubuntu 20.04 installiert, mit denen wir diesen Artikel recherchiert haben. Beginnen wir unsere Untersuchung mit das file Befehl.

Verwenden des Dateibefehls

Wir haben eine Sammlung verschiedener Dateitypen in unserem aktuellen Verzeichnis. Sie sind eine Mischung aus Dokument-, Quellcode-, ausführbaren und Textdateien.

Der ls Befehl zeigt uns, was sich im Verzeichnis befindet, und die -hl (für Menschen lesbare Größen, lange Auflistung) zeigt uns die Größe jeder Datei an:

ls -hl

Lass es uns versuchen file auf ein paar davon und sehen Sie, was wir bekommen:

file build_instructions.odt
file build_instructions.pdf
file COBOL_Report_Apr60.djvu

Die drei Dateiformate werden richtig erkannt. Wo möglich, file gibt uns ein bisschen mehr Informationen. Die PDF-Datei befindet sich angeblich im Version 1.5-Format.

Selbst wenn wir die ODT-Datei umbenennen, um eine Erweiterung mit dem willkürlichen Wert von XYZ zu haben, wird die Datei immer noch korrekt identifiziert, sowohl innerhalb der Files Dateibrowser und in der Befehlszeile mit file.

OpenDocument-Datei im Dateibrowser

Innerhalb des Files Dateibrowser wird das richtige Symbol angezeigt. Auf der Befehlszeile, file ignoriert die Erweiterung und schaut in die Datei, um ihren Typ zu bestimmen:

file build_instructions.xyz

Verwenden von file auf Medien wie Bild- und Musikdateien liefert normalerweise Informationen zu Format, Kodierung, Auflösung usw.:

file screenshot.png
file screenshot.jpg
file Pachelbel_Canon_In_D.mp3

Interessanterweise ist selbst bei Nur-Text-Dateien file beurteilt die Datei nicht nach ihrer Erweiterung. Wenn Sie beispielsweise eine Datei mit der Erweiterung „.c“ haben, die Standard-Klartext, aber keinen Quellcode enthält, file verwechselt es nicht mit einem echten C Quellcodedatei:

file function+headers.h
file makefile
file hello.c

file identifiziert die Header-Datei („.h“) korrekt als Teil einer C-Quellcodesammlung von Dateien und weiß, dass das Makefile ein Skript ist.

Datei mit Binärdateien verwenden

Binärdateien sind eher eine „Black Box“ als andere. Bilddateien können angezeigt, Tondateien abgespielt und Dokumentdateien mit dem entsprechenden Softwarepaket geöffnet werden. Binäre Dateien sind jedoch eine größere Herausforderung.

Beispielsweise sind die Dateien „hello“ und „wd“ binäre ausführbare Dateien. Sie sind Programme. Die Datei „wd.o“ ist eine Objektdatei. Wenn Quellcode von einem Compiler kompiliert wird, werden eine oder mehrere Objektdateien erstellt. Diese enthalten den Maschinencode, den der Computer schließlich ausführen wird, wenn das fertige Programm ausgeführt wird, zusammen mit Informationen für den Linker. Der Linker überprüft jede Objektdatei auf Funktionsaufrufe an Bibliotheken. Es verknüpft sie mit allen Bibliotheken, die das Programm verwendet. Das Ergebnis dieses Prozesses ist eine ausführbare Datei.

Die Datei „watch.exe“ ist eine binäre ausführbare Datei, die für die Ausführung unter Windows querkompiliert wurde:

file wd
file wd.o
file hello
file watch.exe

Nimm den letzten zuerst, file teilt uns mit, dass die Datei „watch.exe“ ein ausführbares PE32+-Konsolenprogramm für die x86-Prozessorfamilie unter Microsoft Windows ist. PE steht für Portable Executable Format, die 32- und 64-Bit-Versionen hat. PE32 ist die 32-Bit-Version und PE32+ ist die 64-Bit-Version.

Die anderen drei Dateien sind alle identifiziert als Ausführbares und verknüpfbares Format (ELF)-Dateien. Dies ist ein Standard für ausführbare Dateien und Dateien mit gemeinsam genutzten Objekten, wie z. B. Bibliotheken. Wir werden uns in Kürze das ELF-Header-Format ansehen.

Was Ihnen vielleicht auffallen könnte, ist, dass die beiden ausführbaren Dateien („wd“ und „hello“) identifiziert werden als Linux-Standardbasis (LSB) Shared Objects, und die Objektdatei „wd.o“ wird als LSB relocable identifiziert. Das Wort ausführbar ist in seiner Abwesenheit offensichtlich.

Objektdateien sind verschiebbar, was bedeutet, dass der darin enthaltene Code an jedem Ort in den Speicher geladen werden kann. Die ausführbaren Dateien werden als gemeinsam genutzte Objekte aufgelistet, da sie vom Linker aus den Objektdateien so erstellt wurden, dass sie diese Fähigkeit erben.

Dies ermöglicht die Randomisierung des Adressraum-Layouts (ASMR)-System, um die ausführbaren Dateien an Adressen seiner Wahl in den Speicher zu laden. Ausführbare Standarddateien haben in ihren Headern eine Ladeadresse codiert, die vorschreibt, wo sie in den Speicher geladen werden.

ASMR ist eine Sicherheitstechnik. Das Laden ausführbarer Dateien in den Speicher an vorhersagbaren Adressen macht sie anfällig für Angriffe. Dies liegt daran, dass Angreifern ihre Eintrittspunkte und die Standorte ihrer Funktionen immer bekannt sind. Positionsunabhängige ausführbare Dateien (PIE), die an einer zufälligen Adresse positioniert ist, überwinden diese Anfälligkeit.

Wenn wir Stellen Sie unser Programm zusammen mit dem gcc Compiler und stellen Sie die -no-pie Option generieren wir eine konventionelle ausführbare Datei.

Der -o Mit der Option (Ausgabedatei) können wir einen Namen für unsere ausführbare Datei angeben:

gcc -o hello -no-pie hello.c

Wir verwenden file auf der neuen ausführbaren Datei und sehen Sie, was sich geändert hat:

file hello

Die Größe der ausführbaren Datei ist dieselbe wie zuvor (17 KB):

ls -hl hello

Die Binärdatei wird jetzt als ausführbare Standarddatei identifiziert. Wir tun dies nur zu Demonstrationszwecken. Wenn Sie Anwendungen auf diese Weise kompilieren, verlieren Sie alle Vorteile des ASMR.

Warum ist eine ausführbare Datei so groß?

Unser Beispiel hello Programm ist 17 KB groß, kann also kaum als groß bezeichnet werden, aber dann ist ja alles relativ. Der Quellcode ist 120 Byte groß:

cat hello.c

Was sperrt die Binärdatei, wenn sie nur eine Zeichenfolge im Terminalfenster ausgibt? Wir wissen, dass es einen ELF-Header gibt, aber dieser ist für eine 64-Bit-Binärdatei nur 64 Byte lang. Offensichtlich muss es etwas anderes sein:

ls -hl hello

Lasst uns scannen Sie die Binärdatei mit dem strings Befehl als einfachen ersten Schritt, um herauszufinden, was darin enthalten ist. Wir leiten es hinein less:

strings hello | less

Es gibt viele Zeichenfolgen in der Binärdatei, abgesehen von «Hello, Geek world!» aus unserem Quellcode. Die meisten von ihnen sind Bezeichnungen für Regionen innerhalb der Binärdatei sowie die Namen und Verknüpfungsinformationen gemeinsam genutzter Objekte. Dazu gehören die Bibliotheken und Funktionen innerhalb dieser Bibliotheken, von denen die Binärdatei abhängt.

Der ldd Befehl zeigt uns die gemeinsamen Objektabhängigkeiten einer Binärdatei:

ldd hello

Die Ausgabe enthält drei Einträge, von denen zwei einen Verzeichnispfad enthalten (der erste nicht):

  • linux-vdso.so: Virtual Dynamic Shared Object (VDSO) ist ein Kernel-Mechanismus, der den Zugriff auf eine Reihe von Kernel-Space-Routinen durch eine User-Space-Binärdatei ermöglicht. Dies vermeidet den Overhead eines Kontextwechsels aus dem Benutzer-Kernel-Modus. Gemeinsam genutzte VDSO-Objekte halten sich an das Format Executable and Linkable Format (ELF), sodass sie zur Laufzeit dynamisch mit der Binärdatei verknüpft werden können. Das VDSO wird dynamisch zugewiesen und nutzt ASMR. Die VDSO-Fähigkeit wird vom Standard bereitgestellt GNU C-Bibliothek wenn der Kernel das ASMR-Schema unterstützt.
  • libc.so.6: Der GNU C-Bibliothek gemeinsames Objekt.
  • /lib64/ld-linux-x86-64.so.2: Dies ist der dynamische Linker, den die Binärdatei verwenden möchte. Der dynamische Linker fragt die Binärdatei ab, um herauszufinden, welche Abhängigkeiten sie hat. Es startet diese gemeinsam genutzten Objekte in den Speicher. Es bereitet die Binärdatei darauf vor, ausgeführt zu werden und die Abhängigkeiten im Speicher zu finden und darauf zuzugreifen. Dann startet es das Programm.

Der ELF-Header

Wir können den ELF-Header untersuchen und decodieren Verwendung der readelf Dienstprogramm und die -h (Dateiheader) Option:

readelf -h hello

Die Überschrift wird für uns interpretiert.

Das erste Byte aller ELF-Binärdateien wird auf den Hexadezimalwert 0x7F gesetzt. Die nächsten drei Bytes werden auf 0x45, 0x4C und 0x46 gesetzt. Das erste Byte ist ein Flag, das die Datei als ELF-Binärdatei identifiziert. Um dies kristallklar zu machen, buchstabieren die nächsten drei Bytes „ELF“ in ASCII:

  • Klasse: Gibt an, ob die Binärdatei eine ausführbare 32- oder 64-Bit-Datei ist (1=32, 2=64).
  • Daten: Zeigt die Endianität in Benutzung. Die Endian-Kodierung definiert die Art und Weise, wie Multibyte-Zahlen gespeichert werden. Bei der Big-Endian-Kodierung wird eine Zahl mit ihren höchstwertigen Bits zuerst gespeichert. Bei der Little-Endian-Kodierung wird die Zahl mit ihren am wenigsten signifikanten Bits zuerst gespeichert.
  • Ausführung: Die Version von ELF (derzeit ist es 1).
  • Betriebssystem/ABI: Repräsentiert die Art von Anwendung binäre Schnittstelle in Benutzung. Dies definiert die Schnittstelle zwischen zwei binären Modulen, beispielsweise einem Programm und einer gemeinsam genutzten Bibliothek.
  • ABI-Version: Die Version des ABI.
  • Typ: Der Typ der ELF-Binärdatei. Die gemeinsamen Werte sind ET_REL für eine verschiebbare Ressource (wie eine Objektdatei), ET_EXEC für eine ausführbare Datei, die mit dem kompiliert wurde -no-pie Flagge, und ET_DYN für eine ASMR-fähige ausführbare Datei.
  • Maschine: Der Befehlssatzarchitektur. Dies gibt die Zielplattform an, für die die Binärdatei erstellt wurde.
  • Ausführung: Für diese Version von ELF immer auf 1 setzen.
  • Adresse des Einstiegspunkts: Die Speicheradresse innerhalb der Binärdatei, bei der die Ausführung beginnt.

Die anderen Einträge sind Größen und Anzahlen von Regionen und Abschnitten innerhalb der Binärdatei, damit ihre Positionen berechnet werden können.

Ein kurzer Blick auf die ersten acht Bytes der Binärdatei mit hexdump zeigt das Signaturbyte und die „ELF“-Zeichenfolge in den ersten vier Bytes der Datei an. Der -C (kanonische) Option gibt uns die ASCII-Darstellung der Bytes zusammen mit ihren hexadezimalen Werten, und die -n Mit der Option (Zahl) können wir angeben, wie viele Bytes wir sehen möchten:

hexdump -C -n 8 hello

objdump und die Granular View

Wenn Sie die Details sehen möchten, können Sie die objdumpBefehl mit dem -d (zerlegen) Option:

objdump -d hello | less

Dadurch wird der ausführbare Maschinencode zerlegt und in hexadezimalen Bytes neben dem Assemblersprachäquivalent angezeigt. Die Adressposition des ersten Byes in jeder Zeile wird ganz links angezeigt.

Dies ist nur nützlich, wenn Sie Assembler lesen können oder neugierig sind, was hinter dem Vorhang passiert. Es gibt viel Output, also haben wir es hinein geleitet less.

Kompilieren und verlinken

Es gibt viele Möglichkeiten, eine Binärdatei zu kompilieren. Beispielsweise entscheidet der Entwickler, ob Debuginformationen hinzugefügt werden sollen. Auch die Art und Weise, wie die Binärdatei verlinkt ist, spielt eine Rolle für Inhalt und Größe. Wenn die Binärreferenzen Objekte als externe Abhängigkeiten teilen, ist sie kleiner als eine, auf die die Abhängigkeiten statisch verweisen.

Die meisten Entwickler kennen die hier behandelten Befehle bereits. Für andere bieten sie jedoch einige einfache Möglichkeiten, herumzustöbern und zu sehen, was sich in der binären Blackbox befindet.

Continue Reading
Click to comment

Leave a Reply

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Tendencia