CTF for BBA

ゲーム時々CTFやるBBAの日常。

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

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

f:id:boxwolf:20200611023306p:plain
ノイズとピー音が流れるが、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になる。

f:id:boxwolf:20200611140725p:plain

「過去を振り返れ」とのことで、pypiのRelease historyを見るとバージョン0.9が存在したことがわかる。
pip install spentalkux==0.9でインストールして実行してみると、また暗号文が出てくる。
ちなみに、01の方は文字列にすると "_herring" になり、red herringじゃないかとか書かれてた。へぇ〜。

燻製ニシンの虚偽 - Wikipedia


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を使うと便利らしいのでこれから使っていきたい。

CyberChef