前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ROP-Ret2dl_resolve学习(1)

ROP-Ret2dl_resolve学习(1)

作者头像
偏有宸机
发布2020-11-04 10:16:50
8300
发布2020-11-04 10:16:50
举报
文章被收录于专栏:宸机笔记

利用原理

该方法的主要原理是利用dl_runtime_resolve函数来对动态链接的函数进行重定位。

在linux下,ELF想要调用动态函数库中的函数,为了避免没必要的消耗,而采用了延迟绑定的方法,其核心思想就是函数用到时才对该函数进行绑定(符号查找及重定位),如果没有用到便不会绑定,以便减少资源的消耗。

运作机制

以图为例

过程

由于延迟绑定机制,所以在第一次调用puts函数时,0x80496f8内并没有存放着真实的write地址,而是跳转到了下一条指令上。

然后push 0再跳转到PLT表的头部,再push 0x80496f0,最后跳转到dl_runtime_resolve函数上

push0,和0x80496f0正是dl_runtime_resolve的两个参数reloc_arglink_map

  • reloc_arg=0是要调用的函数也就是puts在重定向链接表(.rel.plt)中的偏移
  • link_map=0x80496f0则是指向了.dynamic节(GOT+4),使之可以访问到.dynamic

而dl_runtime_resolve函数内实际上是由_dl_fixup实现的,上面的两个参数也都是传到了这个函数里面

代码语言:javascript
复制
_dl_fixup源代码如下:
_dl_fixup(struct link_map **l*, ElfW(Word) *reloc_arg*)
{
  *//* *首先通过参数**reloc_arg**计算重定位入口,这里的**JMPREL**即**.rel.plt**,**reloc_offset**即**reloc_arg*
  const PLTREL *const reloc = (const void *) (D_PTR (l, l_info[DT_JMPREL]) + reloc_offset);
  *//* *然后通过**reloc->r_info**找到**.dynsym**中对应的条目*
  const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (reloc->r_info)];
  *//* *这里还会检查**reloc->r_info**的最低位是不是**R_386_JUMP_SLOT=7*
  assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);
  *//* *接着通过**strtab+sym->st_name**找到符号表字符串,**result**为**libc**基地址*
  result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, l->l_scope, version, ELF_RTYPE_CLASS_PLT, flags, NULL);
  *// value**为**libc**基址加上要解析函数的偏移地址,也即实际地址*
  value = DL_FIXUP_MAKE_VALUE (result, sym ? (LOOKUP_VALUE_ADDRESS (result) + sym->st_value) : 0);
  *//* *最后把**value**写入相应的**GOT**表条目中*
  return elf_machine_fixup_plt (l, result, reloc, rel_addr, value);
}

总结一下_dl_fixup 函数的过程

通过link_map参数得出.rel.plt`.dynsym\.dynstr`三个表的地址

  1. 然后通过reloc_arg(_dl_fixup参数)+.rel.plt(起始地址) 计算出函数在.rel.plt(重定向链接表)中偏移后的地址,记作reloc
  2. 然后通过函数在reloc(重定向链接表)中的info参数索引(忽略掉最后两位)来找到它在.dynsym(符号表)中的位置,记作sym
  3. 之后通过函数在sym(符号表)中的st_name,来确定它在.dynstr(字符串表)中的名字,记作result,而result也就是libc的基地址
  4. 最后通过result(基地址)+sym->st_value(偏移量,在符号表中的st_value的值)得出函数的真实地址,记作value
  5. 最最后将value写入到函数在GOT表地址内

ELF文件结构概括及readelf

文章中所接触到的三个表都存在于PT_DYNAMIC段的.dynamic节中,下面以readelf来说一下这三个表的主要作用

以图为例

.rel.dyn和.rel.plt

.rel.dyn 用于变量重定位

.rel.plt 用于函数重定位,包含了链接C库的函数

例如:wirte函数

  • r_offset=0x401c
  • r_info=0x807

那么就可以通过r_info去掉最后两位07来确定write在符号表中的位置

.dynsym

包含了动态链接符号表

.dynsym[8]指向的就是write函数,而value的值则是该函数的偏移量

.dynstr

字符串表节区包含了以\x00结尾的字符序列,通常称为字符串

Ret2dlresolve学习(2)(https://cloud.tencent.com/developer/article/1740197)

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-02-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 利用原理
  • 运作机制
    • 以图为例
      • 过程
      • ELF文件结构概括及readelf
        • 以图为例
          • .rel.dyn和.rel.plt
            • .rel.dyn 用于变量重定位
            • .rel.plt 用于函数重定位,包含了链接C库的函数
          • .dynsym
            • .dynstr
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档