这篇文章介绍了两种tcache的利用方法,tcache dup和tcache house of spirit,两种方法都是用how2heap中的例题作为讲解。由于tcache attack这部分的内容比较多,所以分开几篇文章去写。例题后补,写完例题后可能会进行重新排版,内容不会少的!!!

往期回顾:
好好说话之Tcache Attack(1):tcache基础与tcache poisoning
好好说话之Large Bin Attack
好好说话之Unsorted Bin Attack
好好说话之Fastbin Attack(4):Arbitrary Alloc
(补题)2015 9447 CTF : Search Engine
好好说话之Fastbin Attack(3):Alloc to Stack
好好说话之Fastbin Attack(2):House Of Spirit
好好说话之Fastbin Attack(1):Fastbin Double Free
好好说话之Use After Free
好好说话之unlink

编写不易,如果能够帮助到你,希望能够点赞收藏加关注哦Thanks♪(・ω・)ノ

tcache dup

这种利用方式和前面fastbin attack中的fastbin dup很像,tcache dup利用的是tcache_put()未做安全检查的缺陷,我们来回顾一下tcache_put()函数:

static __always_inline void *
tcache_get (size_t tc_idx)
{tcache_entry *e = tcache->entries[tc_idx];assert (tc_idx < TCACHE_MAX_BINS);assert (tcache->entries[tc_idx] > 0);tcache->entries[tc_idx] = e->next;--(tcache->counts[tc_idx]); return (void *) e;
}

在具备tcache机制的情况下,申请释放内存的时候,_int_free()函数会调用tcache_put()函数,tcache_put()函数会按照size对应的idx将已释放块挂进tcache bins链表中。插入的过程也很简单,根据_int_free()函数传入的参数,将被释放块的malloc指针交给next成员变量。其中没有任何安全检查和保护机制,在大服务提高性能的同时,安全性几乎舍弃了大半

因为没有做任何的检查,所以我们可以对同一个chunk多次free,这就会造成cycliced list。我们在fastbin attack中经常用到

例题:how2heap 中的 tcache_dup

源码如下,做了一些小小的改动,将不重要的输出省略了,不影响正常执行:

  1 //gcc -g -no-pie hollk.c -o hollk2 //glibc_2_27:3 //patchelf --set-rpath 路径/2.27-3ubuntu1_amd64/ hollk4 //patchelf --set-interpreter 路径/2.27-3ubuntu1_amd64/ld-linux-x86-64.so.2 hollk5 #include <stdio.h>6 #include <stdlib.h>7 #include <assert.h>8 9 int main()10 {11         int *a = malloc(8);12 13         free(a);14         free(a);15 16         void *b = malloc(8);17         void *c = malloc(8);18         printf("Next allocated buffers will be same: [ %p, %p ].\n", b, c);19 20         assert((long)b == (long)c);21         return 0;22 }

我们来简单的解读一下这个程序的执行流程:首先创建了一个size为0x20大小的chunk,并将chunk的malloc指针赋给了指针变量a,接下来连续释放了两次chunk_a。然后重新申请了两个size为0x20大小的chunk,并分别将两个chunk的malloc指针付给了指针变量b和指针变量c。最后打印出chunk_b和chunk_c的malloc指针

由于我们在编译的时候使用-g参数,所以在使用gdb进行动态调试的时候可以在对应代码行下断点,首先我们在第13行下断点,看一下已创建的chunk_a的地址在哪:

可以看到chunk_a的头指针为0x602250,fd所在位置为0x602260,接下来我们将断点下在第14行,看一下第一次释放chunk_a后bin中的情况:

由于我们利用patchelf将程序执行的glibc修改为2.27版本,所以是存在tcache机制的,所以第一次释放chunk_a之后会被挂在tcache bin中0x20这条单向链表中。接下来我们将断点下载第15行,再一次释放chunk_a:

首先看上图的上半部分,再次释放chunk_a之后chunk_a的malloc指针又一次被挂进了tcache bin中,我们也可以观察一下gdb给我们的提示,在0x20后有一个标识当前idx链表中chunk的数量,这里显示的是2,tcache_put()函数并没有意识到chunk_a是一个已被释放的chunk,这就造成了cycliced list,chunk_a有指向了自己(是我S了我! )。我们再来看下半部分的chunk_a内部状况,可以看到chunk_a的fd此时指向的是自身的malloc地址。接下来我们将断点下在第17行,看一下重新申请一个0x20大小的chunk时的情况:

