ELF文件格式第三讲,节头(section header)
一丶节头
1.1 概念简介
段(segment) 和 节(section)是有区别的。 节不是段。 段是程序执行的必要组成部分。 在每个段中会有代码或者数据被划分为不同的节。 而 节头表 则是对这些节的位置和大小的描述,主要是用于链接和调试。
因为节头表没有对程序的内存布局进行描述,对程序内存布局的描述的是 程序头表(第二讲)的任务。 所以
节头表就是对程序头的补充。所以我们将“节头表”都填充为无用的值的话程序还是可以正常启动的。 虽然可以修改,但是随着版本的升级,保不准以后会使用。 就跟window平台上的最小PE一样,在xp下可以是100kb以下。win7下则对各个表的限制更严格了。所以需要100kb以上。 win10同理。 所以节头表以后可能会使用。
readelf -l 显示一个段对应有那些节。 很直观的可以看到节和段的关系。
readelf -S
......
Section to Segment mapping:
段节...
00
01 .interp
02 .interp .note.gnu.build-id .note.gnu.property .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt
03 .init .plt .text .fini
04 .rodata .eh_frame_hdr .eh_frame
05 .init_array .fini_array .dynamic .got .got.plt .data .bss
06 .dynamic
07 .note.gnu.build-id .note.gnu.property .note.ABI-tag
08 .note.gnu.property
09 .eh_frame_hdr
10
11 .init_array .fini_array .dynamic .got
1.2 节头和节
如果二进制文件中缺少了 节头 ,并不意味着节是不存在的。只是没有办法通过节头来引用节了,对于调试器或者反编译(IDA)程序来说,参考的信息就变少了。
每一个节都保存了某种类型的代码和数据。 数据可以是程序中的全局变量,也可以是连接器所需要的动态链接的信息。 这点跟windows平台的 windowsPE文件格式设计很像。 节头可以被抹除,默认的ELF文件是有节头的。
如果节头被抹除,那么 objcopy objdump gdb IDA 等工具就可能无法使用。
而节头表中的 .dynsym这样的节(记录了函数名和偏移地址,导入导出等符号)就无法分析。进而就增大了逆向的难度。
1.3 节头 结构
- 结构
/* Section Header */
typedef struct {
Elf32_Word sh_name; /* name - index into section header
string table section */
Elf32_Word sh_type; /* type */
Elf32_Word sh_flags; /* flags */
Elf32_Addr sh_addr; /* address */
Elf32_Off sh_offset; /* file offset */
Elf32_Word sh_size; /* section size */
Elf32_Word sh_link; /* section header table index link */
Elf32_Word sh_info; /* extra information */
Elf32_Word sh_addralign; /* address alignment */
Elf32_Word sh_entsize; /* section entry size */
} Elf32_Shdr;
typedef struct {
Elf64_Half sh_name; /* section name */
Elf64_Half sh_type; /* section type */
Elf64_Xword sh_flags; /* section flags */
Elf64_Addr sh_addr; /* virtual address */
Elf64_Off sh_offset; /* file offset */
Elf64_Xword sh_size; /* section size */
Elf64_Half sh_link; /* link to another */
Elf64_Half sh_info; /* misc info */
Elf64_Xword sh_addralign; /* memory alignment */
Elf64_Xword sh_entsize; /* table entry size */
} Elf64_Shdr;
- 字段含义如下
索引为0的表是 (SHN_UNDEF) 尽管这个表的意义是未定义的节区应用。
这个节区固定的值为如下:
010Edit中的取值为如下:
-
字段类型
类型定义结果如下
-
sh_flag字段
此字段定义了一个节区中包含的内容是否可以修改,是否可以执行的信息。 如果一个标志位被设置,则该位取值为1. 定义的各位都设置为0
SHF_EXECINSTR: 节区包含可执行的机器指令。
SHF_MASKPROC: 所有包含于刺眼吗中的四位都用于处理器专用的语义
在32 or 64下字段还增加了
typedef enum <Elf32_Xword> {
SF32_None = 0x0, 无
SF32_Exec = 0x1, 执行
SF32_Alloc = 0x2, 此节区执行过程中占用内存。某些控制接续并不会出现于目标文件的内存映像中,对于那些节区此值为0
SF32_Alloc_Exec = 0x3,
SF32_Write = 0x4, 写
SF32_Write_Exec = 0x5, 写执行
SF32_Write_Alloc = 0x6, 写内存
SF32_Write_Alloc_Exec = 0x7
} s_flags32_e;
typedef enum <Elf64_Xword> {
SF64_None = 0x0,
SF64_Exec = 0x1,
SF64_Alloc = 0x2,
SF64_Alloc_Exec = 0x3,
SF64_Write = 0x4,
SF64_Write_Exec = 0x5,
SF64_Write_Alloc = 0x6,
SF64_Write_Alloc_Exec = 0x7
} s_flags64_e;
-
节区类型于字段
根据节区类型的不同,那么s_link s_info也是不同的。
如下表
1.4特殊节区
下图是系统中使用的节区以及他们的类型和属性。 简单概括图。