Können wir Compiler-Informationen aus einer Elf-Binärdatei erhalten?

50

Gibt es eine Chance zu wissen, wie eine Binärdatei unter Linux erstellt wurde? (und oder andere Unix)

Compiler, Version, Zeit, Flags etc ...

Ich habe nachgeschaut readelfund konnte nicht viel finden, aber es könnte andere Möglichkeiten geben, den Binärcode / Abschnitt usw. zu analysieren.

Wissen Sie, wie man extrahiert?

Elmarco
quelle

Antworten:

48

Es gibt keinen universellen Weg, aber Sie können eine fundierte Vermutung anstellen, indem Sie nach Dingen suchen, die nur von einem Compiler ausgeführt werden.

GCC ist am einfachsten; Es schreibt einen .commentAbschnitt, der die GCC-Versionszeichenfolge enthält (dieselbe Zeichenfolge, die Sie erhalten, wenn Sie ausführen gcc --version). Ich weiß nicht, ob es eine Möglichkeit gibt, es anzuzeigen readelf, aber objdumpdamit:

objdump -s --section .comment /path/binary

Mir ist gerade klar geworden, dass ich den Rest Ihrer Frage ignoriert habe. Flags werden im Allgemeinen nirgendwo gespeichert. Sie wären höchstwahrscheinlich in einem Kommentarbereich, aber ich habe das noch nie gesehen. Es gibt einen Punkt in der COFF-Kopfzeile für einen Zeitstempel, aber es gibt keine Entsprechung in ELF, sodass ich auch nicht denke, dass die Kompilierungszeit verfügbar ist

Michael Mrozek
quelle
28

Wie wäre es mit:

readelf -p .comment a.out
Colin King
quelle
3
Wie ist das anders als bei Michael objdump? Gibt es weitere Informationen? Verfügbar auf verschiedenen Plattformen? Saubereres Ausgabeformat?
Caleb
9
Saubereres Ausgabeformat.
Marcin
19

Sie können versuchen, den stringsBefehl zu verwenden. Es wird viel Text ausgegeben; Wenn Sie es überprüfen, können Sie den Compiler erraten.

pubuntu@pubuntu:~$ strings -a a.out |grep -i gcc
GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3

Hier weiß ich, dass es mit kompiliert wurde, gccaber Sie können die stringsAusgabe immer in eine Datei umleiten und sie untersuchen.

Es gibt ein sehr gutes Hilfsprogramm peidfür Windows, aber ich kann keine Alternative für Linux finden.

Hemant
quelle
1
+1, ermöglicht es Ihnen, die Zusammenstellungsflaggen zu sehen (wenn gcc)
Ivan Black
4

Es gibt zwei Methoden. Beide geben das gleiche Ergebnis

objdump -s --section .comment path/to/binary

Wenn Sie den Befehl readelf verwenden, readelf -S binary werden die 40 Abschnittsüberschriften in der Binärdatei angezeigt. Notieren Sie die Seriennummer der .comment Abschnittsüberschrift. In meinem System zeigte es als 27 (kann für Ihren Fall unterschiedlich sein)

readelf -x 30 path/to/binary -> welches den Hex-Dump des Abschnitts '.comment' anzeigt. In diesem Dump sehen Sie den Compiler, mit dem die Binärdatei erstellt wurde.

Ranjini
quelle
4

readelf oder objdump können dies beide tun.

Die von gcc kompilierte ELF-Datei fügt die beiden Abschnitte .note.ABI-tag und .note.gnu.build-id hinzu. beide könnten angezeigt werden von

objdump -sj .note.ABI-tag ELFFILE
objdump -sj .note.gnu-build-id ELFFILE

Option "s" bedeutet, dass der gesamte Inhalt angezeigt wird, "j" für die Angabe des Abschnittsnamens. Dieser Stil erhält den hexadezimalen Inhalt dieser Abschnitte.

readelf -n

zeigt den lesbaren Inhalt von ELFFILE einmal an. Option "n" bedeutet NOTES.

Wählen Sie eine wie Sie möchten.

Verwenden Sie übrigens objcopy und fügen Sie Ihren eigenen Abschnitt in die elf-Datei ein.

liuyang1
quelle
readelf -nArbeitete für mich - Beispiel Ausgabe:Displaying notes found in: .note.gnu.build-id Owner Data size Description GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring) Build ID: b88bae04e9043b71b329bac0ce2a2e5314183272
Den-Jason
4

Sie können auch dieses clevere Skript verwenden , das die Anzahl der verschiedenen CPU-Anweisungen zählt, die von der Binärdatei verwendet werden. Es basiert auf der Analyse der Ausgabe von objdump. Beachten Sie, dass es ziemlich lange dauern kann, bis der Vorgang abgeschlossen ist, wenn Sie ihn auf einer großen Binärdatei verwenden.

rozcietrzewiacz
quelle
Bemerkenswert ist, dass es nur x86 ist.
Victor Sergienko
0

Könnte einen Glücksschuss wert sein, je nachdem welches Programm. Einige Programme haben dies als Information kompiliert und können über einen Versionsaufruf (-V, --version, -Version usw.) darauf zugreifen. Möglicherweise finden Sie eine Untergruppe der gesuchten Elemente (einschließlich der Nullgruppe). Hier ist ein besonders fruchtbares Beispiel, Perl 5:

$ perl -V

