glibc-2.27-how2heap学习

学习参考how2heap,主要用于理解不同版本glibc机制

tcache_dup

思想:2.27引入的tcache机制将当前chunk放进tcache bin时没有检查当前chunk是否在tcache bin中,即是否已经被释放过,单纯地double free 再malloc 两次可以获得指向同一内存区域的两个指针

tcache_house_of_spirit

思想:hos思想参考安全客
相关代码:

#if USE_TCACHE
  {
    size_t tc_idx = csize2tidx (size);

    if (tcache
	&& tc_idx < mp_.tcache_bins
	&& tcache->counts[tc_idx] < mp_.tcache_count)
      {
	tcache_put (p, tc_idx);
	return;
      }
  }
#endif

_int_free释放大小属于tcache的chunk时没有对其是否属于arena的chunk做检查,故可以伪造任意chunk,将其链入tcache
漏洞作用:

  1. 分配任意地址
tcache_poisoning

思想:利用漏洞修改tchache bin中的chunk的fd指针,使其指向目标地址

tcache_stashing_unlink_attack

相关代码

//从small bin中取
  if (in_smallbin_range (nb))
    {
      idx = smallbin_index (nb);
      bin = bin_at (av, idx);

	  // 先执行 victim = last(bin),获取 small bin 的最后一个 chunk
		   // 如果 victim = bin ,那说明该 bin 为空。
		   //如果不相等,small bin中存在空闲chunk

      if ((victim = last (bin)) != bin)
        {
          bck = victim->bk;
		  //检查机制
	  if (__glibc_unlikely (bck->fd != victim))
	    malloc_printerr ("malloc(): smallbin double linked list corrupted");
			//取出chunk,做处理
	  		set_inuse_bit_at_offset (victim, nb);
          bin->bk = bck;
          bck->fd = bin;

          if (av != &main_arena)
	    set_non_main_arena (victim);
          check_malloced_chunk (av, victim, nb);
#if USE_TCACHE
	  /* While we're here, if we see other chunks of the same size,
	     stash them in the tcache.  */
	     //glibc2.27引入的stash机制,如果当前chunk对应的smallbin中存在chunk,则将其放入tcahce中直到tcache满
	  size_t tc_idx = csize2tidx (nb);
	  if (tcache && tc_idx < mp_.tcache_bins)
	    {
	      mchunkptr tc_victim;

	      /* While bin not empty and tcache not full, copy chunks over.  */
	      while (tcache->counts[tc_idx] < mp_.tcache_count
		     && (tc_victim = last (bin)) != bin)
		{
		  if (tc_victim != 0)
		    {
		    //从small bin里取chunk,通过的是bk指针
		      bck = tc_victim->bk;
		      set_inuse_bit_at_offset (tc_victim, nb);
		      if (av != &main_arena)
			set_non_main_arena (tc_victim);
		      bin->bk = bck;
		      bck->fd = bin;

		      tcache_put (tc_victim, tc_idx);
	            }
		}
	    }
#endif
          void *p = chunk2mem (victim);
          alloc_perturb (p, bytes);
          return p;
        }
    }

思想:参考安全客
利用了glibc以下几个特性

  1. 通过控制smallbin last chunk的bk指针,使其指向目标地址
  2. 程序绕过tcache机制,直接向small bin寻取chunk(calloc)
  3. malloc从fastbin或者smallbin取到chunk后,若对应大小tcachebin存在空位,则将chunk嵌入tcache bin

漏洞利用

  1. 修改链表头chunk(bin->fd)的bk指针,同时需要保留chunk的fd指针**(bypass __glibc_unlikely (bck->fd != victim ))**,故需要leak heap
  2. 程序需要使用calloc绕过tcache 向small bin寻求chunk,触发stash unlink,将small bin 放入tcache

漏洞作用:

  1. 改写某一地址为指定值
  2. 向任意地址分配一个Chunk。
fastbin_dup

思路:程序很简单,申明8个同样大小的chunk,释放7个,释放的chunk会填充对应大小的tchche bin,再calloc 3个chunk,分别为a,b,c,,其中c的作用是防止free(b)时,b与top chunk 合并,之后free(a),free(b),free(a),double free a两次之后,fastbin上 顺序为 a->b->a,此时继续calloc 3次,则可以获得a两次。

这里其实有个小tips,就是程序使用的是calloc而不是malloc,单纯地用malloc替换calloc,程序并不会对得到其想要的结果,这里我并没有阅读calloc源码,但是可以猜测calloc直接跳过 tcache bin,去fastbin寻找合适的chunk,而malloc则是按照tcache bin->fastbin->small bin-> unsorted bin-> large bin->top chunk去寻找合适的大小。

fastbin_reverse_into_tcache

思路:这里利用的最主要的思想:tcache bin和fastbin属于LIFO,,同时,malloc从fastbin上获取chunk时,会把fastbin中其余大小的chunk放到其对应的tcache bin中,而在tcache bin中的顺序与在fastbin中的顺序相反,因为把chunk从fastbin移出时,会首先拿去最后释放的,而这个chunk放到tcache bin中成了最先放入的,也就是最后释放的。
程序通过以下步骤完成漏洞利用

  1. malloc 足够多的chunk
  2. free chunks以填充tcache bin
  3. 再free掉一个victim chunk,由于tcache bin被填满,其落入fastbin
  4. 释放其余chunk(这一步释放多个或者1个取决于目标fake chunk的fd指针)
  5. 通过其余漏洞修改victim 的fd指针,使其指向目标地址
  6. malloc一次,由于fastbin的LIFO,申请得到的是fastbin上的最后放入的chunk
  7. glibc机制使得其余fastbin中的chunk依次放入对应大小的tcache bin中,由于victim的fd指向目标地址,故其被最后放入tcache bin
  8. 再malloc一次获取到目标地址
