ELF格式解读 Dynamic节
Posted 不会写代码的丝丽
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ELF格式解读 Dynamic节相关的知识,希望对你有一定的参考价值。
前言
首先抛出一个问题,假设程序A需要动态库中的函数funb
,那你你怎么知道这个函数在哪个动态库中?以及我们加载器怎么知道我们是否启用延迟加载还是立即加载?
为了解决以上问题ELF
推出了一个节名为.Dynamic
,里面包含很多信息比如你需要的动态库,以及是否立即加载以及符号表等。在got表的第一项指像.Dynamic
,并且延迟绑定那个的时候需要传入.Dynamic
对象地址,因为里面包含解析函数地址的上下文。
实战
我们看看下main的例子
//main.c
#include <stdio.h>
static int mystaticVar = 3 ;
int myglobalvar=5;
int myglobalvar2=6;
extern void testfun();
int main()
testfun();
printf("hello world %d \\r\\n",mystaticVar);
return 0;
void hell()
testfun();
//test.c
__attribute__((visibility("default"))) void testfun()
__attribute__((visibility("hidden"))) void testfun2()
int libGLobal=2;
编译命令
gcc -fPIC -shared -o test.so test.c
gcc -o main.out main.c test.so
首先我们查看 main.out
相关节
[图1-1]
你会看到一个.dynamic
节,这个节是由多个Elf64_Dyn
组成的
typedef struct
Elf32_Sword d_tag;
union
Elf32_Word d_val;
Elf32_Addr d_ptr;
Elf32_Off d_off;
d_un;
Elf32_Dyn;//32位程序
typedef struct
Elf64_Xword d_tag;
union
Elf64_Xword d_val;
Elf64_Addr d_ptr;
d_un;
Elf64_Dyn;
其中d_tag
决定这个是什么类别信息,以及该如何解析d_un
内部变量。
其中有一个约定如果d_tag
是偶数那么你使用d_ptr
。奇数不包证一定使用d_val
,但大多数情况下是。
d_ptr
: 表示一个虚拟地址
d_val
:需要根据d_tag
才能决定表示的意思
d_tag
有很多类别具体您可参阅Dynamic Section
我们这里举例其中几个常用的d_tag
枚举 | 数值 | 使用d_un字段 |
---|---|---|
DT_NULL | 0 | 不使用 |
DT_NEEDED | 1 | d_val |
DT_STRTAB | 5 | d_ptr |
DT_FLAGS | 30 | d_val |
… | … | … |
DT_NULL:无意义
DT_NEEDED:所需要的动态库,d_val指向字符表的下标(字符表由DT_STRTAB确定)
DT_STRTAB:字符串表,d_ptr是字符串表地址
DT_FLAGS:一些标志位比如是否立即绑定so符号
你可以通过readelf查看这个结构数据解析结果
[图1-2]
我们手动来解析其中一个DT_NEEDED
(test.so)
首先我们看到DT_STRTAB
指向0x488,也就是我们字符串表所在的文件偏移。通过 [图1-1] 得知是.dynstr
这个节.
我们首先显示16进制下 .dynamic 节区数据,下图高亮就是test.so所对应的Elf64_Dyn
[图1-3]
将上面二进制放入数据结构解析
d_tag
:01000000 00000000
d_un
:01000000 00000000
d_tag为1所以是DT_NEEDED
类型,因此d_un
中有意义的字段是d_val,指向字符表的下标。我们上文说过字符串是.dynstr
这个节.
而下标因为为1
所以指向的字符串是746573 742e736f 00
,对应assic就是test.so
.
参考
PWN基础15:GOT表 和 PLT表_prettyX的博客-程序员宅基地
以上是关于ELF格式解读 Dynamic节的主要内容,如果未能解决你的问题,请参考以下文章
Android 逆向ELF 文件格式 ( ELF 程序头入口大小 | ELF 程序头入口个数 | ELF 文件节区头入口大小 | ELF 文件节区头入口个数 | 字符表序号 )