elf之link map攻击
字数 2063 2025-08-23 18:31:25

ELF Link Map 攻击技术详解

1. 基本概念

1.1 ELF 文件与 Link Map

ELF (Executable and Linkable Format) 文件中的 Link Map 是链接器生成的一个详细的内存布局文件,展示了链接过程中各个段的地址、大小和符号表信息。它描述了程序在内存中的布局,包括:

  • 哪些符号被导入、导出
  • 各个节(如 .text、.data、.bss)的内存地址
  • 依赖库的加载顺序等

1.2 攻击类型

在 pwn 领域,有两种专门针对 link map 的攻击方式:

  1. 栈上的 ret2dl-resolve 攻击
  2. 堆上的 house of banana 攻击

2. ret2dl-resolve 攻击

2.1 基本特征

  • 最大特征:不提供 libc
  • 不能使用 patchelf 修改 elf 文件,因为会移动延迟绑定相关的结构

2.2 关键结构

利用的相关结构主要有四个:

  1. .dynamic 段

    • 作用:包含动态链接器需要的配置信息
    • 内容:存储一系列键值对,如依赖的共享库(DT_NEEDED)、重定位表位置(DT_REL/DT_RELA)等
  2. .dynstr 段

    • 作用:存储动态符号表中用到的符号和库的字符串信息
    • 内容:包含动态符号的名称字符串和共享库名称字符串
  3. .dynsym 段

    • 作用:动态符号表,包含所有动态符号(如全局变量和函数)的相关信息
    • 内容:每个条目包含符号的名称、类型、地址等
  4. .rel.plt 段

    • 作用:包含与PLT相关的重定位信息,用于延迟绑定
    • 内容:存储了待重定位符号的索引和重定位类型

2.3 延迟绑定过程

  1. 调用PLT表:首次调用外部函数时跳转到PLT表入口
  2. PLT跳转到.rel.plt中的重定位项
  3. 读取.dynsym和.dynstr找到函数实际地址
  4. 完成解析并将地址写入GOT

2.4 关键结构体

Dyn 结构体

typedef struct {
    Elf32_Sword d_tag;  // Dynamic entry type
    union {
        Elf32_Word d_val;  // Integer value
        Elf32_Addr d_ptr;  // Address value
    } d_un;
} Elf32_Dyn;

Sym 结构体

typedef struct {
    Elf32_Word st_name;   // Symbol name (string tbl index)
    Elf32_Addr st_value;  // Symbol value
    Elf32_Word st_size;   // Symbol size
    unsigned char st_info; // Symbol type and binding
    unsigned char st_other; // Symbol visibility
    Elf32_Section st_shndx; // Section index
} Elf32_Sym;

Rel 结构体

typedef struct {
    Elf32_Addr r_offset;  // Address
    Elf32_Word r_info;   // Relocation type and symbol index
} Elf32_Rel;

link_map 结构体

struct link_map {
    ElfW(Addr) l_addr;  // Difference between the address in the ELF file and the addresses in memory
    ElfW(Dyn) *l_info[DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM + DT_ADDRNUM];
    // ... other members
};

2.5 _dl_fixup 函数分析

_dl_fixup 是延迟绑定机制的核心函数,其关键逻辑:

  1. 获取符号表地址
  2. 获取字符串表地址
  3. 获取函数对应的重定位表结构地址
  4. 获取函数对应的符号表结构地址
  5. 判断重定位表类型必须为 ELF_MACHINE_JMP_SLOT(7)
  6. 根据 ELFW(ST_VISIBILITY)(sym->st_other) 的值决定重定位策略

2.6 32位程序攻击方法

方法一:改写.dynamic的DT_STRTAB

  • 条件:NO RELRO(.dynamic可写)
  • 原理:修改.dynstr字符串表指针到可控内存,伪造函数名

方法二:操纵第二个参数伪造Elf32_Rel

  • 条件:.dynamic不可写时使用
  • 原理:伪造.rel.plt、.dynsym和.dynstr结构

2.7 64位程序攻击方法

64位下由于地址范围问题,选择 ELFW(ST_VISIBILITY)(sym->st_other) 不为0时的执行流程:

  1. resolve函数传入第二个参数为0
  2. Elf64_Rel的r_offset加上link_map->l_addr指向可读写内存
  3. Elf64_Rel的r_info的低32位设为7
  4. l_info[5]指向可读写内存
  5. r_info的高32位设为0
  6. link_map->l_info[6]->d_un.dptr指向puts@got - 8
  7. link_map的l_addr设置为&system - &puts

3. house of banana 攻击

3.1 基本概念

  • 劫持的是rtld_global结构体中的link_map指针
  • 类似于exit_hook攻击,但exit_hook在2.34之后失效

3.2 rtld_global 结构

struct rtld_global {
    // ...
    struct link_namespaces {
        struct link_map *_ns_loaded;
        unsigned int _ns_nloaded;
        struct r_scope_elem *_ns_main_searchlist;
        // ... other members
    } _dl_ns[DL_NNS];
    size_t _dl_nns;
    // ... other members
};

3.3 _dl_fini 函数逻辑

  1. 遍历_dl_ns数组
  2. 将_ns_loaded链表中的元素放入maps数组
  3. 遍历maps数组,调用符合条件的函数

3.4 伪造link_map的关键点

  1. 令l_real指针指向link_map结构体自身
  2. link_map链表中的元素个数为4(_ns_nloaded默认为4)
  3. l_init_called位置1
  4. 绕过_dl_sort_maps函数的检查

3.5 示例利用代码

from pwn import *

context.log_level = 'debug'
io = process('./pwn')
elf = ELF('./pwn')
libc = ELF('libc-2.27.so')

# ... 省略部分代码 ...

