ELF file headers

前端 未结 9 1084
無奈伤痛
無奈伤痛 2021-02-05 22:15

A quick question about elf file headers, I can\'t seem to find anything useful on how to add/change fields in the elf header. I\'d like to be able to change the magic numbers an

相关标签:
9条回答
  • 2021-02-05 22:33

    This link (teensy elf binary) was someone's answer to another question, but it goes into the intricacies of an ELF header in some detail.

    0 讨论(0)
  • 2021-02-05 22:36

    I didn't finish the book but iirc Linkers and Loaders by John Levine had the gory details that you would need to be able to do this.

    0 讨论(0)
  • 2021-02-05 22:37

    You can create an object file with informative fields like a version number and link that file such that they are included in the resulting ELF binary.

    Ident

    For example, as part of you build process, you can generate - say - info.c that contains one or more #ident directives:

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

    Compile it:

    $ gcc -c info.c
    

    Check if the information is included:

    $ 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)
    

    Alternatively, you can use objdump -s --section .comment info.o. Note that GCC also writes its own comment, by default.

    Check the information after linking an ELF executable:

    $ 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
    

    Comment Section

    Using #ident in a C translation unit is basically equivalent to creating a .comment section in an assembler file. Example:

    $ 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
    

    Using an uncommon section name works, as well (e.g. .section .blahblah). But .comment is used and understood by other tools. GNU as also understands the .ident directive, and this is what GCC translates #ident to.

    With Symbols

    For data that you also want to access from the ELF executable itself you need to create symbols.

    Objcopy

    Say you want to include some magic bytes stored in a data file:

    $ cat magic.bin 
    2342
    

    Convert into a object file with GNU objcopy:

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

    Check for the symbols:

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

    Example usage:

    #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;
    }
    

    Link everything together:

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

    GNU ld

    GNU ld is also able to turn data files into object files using an objcopy compatible naming scheme:

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

    Unlike objcopy, it places the symbols into the .data instead of the .rodata section, though (cf. objdump -h magic.o).

    incbin

    In case GNU objcopy isn't available, one can use the GNU as .incbin directive to create the object file (assemble with 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

    A more portable alternative that doesn't require GNU objcopy nor GNU as is to create an intermediate C file and compile and link that. For example with 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;
    
    0 讨论(0)
  • 2021-02-05 22:39

    You might be able to use libmelf, a dead project on freshmeat, but available from LOPI - http://www.ipd.bth.se/ska/lopi.html

    Otherwise, you can get the spec and (over)write the header yourself.

    0 讨论(0)
  • 2021-02-05 22:45

    I haven't done this in awhile, but can't you just append arbitrary data to an executable. If you always append fixed-size data it would be trivial to recover anything you append. Variable size wouldn't be much harder. Probably easier than messing w/ elf headers and potentially ruining you executables.

    0 讨论(0)
  • 2021-02-05 22:50

    I don't know of linker script commands that can do this, but you can do it post-link using the objcopy command. The --add-section option can be used to add a section containing arbitrary data to the ELF file. If the ELF header doesn't contain the fields you want, just make a new section and add them there.

    0 讨论(0)
提交回复
热议问题