NITIC CTF(36h, 9/5 12時~9/6 24時)に1人で参加して1701ポイントで62位でした~。
今までcpawCTFとかpicoCTFはやったことあったけど、リアルタイムでのコンテストは初めてだった。
初めてのwriteupです。
Web
web_meta (100pt)
ブラウザから覗いても何もないけど、拡張ツール開いてみるとflag is ...
って書いてある。
▶Flag
nitic_ctf{You_can_see_dev_too1!}
long flag (200pt)
Flagがありそうだけど表示されてないっぽいので拡張ツール開いてpタグの中を見る。
<span>n</span><span>i</span>...
とたくさん書いてあるので全部コピーして置換ツールとかで消去する。
▶Flag
nitic_ctf{Jy!Hxj$RdB$uA,b$uM.bN7AidL6qe4gkrB9dMU-jY8KU828ByP9E#YDi9byaF4sQ-p/835r26MT!QwWWM|c!ia(ynt48hBs&-,|3}
Pwn
pwn monster 1 (100pt)
netcatを使ってnc 35.200.120.35 9001
にアクセスするとポ〇モンバトル的なのが始まる。
自分のモンスターのHP/ATKは100/10なのに相手のHP/ATKは9999/9999とめっちゃ不利、普通に負ける。
名前入力の際に長い文字列をぶち込んでやればスタックを破壊してHP/ATKを最強にできるので、勝つ。
(monster 2のATKをマイナスにすると敵を回復させすぎて死ぬって解説面白い、解けなかったんだけども…)
▶Flag
nitic_ctf{We1c0me_t0_pwn_w0r1d!}
Misc
Excel (100pt)
配布されたエクセルファイル開いて、Ctrl+Fで「nitic」で検索するとU869にフラグがある。
▶Flag
nitic_ctf{plz_find_me}
image_conv (200pt)
nitic_ctf{ }
とだけ書かれたpngファイルが配布される。
最初$ file after_flag.png
とかしてたけど唐突にペイントツールとかで塗りつぶしたらフラグ出てきた。
▶Flag
nitic_ctf{high_contrast}
Rev
protected (200pt)
$ file chall
すると実行ファイルらしいので実行してみるとパスワード聞かれる。合ってるとFlagがもらえるっぽい。$ strings chall
するとsUp3r_s3Cr37_P4s5w0Rd
という怪しい文字列が出てくるのでパスワードとして入力するとフラグが得られる。
やらかし大臣なのでnitic_ctf{sUp3r_s3Cr37_P4s5w0Rd}
をして1WA…
▶Flag
nitic_ctf{hardcode_secret}
Crypto
Caesar Cipher (100pt)
暗号文fdhvdu
をrot13.comで適当に試していくとフラグを見つけられる。タイトル通り。
▶Flag
nitic_ctf{caesar}
ord_xor (300pt)
Pythonファイルとテキストファイルが配布される。テキストファイルの中身はnhtjcZcsfroydRx`rl
。
XORは2回繰り返すと元に戻るので、os.environ[“FLAG”]
をテキストファイルの中身に入れ替えるだけでフラグが得られる。
import os flag = "" with open("./flag","r") as f: flag=f.read() def xor(c: str, n: int) -> str: temp = ord(c) for _ in range(n): temp ^= n return chr(temp) dec_flag = "" for i in range(len(flag)): dec_flag += xor(flag[i], i) print(dec_flag)
▶Flag
nitic_ctf{ord_xor}
もしかしてnanigasi_sanはFlagを作るのが下手なんですか?
tanitu_kanji (300pt)
Pythonファイルとテキストファイルが配布される。テキストファイルの中身はl0d0pipdave0dia244im6fsp8x
。
Pythonファイルは10文字の暗号化形式formatとFLAGを環境変数から取り出し、formatのi番目が”1”ならalphabets→after1、それ以外ならalphabets→after2に変換しているらしい。
復号化はformatを210通りをbit全探索でやってみてafter1→alphabetsとafter2→alphabetsを試す。
import os alphabets = "abcdefghijklmnopqrstuvwxyz0123456789{}_" after1 = "fl38ztrx6q027k9e5su}dwp{o_bynhm14aicjgv" after2 = "rho5b3k17pi_eytm2f94ujxsdvgcwl{}a086znq" with open("./flag","r") as f: flag = f.read() def reconv(s: str, table: str) -> str: res = "" for c in s: i = table.index(c) res += alphabets[i] return res for bit in range(1<<10): dec_flag = flag format = "" for j in range(10): if (bit & (1<<j)): format += "1" else: format += "0" for f in format: if f == "1": dec_flag = reconv(dec_flag, after1) else: dec_flag = reconv(dec_flag, after2) if dec_flag[0:9]=="nitic_ctf": print(dec_flag)
▶Flag
nitic_ctf{bit_full_search}
解けなかったやつ
300pt : password(+fixed), pwn monster 2~3, braincheck, report or repeat, summeRSA
500pt : Is it Shell?, baby_IO_jail
ちょっと難しいレベルの問題から上の知識が一切なかったので撃沈。
summeRSA (300pt)
RSA暗号で暗号化された文cと公開鍵e,Nが与えられる。平文mがthe magic words are squeamish ossifrage. nitic_ctf{〇〇}
でありFlagの中身は7文字であることがわかっている。
7文字全通り試してe乗してmod Nをとった結果がcと一致したらOK!みたいな脳筋コード書いたけどとけなかった。 Coppersmith’s Attackは検索したけど実装できなくて死
using Primes function main() N = 139144195401291376287432009135228874425906733339426085480096768612837545660658559348449396096584313866982260011758274989304926271873352624836198271884781766711699496632003696533876991489994309382490275105164083576984076280280260628564972594554145121126951093422224357162795787221356643193605502890359266274703 e = 7 c = 137521057527189103425088525975824332594464447341686435497842858970204288096642253643188900933280120164271302965028579612429478072395471160529450860859037613781224232824152167212723936798704535757693154000462881802337540760439603751547377768669766050202387684717051899243124941875016108930932782472616565122310 ans = "the magic words are squeamish ossifrage. nitic_ctf{" abc = "!\"#\$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[/]^_`abcdefghijklmnopqrstuvwxyz{|}~" len = length(abc) for i in 1:len,j in 1:len,k in 1:len,l in 1:len,n in 1:len,m in 1:len,o in 1:len res = join([ans,abc[i],abc[j],abc[k],abc[l],abc[n],abc[m],abc[o],"}"]) m_res = parse(BigInt, bytes2hex(Vector{UInt8}(res)), base=16) if m_res^e % N == c println(hex2bytes(string(m_res, base=16))) return end end end main()
感想・反省?
(そもそもwriteupって感想書いていいものなのかよくわからないけど…)
nanigasi_sanをはじめ茨城高専の運営の皆さんお疲れさまでした。自分としては、CTFに親しみを持たせつつ学ばないといけない事柄を示してくれるコンテストで有難かったです。
反省は、Ghidraの使い方忘れて逆コンパイルはできないわ、RSA暗号の解き方がわかっても実装できないわ、nanigasi_sanの300点しか解けないわで慌てすぎてTwitterしかすることがなくなってました。反省します。
#nitic_ctf_2 pic.twitter.com/xkSaOOPrnh
— まぁじ (@Hals_SC) 2021年9月5日