Heap 0x04

发布时间 2023-07-19 02:40:46作者: Lu0

系统的开始学一下堆领域的利用和攻击,首先是Fastbin

似乎现在利用fastbin的攻击应该只有2.23的libc了,从Ubuntu18--libc2.27开始就加入了tcache机制,从早到晚推着来吧O。o

这篇有点属于是笔记的那么一种感觉,代码文件思想来源于https://blog.csdn.net/qq_41202237/article/details/109199077
调试过程来源于自己的gdb,大伙要看的时候也最好自己调调,还挺好玩的

Fastbin attack

堆溢出的领域感觉比栈溢出难了不止一个阶级,在溢出之后我们就不像栈一样简单的控制rip,在这更是在和ptmalloc的各种机制斗智斗勇一样。。我的意思是,虽然这个攻击叫这个名字利用的是这个东西但是也是要有一些基础漏洞形如堆溢出、uaf

Fastbin Double Free

从fastbin的机制上来说,它使用单向链表来维护chunk,且prev_inuse不会置空

经过很长时间的努力现在终于可以随便调各种libc了,跟着网上师傅的帖子写了一个

   gcc -g df1.c -o df1
#include<stdio.h>
   int main(void)
   {   
       void *chunk1,*chunk2,*chunk3;
       chunk1 = malloc(0x30);
       chunk2 = malloc(0x30);
       chunk3 = malloc(0x30);
       
      free(chunk1);
      free(chunk2);
      free(chunk3);
      return 0;
}

我们在line10 13下两个断点,看一下

image

这里我们看到了申请的3个chunk,释放之后应该是这样的

image
image

已经看到了单向链表与不置空的过程了
接下来写一个这样的东西去看一下double free:

   #include<stdio.h>
   int main(void)
   {   
       void *chunk1,*chunk2,*chunk3;
       chunk1 = malloc(0x10);
       chunk2 = malloc(0x10);
       
       
      free(chunk1);
      free(chunk2);
      free(chunk1);
      return 0;
}

把断点打在return0之前,这样会看到两个chunk在这里互相指着对方

image
image

但是实际上这个过程和pwndbg里面的显示是不那么对应的,看上去很模棱两可
向左指着的那个白色的箭头总会有一种很强烈的误导感,本来它应该是一个提示“该chunk是第一个进入/该chunk前没有被释放的chunk”这个东西的(毕竟我们是在调试安全问题,可能显示上面和我们要理解要利用的有一些出入),实际的情况大概是这样:

Main-->double(chunk1)-->chunk2-->chunk1

然后我们写这样的一个文件来跑一个更细致的过程:

 #include<stdio.h>
   
   typedef struct _chunk
   {
       long long pre_size;
       long long size;
       long long fd;
       long long bk;
  } CHUNK,*PCHUNK;
  
  CHUNK bss_chunk;
  
  int main(void)
  {
      void *chunk1,*chunk2,*chunk3;
      void *chunk_a,*chunk_b;
  
      bss_chunk.size=0x21;
      chunk1=malloc(0x10);
      chunk2=malloc(0x10);
  
      free(chunk1);
      free(chunk2);
      free(chunk1);
  
      chunk_a=malloc(0x10);
      *(long long *)chunk_a=&bss_chunk;
      malloc(0x10);
      malloc(0x10);
      chunk_b=malloc(0x10);
      printf("%p",chunk_b);
      return 0;
  }

经过上述的分析+自行调试,我们可以知道在double free之后fastbin中大概是这个样子:

Main_arena-->double(chunk1)-->chunk2-->chunk1

此时我们的chunk已经全部释放,如果再次申请,就会先把chunk1(的替身?)拿出来
所以我们申请一次且声明为chunk a,然后此时我们做了一个小动作,将chunk a的内容改为我们之前声明的bss段的模拟chunk的地址,对于chunk a来说的话只是改动了数据而已,但是chunk a实际上就是chunk1,chunk a的数据段起始也同样是chunk1的fd指针位置(替身影响本体,我们的这一修改实际上是改掉了chunk1的fd,让fastbin的布局发生了一点变化:

Main_arena-->double(chunk1)此处已经被启用-->chunk2-->chunk1-->bss段伪造chunk

我们知道bss段上的只是我们模拟出的chunk而非一个真的chunk,但是经过布局过后,它已经被chunk1的fd指针指到了,程序在接下来的malloc申请过程中会将此处也当做一个chunk启用:

image

再经过两次申请过程后,我们看到fastbin中确实还剩着一个“chunk”,但是这个chunk实际上已经属于我们伪造的chunk的范畴了,如果我们当时改的地址不是这个bss而是其他地方,例如可写的某些地址,那就相当于是构造出了一个任意地址写

image

继续执行,我们可以看到第四次申请的chunk b的地址已经是bss段chunk的地址了。

Conclusion

Double free的手段个人总结起来就是利用程序自身的申请与释放构建替身,再通过修改替身的方式来影响到本体,个人觉得堆方面的很多利用手段都有点重合于套娃的核心思想,套来套去可能套出一个x级指针就改掉什么东西了,就绕过什么检查了,就伪造出chunk了,就任意地址写了balabala...

个人有感而发,纯瞎编的X_X