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

Überprüfen, ob eine Binärdatei mit -static kompiliert wurde

Sie können auch den file verwenden Befehl (und objdump könnte auch nützlich sein).


Überprüfen Sie, ob es einen Programmkopf vom Typ INTERP hat

Auf der unteren Ebene ist eine ausführbare Datei statisch, wenn sie keinen Programmkopf vom Typ:

hat
Elf32_Phd.p_type == PT_INTERP

Dies wird in der System V ABI-Spezifikation erwähnt.

Denken Sie daran, dass Programmheader die ELF-Segmente bestimmen, einschließlich derer vom Typ PT_LOAD das in den Speicher geladen und ausgeführt wird.

Wenn dieser Header vorhanden ist, ist sein Inhalt genau der Pfad des dynamischen Ladeprogramms.

readelf prüfen

Wir können dies bei readelf beobachten . Kompilieren Sie zunächst dynamisch ein C-Hallo-Welt:

gcc -o main.out main.c

und dann:

readelf --program-headers --wide main.out

Ausgaben:

Elf file type is DYN (Shared object file)
Entry point 0x1050
There are 11 program headers, starting at offset 64

Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  PHDR           0x000040 0x0000000000000040 0x0000000000000040 0x000268 0x000268 R   0x8
  INTERP         0x0002a8 0x00000000000002a8 0x00000000000002a8 0x00001c 0x00001c R   0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x000560 0x000560 R   0x1000
  LOAD           0x001000 0x0000000000001000 0x0000000000001000 0x0001bd 0x0001bd R E 0x1000
  LOAD           0x002000 0x0000000000002000 0x0000000000002000 0x000150 0x000150 R   0x1000
  LOAD           0x002db8 0x0000000000003db8 0x0000000000003db8 0x000258 0x000260 RW  0x1000
  DYNAMIC        0x002dc8 0x0000000000003dc8 0x0000000000003dc8 0x0001f0 0x0001f0 RW  0x8
  NOTE           0x0002c4 0x00000000000002c4 0x00000000000002c4 0x000044 0x000044 R   0x4
  GNU_EH_FRAME   0x00200c 0x000000000000200c 0x000000000000200c 0x00003c 0x00003c R   0x4
  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x10
  GNU_RELRO      0x002db8 0x0000000000003db8 0x0000000000003db8 0x000248 0x000248 R   0x1

 Section to Segment mapping:
  Segment Sections...
   00
   01     .interp
   02     .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt
   03     .init .plt .plt.got .text .fini
   04     .rodata .eh_frame_hdr .eh_frame
   05     .init_array .fini_array .dynamic .got .data .bss
   06     .dynamic
   07     .note.ABI-tag .note.gnu.build-id
   08     .eh_frame_hdr
   09
   10     .init_array .fini_array .dynamic .got

Beachten Sie also die INTERP Header ist da, und es ist so wichtig, dass readelf gab sogar eine kurze Vorschau auf seinen kurzen Inhalt von 28 (0x1c) Bytes:/lib64/ld-linux-x86-64.so.2 , das ist der Pfad zum dynamischen Ladeprogramm (27 Bytes lang + 1 für \0 ).

Beachten Sie, wie sich dies Seite an Seite mit den anderen Segmenten befindet, einschließlich z. diejenigen, die tatsächlich in den Speicher geladen werden, wie zum Beispiel:.text .

Wir können diese Bytes dann ohne die Vorschau direkter extrahieren mit:

readelf -x .interp main.out

was ergibt:

Hex dump of section '.interp':
  0x000002a8 2f6c6962 36342f6c 642d6c69 6e75782d /lib64/ld-linux-
  0x000002b8 7838362d 36342e73 6f2e3200          x86-64.so.2.

wie unter:Wie kann ich den Inhalt eines Datenabschnitts einer ELF-Datei unter Linux untersuchen?

file Quellcode

file 5.36-Quellcode-Kommentare unter src/readelf.c behaupten, dass es auch nach PT_INTERP sucht :

/*
 * Look through the program headers of an executable image, searching
 * for a PT_INTERP section; if one is found, it's dynamically linked,
 * otherwise it's statically linked.
 */
private int
dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
    int num, size_t size, off_t fsize, int sh_num, int *flags,
    uint16_t *notecount)
{
    Elf32_Phdr ph32;
    Elf64_Phdr ph64;
    const char *linking_style = "statically";

gefunden mit git grep statically aus der Nachricht main.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped .

Dieser Kommentar scheint jedoch im Vergleich zum Code veraltet zu sein, der stattdessen nach PT_DYNAMIC sucht :

    case PT_DYNAMIC:
        linking_style = "dynamically";
        doread = 1;
        break;

Ich bin mir nicht sicher, warum das so ist, und bin zu faul, in git log zu graben jetzt. Insbesondere hat mich das etwas verwirrt, als ich versuchte, eine statisch gelinkte PIE mit --no-dynamic-linker ausführbar zu machen wie gezeigt unter:Wie erstelle ich eine statisch verknüpfte positionsunabhängige ausführbare ELF unter Linux? die nicht PT_INTERP hat hat aber PT_DYNAMIC , und von denen ich nicht erwarte, dass sie den dynamischen Loader verwenden.

Am Ende habe ich eine tiefere Quellenanalyse für -fPIE durchgeführt at:Warum erstellt GCC ein Shared Object statt einer ausführbaren Binärdatei laut Datei? die Antwort ist wahrscheinlich auch dort.

Linux-Kernel-Quellcode

Der Linux-Kernel 5.0 liest die ELF-Datei während des exec-Systemaufrufs unter fs/binfmt_elf.c wie erklärt unter:How does kernel get an executable binary file running under linux?

Der Kernel durchläuft die Programm-Header bei load_elf_binary

    for (i = 0; i < loc->elf_ex.e_phnum; i++) {
        if (elf_ppnt->p_type == PT_INTERP) {
            /* This is the program interpreter used for
             * shared libraries - for now assume that this
             * is an a.out format binary
             */

Ich habe den Code nicht vollständig gelesen, aber ich würde dann erwarten, dass der dynamische Loader nur verwendet wird, wenn INTERP gefunden wird, welchen Pfad sollte es andernfalls verwenden?

PT_DYNAMIC wird in dieser Datei nicht verwendet.

Bonus:Prüfen Sie ob -pie verwendet wurde

Ich habe das ausführlich erklärt unter:Warum erstellt GCC ein gemeinsames Objekt anstelle einer ausführbaren Binärdatei gemäß Datei?


ldd /path/to/binary sollte keine gemeinsam genutzten Bibliotheken auflisten, wenn die Binärdatei statisch kompiliert ist.


Linux
  1. Ausführen eines Programms mit verschiedenen Parametern (Schleife)?

  2. Überprüfen der Verzeichnisgröße mit dem Befehl du unter Linux

  3. Laden Sie Dateien als ASCII oder binär mit FTP hoch

  4. So erstellen Sie Threads in Linux (mit einem C-Beispielprogramm)

  5. Rufen Sie eine Funktion auf, wenn das Programm beendet ist, mit ctrl c

Bash For Loop mit praktischen Beispielen

Verwalten Sie virtuelle KVM-Maschinen mit dem Virsh-Programm

Mein Bootloader lässt sich nicht mit gcc 4.6 und 4.7 kompilieren ... nur 4.5

Kann ich 'rpath' in einer bereits kompilierten Binärdatei ändern?

Linux:Schließen Sie ein Programm mit der Befehlszeile (nicht beenden)

Konvertieren Sie einen Hex-String in Binär und senden Sie ihn mit netcat