在linux内核把ELF文件加载到内存中时,如果此ELF含有动态链接信息就会去解析并加载相应的依赖库。ELF动态链接信息保存在.dynamic节区中,类型为DT_NEEDED的项描述了对应的依赖库信息。
注入思路
- 先将文件末尾进行填充对齐,然后将.dynamic节区移动到文件末尾并增加一个DT_NEEDED类型的项
- 将Program header table移动到文件末尾,并增加一个类型为PT_LOAD类型的项,指向文件末尾新填充的区域
- 将.dynstr字符串表移动到文件末尾,增加需要注入的动态库的字符串信息
- 修复ELF文件中的各个字段
手动增加依赖库
- 将文件末尾填充对齐,然后将.dynamic节区移动到末尾并在开头增加类型为DT_NEEDED的项,此项第二个字段为新的.dynstr字符串表中对应新增加依赖库的字符串偏移
- 新的program header table中尾部新增加PT_LOAD类型的项,此项指向文件尾部新增加的数据,因为此部分需要加载到内存中。
然后先修正ELF文件头中的e_phoff为新的program header table在文件中的偏移,因为新的program header table增加了一个LOAD段所以e_phnum增加1
新的program header table的第一项为PT_PHDR类型,其指向自身所以需要修正指向新的program header table
新的program header table中在最后新增加了PT_LOAD类型的项,此项是为了将文件尾部新增加的数据加载到内存,所以其修正为指向文件尾部新增加的区域
新的.dynamic节区中还保存了各个.dynstr字符串表的偏移个大小信息,因为.dynstr字符串表已经移动到文件尾部并修改,所以需要进行修正。
(这里需要特别注意的是,.dynamic 的STRTAB 05类型的项中保存的是.dynstr字符串表的虚拟地址偏移,不是文件偏移)
实际到这里就可以结束了,但是为了让readelf 可以解析出文件的信息,需要把section中的.dynamic和.dynstr对应的节区头信息修正一下。
-
修正.dynamic的section header
-
修正.dynstr的section header
效果
利用readelf查看增加了依赖库的ELF文件的program header table信息。发现新增加了一个PT_LOAD类型的段,并且此段中包含了.dynamic和.dynstr节区
查看.dynamic中的动态链接信息,发现libhello.so被加入了依赖库列表
运行程序发现我们在文件末尾新增加的PT_LOAD段被map到内存中
查看进程map表发现libhello.so已经map到了内存空间中