GNU/Linux >> LINUX-Kenntnisse >  >> Linux

10 Möglichkeiten zur Analyse von Binärdateien unter Linux

"Es gibt 10 Arten von Menschen auf dieser Welt:diejenigen, die Binär verstehen und diejenigen, die dies nicht tun."

Weitere Linux-Ressourcen

  • Spickzettel für Linux-Befehle
  • Spickzettel für fortgeschrittene Linux-Befehle
  • Kostenloser Online-Kurs:RHEL Technical Overview
  • Spickzettel für Linux-Netzwerke
  • SELinux-Spickzettel
  • Spickzettel für allgemeine Linux-Befehle
  • Was sind Linux-Container?
  • Unsere neuesten Linux-Artikel

Wir arbeiten täglich mit Binärdateien, aber wir verstehen so wenig über sie. Mit Binärdateien meine ich die ausführbaren Dateien, die Sie täglich ausführen, direkt von Ihren Befehlszeilentools bis hin zu vollwertigen Anwendungen.

Linux bietet eine große Auswahl an Tools, die das Analysieren von Binärdateien zum Kinderspiel machen! Was auch immer Ihre berufliche Rolle sein mag, wenn Sie mit Linux arbeiten, hilft Ihnen die Kenntnis der Grundlagen dieser Tools dabei, Ihr System besser zu verstehen.

In diesem Artikel behandeln wir einige der beliebtesten dieser Linux-Tools und -Befehle, von denen die meisten nativ als Teil Ihrer Linux-Distribution verfügbar sein werden. Wenn nicht, können Sie sie jederzeit mit Ihrem Paketmanager installieren und erkunden. Denken Sie daran:Es erfordert viel Geduld und Übung, das richtige Werkzeug zur richtigen Gelegenheit einzusetzen.

Datei

Funktion:Hilft bei der Bestimmung des Dateityps.

Dies ist Ihr Ausgangspunkt für die binäre Analyse. Wir arbeiten täglich mit Dateien. Nicht alles ist ein ausführbarer Typ; Es gibt eine ganze Reihe von Dateitypen da draußen. Bevor Sie beginnen, müssen Sie den zu analysierenden Dateityp verstehen. Handelt es sich um eine Binärdatei, eine Bibliotheksdatei, eine ASCII-Textdatei, eine Videodatei, eine Bilddatei, ein PDF, eine Datendatei usw.?

Die Datei Der Befehl hilft Ihnen dabei, den genauen Dateityp zu identifizieren, mit dem Sie es zu tun haben.

$ file /bin/ls
/bin/ls: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=94943a89d17e9d373b2794dcb1f7e38c95b66c86, stripped
$
$ file /etc/passwd
/etc/passwd: ASCII text
$

ldd

Was es tut:Gemeinsame Objektabhängigkeiten drucken.

Wenn Sie die Datei bereits verwendet haben obigen Befehl auf einer ausführbaren Binärdatei, können Sie die Meldung "dynamisch verknüpft" in der Ausgabe nicht übersehen. Was bedeutet das?

Bei der Entwicklung von Software versuchen wir, das Rad nicht neu zu erfinden. Es gibt eine Reihe allgemeiner Aufgaben, die die meisten Softwareprogramme erfordern, wie z. B. das Drucken von Ausgaben oder das Lesen von Standarddateien oder das Öffnen von Dateien usw. Alle diese allgemeinen Aufgaben werden in einer Reihe allgemeiner Funktionen abstrahiert, die jeder dann verwenden kann, anstatt zu schreiben ihre eigenen Varianten. Diese gemeinsamen Funktionen sind in einer Bibliothek namens libc abgelegt oder glibc .

Wie findet man heraus, von welchen Bibliotheken die ausführbare Datei abhängig ist? Dort steht ldd Befehl kommt ins Bild. Wenn Sie es mit einer dynamisch verknüpften Binärdatei ausführen, werden alle abhängigen Bibliotheken und ihre Pfade angezeigt.

$ ldd /bin/ls
        linux-vdso.so.1 =>  (0x00007ffef5ba1000)
        libselinux.so.1 => /lib64/libselinux.so.1 (0x00007fea9f854000)
        libcap.so.2 => /lib64/libcap.so.2 (0x00007fea9f64f000)
        libacl.so.1 => /lib64/libacl.so.1 (0x00007fea9f446000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fea9f079000)
        libpcre.so.1 => /lib64/libpcre.so.1 (0x00007fea9ee17000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007fea9ec13000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fea9fa7b000)
        libattr.so.1 => /lib64/libattr.so.1 (0x00007fea9ea0e000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fea9e7f2000)
