RACTF 2020 復習編 その1
writeup見て解いた問題を自己学習用にメモ。
ほぼwriteupの写しです、すみませんありがとうございます。
Teleport
10ずつ100回しか移動できないが、(10000000000000, 10000000000000)に移動する必要がある。
pythonのfloatにはNaNという非数があり、
- 四則演算の結果がNaNとなる
- 比較演算の結果がFalseとなる
これを利用するとif dist > 10
がfalseを返すのでフラグの座標に飛ぶことができる。
$ nc 88.198.219.20 37550 Your player is at 0,0 The flag is at 10000000000000, 10000000000000 Enter your next position in the form x,y You can move a maximum of 10 metres at a time Current position: 0.0, 0.0 Enter next position(maximum distance of 10): nan, nan Current position: nan, nan Enter next position(maximum distance of 10): 10000000000000, 10000000000000 ractf{fl0at1ng_p01nt_15_h4rd}
flag: ractf{fl0at1ng_p01nt_15_h4rd}
clamclamclam
競技中、サーバーが落ちてたのかncしても何も返ってこなくて困惑した(私も相方も)
ちゃんと動いていれば下記のようになる。
$ nc 88.198.219.20 31072 > pearl.bin $ xxd pearl.bin 00000000: 6374 667b 7065 6172 6c70 6561 726c 7065 ctf{pearlpearlpe 00000010: 6172 6c7d 0d63 7466 7b70 6561 726c 7065 arl}.ctf{pearlpe 00000020: 6172 6c70 6561 726c 7d0a 6374 667b 7065 arlpearl}.ctf{pe 00000030: 6172 6c70 6561 726c 7065 6172 6c7d 0a63 arlpearlpearl}.c
よく見ると改行コードがCR(0x0d)とLF(0x0a)の二種類ある。
それぞれ0と1に変換して二進数として読むと文字列になる。
with open('pearl.bin', 'rb') as f: b = f.read() b2 = '' for i in range(len(b) // 21): if b[21 * i + 20] == 0xd: b2 += '0' else: b2 += '1' b3 = [b2[i:i+8] for i in range(0, len(b2), 8)] ans = '' for bi in b3: ans += chr(int(bi, 2)) print(ans)
flag: ractf{p34r1_1ns1d3_4_cl4m}
Mad CTF Disease
steghideをかけてくれるオンラインツールに投げて何やらデータは出てきたのは確認したのだが、stegの問題じゃないしなぁ…と思ってそこでやめてしまった。勿体ない。
steghideの使い方は以下。
Steganography - A list of useful tools and resources - 0xRick
$ steghide info cow.jpg "cow.jpg": format: jpeg capacity: 6.9 KB Try to get information about embedded data ? (y/n) y Enter passphrase: embedded file "moo.txt": size: 3.1 KB encrypted: rijndael-128, cbc compressed: yes $ steghide extract -sf cow.jpg Enter passphrase: wrote extracted data to "moo.txt".
moo.txtを見るとなんかMoOMoO言ってる。
COWというesolangがあるらしい。オンラインインタプリタで実行した。
flag: ractf{exp3rt-mo0neuv3r5}
ST.MOV
youtubeの動画を拾いたい場面はこれからもありそうなので、youtube-dlを入れた。
$ youtube-dl "https://www.youtube.com/watch?v=HkIJRzzHP5E&feature=youtu.be" -x --audio-format mp3
ノイズとピー音が流れるが、30秒ごとに区切ることができるので、01に変換する。
7ビット区切りで文字列に変換してみる。
b = '11100101100001110001111101001100110111101111101101101001110010011001011101111100000111010011010011101101110010110000011000101101111110100111100111111101' bl = [b[i:i+7] for i in range(0, len(b), 7)] ans = '' for bi in bl: ans += chr(int(bi, 2)) print(ans)
"ractf{videoAiS[K\x03\x0b?'O\x1d"
になってしまう。10000の部分だけ6ビット区切りになっている。
6ビットの部分の頭を0埋めする(スクリプトは上と同様なので省略)。
bs = '1110010110000111000111110100110011011110111110110110100111001001100101110111101000001110100110100111011011100101010000011000101101111110100111100111111101'
flag: ractf{video time bois}
Spentalkux
spentalkuxで検索するとpythonパッケージが出てくる。
インストールして実行してみると、暗号文とキーは10文字という情報が出てくる。
Hello. Can I help you? Oh, you're looking for something to do with *that*. My creator left this behind but, I wonder what the key is? I don't know, but if I did I would say it's about 10 characters. Enjoy this. Ztpyh, Iq iir'jt vrtdtxa qzxw lhu'go gxfpkrw tz pckv bc ybtevy... *ffiieyano*. New cikm sekab gu xux cskfiwckr bs zfyo si lgmpd://zupltfvg.czw/lxo/QGvM0sa6 Goodbye now. That's your cue to leave, bro Exit stage left, pal OFF YOU POP. You know what I haven't got time for this Forking and executing rm -rf.
"spentalkux"が10文字だな…。ヴィジュネル暗号。
Hello, If you're reading this you've managed to find my little... *interface*. The next stage of the challenge is over at https://pastebin.com/raw/BCiT0sp6
となるので、
URLに飛ぶと、89 50 ...から始まる数字列。バイナリに変換するとpngになる。
「過去を振り返れ」とのことで、pypiのRelease historyを見るとバージョン0.9が存在したことがわかる。
pip install spentalkux==0.9
でインストールして実行してみると、また暗号文が出てくる。
ちなみに、01の方は文字列にすると "_herring" になり、red herringじゃないかとか書かれてた。へぇ〜。
Urgh. Not you again. Fine. I'll tell you more. ... But, being the chaotic evil I am, I'm not giving it to you in plaintext. Enjoy this. JA2HGSKBJI4DSZ2WGRAS6KZRLJKVEYKFJFAWSOCTNNTFCKZRF5HTGZRXJV2EKQTGJVTXUOLSIMXWI2KYNVEUCNLIKN5HK3RTJBHGIQTCM5RHIVSQGJ3C6MRLJRXXOTJYGM3XORSIJN4FUYTNIU4XAULGONGE6YLJJRAUYODLOZEWWNCNIJWWCMJXOVTEQULCJFFEGWDPK5HFUWSLI5IFOQRVKFWGU5SYJF2VQT3NNUYFGZ2MNF4EU5ZYJBJEGOCUMJWXUN3YGVSUS43QPFYGCWSIKNLWE2RYMNAWQZDKNRUTEV2VNNJDC43WGJSFU3LXLBUFU3CENZEWGQ3MGBDXS4SGLA3GMS3LIJCUEVCCONYSWOLVLEZEKY3VM4ZFEZRQPB2GCSTMJZSFSSTVPBVFAOLLMNSDCTCPK4XWMUKYORRDC43EGNTFGVCHLBDFI6BTKVVGMR2GPA3HKSSHNJSUSQKBIE This is the part where you *leave*, bro. Look, if you don't get outta here soon ima run rm -rf on ya I don't want you here. GO AWAY. Leave me alone now. GOODBYE! I used to want you dead but... now I only want you gone.
base系かな?とは思ったがbase32とは…。base32は'A'〜'Z', '2'〜'7', '='の33文字を用いるエンコード方式。
パディングが足りないため足す必要がある。
デコードするとさらにbase64の文字列が出てくる。
In [16]: import base64 In [17]: b = base64.b32decode('JA2HGSKBJI4DSZ2WGRAS6KZRLJKVEYKFJFAWSOCTNNTFCKZRF5HTGZRXJV2EKQTGJVTXUOLSIMXWI2KYNVEUCNLIKN5HK3RTJBHGIQTCM5RHIVSQGJ3C6MRLJRXXOTJYGM3XORSIJN4FUYTNIU4XAULGONGE6YLJJRAUYODLOZE ...: WWNCNIJWWCMJXOVTEQULCJFFEGWDPK5HFUWSLI5IFOQRVKFWGU5SYJF2VQT3NNUYFGZ2MNF4EU5ZYJBJEGOCUMJWXUN3YGVSUS43QPFYGCWSIKNLWE2RYMNAWQZDKNRUTEV2VNNJDC43WGJSFU3LXLBUFU3CENZEWGQ3MGBDXS4SGLA3GMS3LIJCUEVCCONYS ...: WOLVLEZEKY3VM4ZFEZRQPB2GCSTMJZSFSSTVPBVFAOLLMNSDCTCPK4XWMUKYORRDC43EGNTFGVCHLBDFI6BTKVVGMR2GPA3HKSSHNJSUSQKBIE======') In [18]: b Out[18]: b'H4sIAJ89gV4A/+1ZURaEIAi8SkfQ+1/O3f7MtEBfMgz9rC/diXmIA5hSzun3HNdBbgbtVP2v/2+LowM837wFHKxZbmE9pQfsLOaiLAL8kvIk4MBma17ufHQbIJCXoWNZZKGPWB5QljvXIuXOmm0SgLixJw8HRC8Tbmz7x5eIspypaZHSWbj8cAhdjli2WUkR1sv2dZmwXhZlDnIcCl0GyrFX6fKkBEBTBsq+9uY2Ecug2Rf0xtaJlNdYJuxjP9kcd1LOW/fQXtb1sd3fSTGXFTx3UjfGFx6uJGjeIAAA' In [19]: b2 = base64.b64decode(b) In [20]: b2 Out[20]: b'\x1f\x8b\x08\x00\x9f=\x81^\x00\xff\xedYQ\x16\x84 \x08\xbcJG\xd0\xfb_\xce\xdd\xfe\xcc\xb4@_2\x0c\xfd\xac/\xdd\x89y\x88\x03\x98R\xce\xe9\xf7\x1c\xd7An\x06\xedT\xfd\xaf\xffo\x8b\xa3\x03<\xdf\xbc\x05\x1c\xacYna=\xa5\x07\xec,\xe6\xa2,\x02\xfc\x92\xf2$\xe0\xc0fk^\xee|t\x1b \x90\x97\xa1cYd\xa1\x8fX\x1eP\x96;\xd7"\xe5\xce\x9am\x12\x80\xb8\xb1\'\x0f\x07D/\x13nl\xfb\xc7\x97\x88\xb2\x9c\xa9i\x91\xd2Y\xb8\xfcp\x08]\x8eX\xb6YI\x11\xd6\xcb\xf6u\x99\xb0^\x16e\x0er\x1c\n]\x06\xca\xb1W\xe9\xf2\xa4\x04@S\x06\xca\xbe\xf6\xe66\x11\xcb\xa0\xd9\x17\xf4\xc6\xd6\x89\x94\xd7X&\xecc?\xd9\x1cwR\xce[\xf7\xd0^\xd6\xf5\xb1\xdd\xdfI1\x97\x15<wR7\xc6\x17\x1e\xae$h\xde \x00\x00' In [23]: with open('b2.bin', 'wb') as f: ...: f.write(b2)
1f 8b ... から始まるバイナリはgzip形式のファイル。
$ file b2.gz b2.gz: gzip compressed data, last modified: Mon Mar 30 00:30:23 2020, original size modulo 2^32 8414 $ gzip -d b2.gz $ file b2 b2: ASCII text, with very long lines, with no line terminators $ cat b2 00110000 00110000 00110001 00110001 ...
これを文字列に直すと更に01の文字列が出てきて、それをまた文字列に直すと'45 61 60 49 22 41 70 5b 36 74 32 30 3a 57 70 30 65 64 60 2d 3f 53 51 47 3f 31 4e 49 28 61 40 6c 24 3e 74'
、文字列にすると'EaI"Ap[6t20:Wp0ed
-?SQG?1NI(a@l$>t'になる。
これはascii85(base85との違いがよくわかっていないのでわかる方教えてください)。
In [4]: base64.a85decode('Ea`I"Ap[6t20:Wp0ed`-?SQG?1NI(a@l$>t') Out[4]: b'ractf{My5t3r10u5_1nt3rf4c3?}'
flag: ractf{My5t3r10u5_1nt3rf4c3?}
binやhexを行き来するような問題はCyberChefを使うと便利らしいのでこれから使っていきたい。