Summary of my perl5 (revision 5 version 26 subversion 2) configuration:

  Platform:
    osname=linux
    osvers=4.15.15-1-arch
    archname=x86_64-linux-thread-multi
    uname='linux flo-64 4.15.15-1-arch #1 smp preempt sat mar 31 23:59:25 utc 2018 x86_64 gnulinux '
    config_args='-des -Dusethreads -Duseshrplib -Doptimize=-march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong -fno-plt -Dprefix=/usr -Dvendorprefix=/usr -Dprivlib=/usr/share/perl5/core_perl -Darchlib=/usr/lib/perl5/5.26/core_perl -Dsitelib=/usr/share/perl5/site_perl -Dsitearch=/usr/lib/perl5/5.26/site_perl -Dvendorlib=/usr/share/perl5/vendor_perl -Dvendorarch=/usr/lib/perl5/5.26/vendor_perl -Dscriptdir=/usr/bin/core_perl -Dsitescript=/usr/bin/site_perl -Dvendorscript=/usr/bin/vendor_perl -Dinc_version_list=none -Dman1ext=1perl -Dman3ext=3perl -Dcccdlflags='-fPIC' -Dlddlflags=-shared -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -Dldflags=-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now'
    hint=recommended
    useposix=true
    d_sigaction=define
    useithreads=define
    usemultiplicity=define
    use64bitint=define
    use64bitall=define
    uselongdouble=undef
    usemymalloc=n
    default_inc_excludes_dot=define
    bincompat5005=undef
  Compiler:
    cc='cc'
    ccflags ='-D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2'
    optimize='-march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong -fno-plt'
    cppflags='-D_REENTRANT -D_GNU_SOURCE -fwrapv -fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include'
    ccversion=''
    gccversion='7.3.1 20180312'
    gccosandvers=''
    intsize=4
    longsize=8
    ptrsize=8
    doublesize=8
    byteorder=12345678
    doublekind=3
    d_longlong=define
    longlongsize=8
    d_longdbl=define
    longdblsize=16
    longdblkind=3
    ivtype='long'
    ivsize=8
    nvtype='double'
    nvsize=8
    Off_t='off_t'
    lseeksize=8
    alignbytes=8
    prototype=define
  Linker and Libraries:
    ld='cc'
    ldflags ='-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -fstack-protector-strong -L/usr/local/lib'
    libpth=/usr/local/lib /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.1/include-fixed /usr/lib /lib/../lib /usr/lib/../lib /lib /lib64 /usr/lib64
    libs=-lpthread -lnsl -lgdbm -ldb -ldl -lm -lcrypt -lutil -lc -lgdbm_compat
    perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
    libc=libc-2.26.so
    so=so
    useshrplib=true
    libperl=libperl.so
    gnulibc_version='2.26'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs
    dlext=so
    d_dlsymun=undef
    ccdlflags='-Wl,-E -Wl,-rpath,/usr/lib/perl5/5.26/core_perl/CORE'
    cccdlflags='-fPIC'
    lddlflags='-shared -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -L/usr/local/lib -fstack-protector-strong'


Characteristics of this binary (from libperl): 
  Compile-time options:
    HAS_TIMES
    MULTIPLICITY
    PERLIO_LAYERS
    PERL_COPY_ON_WRITE
    PERL_DONT_CREATE_GVSV
    PERL_IMPLICIT_CONTEXT
    PERL_MALLOC_WRAP
    PERL_OP_PARENT
    PERL_PRESERVE_IVUV
    USE_64_BIT_ALL
    USE_64_BIT_INT
    USE_ITHREADS
    USE_LARGE_FILES
    USE_LOCALE
    USE_LOCALE_COLLATE
    USE_LOCALE_CTYPE
    USE_LOCALE_NUMERIC
    USE_LOCALE_TIME
    USE_PERLIO
    USE_PERL_ATOF
    USE_REENTRANT_API
  Built under linux
  Compiled at Apr 18 2018 22:21:20
  %ENV:
    PERL5LIB="/home/jhuber/perl5/lib/perl5"
    PERL_LOCAL_LIB_ROOT="/home/jhuber/perl5"
    PERL_MB_OPT="--install_base "/home/jhuber/perl5""
    PERL_MM_OPT="INSTALL_BASE=/home/jhuber/perl5"
  @INC:
    /home/jhuber/perl5/lib/perl5/x86_64-linux-thread-multi
    /home/jhuber/perl5/lib/perl5
    /usr/lib/perl5/5.26/site_perl
    /usr/share/perl5/site_perl
    /usr/lib/perl5/5.26/vendor_perl
    /usr/share/perl5/vendor_perl
    /usr/lib/perl5/5.26/core_perl
    /usr/share/perl5/core_perl
Joshua Huber
quelle
0

Wenn Sie eine ELF-Binärdatei in 7-zip öffnen, werden die verschiedenen Abschnitte darin aufgelistet. Von dort aus können Sie über die Kontextmenüoption "Ansicht" im Abschnitt ".comment" die Kommentare des Compilers anzeigen (z. B. "GCC: (GNU) 4.9 20150123 (Vorabversion) Android-Clang-Version 3.8.256229 (basierend auf LLVM 3.8.256229)).

Beachten Sie, dass der Abschnitt ".comment", falls vorhanden, mit einem Nullzeichen zu beginnen scheint. Wählen Sie daher eine Viewer-Anwendung für die Verwendung in 7-zip aus, die dadurch nicht verwirrt wird (z. B. versucht, das zu interpretieren) Daten als Unicode). Andere Abschnitte, die existieren und von Interesse sein können, sind ".note. *".

Joe
quelle