$

ltrace

Was es tut:Ein Tracer für Bibliotheksaufrufe.

Wir wissen jetzt, wie man die Bibliotheken findet, von denen ein ausführbares Programm abhängig ist, indem man ldd verwendet Befehl. Eine Bibliothek kann jedoch Hunderte von Funktionen enthalten. Welche von diesen Hunderten sind die eigentlichen Funktionen, die von unserer Binärdatei verwendet werden?

Der ltrace zeigt alle Funktionen an, die zur Laufzeit aus der Bibliothek aufgerufen werden. Im folgenden Beispiel sehen Sie die aufgerufenen Funktionsnamen zusammen mit den Argumenten, die an diese Funktion übergeben werden. Sie können auch ganz rechts in der Ausgabe sehen, was von diesen Funktionen zurückgegeben wurde.

$ ltrace ls
__libc_start_main(0x4028c0, 1, 0x7ffd94023b88, 0x412950 <unfinished ...>
strrchr("ls", '/')                                                                  = nil
setlocale(LC_ALL, "")                                                               = "en_US.UTF-8"
bindtextdomain("coreutils", "/usr/share/locale")                                    = "/usr/share/locale"
textdomain("coreutils")                                                             = "coreutils"
__cxa_atexit(0x40a930, 0, 0, 0x736c6974756572)                                      = 0
isatty(1)                                                                           = 1
getenv("QUOTING_STYLE")                                                             = nil
getenv("COLUMNS")                                                                   = nil
ioctl(1, 21523, 0x7ffd94023a50)                                                     = 0
<< snip >>
fflush(0x7ff7baae61c0)                                                              = 0
fclose(0x7ff7baae61c0)                                                              = 0
+++ exited (status 0) +++
$

Hexdump

Was es tut:Dateiinhalte in ASCII, dezimal, hexadezimal oder oktal anzeigen.

Oft passiert es, dass Sie eine Datei mit einer Anwendung öffnen, die nicht weiß, was mit dieser Datei zu tun ist. Versuchen Sie, eine ausführbare Datei oder eine Videodatei mit vim zu öffnen; Alles, was Sie sehen werden, ist Kauderwelsch, das auf den Bildschirm geworfen wird.

Das Öffnen unbekannter Dateien in Hexdump hilft Ihnen zu sehen, was genau die Datei enthält. Mit einigen Befehlszeilenoptionen können Sie auch die ASCII-Darstellung der in der Datei vorhandenen Daten anzeigen. Dies könnte Ihnen helfen, Hinweise darauf zu geben, um welche Art von Datei es sich handelt.

$ hexdump -C /bin/ls | head
00000000  7f 45 4c 46 02 01 01 00  00 00 00 00 00 00 00 00  |.ELF............|
00000010  02 00 3e 00 01 00 00 00  d4 42 40 00 00 00 00 00  |..>......B@.....|
00000020  40 00 00 00 00 00 00 00  f0 c3 01 00 00 00 00 00  |@...............|
00000030  00 00 00 00 40 00 38 00  09 00 40 00 1f 00 1e 00  |[email protected]...@.....|
00000040  06 00 00 00 05 00 00 00  40 00 00 00 00 00 00 00  |........@.......|
00000050  40 00 40 00 00 00 00 00  40 00 40 00 00 00 00 00  |@.@.....@.@.....|
00000060  f8 01 00 00 00 00 00 00  f8 01 00 00 00 00 00 00  |................|
00000070  08 00 00 00 00 00 00 00  03 00 00 00 04 00 00 00  |................|
00000080  38 02 00 00 00 00 00 00  38 02 40 00 00 00 00 00  |8.......8.@.....|
00000090  38 02 40 00 00 00 00 00  1c 00 00 00 00 00 00 00  |8.@.............|
$

Zeichenfolgen

Was es tut:Gibt die Zeichenfolgen druckbarer Zeichen in Dateien aus.

Wenn Hexdump für Ihren Anwendungsfall etwas übertrieben erscheint und Sie einfach nach druckbaren Zeichen in einer Binärdatei suchen, können Sie die Strings verwenden Befehl.

Wenn Software entwickelt wird, wird ihr eine Vielzahl von Text-/ASCII-Meldungen hinzugefügt, z. B. Druckinfomeldungen, Debugging-Infos, Hilfemeldungen, Fehler und so weiter. Sofern alle diese Informationen in der Binärdatei vorhanden sind, werden sie mithilfe von Strings auf den Bildschirm ausgegeben .

$ strings /bin/ls

selbst lesen

Was es tut:Informationen zu ELF-Dateien anzeigen.

ELF (Executable and Linkable File Format) ist das vorherrschende Dateiformat für ausführbare Dateien oder Binärdateien, nicht nur unter Linux, sondern auch auf einer Vielzahl von UNIX-Systemen. Wenn Sie Tools wie den Dateibefehl verwendet haben, der Ihnen mitteilt, dass die Datei im ELF-Format vorliegt, besteht der nächste logische Schritt darin, das readelf zu verwenden Befehl und seine verschiedenen Optionen, um die Datei weiter zu analysieren.

Eine Referenz der aktuellen ELF-Spezifikation zur Hand haben, wenn readelf verwendet wird kann sehr nützlich sein. Die Spezifikation finden Sie hier.

$ readelf -h /bin/ls
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x4042d4
  Start of program headers:          64 (bytes into file)
  Start of section headers:          115696 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         9
  Size of section headers:           64 (bytes)
  Number of section headers:         31
  Section header string table index: 30
$

objdump

Was es tut:Zeigt Informationen aus einer Objektdatei an.

Binärdateien werden erstellt, wenn Sie Quellcode schreiben, der mit einem Tool kompiliert wird, das wenig überraschend Compiler genannt wird. Dieser Compiler generiert Anweisungen in Maschinensprache, die dem Quellcode entsprechen, die dann von der CPU ausgeführt werden können, um eine bestimmte Aufgabe auszuführen. Dieser Maschinensprachcode kann über Mnemonik, die als Assemblersprache bezeichnet wird, interpretiert werden. Eine Assemblersprache ist eine Reihe von Anweisungen, die Ihnen helfen, die Operationen zu verstehen, die von dem Programm durchgeführt und schließlich auf der CPU ausgeführt werden.

objdump liest die binäre oder ausführbare Datei und gibt die Assembler-Anweisungen auf dem Bildschirm aus. Assemblerkenntnisse sind entscheidend, um die Ausgabe von objdump zu verstehen Befehl.

Denken Sie daran:Assemblersprache ist architekturspezifisch.

$ objdump -d /bin/ls | head

/bin/ls:     file format elf64-x86-64


Disassembly of section .init:

0000000000402150 <_init@@Base>:
  402150:       48 83 ec 08             sub    $0x8,%rsp
  402154:       48 8b 05 6d 8e 21 00    mov    0x218e6d(%rip),%rax        # 61afc8 <__gmon_start__>
  40215b:       48 85 c0                test   %rax,%rax
$

Strasse

Was es tut:Systemaufrufe und -signale verfolgen.

Wenn Sie ltrace verwendet haben , bereits erwähnt, denken Sie an strace ähnlich sein. Der einzige Unterschied besteht darin, dass anstelle einer Bibliothek der strace Dienstprogramm verfolgt Systemaufrufe. Systemaufrufe stellen eine Schnittstelle zum Kernel dar, um die Arbeit zu erledigen.

Um ein Beispiel zu geben, wenn Sie etwas auf dem Bildschirm drucken möchten, verwenden Sie die printf oder Puts Funktion aus der Standardbibliothek libc; Unter der Haube befindet sich jedoch letztendlich ein Systemaufruf namens write wird gemacht, um tatsächlich etwas auf den Bildschirm zu drucken.

$ strace -f /bin/ls
execve("/bin/ls", ["/bin/ls"], [/* 17 vars */]) = 0
brk(NULL)                               = 0x686000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f967956a000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=40661, ...}) = 0
mmap(NULL, 40661, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f9679560000
close(3)                                = 0
<< snip >>
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f9679569000
write(1, "R2  RH\n", 7R2  RH
)                 = 7
close(1)                                = 0
munmap(0x7f9679569000, 4096)            = 0
close(2)                                = 0
exit_group(0)                           = ?
+++ exited with 0 +++
$

nm

Was es tut:Symbole aus Objektdateien auflisten.

Wenn Sie mit einer nicht gestrippten Binärdatei arbeiten, wird die Datei nm Der Befehl liefert Ihnen die wertvollen Informationen, die während der Kompilierung in die Binärdatei eingebettet wurden. Nm kann Ihnen helfen, Variablen und Funktionen aus der Binärdatei zu identifizieren. Sie können sich vorstellen, wie nützlich dies wäre, wenn Sie keinen Zugriff auf den Quellcode der zu analysierenden Binärdatei haben.

Um nm zu präsentieren , schreiben wir schnell ein kleines Programm und kompilieren es mit dem -g Option, und wir werden auch sehen, dass die Binärdatei nicht durch die Verwendung des file-Befehls entfernt wird.

$ cat hello.c 
#include <stdio.h>

int main() {
    printf("Hello world!");
    return 0;
}
$
$ gcc -g hello.c -o hello
$
$ file hello
hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=3de46c8efb98bce4ad525d3328121568ba3d8a5d, not stripped
$
$ ./hello
Hello world!$
$


$ nm hello | tail
0000000000600e20 d __JCR_END__
0000000000600e20 d __JCR_LIST__
00000000004005b0 T __libc_csu_fini
0000000000400540 T __libc_csu_init
                 U __libc_start_main@@GLIBC_2.2.5
000000000040051d T main
                 U printf@@GLIBC_2.2.5
0000000000400490 t register_tm_clones
0000000000400430 T _start
0000000000601030 D __TMC_END__
$

gdb

Was es tut:Der GNU-Debugger.

Nun, nicht alles in der Binärdatei kann statisch analysiert werden. Wir haben einige Befehle ausgeführt, die die Binärdatei ausgeführt haben, wie ltrace und strace; Software besteht jedoch aus einer Vielzahl von Bedingungen, die dazu führen können, dass verschiedene alternative Pfade ausgeführt werden.

Die einzige Möglichkeit, diese Pfade zu analysieren, ist zur Laufzeit, da man die Möglichkeit hat, das Programm an jeder beliebigen Stelle zu stoppen oder anzuhalten, Informationen zu analysieren und dann weiter nach unten zu gehen.

Hier kommen Debugger ins Spiel ins Bild und unter Linux gdb ist der Defacto-Debugger. Es hilft Ihnen, ein Programm zu laden, Haltepunkte an bestimmten Stellen zu setzen, Speicher und CPU-Register zu analysieren und vieles mehr. Es ergänzt die anderen oben genannten Tools und ermöglicht Ihnen viel mehr Laufzeitanalysen.

Eine Sache, die Sie beachten sollten, ist, sobald Sie ein Programm mit gdb laden , wird Ihnen ein eigenes (gdb) angezeigt prompt. Alle weiteren Befehle werden in dieser gdb ausgeführt Eingabeaufforderung bis zum Beenden.

Wir verwenden das zuvor kompilierte "hello"-Programm und verwenden gdb um zu sehen, wie es funktioniert.

$ gdb -q ./hello
Reading symbols from /home/flash/hello...done.
(gdb) break main
Breakpoint 1 at 0x400521: file hello.c, line 4.
(gdb) info break
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000400521 in main at hello.c:4
(gdb) run
Starting program: /home/flash/./hello

Breakpoint 1, main () at hello.c:4
4           printf("Hello world!");
Missing separate debuginfos, use: debuginfo-install glibc-2.17-260.el7_6.6.x86_64
(gdb) bt
#0  main () at hello.c:4
(gdb) c
Continuing.
Hello world![Inferior 1 (process 29620) exited normally]
(gdb) q
$

Schlussfolgerung

Sobald Sie mit der Verwendung dieser nativen Linux-Binäranalysetools vertraut sind und die von ihnen bereitgestellten Ergebnisse verstanden haben, können Sie zu fortgeschritteneren und professionelleren Open-Source-Binäranalysetools wie radare2 übergehen.


Linux
  1. 5 Möglichkeiten, den Move-Befehl unter Linux zu verwenden

  2. Linux-ls-Befehl - Dateien auflisten

  3. Wie kann man unter Linux Binärdateien von Textdateien unterscheiden?

  4. Wie vergleiche ich Binärdateien in Linux?

  5. Binärer Diff/Patch für große Dateien unter Linux?

Die 6 besten Möglichkeiten zum Anzeigen von Dateien unter Linux

Binärdateien unter Linux ausführen

3 Möglichkeiten, Dateien und Verzeichnisse in Linux zu finden

Sysadmin-Tools:11 Möglichkeiten, den Befehl ls unter Linux zu verwenden

4 Möglichkeiten zum Übertragen von Dateien und Verzeichnissen unter Linux

ls-Befehl unter Linux/UNIX