解法
output.txtにある16進数の値を10進数に変換後、素因数分解。
素因数分解の指数部分だけを取り出して、それらをUnicodeで文字にした後、結合してFLAGを得る。
過程
CTF初心者ということもあり、outputとは何だ・・・?と思いながら、pythonのコードを実行。
なんかクソ長い16進数の値が得られた。
これを復号するのかな?と思って配られたコードの解析に取り掛かった。
flag = os.environ.get("FLAG","not_a_flag")
pythonのライブラリ?かなんかで、OSにアクセスできるやつ。今回はFLAGという環境変数を参照して取得。環境変数がなければ、後ろの引数を利用する。
assert 式
式が成り立っていなかったら例外を投げる。(アサーションエラー)
for i, c, in enumarate(flag):
enumarate()は配列のインデックスと値を取得できるらしい。マップ?
ord(c)
文字cをUnicodeの数字に変換してくれる。
地道に読み取っていたところ、暗号文ctについて、

みたいな関係が成り立っていそう。
そして、その計算結果がoutput.txtに出力されているのではないかと推測。
ローカルでやってもnot_a_flagが変換されて、多分意味はなさそう。
なので、やることは、output.txtにある16進数の値を引っ張ってきて復号。
10進数に変換(もしかしたらいらないかも)→素因数分解→指数部の抽出→Unicodeの文字変換ができればよい。
というわけでこんなコードを書いてみた。
実行環境:Google colaboratory
import sympy
ct_10 = int('(output.txt内の数字)',16)
print(sympy.factorint(ct_10))
indexes = list(sympy.factorint(ct_10).values())
print(indexes)
pt = []
for i in range(0,len(indexes)):
pt.append(chr(indexes[i]))
print(''.join(pt))
素因数分解をいちいち実装したくないので調べたところ、sympyというライブラリのfactorint()関数で素因数分解ができることを知る。
どうやらマップ{基数:指数}で返しているらしいので、.values()で値の部分のみ抽出。文字列にしたいので、配列の中にいれる。
最後に''.join()で結合させて終わり。目当てのフラグを得る。
余談
ローカルで値を出して、それを復号したとて意味はなさそうと考えた。
実際に確かめてみると、

その通りだった。
## 感想
2日目にして色々考えて、自分で復号ツールまで作って解いたので、結構パワーを使った。でもかなり面白かった。