首页
社区
课程
招聘
[原创]ret2dlresolve分析
发表于: 6小时前 212

[原创]ret2dlresolve分析

6小时前
212

该方法最大的作用在无法泄露libc时可以调用libc中的函数,其本质是向一个地址,写入一个值,而这两个部分都可以在一定程度上被控制的。

分析源码前,先看一些相关的结构体与宏。

该节存放了许多Elf64_Dyn结构体,在IDA中位于got表的上面,保存了动态链接器所需要的基本信息,比如存放了ELF文件其他节的标识和起始地址。结构体定义如下所示。

其中关键字d_tag定义如下:

该节存放了许多Elf64_Rela结构体,是对函数引用的修正,修正的位置在got.plt表,每个libc库函数都有自己的Elf64_Rela结构体。在程序入口附近,位于LOAD段。

r_info是一个复合值,其高32位表示该重定位项在动态链接符号表.dynsym中对应项的下标低32位表示该重定位项的重定向类型

重定位类型(Relocation Types)

32位ELF一般用来函数重定位的重定位类型就是R_386_JMP_SLOT类型,64位ELF函数重定位的重定位类型就是R_X86_64_JUMP_SLOT类型,源码对其的注释是Create PLT entry。这种类型的函数重定位都会在ELF中创建一个PLT入口

该节,用于普通动态重定位,程序加载时处理,常见定位项:

其中结构体也为Elf64_Rela

该节存放了许多Elf64_Sym结构体,同样地,每个libc函数都有自己的Elf64_Sym。在程序入口附近,位于LOAD段。

st_info大小为 1 Btyes,高4位表示符号的绑定特征,低4位表示符号类型。

绑定特征(高四位)

绑定特征0,1,2均可取。

符号类型(低四位)

变量、函数分别取1, 2 即可。

那么稍微总结一下得到st_info取值的一般规律如下:

节头表

即字符串表(STRTAB),该节存放的是libc函数的符号名,就是一个一个的字符串,诸如此类'exit'、'read'。在程序入口附近,位于LOAD段。

link_mapglibc 动态链接器 ld-linux 用来描述“一个已加载 ELF 对象”的核心结构体

一个进程里每加载一个 ELF 对象,就会有一个对应的 struct link_map

它们通过链表串起来:

该结构体在 ld 中。

无pie示例:

开pie实例:

ELFW( 是 glibc / ELF 代码里常见的宏,用来根据当前平台自动选择 32 位 ELF 类型/宏64 位 ELF 类型/宏

找 .dynamic 中的 tab 的地址

计算符号 ref 的运行时地址。

elf中的link_map与_dl_runtime_resolve_xsavec()指针在.bss段中.got段开头


下图省略所有被调用函数,调试模块,部分结构体,绿色为常规执行(判断返回为 ture),红色为可控执行流,蓝色为相加

该方法最大的作用在无法泄露libc时可以调用libc中的函数,其本质是向一个地址,写入一个值,而这两个部分都可以在一定程度上被控制:

该利用并不只限制于覆盖got表段,可以覆盖任意位置可被覆盖(可写)的能被调用的函数指针,然后调用 libc 任意位置的代码片段(内核未开启ibt保护时)。

汇编层面,延迟绑定第一次执行函数执行流如下:

所以,有如下两种触发方式:

触发前栈布局:

出发后栈布局:

该模式下,上如所有表段中的结构体可写

有任意写可以根据以上执行流,覆盖任意偏移进行利用;
只有溢出,需泄露pie或无pie,泄露 ld 地址,伪造link_map

这种情况下思路比较广泛,只需知道调用过程、各结构体位置,就可以根据具体情况利用。

该模式下,所有表段不可被写,但是.bss段的link_map_dl_runtime_resolve_xsavec()的指针可以被写

有任意写,可以覆盖.bss段指针,伪造link_map
只有溢出,需泄露pie或无pie,需泄露 ld 地址,伪造link_map

伪造link_map

根据上面的执行流,可以有如下的利用思路:

通过将sym结构体伪造在got表附近,使st_valuest_other命中合适位置

使st_other非 0 ,将执行流导向非常规流程(红色)

使vt_value为已经被写过的 libc 函数入口地址,此时link_map为通过参数传入的link_map,通过l_addr调整偏移,到目标代码段地址

由于调整了传入的link_mapl_addr,所以在写rela结构体时,需将r_offset设置为target - l_addr

以上思路,只是需要一个共享器内的地址,以及其版本,就能通过偏移计算调用共享器中的函数,调用 ld 的思路相同。

当开启FULL_RELERO时,整个GOT表将标记为read-only,并且所有的外部引用变量/函数都将在程序装载时由动态链接器解析完成。

此时.got.plt表中的第二项 表项GOT[1]装载的link_map地址 以及第二项 表项GOT[2]装载的dl_runtime_resolve函数地址将是0。

所以此时,利用方式与上面完全一样,仍然可以在.got表进行伪造,只是很难泄露 ld 的地址。

下面介绍一个结构体:


[培训]《冰与火的战歌:Windows内核攻防实战》!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 230
活跃值: (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
参考:58bK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2@1k6i4y4@1P5X3g2J5L8#2)9J5k6s2N6*7i4K6u0W2j5$3!0E0i4K6u0r3x3U0l9J5x3W2)9J5c8U0l9K6i4K6u0r3x3o6g2Q4x3V1k6d9k6i4b7J5k6r3I4J5k6i4y4G2L8s2k6W2i4K6t1#2c8e0u0Q4x3U0f1^5x3q4)9J5y4e0V1@1i4K6t1#2c8e0u0Q4x3U0f1^5x3q4)9J5y4e0V1@1i4K6t1#2c8e0c8Q4x3U0g2n7b7W2)9J5y4e0S2q4e0X3!0Q4x3X3c8d9c8f1I4d9e0#2)9J5y4f1f1#2i4K6t1#2z5o6S2Q4x3U0g2n7x3p5k6g2e0p5I4Q4x3X3c8d9c8f1I4d9e0#2)9J5c8W2)9J5x3$3k6#2L8r3I4Q4y4h3k6J5k6h3I4W2M7X3)9`.
4d1K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2U0L8X3u0D9L8$3N6K6i4K6u0W2j5$3!0E0i4K6u0r3f1%4c8S2z5s2t1&6i4K6u0r3M7q4)9J5c8U0p5%4y4K6x3J5z5e0j5#2i4K6u0W2K9s2c8E0L8l9`.`.
4小时前
0
游客
登录 | 注册 方可回帖
返回