unsafe_unlink

思路:unsafe_unlink解释参考安全客,其适用于除了fastbin与tcachebin以外的bin,因为处于fastbin和tcache bin中的chunk,其pre_inuse永远为1
漏洞利用點

  1. 构造fake chunk,其中fake chunk的fd为target address -0x18,bk为target address-0x10(bypass (P->fd->bk != P || P->bk->fd != P) == False )
  2. fake chunk中需要构造next chunk的prev_size (bypass chunksize§ != prev_size (next_chunk§)
  3. 存在堆溢出,可以改写待unlink chunk的next chunk,将其prev_inuse位置0
  4. free next chunk

作用

  1. 改变全局指针指向,使其指向自身-0x18处,通常用于该heap指针数组,填充相关got
unsorted_bin_attack

原理:参考CTFWiki-unsorted-bin-attack
思路:这个漏洞的利用思路很简单,即利用其余漏洞(如堆溢出)覆写存放在unsorted bin中的chunk的bk指针,将其改为目的地址-2*sizeof(byte),从而程序从unsorted bin中拿出chunk时,会依据如下程序逻辑,将移出chunk的下一个chunk(bck)的fd指针改为unsorted_chunks (av);这也就是为什么我们修改bk值为目标地址-2*sizeof(byte);这里通过 unlink 将 libc 的信息写入到我们可控的内存中,从而导致信息泄漏,为进一步的攻击提供便利。

          /* remove from unsorted list */
          if (__glibc_unlikely (bck->fd != victim))
            malloc_printerr ("malloc(): corrupted unsorted chunks 3");
          unsorted_chunks (av)->bk = bck;
          bck->fd = unsorted_chunks (av);
unsorted_bin_into_stack

思路:利用思路同unsorted_bin_attack,只是将victim的大小修改的比接下来要申请的chunk大小小(因为chunk会切片),并且将victim的bk修改为目标地址,同时目标地址处需要构造fake chunk,将其bk指针指向fake chunk自身,在下一次 malloc 的时候,malloc 会顺着 bk 指针进行遍历,于是就找到了大小正好合适的 fake chunk:fake chunk 被取出,而 victim chunk 被从 unsorted bin 中取出来放到了 small bin 中。另外值得注意的是 fake chunk 的 fd 指针被修改了,这是 unsorted bin 的地址,通过它可以泄露 libc 地址

large bin attack

思路:利用的是将unsorted bin中的chunk链入large bin中时的各种解链加链操作,修改已在large bin中chunk的bk和bk_nextsize指针
利用前提

  1. 可以修改large bin中chunk的大小、bk、bk_nextsize,修改其大小小于待放入chunk的大小,修改bk指针为&target_address-0x10,修改bk_nextsize为&target_address-0x20
  2. 从 unsorted bin 中来的 large bin chunk 要紧跟在被构造过的 chunk 的后面
overlapping_chunks

这个思想还是很好理解的,通过某些漏洞修改进入unsorted bin中的chunk的大小,使其覆盖某一chunk。

mmap_overlapping_chunks

思想,这个思想还是很好理解的,只不过有一些细节需要注意

  1. malloc 向mmap区域申请chunk时,chunk的地址时从高往低去分配的
  2. free mmap区域的chunk,实际上调用的是munmap,改变chunk3的size大小,同时需要改变metadata的m位,使其覆盖chunk2,并且释放chunk3时,chunk2和chunk3都被系统收回了,所以这时候直接对chunk2进行读写会导致程序崩溃
  3. 要想再次能够读写chunk2,需要再次malloc一次大内存,同时这一次malloc的值需要大于free掉的mmap区域的内存的最大值;满足上述要求后,则同时具有指向chunk2的两个指针,这时可以执行后续操作。
poison_null_byte

详细步骤可以参考pzhxbz的Blog

house_of_botcake

思想:精心构造chunk,使得victim chunk落在tcache bin中,通过改变victim的fd,获得任意地址读权限
主要步骤有以下几点

  1. 填充满tcache bin
  2. malloc 两个chunk:prev和victim,并且free掉victim,victim(因为tcache bin满了)落入unsorted bin中,接着free prev,使得malloc_consolidate被调用,合并后的chunk落在unsorted bin中,且chunk地址为prev地址
  3. 通过malloc()使得tcache bin有空位,并且通过free(victim)将victim放入tcache bin中(因为victim大小满足tcache bin的大小)
  4. 再次tmp=malloc(size),其中size应该大于prev的大小+0x20,程序进入unsorted bin中寻找chunk,并将unsorted bin中的chunk 切片,并将切片剩余的chunk(放在unsorted bin中,这里为什么不放在small bin?
  5. malloc得到的tmp包含部分victim地址,通过tmp改写victim的fd指针,由于victim位于tcache bin中,修改了fd指针便实验了任意地址分配的能力。
house_of_einherjar

思想:通过off_by_one修改next chunk的pre_inuse位,精心构造next chunk的prev_size,使得free(next_chunk)时通过后向合并(合并低地址chunk),可以将chunk指向任意地址。

house_of_force

原理参考
CTFWiki-HOF
主要思想

  1. 修改top chunk大小为很大的值,从而使得我们申请多大的chunk都不会走mmap
  2. 计算目标地址与当前top chunk的距离,公式为

/*
* The evil_size is calulcated as (nb is the number of bytes requested + space for metadata):
* new_top = old_top + nb
* nb = new_top - old_top
* req + 2sizeof(long) = new_top - old_top
* req = new_top - old_top - 2sizeof(long)
* req = dest - 2sizeof(long) - old_top - 2sizeof(long)
* req = dest - old_top - 4*sizeof(long)
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值