可以看到,由于tcache bin中有符合申请size要求的空闲块,所以在申请0x20大小的chunk时,tcache bin中0x20链表最后一个被释放的chunk_a理所应当的被重新启用。这个时候可以看一下gdb标识当前链表中的chunk数量的确从2变为了1,但是chunk_a虽然被启用,链表中依然还会存在chunk_a的malloc指针,这是由于第一次被启用的是第二次被释放的chunk_a

接下来我们间断点下在第20行,完成第二次申请0x20的chunk,并打印出chunk_b和chunk_c的malloc指针:

可以看到打印出的chunk_b和chunk_c的malloc指针都是chunk_a的malloc指针,这是因为chunk_a被释放的两次,第一次申请的chunk_b启用了第二次释放的chunk_a,第二次申请的chunk_c启用了第一次被释放的chunk_a。

总体来说和前面的fastbin attack构造循环单项链表的方式差不多,只是对利用的机制不一样

tcache house of spirit

tcache house of spirit这种利用方式是由于tcache_put()函数检查不严格造成的,在释放的时候没有检查被释放的指针是否真的是堆块的malloc指针,如果我们构造一个size符合tcache bin size的fake_chunk,那么理论上讲其实可以将任意地址作为chunk进行释放。这里就直接采用wiki上面列出的例子进行讲解了:

how2heap中的tcache_house_of_spirit

源码如下,稍作改动,去掉了一些输出语句,不影响正常程序执行流程:

  1 //gcc -g -no-pie hollk.c -o hollk2 //patchelf --set-rpath 路径/2.27-3ubuntu1_amd64/ hollk3 //patchelf --set-interpreter 路径/2.27-3ubuntu1_amd64/ld-linux-x86-64.so.2 hollk4 #include <stdio.h>5 #include <stdlib.h>6 #include <assert.h>7 8 int main()9 {10         setbuf(stdout, NULL);11 12         malloc(1);13 14         unsigned long long *a;15         unsigned long long fake_chunks[10];16 17         printf("fake_chunk addr is %p\n", &fake_chunks[0]);18 19         fake_chunks[1] = 0x40; 20 21         a = &fake_chunks[2];22 23         free(a);24 25         void *b = malloc(0x30);26         printf("malloc(0x30): %p\n", b);27 28         assert((long)b == (long)&fake_chunks[2]);29 }

我们简单的说明一下这个程序的执行流程:首先使用setbuf()函数进行初始化,然后创建了一个堆块,这个堆块的作用其实是为了防止后面的chunk与top chunk合并的。接下来定义了一个指针变量a,还定义了一个整型数组fake_chunk[10]。接下来打印了fake_chunk的起始地址,将fake_chunk[1]中的内容修改成了0x40。接下来将fake_chunk[2]所在地址赋给指针变量a,然后释放a。接着重新申请一个size为0x40大小的chunk,并将其malloc地址赋给指针变量b,最后打印出chunk_b的malloc地址

由于我们在编译阶段使用了-g参数,所以在使用gdb调试过程中可以在代码行下断点。首先我们在第19行下断点,看一下打印出来的fake_chunk[]的起始地址:

可以看到fake_chunk[]的起始地址为0x7fffffffdea0,接下来我们将断点下在第21行,执行fake_chunks[1] = 0x40;这段代码:

fake_chunks[1] = 0x40这段代码修改了fake_chunk[1]中的内容,这其实是一个构造fake_chunk的过程,0x40就是这个fake_chunk的size,接下来我们将断点下在第25行,我们看一下在释放fake_chunk后bin中的状况:

可以看到由于我们使用了patchelf将程序的glibc修改成了2.27版本,所以存在tcache机制,释放的chunk会被挂进tcache bin中。那么由于我们将fake_chunk[2]所在地址赋给了指针变量a,并且free(a)。由于tcache_put()函数没有做任何的安全检查,所以就将fake_chunk看作为一个正常的chunk给释放了。所以我们可以在tcache bin的0x40这条单向链表中看到fake_chunk的malloc指针。接下来我们将断点下在第28行,重新申请一个size为0x40大小的chunk_b,并打印其malloc地址:

可以看到打印出的chunk_b的malloc地址就是fake_chunk的malloc地址。这是由于在tcache bin中的0x40链表里刚好有符合申请size要求的空闲块,这个空闲块就是fake_chunk,所以再次申请的时候fake_chunk作为链表中最后一个chunk,就被重新启用了

例题后补~

