zoukankan      html  css  js  c++  java
  • how2heap学习笔记

    github源代码地址

    这里只分析glibc2.25堆分配的特性,为了方便调试编译时使用

    gcc -g -no-pie <input_file_name> -o <output_file_name>

    0.fastbin_dup_consolidate

      glibc在分配一个large chunk时会先检查是否存在fastbins,如果存在则合并fastbins到unsortedbins,并根据unsortedbins大小将其划入small bins或large bins。所以第一次free后p1会划入small bins,第二次可以free的原因是double free只检查fastbins的头节点和所释放的堆是否一致。malloc两次依次从fastbins和smallbins取出p1

    1.fastbin_dup_into_stack

     源代码中11行要输出的值和48行的指针赋值不一致,都改成+或-就行了

      double free的一种利用,这种攻击的本质是我们可以控制一个存在于fast bin的堆的内容。free(a),free(b),free(a).然后malloc两次,这时fastbins中只有a,但此时a的chunk内容我们可控,所以此时伪造a的fd,在栈中伪造size,此时fastbin内容就变为a->a.fd,此时我们malloc两次,第二次就会得到a.fd的地址,造成任意地址写。

    PS:关于Fastbin的LIFO。malloc fastbin大小的堆时取fastbin头结点直接指向的堆,向fastbin链表添加堆时也是添加到头结点的位置。如果是取堆和放堆都在链表结束位置,则取堆和放堆都需要遍历一遍fastbin,O(n)复杂度;而直接在fastbin头部取堆和放堆只需要修改头结点指针就行,O(1)复杂度

    2.house_of_einherjar

      off by one的一种利用。假设我们有两个分配的堆p0和p1,其中p0位于物理低地址,此时p0和p1共享p1的prev_size域;假设此时存在一个off by one,则我们可以覆盖p1 size的pre_inuse为0(空闲)。由于glibc为了减少碎片化会进行后向合并,所以会得到下一个空闲堆为chunk_at_offset(p1,(long)prev_size),由于p1的prev_size域我们可控,随意修改prev_size为p1和ptr的偏移offset就可以得到ptr地址处的堆。修改后得到下一个空闲堆的效果为chunk_at_offset(p1,(long)offset),offset=p1-ptr

    3.house_of_force

      top_chunk域可以溢出的一种利用。具体操作是覆盖top_chunk的size域为一个大整数(-1),以保证我们无论申请多大的内存都不需要调用mmap。计算malloc返回需要任意地址写的地址和top_chunk的偏移offset,这里得到的offset一定是一个负数(相当于一个整型溢出),然后此时我们malloc(offset),由于offset大小的chunk属于largebins,此时unsortedbins和largebins都为空,所以从topchunk得到这个chunk,所以new_ptr会得到top_chunk的地址。

    offset的计算过程:

    /*
         * 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)
         */

      此时我们再次malloc一个任意大小的堆,第二次malloc时top_chunk如下。所以此时malloc会得到dest的原因是与av->top的更新有关,以下有计算过程

    
    

    pwndbg> print ctr_chunk

    
    

    $2 = (void *) 0x602080 <bss_var>

    
    

    pwndbg> print ptr_top

    
    

    $3 = (intptr_t *) 0x603110

    
    

    pwndbg> x/20xg 0x603110

    
    

    0x603110:    0x0000000000000000      0xffffffffffffef61

    
    

    0x603120:    0x0000000000000000      0x0000000000000000

    
    

    0x603130:    0x0000000000000000      0x0000000000000000

    
    

    0x603140:    0x0000000000000000      0x0000000000000000

    
    

    0x603150:    0x0000000000000000      0x0000000000000000

    
    

    0x603160:    0x0000000000000000      0x0000000000000000

    
    

    0x603170:    0x0000000000000000      0x0000000000000000

    
    

    0x603180:    0x0000000000000000      0x0000000000000000

    
    

    0x603190:    0x0000000000000000      0x0000000000000000

    
    

    0x6031a0:    0x0000000000000000      0x0000000000000000

    
    

     

    
    

    av->top=chunk_at_offset(victim,nb)

    
    

    0x603110+0xffffffffffffef50+4*sizeof(long)=0x602080

     

    一个细节的地方:malloc(256)而malloc_usable_size()=264的原因是当前chunk数据域+next_chunk'pre_size。

    这种利用方式能成功的原因是unsortedbins和largebins为空时申请largechunk会从top_chunk分配,利用一个leak得到dest和top_chunk的偏移就可以在下一次malloc时实现dest的写。

    4.house_of_lore

      需要控制victim(smallbin最后一个chunk)的bk和stack_buffer的fd(stack中伪造堆)。具体操作是申请一个>fastbin大小的堆victim(例,64bit100;另,victim堆头起始记为victim_header),stack_buffer的fd覆盖为victim_header(绕过smallbin的双向链表检测)。

    smallbin的双向链表检测

    // 获取 small bin 中倒数第二个 chunk 。
                    bck = victim->bk;
                    // 检查 bck->fd 是不是 victim,防止伪造
                    if (__glibc_unlikely(bck->fd != victim)) {
                        errstr = "malloc(): smallbin double linked list corrupted";
                        goto errout;
                    }
                    // 设置 victim 对应的 inuse 位
                    set_inuse_bit_at_offset(victim, nb);
                    // 修改 small bin 链表,将 small bin 的最后一个 chunk 取出来
                    bin->bk = bck;
                    bck->fd = bin;

      此时我们malloc()一个chunk为了防止free(victim)时victim和top_chunk合并(victim释放后放入unsortedbin的条件是size>max(fastbin)&&victim不与top_chunk紧邻)。此时free(victim) victim链入unsortedbin,然后我们malloc()一个和victim大小不等且大小大于smallbin的堆,这样victim会被链入smallbin。我们修改victim->bk=stack_buffer,这样smallbin的变为stack_buffer->victim,此时malloc一个victim大小的堆就会得到victim,然后再次malloc就会得到stack_buffer。

    这种利用的原理还是伪造堆利用smallbin分配FIFO,只不过如何绕过victim和top_chunk合并,如何让victim链入smallbin,都是比较细节的问题,还是需要对glibc堆分配有很深的理解

    5.house_of_orange

     无法使用free的一种堆利用。利用当前top_chunk不满足申请堆大小,old top chunk会被链入unsortedbin(glibc在尝试得到申请大小堆的时候会依次检测fastbin、smallbins、unsortedbin、largebins,从这些bin得不到申请大小的堆会从topchunk获得,但这里topchunk也不满足,所以执行topchunk拓展;因为我们需要以brk方式扩展,所以接下来就是绕过brk扩展的check)

            1) Top chunk + size has to be page aligned
            2) Top chunk's prev_inuse bit has to be set.

    即伪造的size页对齐,size的PRE_INUSE位置1。如此得到链入unsortedbin的old top chunk

      然后修改old top chunk的bk指针为io_list_all,利用一次任意地址写修改io_list_all为system,修改io_list_all前八字节为"/bin/sh"得到shell。

    这里是如何触发一次任意地址写没看懂,有时间补,QAQ

    6.house_of_spirit

      这个针对fastbin的攻击是在栈上构造fake_chunk,伪造堆指针free(fake_chunk)实现fake_chunk地址写。难点在于构造fake_chunk过程需要绕过一些检测

    1)因为堆大小是fastbin范围,所以pre_inuse位固定;但是ISMMAP要覆盖为1(MMAP分配的堆和SBRK处理方式不一样),例子中NON_MAIN_ARENA位是0

    2)fake_chunk 16字节对齐,size在fastbin范围内

    3)fake chunk的next chunk的大小范围:> 2*SIZE_SZ (> 16 on x64) && < av->system_mem (< 128kb by default for the main arena),以绕过nextsize的完整性检查

      满足以上条件构造fake_chunk后free(fake_chunk)再malloc() fake_chunk'size-chunk_header大小的堆就可以实现fake_chunk地址处的写

    7.overlapping_chunks

      malloc三个unsortedbin范围堆P1,P2,P3;假设有一个溢出可以导致覆盖P2的size为P2+P3大小,free(P2),malloc(P2+P3-8)使malloc返回P2,由于此时P2堆大小为P2+P3,所以此时P3内容可控。

    8.overlapping_chunks_2

      跟上一个的区别是先修改溢出堆的size,使其包含下一chunk,记fake_chunk,然后free(fake_chunk),malloc()fake_chunk size域大小的堆实现堆的覆写。利用的过程中注意不要使free的堆和top_chunk合并

  • 相关阅读:
    【转载】python自动提取文本中的时间(包含中文日期)
    【转载】PCA降维
    【转载】从头到尾彻底理解KMP算法
    【转载】傅里叶分析之掐死教程(完整版)更新于2014.06.06(Heinrich)
    【转载】白素贞的身世之谜
    React 路由参数改变页面不刷新问题
    前端学习资源笔记
    Nginx配置网站默认https
    基于Docker搭建大数据集群(一)Docker环境部署
    基于Docker搭建大数据集群(三)Hadoop部署
  • 原文地址:https://www.cnblogs.com/snip3r/p/9770606.html
Copyright © 2011-2022 走看看