GNU/Linux >> Znalost Linux >  >> Linux

kontrola, zda je binární soubor zkompilován s -static

Můžete také použít file příkaz (a objdump může být také užitečné).


Zkontrolujte, zda má hlavičku programu typu INTERP

Na nižší úrovni je spustitelný soubor statický, pokud nemá hlavičku programu s typem:

Elf32_Phd.p_type == PT_INTERP

To je zmíněno ve specifikaci System V ABI.

Pamatujte, že hlavičky programů určují segmenty ELF, včetně segmentů typu PT_LOAD který se načte do paměti a spustí se.

Pokud je toto záhlaví přítomno, jeho obsah je přesně cestou dynamického zavaděče.

readelf zkontrolovat

Můžeme to pozorovat pomocí readelf . Nejprve dynamicky zkompilujte svět C hello:

gcc -o main.out main.c

a poté:

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

výstupy:

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

takže si všimněte INTERP hlavička je tam a je tak důležité, aby readelf dokonce poskytl rychlý náhled svého krátkého obsahu 28 (0x1c) bajtů:/lib64/ld-linux-x86-64.so.2 , což je cesta k dynamickému zavaděči (délka 27 bajtů + 1 ​​pro \0 ).

Všimněte si, jak se toto nachází vedle sebe s ostatními segmenty, včetně např. ty, které se skutečně načtou do paměti, jako například:.text .

Tyto bajty pak můžeme přímo extrahovat bez náhledu pomocí:

readelf -x .interp main.out

což dává:

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

jak je vysvětleno v:Jak mohu prozkoumat obsah datové části souboru ELF v systému Linux?

file zdrojový kód

file Komentáře ke zdrojovému kódu 5.36 na src/readelf.c tvrdí, že také kontroluje PT_INTERP :

/*
 * 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";

nalezen s git grep statically ze zprávy main.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped .

Tento komentář se však zdá být zastaralý ve srovnání s kódem, který místo toho kontroluje PT_DYNAMIC :

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

Nejsem si jistý, proč se to dělá, a jsem líný kopat do git log Nyní. Zejména mě to trochu zmátlo, když jsem se snažil vytvořit staticky propojený spustitelný soubor PIE s --no-dynamic-linker jak je uvedeno na:Jak vytvořit staticky propojený spustitelný ELF nezávislý na pozici v Linuxu? který nemá PT_INTERP ale má PT_DYNAMIC , a neočekávám, že bude používat dynamický zavaděč.

Nakonec jsem provedl hlubší analýzu zdroje pro -fPIE at:Proč GCC vytváří sdílený objekt namísto spustitelného binárního souboru podle souboru? odpověď je tam pravděpodobně také.

Zdrojový kód linuxového jádra

Linuxové jádro 5.0 čte soubor ELF během systémového volání exec na fs/binfmt_elf.c, jak je vysvětleno v:Jak jádro získá spustitelný binární soubor běžící pod linuxem?

Jádro prochází přes hlavičky programu na 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
             */

Nečetl jsem celý kód, ale očekával bych, že použije pouze dynamický zavaděč, pokud INTERP je nalezen, jinak jakou cestu má použít?

PT_DYNAMIC se v tomto souboru nepoužívá.

Bonus:zkontrolujte, zda -pie byl použit

Podrobně jsem to vysvětlil na:Proč GCC vytváří sdílený objekt namísto spustitelného binárního souboru podle souboru?


ldd /path/to/binary neměl by uvádět žádné sdílené knihovny, pokud je binární soubor staticky zkompilován.


Linux
  1. Oprava binárního kódu pomocí Dd?

  2. Jednoduchý program vláken C++ nelze zkompilovat?

  3. Jak upgradovat program nainstalovaný pomocí Softaculous

  1. Mohu změnit 'rpath' v již zkompilovaném binárním souboru?

  2. otevřete soubor s výchozím programem v node-webkit

  3. Linux:zavřete program pomocí příkazového řádku (nezabijte jej)

  1. Provádění programu s různými parametry (smyčka)?

  2. Kontrola velikosti adresáře pomocí příkazu du v systému Linux

  3. Spuštění bash skriptu nebo binárního c na souborovém systému s možností noexec