rtld_global = libc_base + 0x62a060
link_map3 = rtld_global + 0x1ccfb8
one_gadget = libc_base + 0x4f302

# 伪造link_map结构
fake_addr = heap_base + 0xb90
payload = p64(0)*3 + p64(fake_addr)
payload = payload.ljust(0x48-0x10, b'\x00') + p64(fake_addr+0x58) + p64(8) + p64(one_gadget)
payload = payload.ljust(0x110-0x10, b'\x00') + p64(fake_addr+0x40)
payload = payload.ljust(0x120-0x10, b'\x00') + p64(fake_addr+0x48)
payload = payload.ljust(0x314-0x10, b'\x00') + p64(0x1c)

# 触发exit调用链
io.sendlineafter('Your choice:\n', str(5))
io.interactive()

4. 防御措施

  1. Full RELRO:使.dynamic段不可写
  2. 地址随机化(ASLR):增加预测地址难度
  3. 堆保护机制:检测堆结构完整性
  4. 高版本glibc中对rtld_global的保护

5. 总结

ELF link map攻击技术提供了在特定条件下绕过常规防护的手段:

  1. ret2dl-resolve适用于无libc泄露的场景
  2. house of banana适用于高版本glibc的堆利用
  3. 两种方法都需要对ELF结构和动态链接过程有深入理解

理解这些攻击技术有助于更好地设计防御措施和编写安全的代码。

ELF Link Map 攻击技术详解 1. 基本概念 1.1 ELF 文件与 Link Map ELF (Executable and Linkable Format) 文件中的 Link Map 是链接器生成的一个详细的内存布局文件,展示了链接过程中各个段的地址、大小和符号表信息。它描述了程序在内存中的布局,包括: 哪些符号被导入、导出 各个节(如 .text、.data、.bss)的内存地址 依赖库的加载顺序等 1.2 攻击类型 在 pwn 领域,有两种专门针对 link map 的攻击方式: 栈上的 ret2dl-resolve 攻击 堆上的 house of banana 攻击 2. ret2dl-resolve 攻击 2.1 基本特征 最大特征:不提供 libc 不能使用 patchelf 修改 elf 文件,因为会移动延迟绑定相关的结构 2.2 关键结构 利用的相关结构主要有四个: .dynamic 段 作用:包含动态链接器需要的配置信息 内容:存储一系列键值对,如依赖的共享库(DT_ NEEDED)、重定位表位置(DT_ REL/DT_ RELA)等 .dynstr 段 作用:存储动态符号表中用到的符号和库的字符串信息 内容:包含动态符号的名称字符串和共享库名称字符串 .dynsym 段 作用:动态符号表,包含所有动态符号(如全局变量和函数)的相关信息 内容:每个条目包含符号的名称、类型、地址等 .rel.plt 段 作用:包含与PLT相关的重定位信息,用于延迟绑定 内容:存储了待重定位符号的索引和重定位类型 2.3 延迟绑定过程 调用PLT表:首次调用外部函数时跳转到PLT表入口 PLT跳转到.rel.plt中的重定位项 读取.dynsym和.dynstr找到函数实际地址 完成解析并将地址写入GOT 2.4 关键结构体 Dyn 结构体 Sym 结构体 Rel 结构体 link_ map 结构体 2.5 _ dl_ fixup 函数分析 _dl_fixup 是延迟绑定机制的核心函数,其关键逻辑: 获取符号表地址 获取字符串表地址 获取函数对应的重定位表结构地址 获取函数对应的符号表结构地址 判断重定位表类型必须为 ELF_ MACHINE_ JMP_ SLOT(7) 根据 ELFW(ST_VISIBILITY)(sym->st_other) 的值决定重定位策略 2.6 32位程序攻击方法 方法一:改写.dynamic的DT_ STRTAB 条件:NO RELRO(.dynamic可写) 原理:修改.dynstr字符串表指针到可控内存,伪造函数名 方法二:操纵第二个参数伪造Elf32_ Rel 条件:.dynamic不可写时使用 原理:伪造.rel.plt、.dynsym和.dynstr结构 2.7 64位程序攻击方法 64位下由于地址范围问题,选择 ELFW(ST_VISIBILITY)(sym->st_other) 不为0时的执行流程: resolve函数传入第二个参数为0 Elf64_ Rel的r_ offset加上link_ map->l_ addr指向可读写内存 Elf64_ Rel的r_ info的低32位设为7 l_ info[ 5 ]指向可读写内存 r_ info的高32位设为0 link_ map->l_ info[ 6]->d_ un.dptr指向puts@got - 8 link_ map的l_ addr设置为&system - &puts 3. house of banana 攻击 3.1 基本概念 劫持的是rtld_ global结构体中的link_ map指针 类似于exit_ hook攻击,但exit_ hook在2.34之后失效 3.2 rtld_ global 结构 3.3 _ dl_ fini 函数逻辑 遍历_ dl_ ns数组 将_ ns_ loaded链表中的元素放入maps数组 遍历maps数组,调用符合条件的函数 3.4 伪造link_ map的关键点 令l_ real指针指向link_ map结构体自身 link_ map链表中的元素个数为4(_ ns_ nloaded默认为4) l_ init_ called位置1 绕过_ dl_ sort_ maps函数的检查 3.5 示例利用代码 4. 防御措施 Full RELRO:使.dynamic段不可写 地址随机化(ASLR):增加预测地址难度 堆保护机制:检测堆结构完整性 高版本glibc中对rtld_ global的保护 5. 总结 ELF link map攻击技术提供了在特定条件下绕过常规防护的手段: ret2dl-resolve适用于无libc泄露的场景 house of banana适用于高版本glibc的堆利用 两种方法都需要对ELF结构和动态链接过程有深入理解 理解这些攻击技术有助于更好地设计防御措施和编写安全的代码。