fastbin_dup_consolidate

how2heap fastbin_dup_consolidate

0x01 简介

同样是double free,这次利用了 malloc_consolidate() 函数

0x02 源码分析

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

int main() {
  // malloc 两个相同大小为 0x40 的空间
  void* p1 = malloc(0x40);
  void* p2 = malloc(0x40);
  fprintf(stderr, "Allocated two fastbins: p1=%p p2=%p\n", p1, p2);
  // free p1
  fprintf(stderr, "Now free p1!\n");
  free(p1);
    
  //分配一个large bin来触发malloc_consolidate函数
  void* p3 = malloc(0x400);
  fprintf(stderr, "Allocated large bin to trigger malloc_consolidate(): p3=%p\n", p3);
    
  //通过malloc_consolidate函数我们可以把free掉的p1移动到unsorted bin中
  fprintf(stderr, "In malloc_consolidate(), p1 is moved to the unsorted bin.\n");
  free(p1);
    
  //然后就可以触发double free漏洞了
  fprintf(stderr, "Trigger the double free vulnerability!\n");
  fprintf(stderr, "We can pass the check in malloc() since p1 is not fast top.\n");
  //现在p1既在unsorted bin中又在fastbin中,因此我们再分配两次p1大小的内存,就可以分配到同一款内存
  fprintf(stderr, "Now p1 is in unsorted bin and fast bin. So we'will get it twice: %p %p\n", malloc(0x40), malloc(0x40));
}

0x03 调试

1. 第一次free(p1) 后

pwndbg> heap
0x602000 FASTBIN {
  prev_size = 0, 
  size = 81, 
  fd = 0x0, 
  bk = 0x0, 
  fd_nextsize = 0x0, 
  bk_nextsize = 0x0
}
0x602050 FASTBIN {
  prev_size = 0, 
  size = 81, 
  fd = 0x0, 
  bk = 0x0, 
  fd_nextsize = 0x0, 
  bk_nextsize = 0x0
}
0x6020a0 PREV_INUSE {
  prev_size = 0, 
  size = 135009, 
  fd = 0x0, 
  bk = 0x0, 
  fd_nextsize = 0x0, 
  bk_nextsize = 0x0
}
pwndbg> bins
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x602000 ◂— 0x0 
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
empty
largebins
empty

p1 地址 0x602000,free以后被放到 fastbins中

2.  void* p3 = malloc(0x400); 

malloc_consolidate() 函数是定义在 malloc.c 中的一个函数,用于将 fastbin 中的空闲 chunk 合并整理到 unsorted_bin 中以及进行初始化堆的工作,在 malloc() 以及 free() 中均有可能调用 malloc_consolidate() 函数

在p3 malloc 中就调用了malloc_consolidate() 函数

pwndbg> bins
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
0x50: 0x602000 —▸ 0x7ffff7dd1bb8 (main_arena+152) ◂— 0x602000
largebins
empty

p1 被放到 smallbins 中

关于 malloc_consolidate 函数

   static void malloc_consolidate(mstate av)
{
  mfastbinptr*    fb;                 /* current fastbin being consolidated */
  mfastbinptr*    maxfb;              /* last fastbin (for loop control) */
  mchunkptr       p;                  /* current chunk being consolidated */
  mchunkptr       nextp;              /* next chunk to consolidate */
  mchunkptr       unsorted_bin;       /* bin header */
  mchunkptr       first_unsorted;     /* chunk to link to */
  /* These have same use as in free() */
  mchunkptr       nextchunk;
  INTERNAL_SIZE_T size;
  INTERNAL_SIZE_T nextsize;
  INTERNAL_SIZE_T prevsize;
  int             nextinuse;
  atomic_store_relaxed (&av->have_fastchunks, false);
  unsorted_bin = unsorted_chunks(av);
  /*
    Remove each chunk from fast bin and consolidate it, placing it
    then in unsorted bin. Among other reasons for doing this,
    placing in unsorted bin avoids needing to calculate actual bins
    until malloc is sure that chunks aren't immediately going to be
    reused anyway.
    从 fast bin 中移除每一个chunk,并且合并,然后将它放在 unsorted bin。其中包含其他的原因,放置在
    unsorted bin 不需要计算实际的bins,除非malloc 确定chunks 不会马上被重用。
  */
  maxfb = &fastbin (av, NFASTBINS - 1);
  fb = &fastbin (av, 0);
  do {
    p = atomic_exchange_acq (fb, NULL);
    if (p != 0) {
      do {
        {
          unsigned int idx = fastbin_index (chunksize (p));
          if ((&fastbin (av, idx)) != fb)
            malloc_printerr ("malloc_consolidate(): invalid chunk size");
        }
        check_inuse_chunk(av, p);
        nextp = p->fd;
        /* Slightly streamlined version of consolidation code in free() */
        size = chunksize (p);
        nextchunk = chunk_at_offset(p, size);
        nextsize = chunksize(nextchunk);
        if (!prev_inuse(p)) {
          prevsize = prev_size (p);
          size += prevsize;
          p = chunk_at_offset(p, -((long) prevsize));
          if (__glibc_unlikely (chunksize(p) != prevsize))
            malloc_printerr ("corrupted size vs. prev_size in fastbins");
          unlink_chunk (av, p);
        }
        if (nextchunk != av->top) {
          nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
          if (!nextinuse) {
            size += nextsize;
            unlink_chunk (av, nextchunk);
          } else
            clear_inuse_bit_at_offset(nextchunk, 0);
          first_unsorted = unsorted_bin->fd;
          unsorted_bin->fd = p;
          first_unsorted->bk = p;
          if (!in_smallbin_range (size)) {
            p->fd_nextsize = NULL;
            p->bk_nextsize = NULL;
          }
          set_head(p, size | PREV_INUSE);
          p->bk = unsorted_bin;
          p->fd = first_unsorted;
          set_foot(p, size);
        }
        else {
          size += nextsize;
          set_head(p, size | PREV_INUSE);
          av->top = p;
        }
      } while ( (p = nextp) != 0);
    }
  } while (fb++ != maxfb);
}

