ångstromCTF 2023 Writeup
投稿日: 更新日:
コンテストサイト:https://2023.angstromctf.com/
結果
解けた問題数は MISC:4問、WEB:5問、CRYPTO:3問、REV:1問の計13問で382位でした
meow [misc]
だた、nc challs.actf.co 31337
とコマンドを入力すれば良い。
sanity check [misc]
Discodeに登録してgeneralの所に行くとヘッダー部分に書いてある。
Admiral Shark [misc]
Wiresharkで与えられたパケットを見てみる。分析->追跡と進むとストリーム2で何らかのバイナリファイルが流れている。バイナリをよく見てみるとl/worksheets/sheet1.xml
という文字列がある。これを調べるとExcelについての記事がヒットしたのでExcelファイルだと予想した。拡張子.xlsx
で保存してみたが開けなかった。更に調べると7zipで開けるので開いてみた。するとxl/sharedStrings.xml
のファイルにフラグを発見した。
better me [misc]
何か適当に話すと会話してくれる。ChatGPT
かな?プロンプトインジェクションだと思うので行う。
いろいろ試して何回かやり直した。以下が結果。

catch me if you can [web]
ぐるぐる回ってる。開発者ツールを開けば良い。
Celeste Speedrunning Association
言われるがままhttps://mount-tunnel.web.actf.co/play にアクセスする。どうやら、そこを開いてからPress when done!
を押すまでの短さを競うらしい。前ページの1位が0秒なのでそれよりも早くする必要がある。開発ツールを見てみると、from
のとこにname="start"
と時刻を記録している値がある。これをある程度大きな数字にしてPress when done!
を押すとフラグが得れた。
shortcircuit [web]
とりあえず開発者ツールを開いた。すると、head
にフラグらしき文字列が入っている。コードを読むと文字列を30文字ごとに切り出し、swapしている。逆の操作を行えば良いので、swapの部分を書き換え、フラグであろう文字れつを流すとフラグを得た。
directory [web]
pageがものすごくある。page0
を開くとyour flag is in another file
と言われた。この大量のページのどれかにあるのだろう。
全てにアクセスするために以下のコードを書いた。フラグが出てくるまでかなりの時間を要した。
import requests
for i in range(5000):
resu = requests.get(f"https://directory.web.actf.co/{i}.html")
if not resu.ok:
print(f"error{i}")
if resu.text != "your flag is in another file":
print(resu.text)
break
Celeste Tunneling Association [web]
与えられたコードを見る。するとname
がhost
でvalue
がflag.local
であるリクエストを送れば良いことが分かる。
SECRET_SITE = b"flag.local"
~~~
num_hosts = 0
for name, value in headers:
if name == b"host":
num_hosts += 1
if num_hosts == 1:
for name, value in headers:
if name == b"host" and value == SECRET_SITE:
await send({
'type': 'http.response.body',
'body': FLAG.encode(),
})
return
以下のコードを作成しフラグを得た。
import requests
headers = {"host":"flag.local"}
resu = requests.get("https://pioneer.tailec718.ts.net/", headers=headers)
print(resu.text)
ranch [crypto]
シーザー暗号。CyberChefのEncryption / EncodingにあるRot13のAmountの値を試して行く。
CyberChef:https://gchq.github.io/CyberChef/
impossible [crypto]
与えられたコードを見てみる。len(fake_psi(one_encoding(x, 64), zero_encoding(y, 64))) == 0
の部分から、one_encoding(x, 64)
とzero_encoding(y, 64)
が同じ値を持っていてはならない。そして、x > y and x > 0 and y > 0
となるx,y
が必要であることが分かる。
それで、one_encoding(x, 64)
はシフトして1ビット目が1である数を配列に格納している。zero_encoding(x, 64)
はシフトして1ビット目が0である数を格納している。
x
がの時、シフトしてもどの1ビット目も1が立つので返す配列は空となる。これで、len(fake_psi(one_encoding(x, 64), zero_encoding(y, 64))) == 0
の条件は満たせる。よって任意のyを選ぶことが出来るので、x>yを満たすものを選ぶ。1を選んだ。
Royal Society of Arts [crypto]
RSA暗号の計算知識が必要。
とからを導き出せればば復号鍵が作成出来るので式変形で導く。
とりあえず展開する。
二つを足す
ここで、目標は
であるので、近い。3で割れば一致させれるのでいじる。
であることを用て両辺に足し、更に両辺を-1すると
よっての値を得た。
あとはこれらの計算を実装する。数字は長いので省略
from Crypto.Util.number import long_to_bytes
N =
e =
c =
# (p-2)*(q-1)
a =
# (p-1)*(q-2)
b =
phi = (a + b + N -1)//3
d = pow(e, -1, phi)
m = pow(c, d, N)
print(long_to_bytes(m))
checkers [rev]
ファイルが与えられる。とりあえずstringsコマンドを実行してみるとフラグを得た。