ELF文件分析(八) 动态链接之辅助向量
0x01 辅助向量
当内核加载器把程序加载到内存中时,对应可执行文件会被映射到内存中的一片地址空间,同时加载器也会为该进程分配栈、堆等空间。而本次的话题辅助向量(auxv)就是存放在栈上的一组数据,其作用是为动态链接器提供信息。
1. 内存布局
可以查看下这张实例图,栈顶在低地址的范围,按照顺序分别是:
1 | [argc][argv][envp][auxv][.ascii data for argv/envp] |
2. 表项结构
1 | # 通过gdb断点然后获取auxv信息,前提是_start开始,如果使用链接器脚本修改会失效 |
表项的结构如下图所示,你可以参考glibc的elf.h文件了解相关的宏定义
1 | typedef struct |
下面列出比较重要的一些a_type
AT_NULL
一般是最后一个表项的类型,a_val一般未定义,不关心
AT_EXECFD
程序的文件描述符,a_val保存着该字符串地址值
AT_PHENT
程序头表项的大小
AT_PHNUM
程序头表项的数量
AT_PAGESZ
系统页表大小
AT_ENTRY
程序入口点位置,a_val保存着该地址值
AT_BASE
程序基地址
AT_UID
程序的实际UID信息,在权限访问控制中发挥非常重要的作用
AT_GID
程序的实际GID信息
AT_EUID
程序的有效UID信息
AT_EGID
程序的有效GID信息
3. 实例
运行gdb获取auxv的信息如下:
0x02 寻找与解析辅助向量数组
基本的代码依然在我的仓库中可以找到,解析辅助向量数组这里提供三种方法:
- 从
/proc/<pid>/auxv中读取并解析 - 从envp结束的NULL后进行读取并解析
- 通过getauxval函数进行读取并解析
我们主要来来看看第二种方法,直接从栈上进行解析
1 | // 方法3: 直接从栈上访问 auxv (通过main参数) |
代码主要的逻辑就是通过envp来找到辅助向量的位置,然后进行打印。
0x03 小问题
关于辅助向量
- 如果能直接修改辅助向量,能实现程序权限上的变化吗?
- 在IDA中调试程序,观察栈上的布局,指出argc、argv、envp和auxv的位置
- 为什么辅助向量中有程序入口点和基地址信息,没有这些程序能正常工作吗?