先确定堆是否被初始化了(也就是get_max_fast()函数),如果没有就初始化堆,然后退出函数
从 fastbin 中获取一个空闲 chunk,尝试向后合并
如果不能向后合并就尝试向前合并
如果向前合并的时候与top_chunk相邻,就直接归到top_chunk中
如果并不相邻就插入到unsorted bin,然后继续取fastbin chunk直到fastbin list为空结束

Debug的时候 为什么不在unsorted呢:

     我们在分配largebin时,ptmalloc会先遍历一下fastbin,将相邻的 chunk 进行合并,并链接到 unsorted bin 中然后遍历 unsorted bin 中的 chunk,如果 unsorted bin 只 有一个 chunk,并且这个 chunk 在上次分配时被使用过,并且所需分配的 chunk 大 小属于 small bins,并且 chunk 的大小大于等于需要分配的大小,这种情况下就直接将该 chunk 进行切割,分配结束,否则将根据 chunk 的空间大小将其放入 small bins 或是 large bins 中

再次力推华庭前辈的《Glibc 内存管理》- Ptmalloc2 源代码分析 ,写的很好,简单易懂又严谨

这就是为什么不在unsorted bin而在small bin中的原因了

3. 第二次 free(p1)后

pwndbg> bins
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x602000 ◂— 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
0x50 [corrupted]
FD: 0x602000 ◂— 0x0
BK: 0x602000 —▸ 0x7ffff7dd1bb8 (main_arena+152) ◂— 0x602000
largebins
empty

可以看到 p1 既在 fast bins 中,也在 small bins 中

因为再free的时候ptmalloc会发现fastbin是空的,因此就把他扔到fastbin中去了

此时就可以分配两次p1了,一次系统会在fastbin中取出(优先查看fastbin),第二次就会在smallbins中取出 : )

0x04 结论

程序先malloc了两个fastbin chunk(0x40),然后free掉第一个chunk

这里为啥不free第二个呢,因为如果free第二个的话就会和top chunk相邻了,此时会触发top chunk的合并

之后程序调用了malloc函数malloc了一个large bin,触发了malloc_consoldate()函数,导致我们free掉的chunk1被放入了small bin中

然后程序第二次free chunk1,ptmalloc会先看fastbin中有没有,发现没有,于是就把chunk1放到fast bin中了,这时chunk1就在fastbin和smallbin中各有一个

此时程序再申请两次0x40的chunk,ptmalloc先从fastbin中把chunk1取出来给用户,然后再从smallbin中再次把chunk1取出来给用户

我们就有了两个拥有同样内存的chunk

添加新评论

请不要水评论

已有 46 条评论

sildenafil 100mg online india online cheap tadalafil generic cialis buy toradol advair diskus 500 50 mg tadalafil generic price usa buy levitra amoxicillin buy online where to get prednisone over the counter lasix

how to buy amoxicillin online diclofenac topical gel buy kamagra online uk where can i buy ampicillin sildenafil 100 mg trazodone 50 mg levitra lowest price anafranil 25 mg cymbalta price australia female pink viagra

cymbalta 40 mg capsule

tadalafil 20mg india buy cheap advair tadalafil canadian pharmacy price benicar discount

seroquel generic cymbalta 60 mg capsules buy prednisone canadian pharmacy levitra 20 mg tadalafil online 5mg accutane pill buy diclofenac tadalafil online uk amoxicillin generic sildenafil 100

