首页
社区
课程
招聘
[原创] Safe-Linking机制分析及绕过
发表于: 2020-9-11 10:11 8048

[原创] Safe-Linking机制分析及绕过

2020-9-11 10:11
8048

下载glibc引入Safe-Linking机制版本:

编译:

指定glibc编译poc代码:

安装pwngdb,之后就可以愉快地调试了。

打算从glibc 2.32引入Safe-Linking 保护,将堆块头部保存的地址重新计算,具体计算过程如下:

将指针的地址右移PAGE_SHIFT 再和指针本身异或,如下,L为指针的地址,P为指针本身,该操作是可逆的,取指针时再做一次操作就可以还原得到原来的指针:

上述这种方法相当于对指针进行了随机化,有点像linux 内核下CONFIG_SLAB_FREELIST_HARDENED的缓解机制,CONFIG_SLAB_FREELIST_HARDENED的计算是:

在 kmem_cache 增加了一个unsigned long类型的变量random。

主要就是泄漏L>>12的值,通过构造堆块,使得chunkC被包含在一个大堆块中,有两个指针同时指向chunkC,造成UAF,释放一个chunkC指针到tcache中,此时chunkC为tcache中第一个bin,fd引入补丁前填充的是0,此时因为Safe-Linking,P' = L >> 12 ^ P = L >> 12 ^ 0 = L >> 12。所以fd填充的是L>>12的值,所以通过另一个chunkC指针就可以泄露该值,后续将目标地址和L12异或计算填充到fd,就可以达到任意地址的读写。

以下demo代码最终效果是将arbitrary_variable变量改写成0x112233445566。并且没有Safe-Linking的引入,demo代码也能达到相同效果,因为此时泄露出来的L>>12为0,目标地址和0异或还是正确的地址。

综上所述,要绕过Safe-Linking主要就是泄露L的信息。其实如果能泄露堆的地址也可以。

(1)首先将tcachebin_0xa0全部填满:

(2)再释放chunkB后,chunkB就会进入unsorted bin中

(3)覆盖chunkD的pre_size为0x140,size为0xa0,并填充 chunkD[0x98] = '\x21';

(4)伪造chunkB的size为0x141,再释放chunkD,就会将chunkD当成0xa0大小的堆块进行释放,并和之前chunkB进行合并,得到0x140+0xa0=0x1e0的unsorted bin,将chunkC包含其中:

(5)将0x1e0大小的chunkB分割成junk(就是最开始的chunkB)和chunkC2(即最开始的chunkC),此时chunkC和chunkC2同时指向同一个堆块,释放chunkC2后,进入tcachebin_0xa0,fd填充的是L>>12的值

(6)泄露得到L>>12的值,伪造要分配的目标堆块地址,将arbitrary_variable变量包含在堆块中。重新申请chunkC3,此时chunkC和chunkC3指向同一个堆块

(7)修改chunkC的fd为伪造的目标堆块地址,利用house of spirit ,分配到该堆块,就可以修改arbitrary_variable变量的值。

完整demo代码如下:

每个线程通过一个tcache_perthread_struct线程本地变量保存tcache bin以及相关的chunk计数。tcache_perthread_struct的初始化过程如下,在分配堆块时,会先分配tcache_perthread_struct结构体,大小为0x290,在堆块的最开始位置。

tcache_perthread_struct的结构如下:

count是一个字节数组(共64个字节,对应64个tcache链表),其中每一个字节表示的是tcache每一个链表中有多少个元素。entries是一个指针数组(共64个元素,对应64个tcache链表, tcache bin中最大为0x400字节),每一个指针指向的是对应tcache_entry结构体的地址。

如果我们能够修改tcache_perthread_struct这个结构体的内容,就可以完全控制malloc的内存分配。

(1)因为tcache_perthread_struct结构体,在堆块的最开始位置,可以通过计算偏移,通过当前堆块的地址减去偏移,得到tcache_perthread_struct的地址。

(2)在释放一个堆块后,会在堆块的bk位置填充tcache_perthread_struct的地址。

houseofio.c

上述demo还是需要泄露得到tcache_perthread_struct结构体的地址,以下的demo不需要:

houseofstructuredio.c

另一个类似的demo,只是不通过释放再重新申请得到tcache_perthread_struct结构体,而是直接修改tcache_perthread_struct结构体:

houseofiostructuaf.c

在uclibc-ng中引入的补丁:e4dK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4L8$3N6K6i4K6u0W2N6$3q4D9k6r3g2E0j5i4u0Q4x3X3c8T1M7X3!0V1K9$3!0J5j5W2)9J5k6h3c8W2i4K6u0r3L8%4y4K6i4K6u0r3N6h3y4D9K9h3u0U0i4K6u0V1L8X3N6Q4x3V1k6U0L8$3#2E0K9i4c8Q4x3V1j5^5z5o6j5^5y4K6S2T1x3U0t1@1x3U0c8V1y4X3j5&6y4h3u0U0k6r3g2W2k6e0f1#2j5h3c8S2y4K6t1H3y4o6W2V1x3U0p5#2y4o6N6U0 就是在取p->fd和存放p->fd时都改成调用REVEAL_PTR

bd8K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6J5k6i4y4W2j5i4u0U0K9q4)9J5k6h3y4Z5k6h3y4C8M7r3!0A6L8Y4c8Q4x3X3g2U0L8$3#2Q4x3V1j5J5x3o6t1H3i4K6u0r3M7$3q4X3k6g2)9J5k6r3I4A6L8X3E0A6L8X3N6Q4x3X3c8W2L8r3W2E0K9h3&6S2N6r3W2F1k6#2)9J5k6r3q4Q4x3X3b7J5x3q4)9J5k6s2W2W2j5i4u0Q4x3X3c8G2L8r3c8Q4x3X3c8E0j5h3I4D9L8$3y4Q4x3X3c8W2P5s2m8D9L8$3W2@1i4K6u0V1M7s2u0A6L8h3W2@1K9i4k6W2i4K6u0r3 机制介绍

863K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2J5k6i4y4W2j5i4u0U0K9r3W2F1L8X3!0$3j5i4c8A6L8$3&6K6i4K6u0W2j5$3!0E0i4K6u0r3M7r3!0K6N6q4)9J5c8X3u0&6M7r3q4K6M7$3W2F1k6#2)9J5k6s2c8Z5k6g2)9J5k6s2g2H3j5$3!0E0K9h3&6Y4i4K6u0V1M7$3q4X3k6g2)9J5k6r3I4A6L8X3E0A6L8X3N6Q4x3X3c8E0K9i4c8A6k6$3q4@1K9h3!0F1 机制绕过


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 4
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回