CTF for Beginners 2018 で CTF問題演習 Crypto [Warmup] Veni, vidi, vici を解く
セキュリティコンテストチャレンジブック -CTFで学ぼう! 情報を守るための戦い方-
- 作者: 碓井利宣,竹迫良範,廣田一貴,保要隆明,前田優人,美濃圭佑,三村聡志,八木橋優,SECCON実行委員会
- 出版社/メーカー: マイナビ出版
- 発売日: 2015/09/30
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (4件) を見る
経緯
こういう感じで、 k-mawa.hateblo.jp
とりあえず、CTFにてもっと解けるように残った問題で手習い開始。
Crypto [Warmup] Veni, vidi, vici
1:問題をダウンロードする。
次のような文字列のファイルが見える
#part1 Gur svefg cneg bs gur synt vf: pgs4o{a0zber
#part2 Lzw kwugfv hsjl gx lzw xdsy ak: _uDskk!usd_u
#part3 {ʎɥdɐɹɓ0ʇdʎᴚ :sı ɓɐlɟ ǝɥʇ ɟo ʇɹɐd pɹıɥʇ ǝɥ⊥
ふーん。経験値が少なすぎてなんじゃこりゃ・・・って感じ。part3は可読だね。逆さになってるだけだ。逆さになってる文字列を180度回転するモジュールとかあるんかしら・・・
2逆さにした文字を戻す
rot180って通称で呼ばれているようだ。原理は下記のような感じ。W→Mに変換と似ている文字を探して置換しているだけ。
pythonよく使うからpythonでできないかな。これ・・・で、ありました^^/
How to rotate a character or string by 90 or 180 degree in python? - Stack Overflow
upsidedownってモジュールかやってみよ。
$pip install upsidedown==0.3 #!python3.x系はエラー! #python2.7.10でインストール成功 $python Python 2.7.10 >>> import upsidedown >>> print upsidedown.transform('hello world!') ¡pꞁɹoʍ oꞁꞁǝɥ
よしできた!やってみよう。
UnicodeDecodeError: 'ascii' codec can't decode byte 0xca in position 1: ordinal not in range(128)
ん〜もうこの辺は核心部分じゃないから、いいや。多分アルファベットくらいの対応表しか用意してなくて、十分な対応表がないんじゃないかな・・・そのメンテナンスが遊びの割に面倒だから、pythonモジュールあんまなかったのかも。ふつうにWebのツールでやろう。
一瞬でできた、楽やな^^
#part3 解決後 The third part of the flag is: Rypt0graphy}
3
part1,part2は、意味不明な文字列・・・The third part of the flag is: Rypt0graphy}
をからすると、The first part of the flag is: …
The second part of the flag is: …
と、なりそうかなと当たりをつけることはできる。それで、文字自体は対応してないけど、区切りごとの文字数は同じ・・・つまりシーザー暗号かもね。ということで、調べてみた。
wikiわかりやすい。なるほど。アルファベットを半分にして、逆に対応させるのか。それでROT13か。なんかカッコイイな^^ ROT13 - Wikipedia
そのためのツールがpythonにはあると。今度こそpythonで解きたいよね。
#part1を解く >>> import codecs >>> str = "Gur svefg cneg bs gur synt vf: pgs4o{a0zber" >>> codecs.decode(str, 'rot13') 'The first part of the flag is: ctf4b{n0more'
行けたやん!
4 part2を解く
>>> import codecs >>> str = "Lzw kwugfv hsjl gx lzw xdsy ak: _uDskk!usd_u!" >>> codecs.decode(str, 'rot13') 'Ymj xjhtsi ufwy tk ymj kqfl nx: _hQfxx!hfq_h!'
意味不明だなァ
ここでpythonの文字列の比較演算子の挙動をチェックしてみる…
>>> "a" > "b" False >>> "a" < "b" True >>> "a" < "a" False >>> "a" < "z" True >>> "a" < "B" <"z" False >>> "a" < "b" <"z" True >>> "z" < "b" <"z" False
うーむつまり、単純に文字列がアルファベット順になっていればTrueというわけか。ふーん。
さらに調べると、アスキーコードの数字の大小で調べていることがわかった。つまりこういうこと。ordは組み込みメソッド
>>> ord('A') 65 >>> ord('B') 66 >>> ord('C') 67 >>> ord('a') 97 >>> ord('b') 98 >>> ord('c') 99
つまり1文字ずらすというのは
>>> chr(ord('A') + 1) 'B' >>> chr(ord('Z') + 1) '[' おっと循環しているわけではないか。
>>> ord('A') 65 >>> ord('Z') 90
解説を読みながらテスト
>>> str="J" >>> chr((ord(str) - ord('A') + 13) % 26 + ord('A')) 'W'
OK、じゃあこれで1文字〜13文字までずらした結果を導く関数をつくってみるか。コード書こう。自分でもツールを作りたいからね^^
と、いうわけで小1時間くらい書いてできた!!
#str_rot_n.py #!/usr/bin/env python # -*- coding: utf-8 -*- import re def str_rot_n(strings): strlist = list(strings) answer_list =[] for i in range(13): print("[+]Info:strings rot {}...".format(i+1)) for j in strlist: if 'A' <= j and j <= 'Z': roted_str = chr((ord(j) - ord('A') + i+1) % 26 + ord('A')) answer_list.append(roted_str) if 'a' <= j and j <= 'z': roted_str = chr((ord(j) - ord('a') + i+1) % 26 + ord('a')) answer_list.append(roted_str) m = re.match(r"[a-z,A-Z]", j) if not m: answer_list.append(j) answer_list = ','.join(answer_list) answer_list = answer_list.replace(",","") print("[+]Info:strings rot {}: decode strings is '{}'".format(i+1,answer_list)) answer_list =[]
これを動かすと・・・
>>> import str_rot_n >>> str = "Lzw kwugfv hsjl gx lzw xdsy ak: _uDskk!usd_u" >>> str_rot_n.str_rot_n(str) [+]Info:strings rot 1... [+]Info:strings rot 1: decode strings is 'Max lxvhgw itkm hy max yetz bl: _vEtll!vte_v' [+]Info:strings rot 2... [+]Info:strings rot 2: decode strings is 'Nby mywihx juln iz nby zfua cm: _wFumm!wuf_w' [+]Info:strings rot 3... [+]Info:strings rot 3: decode strings is 'Ocz nzxjiy kvmo ja ocz agvb dn: _xGvnn!xvg_x' [+]Info:strings rot 4... [+]Info:strings rot 4: decode strings is 'Pda oaykjz lwnp kb pda bhwc eo: _yHwoo!ywh_y' [+]Info:strings rot 5... [+]Info:strings rot 5: decode strings is 'Qeb pbzlka mxoq lc qeb cixd fp: _zIxpp!zxi_z' [+]Info:strings rot 6... [+]Info:strings rot 6: decode strings is 'Rfc qcamlb nypr md rfc djye gq: _aJyqq!ayj_a' [+]Info:strings rot 7... [+]Info:strings rot 7: decode strings is 'Sgd rdbnmc ozqs ne sgd ekzf hr: _bKzrr!bzk_b' [+]Info:strings rot 8... [+]Info:strings rot 8: decode strings is 'The second part of the flag is: _cLass!cal_c' [+]Info:strings rot 9... [+]Info:strings rot 9: decode strings is 'Uif tfdpoe qbsu pg uif gmbh jt: _dMbtt!dbm_d' [+]Info:strings rot 10... [+]Info:strings rot 10: decode strings is 'Vjg ugeqpf rctv qh vjg hnci ku: _eNcuu!ecn_e' [+]Info:strings rot 11... [+]Info:strings rot 11: decode strings is 'Wkh vhfrqg sduw ri wkh iodj lv: _fOdvv!fdo_f' [+]Info:strings rot 12... [+]Info:strings rot 12: decode strings is 'Xli wigsrh tevx sj xli jpek mw: _gPeww!gep_g' [+]Info:strings rot 13... [+]Info:strings rot 13: decode strings is 'Ymj xjhtsi ufwy tk ymj kqfl nx: _hQfxx!hfq_h' >>>
おお![+]Info:strings rot 8...
[+]Info:strings rot 8: decode strings is 'The second part of the flag is: _cLass!cal_c'
というわけで、最後のパーツもそろった!
The first part of the flag is: ctf4b{n0more The second part of the flag is: _cLass!cal_c The third part of the flag is: Rypt0graphy}
あわせて、
ctf4b{n0more_cLass!cal_cRypt0graphy}
解けたぁ!!
解説
これを読みつつ復習中 ^^/