好好说话之Tcache Attack(2):tcache dup与tcache house of spirit相关推荐

  1. 好好说话之Tcache Attack(3):tcache stashing unlink attack

    tcache stashing unlink attack这种攻击利用有一个稍微绕的点,就是small bin中的空闲块挂进tcache bin这块.弯不大,仔细想想就好了 往期回顾: 好好说话之Tc ...

  2. 好好说话之Tcache Attack(1):tcache基础与tcache poisoning

    进入到了Tcache的部分,我还是觉得有必要多写一写基础的东西.以往的各种攻击手法都是假定没有tcache的,从练习二进制漏洞挖掘的角度来看其实我们一直模拟的都是很老的环境,那么这样一来其实和真正的生 ...

  3. 好好说话之Fastbin Attack(1):Fastbin Double Free

    好像拖更了好久...实在是抱歉....主要是fastbin attack包含了四个部分,后面的例题不知道都对应着哪个方法,所以做完了例题才回来写博客.fastbin attack应该也会分四篇文章分开 ...

  4. 好好说话之IO_FILE利用(1):利用_IO_2_1_stdout泄露libc

    前言 本来是在做tcache attack的例题的,但是wiki上的challenge2考察的重点不仅仅是在tcache.题目程序中没有输出的功能,所以无法像往常一样去泄露libc,这个时候就需要进行 ...

  5. 好好说话之House Of Einherjar

    前言 又鸽了好久,抱歉哈~ 总的来说House Of Einherjar这种利用方法还是挺简单的,有点像chunk extend/shrink技术,只不过该技术是后向,并且利用top_chunk合并机 ...

  6. 好好说话之Large Bin Attack

    large bin attack这种方法本质上并不难,只是有点绕而已.他和上一篇unsorted bin attack有点类似,都是chunk挂进bin链表的时候通过完成链表结构连接时发生的问题,只不 ...

  7. 好好说话之Use After Free

    到了Use After Free啦,总体来说这种手法并不复杂,特征也很明显,就是在静态分析阶段观察释放chunk之后指针是否置空.本以为参加hw会往后拖更,没想到这么快就写完了.如果前面一直跟着学的话 ...

  8. 如何看当前windows是utf8还是gbk_职场中的OKR如何“好好说话”

    在工作中,经常会遇到各种各样的问题需要沟通,不管是团队内部的,还是跨部分,或者是对上级汇报还是管理下属.我们发现,有些能力很优秀的人,他们讲的内容,别人很快能理解.但是有的人,说了半天,大家也不知道他 ...

  9. ⊱人永远需要两种能力:好好说话和情绪稳定

    昨晚已经躺下,收到朋友的一条微信. 是一张截图,题目是:武昌火车站附近爆发社会恶劣事件--面馆老板因与食客发生口角冲突被砍头断臂,事后扔进垃圾桶. 现场十分血腥,被围观群众拍下迅速在微博等网络媒体上传 ...

最新文章

  1. 毕业三年,贷款40万创业之后我又做回了程序员
  2. 动漫风html源码,CSS3动画制作一个卡通风格的404错误页面代码
  3. OpenCV4Android JavaCameraView实现
  4. spring3.2 aop 搭建 (1)
  5. Android中的一个定时任务的方法
  6. .NET Core 必备安全措施
  7. Mingw编译DLib
  8. linux-noshell的模式
  9. golang基础02
  10. C 编译器、链接器、加载器详解
  11. datagrip连接oracle
  12. Fiddler中文版 软件分享(亲测可用!)
  13. 福昕高级PDF 专业版程序安装及注意事项
  14. matlab 振动,振动系统固有特性的matlab计算
  15. 哈理工OJ 1983 Math(前缀和)
  16. linux安装文泉驿字体,文泉驿的安装及配置
  17. 史上最简单的教程——“21天”自学C语言
  18. 磁力mysql搜索_求一份磁力链接搜索网站的源码,最好能来个大神讲一下这个搜索的原理...
  19. 什么是失血模型和充血模型?(DDD)
  20. 动态内存分配Dynamic allocation(C语言划重点)

热门文章

  1. 【Python】一篇文章学习Pandas包 Pandas Series、DataFrame 对比学习
  2. aspx 微型_如何使用微型可编程机器人向孩子介绍编码
  3. C语言(一):C语言概述介绍
  4. 上界通配符、下界通配符
  5. 13种APP推广手段与渠道
  6. TweenMax特效
  7. Apache Spark源码阅读环境搭建
  8. could not delete: [org.jbpm.pvm.internal.model.ExecutionImpl#20007] 使用jbpm流程结束时出现异常
  9. ElasticSearch 学习笔记(一)
  10. Selenium基于Python web自动化测试框架 —— PO模型