GNU/Linux >> Linux Esercitazione >  >> Linux

Intestazioni file ELF

Non conosco i comandi di script del linker che possono farlo, ma puoi farlo post-link usando objcopy comando. La --add-section L'opzione può essere utilizzata per aggiungere una sezione contenente dati arbitrari al file ELF. Se l'intestazione ELF non contiene i campi desiderati, basta creare una nuova sezione e aggiungerli lì.


Questo link (teensy elf binary) era la risposta di qualcuno a un'altra domanda, ma entra nel dettaglio delle intricate intestazioni ELF.


Puoi creare un file oggetto con campi informativi come un numero di versione e collegare quel file in modo che siano inclusi nel binario ELF risultante.

Identificazione

Ad esempio, come parte del processo di compilazione, puoi generare, ad esempio, info.c che contiene uno o più #ident direttive:

#ident "Build: 1.2.3 (Halloween)"
#ident "Environment: example.org"

Compilalo:

$ gcc -c info.c

Controlla se le informazioni sono incluse:

$ readelf -p .comment info.o
String dump of section '.comment':
  [     1]  Build: 1.2.3 (Halloween)
  [    1a]  Environment: example.org
  [    33]  GCC: (GNU) 7.2.1 20170915 (Red Hat 7.2.1-2)

In alternativa, puoi usare objdump -s --section .comment info.o . Nota che GCC scrive anche il proprio commento, per impostazione predefinita.

Controlla le informazioni dopo aver collegato un eseguibile ELF:

$ gcc -o main main.o info.o
$ readelf -p .comment main 
String dump of section '.comment':
  [     0]  GCC: (GNU) 7.2.1 20170915 (Red Hat 7.2.1-2)
  [    2c]  Build: 1.2.3 (Halloween)
  [    45]  Environment: example.org

Sezione commenti

Usando #ident in un'unità di traduzione C equivale sostanzialmente a creare un .comment sezione in un file assembler. Esempio:

$ cat info.s
.section .comment
.string "Build: 1.2.3 (Halloween)"
.string "Environment: example.org"
$ gcc -c info.s
$ readelf -p .comment info.o
String dump of section '.comment':
  [     0]  Build: 1.2.3 (Halloween)
  [    19]  Environment: example.org

Anche l'utilizzo di un nome di sezione non comune funziona (ad es. .section .blahblah ). Ma .comment viene utilizzato e compreso da altri strumenti. GNU comprende anche il .ident direttiva, e questo è ciò che GCC traduce #ident a.

Con simboli

Per i dati a cui vuoi accedere anche dall'eseguibile ELF stesso, devi creare dei simboli.

Oggettocopia

Supponi di voler includere alcuni magic byte memorizzati in un file di dati:

$ cat magic.bin 
2342

Converti in un file oggetto con GNU objcopy:

$ objcopy -I binary -O elf64-x86-64 -B i386 \
    --rename-section .data=.rodata,alloc,load,readonly,data,contents \
    magic.bin magic.o

Controlla i simboli:

$ nm  magic.o  
0000000000000005 R _binary_magic_bin_end
0000000000000005 A _binary_magic_bin_size
0000000000000000 R _binary_magic_bin_start

Esempio di utilizzo:

#include <stdio.h>
#include <string.h>
#include <inttypes.h>

extern const char _binary_magic_bin_start[];
extern const char _binary_magic_bin_end[];
extern const unsigned char _binary_magic_bin_size;
static const size_t magic_bin_size = (uintptr_t) &_binary_magic_bin_size;

int main()
{
  char s[23];
  memcpy(s, _binary_magic_bin_start,
      _binary_magic_bin_end - _binary_magic_bin_start);
  s[magic_bin_size] = 0;
  puts(s);
  return 0;
}

Collega tutto insieme:

$ gcc -g -o main_magic main_magic.c magic.o

GNU ld

GNU ld è anche in grado di trasformare i file di dati in file oggetto utilizzando uno schema di denominazione compatibile con objcopy:

$ ld -r -b binary magic.bin -o magic-ld.o

A differenza di objcopy, inserisce i simboli nel .data invece del .rodata sezione, tuttavia (cfr. objdump -h magic.o ).

incbin

Nel caso in cui GNU objcopy non sia disponibile, si può usare GNU come .incbin direttiva per creare il file oggetto (assemble con gcc -c incbin.s ):

    .section .rodata

    .global _binary_magic_bin_start
    .type _binary_magic_bin_start, @object
_binary_magic_bin_start:
    .incbin "magic.bin"
    .size _binary_magic_bin_start, . - _binary_magic_bin_start

    .global _binary_magic_bin_size
    .type _binary_magic_bin_size, @object
    .set _binary_magic_bin_size, . - _binary_magic_bin_start

    .global _binary_magic_bin_end
    .type _binary_magic_bin_end, @object
    .set _binary_magic_bin_end, _binary_magic_bin_start + _binary_magic_bin_size
    ; an alternate  way to include the size    
    .global _binary_magic_bin_len
    .type _binary_magic_bin_len, @object
    .size _binary_magic_bin_len, 8
_binary_magic_bin_len:
    .quad _binary_magic_bin_size

xxd

Un'alternativa più portabile che non richiede GNU objcopy né GNU come è creare un file C intermedio e compilarlo e collegarlo. Ad esempio con xxd:

$ xxd -i magic.bin | sed 's/\(unsigned\)/const \1/' > magic.c
$ gcc -c magic.c
$ nm magic.o
0000000000000000 R magic_bin
0000000000000008 R magic_bin_len
$ cat magic.c
const unsigned char magic_bin[] = {
  0x32, 0x33, 0x34, 0x32, 0x0a
};
const unsigned int magic_bin_len = 5;

Linux
  1. Ordinare parte di un file?

  2. Esecuzione di un file binario piatto sotto Linux

  3. a.out sostituito dal formato di file ELF?

  4. Lettura da un file in assembly

  5. Come estrarre solo i contenuti grezzi di una sezione ELF?

Editor VIM

C fopen vs open

Strumento per modificare la sezione dinamica di un binario ELF

glibc:file elf OS ABI non valido

Scrivere su file .txt?

cp -L contro cp -H