ELF与动态链接
2022-10-24 15:56:58
217
{{single.collect_count}}

ELF与动态链接

ELF文件

  • 一种Linux下常用的可执行文件
  • ELF中的数据按照Segment和Section两个概念来划分
  • Segment
    • 用于告诉内核,在执行ELF文件时应该如何映射内存
    • 每个Segment主要包含加载地址,文件中的范围,内存的权限,对齐方式
    • 是运行时必须提供的信息
  • Section
    • 用于告诉链接器,ELF中每个部分是什么,哪里是代码,哪里是只读数据,哪里是重定位信息
    • 每个Section主要包含Section类型,文件中的位置,大小等信息
    • 链接器依赖Section信息将不同的对象文件的代码,数据信息合并,并修复互相引用
  • Segment与Section的关系
    • 相同权限的Section会放入同一个Segment
    • 一个Segment包含许多Section,一个Section可以属于多个Segment

ELF文件格式

  • ELF Header
    • 架构,ABI版本等基础信息
    • program header table的位置和数量
    • section header table的位置和数量
  • Program header table
    • 每个表项定义了一个segment
    • 每个segment可包含多个section
  • Section header table
    • 每个表项定义了一个section

动态链接

  • 例如在调用libc库中的时,由于动态链接在运行时才会加载,那么一开始我们并不知道要调用的函数在哪,这是需要用到重定位

  • 重定位:

    • 指二进制文件中的待填充项
      • 链接器在链接时填充,例如链接多个目标文件时,修正互相应用的函数,变量地址
      • 动态链接器在运行时填充,例如动态解析库函数printf
  • 动态链接中的延迟绑定

    • 外部函数的地址在运行时才会确定
    • 外部函数符号通常在首次调用时才会被解析
    • 外部变量不使用延迟绑定机制
  • 原因:当整个程序调用了多个外部函数时,在一开始就绑定了所有外部函数这样会影响运行速度。

  • 目的:按需解析,提高效率

GOT表

  • GOT表常常用于存放外部库函数地址或局部变量(就是一些待填充项)

  • GOT表项初始状态指向一段PLT代码

  • 当库函数被首次调用,真正的函数地址会被解析并填入相应的GOT表项

  • 每个外部函数均有一段独立的PLT代码,用于跳转到相应GOT表项中存储的地址

以调用printf函数为例:

​ 最初代码编译时并不会去找printf函数在哪,只是知道要调用libc库(待填充项),运行到含有printf函数的代码时,就会去GOT表里查找。可以从GOT查找到一段PLT代码,通过这段代码去找到printf函数。然后将printf函数的地址存到GOT表中,下次再调用printf只需在GOT表上查找即可

  • .got Section中存放外部全局变量的GOT表,采用非延迟绑定

  • .got.plt Section中存放外部函数的GOT表,采用延迟绑定

  • .got.plt前三项有特殊含义,第四项开始保存引用的外部函数的

  • .plt Section存放了所有外部函数对于的PLT代码

延迟绑定

1.调用了一个外部函数foo call foo@plt

2.跳转至foo@GOT处的地址,实际指向下一条指令,即foo@plt+6 jmp *(foo@GOT)

3.将符号’foo’的符号入栈 push index

4.调用dl_runtime_resolve(link_map, index),这时会把foo()函数的真实地址填入GOT表

5.再次调用foo()函数时只需

GOT表劫持

  • 延迟绑定机制要求GOT表必须可写

  • 内存漏洞可导致GOT表项被改写,从而劫持PC

  • 例:GOT表内本来应该是foo()函数地址的地方,但是由于恶意修改现在指向了system函数。

  • 如何防御GOT表劫持

    • 重定位只读缓解措施

      • 编译选项:gcc -z,relro

      • 在进入main()之前,所有的外部函数都会被解析

      • 所有GOT表设置为只读

      • 绕过方法:

        ​ 1.劫持为开启该保护的动态库中的GOT表(例如libc中的GOT表)

        ​ 2.改写函数返回地址或是函数指针

回帖
全部回帖({{commentCount}})
{{item.user.nickname}} {{item.user.group_title}} {{item.friend_time}}
{{item.content}}
{{item.comment_content_show ? '取消' : '回复'}} 删除
回帖
{{reply.user.nickname}} {{reply.user.group_title}} {{reply.friend_time}}
{{reply.content}}
{{reply.comment_content_show ? '取消' : '回复'}} 删除
回帖
收起
没有更多啦~
{{commentLoading ? '加载中...' : '查看更多评论'}}