lasix buy sildenafil 100 mg tablet kamagra tablets online buy generic cymbalta ampicillin 2g prednisone 10mg ventolin for sale seroquel generic

how to order levitra online

advair no prescription prednisone 20 mg tablet anafranil for dogs how to get female viagra otc tadalafil cost australia buy accutane

order viagra without prescription http://generviagara.com/ - india
pharmacy viagra

robaxin 750 mg tablet

can you buy cialis from canada without a prescription

where to buy kamagra order amoxicillin canada baclofen 10mg generic cialis tadalafil 20mg buy lasix

prednisone 10 mg tablets

baclofen cheap buy prednisone without prescription cialis 20mg in australia where can i buy toradol where can i buy trazodone prozac 80 mg cap female pink viagra benicar hct buy amoxicillin sildenafil price 100mg amoxicillin 500 generic propecia online buy accutane cymbalta generic over the counter lasix drug prednisone 10mg advair diskus price of generic seroquel robaxin 750 mg generic anafranil 25 mg tablet

cialis generic prednisone for sale online trazodone hcl 50 mg anafranil generic buy kamagra diclofenac sodium 75 mg

prednisone tablet 100 mg generic cialis tadalafil 20mg anafranil generic buy accutane online trazodone medicine amoxicillin 500 mg capsule buy kamagra

buy tadalafil online without a prescription buy amoxicillin propecia online uk buy generic cialis ventolin salbutamol

prednisone 20mg price synthroid medication prednisone 5mg coupon generic seroquel levitra pills

ampicillin 1000 diclofenac over the counter cialis generic seroquel 75 mg prozac pills buy synthroid lasix 40 mg pill sildenafil citrate tablets 100mg amoxicillin 3107 buy generic cymbalta online

kamagra tablets online tadalafil 5mg prednisone generic cost toradol cream cymbalta 400 mg

cialis daily use 5mg side effects cialis help libido http://canadianpillsbuy.com/ - buy cialis online

comprar vardenafil barato levitra sin receta https://levitramen.com/ - levitra effectiveness

sildenafil price comparison in india where can i buy prednisone without a prescription cialis generic amoxicillin 500mg capsule ampicillin generic buy diclofenac tadalafil 20 buy anafranil online uk buy generic seroquel levothyroxine synthroid

sildenafil 100mg prozac fluoxetine buy tadalafil online 1600 mg amoxicillin trazodone 100mg

buy toradol prozac for sale no prescription cost of trazodone 50 mg tablet generic advair diskus lowest price levitra

amoxicillin 500mg online no prescription baclofen buy online uk benicar hct generic robaxin 750

prednisone 20 mg tablets

prednisone purchase canada 6mg tadalafil ampicillin cost uk generic sildenafil 20 mg generic propecia cost

sildenafil 50mg where to buy baclofen prednisone 20 mg benicar hctz lasix pills

female viagra online advair diskus cymbalta 60 mg coupon levitra tablets in india accutane pills online how to purchase propecia where can i buy prednisone without prescription robaxin gold

where can you buy accutane lasix 100mg online order baclofen online usa fluoxetine prozac seroquel generic amoxicillin 500 mg price generic propecia cost synthroid cost without insurance ventolin 500 mg generic indocin

where can i buy kamagra with paypal prednisone amoxicillin 150 mg robaxin 500 mg generic buy generic accutane cialis generic synthroid 100 mcg

cheap viagra canada cvs pharmacy viagra coupon viagra brand prendre viagra et cialis en meme
temps prezzo del viagra masticabile

viagra nigeria viagra online price comparison generic viagra 50mg
cialis equivalent dosage viagra generisk viagra billigt

buy viagra professional cheap female viagra order viagra online

cuanto cuesta sildenafil en lima en ucuz sildenafil
viagra for men side effect of viagra overdose female viagra pills names

Hi! generika cialis billigcialis pssd buy cialis jakarta acquistare cialis su internetcialis i srce buy cialis online vipps

Hi! cialis rubor facialfungsi cialis 50mg where to buy cialis bangkok www cialis com free offercialis sur le long terme cialisnw

Hi! lushan.me vendita cialis generico in italiacialis duvidas buy cialis online mexico cialis aptekicialis na srpskom buy cialis 20mg in australia

Hi! cialis and lower back achehow does female cialis work buy cialis by phone cialis 0 25cialis bathtubs wtf cialisonline

lushan.me free trial sample of cialiscialis consumer reviews Cialis cialis original baratowhen does cialis become generic Cialis Online does cialis have generic

Medicinale Levitra https://buyciallisonline.com/# - buy cialis online with prescription Viaga Online Buy Cialis Amoxicillin Bronchitis Dosage