runtime 分类结构体_64位ret2_dl_runtime_resolve模版题以及踩坑记录

什么是ret2dl攻击

  • 当程序在第一次加载某个函数的时候,got表中对应的表项还没有写入真实的地址(因为是第一次调用),所以这个时候就需要调用_dl_runtime_resolve函数将真实的地址写入got表对应的表项中,然后将控制权交还这个函数,此时就完成了第一次的调用,got表中也有了对应的真实地址。

整个调用过程梳理

_dl_fixup之前

  • 当我们第一调用read时,他的跳转过程是read@plt -> read@got -> read@plt -> plt[0] -> _dl_runtime_resolve_xsave -> _dl_fixup

76d284203e83021701f988c009ff124f.png

我们可以再看一下0x4004e0到底是什么。

3c3281b56f521b034131eccb88ec9236.png

已知 <read@plt> 是plt中的第一个函数,那么0x4004e0就是plt[0]即plt的首项。这里对应两条汇编,第一条实际上做了一个push操作,他负责将一个参数压栈。这里需要实际解释一下:在_dl_runtime_resolve_xsave中实际调用了_dl_fixup而忽略掉宏定义,这个函数是: ```c / This function is called through a special trampoline from the PLT the first time each PLT entry is called. We must perform the relocation specified in the PLT of the given shared object, and return the resolved function address to the trampoline, which will restart the original call to that address. Future calls will bounce directly from the PLT to the function. /DL_FIXUP_VALUE_TYPE attribute_hidden __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE _dl_fixup (struct link_map *l, ElfW(Word) reloc_arg)
```

可以看到一共有两个参数:struct link_map *l, ElfW(Word) reloc_arg,然后我们再回过来看刚刚的代码,其实两个push就是做了参数压栈

7b7e6cf34d09e2b9a726870ee2d58320.png

_dl_fixup进入以后

  • 嗯这、这里是关键,我们一步步分析一下_dl_fixup源代码。在这之前,我们先要研究一下几个重要的section和段。

.dynamic

8e0c938fda72601384fe57777a003e9c.png

.dynamic是动态链接中非常重要和经典的一个段。首先看一下ELF64_Dyn的结构如下:

// 该结构都有 64 位程序和 32 位程序的区别,不过大致结构相似,此处只讨论 64 位程序中的
// /usr/include/elf.h
typedef struct
{
    
Elf64_Sxword d_tag; /* Dynamic entry type */
// d_tag 识别该结构体表示的哪一个节,通过以此字段不同来寻找不同的节
    union
    {
    
        Elf64_Xword d_val; /* Integer value */
        // 对应节的地址,用于存储该结构体表示下的节所在的地址
        Elf64_Addr d_ptr; /* Address value */
    } d_un;

} Elf64_Dyn;

而在.dynamic之中有几个重要的section如下: | d_tag类型 | d_un含义 | | ------ | ------ | | DT_SYMTAB | 动态链接符号表的地址,d_ptr指向".dynsym"的地址 | | DT_STRTAB | 动态链接字符串表的地址 ,d_ptr指向".dynstr"的地址 | | DT_JMPREL | 动态链接重定位表的信息,d_ptr指向".rel.plt"地址 | | DT_VERSYM | .gnu.version的节的位置 |

.dynsym

3bc0e26da9eecad91543bcd5e43e1eae.png

其中,ELF64_Sym结构体为:

typedef struct
{
    
Elf64_Word st_name; /* Symbol name (string tbl index) */
// 保存着该函数函数名在 .dynstr 中的偏移,可以结合 .dynstr 找到准确函数名。
unsigned char st_info; /* Symbol type and binding */
unsigned char st_other; /* Symbol visibility */
Elf64_Section st_shndx; /* Section index */
Elf64_Addr st_value; /* Symbol value */
// 如果这个符号被导出,则存有这个导出函数的虚拟地址,否则为NULL.
Elf64_Xword st_size; /* Symbol size */
} Elf64_Sym;

.dynstr

1a91aa27050fcfd74cd5c7a33804d97b.png

.rel.plt

24a2c53f2d10544c0890ff83078cc62c.png

其中,ELF64_Rela结构体为:

typedef struct {
    
           Elf64_Addr r_offset; //保存的是应用重定位操作的偏移量。对于一个重定位文件,这个值是从节开始到受重定位影响的存储单元的偏移量。对于一个可执行或共享目标文件,这个值是受重定位影响的存储单元的虚拟地址。
           uint64_t   r_info;   //This member gives both the symbol table index with respect to which the relocation must be made and the type of relocation to apply. 
           int64_t    r_addend; //指定了一个附加的常数用来去计算保存在重定位位置的值。
       } Elf64_Rela;

link_map结构

struct link_map
  {
    
    ElfW(Addr) l_addr;                /* Base address shared object is loaded at.  */
    char *l_name;                     /* Absolute file name object was found in.  */
    ElfW(Dyn) *l_ld;                  /* Dynamic section of the s
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值