常见的五个程序头讲解
PT_LOAD程序头
PT_LOAD描述了段的类型。一个可执行文件至少要有一个PT_LOAD类型的段。这类程序头描述的是可装的段,也就是说,这种类型的段会被装载或者映射到内存中。
比如,有一个需要动态链接的ELF可执行二进制文件通常包含以下两个可装载的段(类型为PT_LOAD):
存放程序代码的text段
存放全局变量和动态链接信息的data段
上面的两个段将会被映射到系统内存中,根据p_align中存放的值在系统内存中对齐。建议去阅读一下Linux的ELF手册,以便理解Phdr结构体中所有变量的含义,这些变量描述了段在文件和内存中的布局。
text段(也称代码段)的权限设为PF_X | PF_R(读和可执行)。
data段的权限设为PF_W | PF_R(读和写)。
如果感染了千面人病毒(polymorphic virus)文件的text段或data段的权限会被修改,然后通过在程序头的段标记在(p_flags)处增加PF_W标记来修改text段的权限。
PT_DYNAMIC----动态段的 Phdr
动态段是动态链接可执行二进制文件所特有,包含了动态链接器必要的一些信息。在动态段中包含了标记值和指针,包括不限于以下的内容:
运行时需要链接的共享库列表
全局偏移表(GOT)的地址 //在后续的动态链接讲解部分会进行讨论
重定位条目的相关信息
下面完整的标记名列表:
标记名 标记名描述
DT_HASH //符号散列表的地址
DT_STRTAB //字符串表的地址
DT_SYMTAB //符号表地址
DT_RELA //相对地址重定位表的地址
DT_RELASZ //Rela表的字节大小
DT_RELAENT //Rela表条目的字节大小
DT_STRSZ //字符串表的字节大小
DT_SYMENT //符号表条目的字节大小
DT_INIT //初始化函数的地址
DT_FINI //终止函数的地址
DT_SONAME //共享目标文件名的字符串表偏移量
DT_RPATH //库搜索路径的字符串表偏移量
DT_SYMBOLIC //修改链接器,在可执行文件之前的共享目标文件中搜索符号
DT_REL //Rel relocs表的地址
DT_RELSZ //Rel表的字节大小
DT_RELENT //Rel表条目的字节大小
DT_PLTREL //PLT引用的reloc类型(Rela或Rel)
DT_DEBUG //还未进行定义,为调试保留
DT_TEXTREL //缺少此项表明重定位只能应用于可写段
DT_JMPREL //仅用于PLT的重定位条目地址
DT_BIND_NOW //指示动态链接器在将控制权交给可执行文件之前处理所有的重定位
DT_RUNPATH //库搜索路径的字符串表偏移量
动态段包含了一些结构体,这些结构体里面存放了关于与动态链接相关的信息。d_tag成员变量控制着d_un的含义。
下列是32位elf二进制文件的动态段结构体:
typedef struct{
Elf32_Swordd_tag;
union{
Elf32_Word d_val;
Elf32_Addr d_ptr;
} d_un;
} Elf32_Dyn;
extern Elf32_Dyn _DYNAMIC[ ];
还会继续对动态链接进行更深入的学习
PT_NOTE
PT_NOTE这个段指向了一个以”null”结尾的字符串,这个字符串包含一些附加的信息。
有的时候一些供应商或者系统构建者需要在一些目标文件上标记特定的信息,方便用于其他程序对一致性、兼容性等进行检查。SHT_NOTE类型的节(section)和PT_NOTE类型的程序头就可以用在这个目的上。
这个段同时也是最容易被病毒感染的的一个地方。
同时这个段也可以称为注释段,还了包含一些辅助信息。
PT_INTERP
PT_INTERP这个段包含一个路径字符串,也是路径存放解释器
PT_INTERP段还将位置和大小信息存放在一个以null为终止符的字符串中,这是是对程序解释器位置的描述。
比如,/lib/linux-ld.so.2这个路径也是指动态链接器的位置,也就是程序解释器的位置。
PT_PHDR
PT_PHDR此段位于elf文件的第一个段。PT_PHDR段保存了程序头表本身的位置和大小。phdr表则保存了所有的phdr对文件和内存镜像中段的描述信息。
我们可以使用readelf工具来进行查看:
readelf -l
如下:
Elf 文件类型为 DYN (共享目标文件)
Entry point 0x1070
There are 12 program headers, starting at offset 52
程序头:
TypeOffsetVirtAddrPhysAddrFileSiz MemSizFlg Align
PHDR0x000034 0x00000034 0x00000034 0x00180 0x00180 R0x4
INTERP0x0001b4 0x000001b4 0x000001b4 0x00013 0x00013 R0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD0x000000 0x00000000 0x00000000 0x00430 0x00430 R0x1000
LOAD0x001000 0x00001000 0x00001000 0x00284 0x00284 R E 0x1000
LOAD0x002000 0x00002000 0x00002000 0x00144 0x00144 R0x1000
LOAD0x002ef4 0x00003ef4 0x00003ef4 0x0012c 0x00130 RW0x1000
DYNAMIC0x002efc 0x00003efc 0x00003efc 0x000f0 0x000f0 RW0x4
NOTE0x0001c8 0x000001c8 0x000001c8 0x00078 0x00078 R0x4
GNU_PROPERTY0x0001ec 0x000001ec 0x000001ec 0x00034 0x00034 R0x4
GNU_EH_FRAME0x002018 0x00002018 0x00002018 0x0003c 0x0003c R0x4
GNU_STACK0x000000 0x00000000 0x00000000 0x00000 0x00000 RW0x10
GNU_RELRO0x002ef4 0x00003ef4 0x00003ef4 0x0010c 0x0010c R0x1
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
原文始发于微信公众号(Kone安全):常见的五个ELF二进制程序头讲解
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论