内核处理 ELF 中的节头

逆向工程 linux 文件格式 小精灵 内核模式
2021-07-06 18:11:35

我最近读到内核和动态加载器主要处理program header tablesELF 文件中的 ,而汇编器、编译器和链接器处理section header tables.

程序头表和节头表的数量在 ELF 头中分别命名为e_phnum和 的字段中提及 e_shnume_phnum是两个字节的大小,所以如果程序头的数量 > 65535,我们使用一种称为extended numberingwhere的方案e_phnum设置为 0xffff 并且sh_link第零节头表的字段保存实际计数。

我的疑问是:

如果程序头的数量超过 65535,这是否意味着内核和/或动态加载器最终必须读取节表?

1个回答

我刚刚检查了 linux 内核加载 ELF 函数(loading_elf_binary),我发现如果e_phnum > (65536U / sizeof(struct elf_phdr))e_phnum < 1,当前加载例程将停止(第 613-615 行),不会加载 ELF 文件:

610         /* Now read in all of the header information */
611         if (loc->elf_ex.e_phentsize != sizeof(struct elf_phdr))
612                 goto out;
613         if (loc->elf_ex.e_phnum < 1 ||
614                 loc->elf_ex.e_phnum > 65536U / sizeof(struct elf_phdr))
615                 goto out;
616         size = loc->elf_ex.e_phnum * sizeof(struct elf_phdr);
617         retval = -ENOMEM;
618         elf_phdata = kmalloc(size, GFP_KERNEL);
619         if (!elf_phdata)
620                 goto out;

参考:http : //lxr.free-electrons.com/source/fs/binfmt_elf.c

此外,ELF32/64 中程序头 (e_phnum) 的数量始终为 16 位变量

203 typedef struct elf32_hdr{
204   unsigned char e_ident[EI_NIDENT];
205   Elf32_Half    e_type;
206   Elf32_Half    e_machine;
207   Elf32_Word    e_version;
208   Elf32_Addr    e_entry;  /* Entry point */
209   Elf32_Off     e_phoff;
210   Elf32_Off     e_shoff;
211   Elf32_Word    e_flags;
212   Elf32_Half    e_ehsize;
213   Elf32_Half    e_phentsize;
214   Elf32_Half    e_phnum;
215   Elf32_Half    e_shentsize;
216   Elf32_Half    e_shnum;
217   Elf32_Half    e_shstrndx;
218 } Elf32_Ehdr;
219 
220 typedef struct elf64_hdr {
221   unsigned char e_ident[EI_NIDENT];     /* ELF "magic number" */
222   Elf64_Half e_type;
223   Elf64_Half e_machine;
224   Elf64_Word e_version;
225   Elf64_Addr e_entry;           /* Entry point virtual address */
226   Elf64_Off e_phoff;            /* Program header table file offset */
227   Elf64_Off e_shoff;            /* Section header table file offset */
228   Elf64_Word e_flags;
229   Elf64_Half e_ehsize;
230   Elf64_Half e_phentsize;
231   Elf64_Half e_phnum;
232   Elf64_Half e_shentsize;
233   Elf64_Half e_shnum;
234   Elf64_Half e_shstrndx;
235 } Elf64_Ehdr;

定义数据类型如下:

9 typedef __u16   Elf32_Half;
16 typedef __u16   Elf64_Half;

参考:http : //lxr.free-electrons.com/source/include/uapi/linux/elf.h#L263

因此,同样在 e_phnum 值无效的情况下(无效的 ELF 文件),e_phnum 的最大值为 65535。

希望这有帮助!