SECCON Beginners CTF 2023 WriteUp

# SECCON Beginners CTF 2023 WriteUp
ctf4bに参加しました。公式サイトはこちら  
https://score.beginners.seccon.jp/
問題のリポジトリはこちら
https://github.com/SECCON/SECCON_Beginners_CTF_2023

# 結果
5問解けて302位でした！Beginnerがいくつか解けなかったのが悔しすぎます。復習して身につけます。。。
ただ、色々調べて試行錯誤する過程がとても楽しかったです！次もBegginer向けのCTFを見つけたら参加します！

# 筆者について
- 最近セキュリティの勉強を始めた情報系？の大学生。研究室は微分幾何です。
- CTFの問題はcpawCTFで20問程度解いた事がある状態。CTFは2回目
- 競技プログラミングやってた。(AtCoder緑)

# WriteUp
## Crypto
### CoughingFox2
暗号の解読の問題。最後にシャッフルが挟んであって、「え、解けるの？？」と思ったが、  
`cipher`の各数字は大きい数(200くらい以上)の平方数+要素番号の形になっているので、それをみて順番を並べ替えて、隣との差を見ていけばOK。flagの先頭が`c`であることを使った。
``` python:solve.py
# cipherは配られたものに置き換えます。
# 長いのでwriteupでは省略しました。
cipher = []
# 並び替えて配列に追加していくため、答得に使う配列は先に要素数分確保しておきました。
ans = [0] * 43
for c in cipher:
    for i in range(len(cipher)):
        # iを引いて平方数なら、ansのi番目にその平方根を追加しました。
        if ((c - i) ** 0.5).is_integer():
            ans[i] = int((c - i) ** 0.5)

flag = "c"
for i in range(1, len(ans) + 1):
    # 暗号化で隣り合うものを足していたので、復号では引いていきました。
    flag += chr(ans[i - 1] - ord(flag[i - 1]))

print(flag)
```
flag > `ctf4b{hi_b3g1nner!g00d_1uck_4nd_h4ve_fun!!!}`

### Conquer
暗号の問題 。逆算する方法を探していきました。  
`x = a ^ b` のとき、`a = x ^ b`となることを使いました。また、ROLではbitを左にずらして溢れた桁を1桁目に持っていくことをしているので、それを逆にする関数`revROL`を作って逆算しました。  
一番悩んだポイントは`length`の扱いです。`key.bit_length()`とか`cipher.bit_length()`でやってもうまく行かなったので、とりあえず有り得そうな値を全探索していく方向にしました。とりあえず計算し、flagと思われる文字列が`ct`から始まれば出力する形にしています。 

``` python:solve.py
from Crypto.Util.number import *

def revROL(bits, N):
    for _ in range(N):
        bits = ((bits << (length - 1)) & (2**length - 1)) | (bits >> 1)
    return bits

constkey = 364765105385226228888267246885507128079813677318333502635464281930855331056070734926401965510936356014326979260977790597194503012948
constcipher = 92499232109251162138344223189844914420326826743556872876639400853892198641955596900058352490329330224967987380962193017044830636379

key = constkey
cipher = constcipher

length = 50
flag = 1000000
while long_to_bytes(flag)[0] != 99 or (long_to_bytes(flag)[1] != 116):
    key = constkey
    cipher = constcipher
    length += 1
    for i in range(32):
        cipher ^= key
        key = revROL(key, pow(cipher, 3, length))
    flag = cipher ^ key
print(long_to_bytes(flag))
```

flag > `ctf4b{SemiCIRCLErCanalsHaveBeenConqueredByTheCIRCLE!!!}`

## misc
### YARO
YARAについての問題。言われたとおりに接続すると、`rule:`と聞かれる。適当に打つと`something wrong`と返ってくる。配布されたソースコードの`server.py`を見てみると、中身がどう動いているかわかる。どうやら、入力したものを受け取ってそれをルールにYAROでマルウェアチェック的なことをしているらしい！そこでサンプルの`rule_example.yar`をそのまま入力に貼り付けてみる。
``` yar:rule_example.yar
rule shebang {
    strings:
        $shebang = /^#!(\/[^\/ ]*)+\/?/
    condition:
        $shebang
}
rule maybe_python_executable {
    strings:
        $ident = /python(2|3)\r*\n/
    condition:
        shebang and $ident
}
```
  
``` :レスポンス
Found: ./redir.sh, matched: [shebang]
Found: ./server.py, matched: [shebang, maybe_python_executable]
Not found: ./flag.txt
Not found: ./requestments.txt
```
どうやら、中のファイルを自分が送ったルールに従ってフィルタリング？しているらしい。  
試しに
```
rule f {
    strings:
        $flag = "ctf4b"
    condition:
        $flag
}
```
と送ってみると、
``` 
Not found: ./redir.sh
Not found: ./server.py
Found: ./flag.txt, matched: [f]
Not found: ./requestments.txt
```
と返ってくる。  
よし！！だいぶ見えてきた！  
あとは`nc`コマンドをpythonで使う方法を調べて、うまく総当りする方法をpythonで記述して、実行するだけ！(約2時間かかった、、、。。)  
  
https://scrapbox.io/progfay-pub/netcat.py  
こちらのサイトから、`netcat.py`を拝借しました。とても便利でした。ありがとうございます！！！  
上記サイトのnetcat.pyを同じ階層に置くとsolve.pyが動くはずです。  
``` python:solve.py
from netcat import Netcat
chars = ["0","1","2","3","4","5","6","7","8","9","_","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","{","}"]
x = "ctf4b{"
for i in range(100):
    for c in chars:
        attack = x + c
        nc = Netcat("yaro-2.beginners.seccon.games", 5003)
        lines = nc.read().decode("utf-8").split("\n")
        s = (
            f"""rule a"""
            + """ {"""
            + f"""strings:
            $shebang = "{attack}"
        condition:
            $shebang"""
            + """}


        """
        )
        nc.write(s)
        lines = nc.read().decode("utf-8").split("\n")
        for line in lines:
            if len(line) > 9:
                if line[9] == "f":
                    x += c
                    if c == "}":
                        print(attack)

        nc.close()
```

flag > `ctf4b{Y3t_An0th3r_R34d_Opp0rtun1ty}`


### polyglot4b(解けなかった)
polyglotに関する問題？  
`test_script.sh`を、ncコマンドの部分を`nc polyglot4b.beginners.seccon.games 31416`に変更して実行してみると、jpgだけ緑になって返ってくる。どうやらjpgファイルを認識しているっぽい。`polyglot4b.py`を見ても、
- 送られてきたものをファイルとして保存
- その形式を確認
- その形式がJPG,PNG,GIF,TXT(ASCII)であればその項目を緑にして返す
といった形のようです。  
考えた方法としては
- 複数のファイルを送ることはできないか
- 複数の形式として読み取れてしまうファイルを送ることはできないか(←これは問題文からの推測)
でした。ただ、、その具体的な方法はよく分からず。ヘッダ部分の工夫でなんとかなりそうだけど、、、。  

## reversing
### Half
与えられたファイルを解凍し、stringsをかけてみると、見つかった。すんなりできてctfに慣れてきた気分に慣れました。いぇい！  

# 最後に
読んでいただきありがとうございました。Begginerがいくつか解けなかったのが悔しいので復習します。Cryptoが得意っぽいことがわかりました。あと、とても楽しかったです！