.elf格式内部检查

.elf格式内部检查

我正在阅读 ELF 格式规范,其中告诉了所有这些内容,包括 elf-headers、程序头、节、段等。所有这些都被引用为具有各种字段和值的结构。

那么问题是,这一切都去哪里了?我的意思是,我可以将它们视为结构,而不是readelfutil 的输出吗?

是否有任何中间文件,其中所有这些精灵魔法存在,合并到源代码中吗?或者它只是编译器的内部结构,并且在规范中仅针对人类提到了结构?)

对我来说,这看起来像是“先有鸡还是先有蛋的问题”(用代码来谈论编译后的代码)。

答案1

这些结构存在于 ELF 文件中。

我们看一下ELF头:

#define EI_NIDENT (16)

typedef struct
{
  unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */
  Elf32_Half    e_type;                 /* Object file type */
  Elf32_Half    e_machine;              /* Architecture */
  Elf32_Word    e_version;              /* Object file version */
  Elf32_Addr    e_entry;                /* Entry point virtual address */
  Elf32_Off     e_phoff;                /* Program header table file offset */
  Elf32_Off     e_shoff;                /* Section header table file offset */
  Elf32_Word    e_flags;                /* Processor-specific flags */
  Elf32_Half    e_ehsize;               /* ELF header size in bytes */
  Elf32_Half    e_phentsize;            /* Program header table entry size */
  Elf32_Half    e_phnum;                /* Program header table entry count */
  Elf32_Half    e_shentsize;            /* Section header table entry size */
  Elf32_Half    e_shnum;                /* Section header table entry count */
  Elf32_Half    e_shstrndx;             /* Section header string table index */
} Elf32_Ehdr;

typedef struct
{
  unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */
  Elf64_Half    e_type;                 /* Object file type */
  Elf64_Half    e_machine;              /* Architecture */
  Elf64_Word    e_version;              /* Object file version */
  Elf64_Addr    e_entry;                /* Entry point virtual address */
  Elf64_Off     e_phoff;                /* Program header table file offset */
  Elf64_Off     e_shoff;                /* Section header table file offset */
  Elf64_Word    e_flags;                /* Processor-specific flags */
  Elf64_Half    e_ehsize;               /* ELF header size in bytes */
  Elf64_Half    e_phentsize;            /* Program header table entry size */
  Elf64_Half    e_phnum;                /* Program header table entry count */
  Elf64_Half    e_shentsize;            /* Section header table entry size */
  Elf64_Half    e_shnum;                /* Section header table entry count */
  Elf64_Half    e_shstrndx;             /* Section header string table index */
} Elf64_Ehdr;

ELF 标头位于每一个ELF 文件。

这实际上意味着 ELF 文件的前 16 个字节是e_identELF 标头中的字段:

  • 第一个字节是0x7f;

  • 第二个是'E'

  • 第三个是'L'

  • 第四个是'F'

  • 第五是班级;

  • 第六是数据编码;

  • 第七个是文件版本;

  • 八是操作系统ABI;

  • ETC。

该字段之后e_ident,接下来的 2 个字节是e_type.

如果是你head /bin/bash,你将能够看到ELF接近开始的地方。

现在,如果您获取 ELF 文件开头的十六进制转储:

$ xxd /bin/bash | xxd头
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............
00000010: 0200 3e00 0100 0000 7005 4200 0000 0000 ..>.....pB....
00000020: 4000 0000 0000 0000 c0cd 0f00 0000 0000 @..............
00000030: 0000 0000 4000 3800 0900 4000 1d00 1c00  [电子邮件受保护]...@.....
00000040: 0600 0000 0500 0000 4000 0000 0000 0000 ........@.......
00000050: 4000 4000 0000 0000 4000 4000 0000 0000 @.@.....@.@.....
00000060: f801 0000 0000 0000 f801 0000 0000 0000 ........
00000070: 0800 0000 0000 0000 0300 0000 0400 0000 ................
00000080: 3802 0000 0000 0000 3802 4000 0000 0000 8.......8.@.....
00000090: 3802 4000 0000 0000 1c00 0000 0000 0000 8.@........................

此十六进制转储的第一行是前 16 个字节 ( e_ident):

  • 第一个字节确实是0x7f

  • 然后来了"ELF"

  • 之后是(ELF64)0x02类;ELFCLASS64

  • 然后是编码,0x01对于ELFDATA2LSB;

  • ETC。

第二行的前两个字节是e_type.它们以 LSB 编码(因为ELFDATA2LSB),因此该值实际上0x0002意味着ET_EXEC(这是一个可执行文件)。

接下来的两个字节是体系结构 ( e_machine):0x003e因为EM_X86_64这是一个x86_64可执行文件。

您应该能够手动解码 ELF 标头中的所有字段,并且您应该找到与 给出的值相同的值readelf。由此,您可以在文件中找到其他 ELF 结构,例如ElfXX_ShdrElfXX_Phdr,并根据它们的定义对其进行解码(您应该找到与 给出的信息相同的信息readelf)。

答案2

使用过xxdawk

$ xxd hello_arm64   | awk '{for(i=2;i<NF;i++){a=a$i;c++;if(c>9){print a;exit;}}}'
7f454c460201010000000000000000000200b700
$ cat /proc/sys/fs/binfmt_misc/qemu-aarch64
enabled
interpreter /usr/bin/qemu-aarch64-static
flags: F
offset 0
magic 7f454c460201010000000000000000000200b700
mask ffffffffffffff00fffffffffffffffffeffffff

相关内容