wanictf2024

# waniCTF2024
運営のみな様、お疲れさまでした。3問くらいは解いたのでwriteupを書きました。

## [Rev] lambda
見たらラムダ式を使って冗長にされたコードだと分かります。
```python
import sys

sys.setrecursionlimit(10000000)

(lambda _0: _0(input))(lambda _1: (lambda _2: _2('Enter the flag: '))(lambda _3: (lambda _4: _4(_1(_3)))(lambda _5: (lambda _6: _6(''.join))(lambda _7: (lambda _8: _8(lambda _9: _7((chr(ord(c) + 12) for c in _9))))(lambda _10: (lambda _11: _11(''.join))(lambda _12: (lambda _13: _13((chr(ord(c) - 3) for c in _10(_5))))(lambda _14: (lambda _15: _15(_12(_14)))(lambda _16: (lambda _17: _17(''.join))(lambda _18: (lambda _19: _19(lambda _20: _18((chr(123 ^ ord(c)) for c in _20))))(lambda _21: (lambda _22: _22(''.join))(lambda _23: (lambda _24: _24((_21(c) for c in _16)))(lambda _25: (lambda _26: _26(_23(_25)))(lambda _27: (lambda _28: _28('16_10_13_x_6t_4_1o_9_1j_7_9_1j_1o_3_6_c_1o_6r'))(lambda _29: (lambda _30: _30(''.join))(lambda _31: (lambda _32: _32((chr(int(c,36) + 10) for c in _29.split('_'))))(lambda _33: (lambda _34: _34(_31(_33)))(lambda _35: (lambda _36: _36(lambda _37: lambda _38: _37 == _38))(lambda _39: (lambda _40: _40(print))(lambda _41: (lambda _42: _42(_39))(lambda _43: (lambda _44: _44(_27))(lambda _45: (lambda _46: _46(_43(_45)))(lambda _47: (lambda _48: _48(_35))(lambda _49: (lambda _50: _50(_47(_49)))(lambda _51: (lambda _52: _52('Correct FLAG!'))(lambda _53: (lambda _54: _54('Incorrect'))(lambda _55: (lambda _56: _56(_41(_53 if _51 else _55)))(lambda _57: lambda _58: _58)))))))))))))))))))))))))))

```
まず継続渡し形式になってるので、単純作業でβ簡約していきます。
４０分くらいするとこれくらいになります。
```python
print('Correct FLAG!'
 if 
 (
    (
        (
            (lambda _37: lambda _38: _37 == _38)
        )

        (
            (
                (''.join((((lambda _20: ''.join((chr(123 ^ ord(c)) for c in _20)))(c) 
                for c in 
                (''.join(
                    (
                        (chr(ord(c) - 3) for c in ''.join((chr(ord(c) + 12) for c in input('Enter the flag: '))))
                    )))))))
            )
        )
    )
    (
        (
            (''.join(((chr(int(c,36) + 10) for c in '16_10_13_x_6t_4_1o_9_1j_7_9_1j_1o_3_6_c_1o_6r'.split('_')))))
        )
    )
)
 else 'Incorrect')
```
…はい、つらいですね。
ちなみに最初、chrを
```python
def pchr(a):
    print(a)
    return chr(a)
```
の様にして、コードを置換（chr->pchr)してフラグが取れないか試しましたが、入力にも処理をして、フラグにも処理をして一致するのかを判定しているので、ダメでした。（ずるをするような、ちゃんと単純な思考のリバーシングする人たちは弾かれる）
正直処理の部分はラムダ式にしてないし、３項単子演算子でさらっと書いてるし、読み解くだけで解けたきがしましたが、Lisperとしての意地があるので、全部β簡約します

```python
print('Correct FLAG!' if ''.join(''.join(chr(123 ^ (ord(c) + 9))) for c in input('Enter the flag: ')) == (''.join(((chr(int(c,36) + 10) for c
 in '16_10_13_x_6t_4_1o_9_1j_7_9_1j_1o_3_6_c_1o_6r'.split('_')))))  else 'Incorrect')
 ```
 こうなりました
なんだこの自明なコード…

はい、123とのxor演算と９の足し算なので逆演算してフラグゲットです。（順番最初間違えたりしたけど…）
```python
>>> ''.join(''.join(chr(123 ^ (ord(c)-9)) for c in (''.join(((chr(int(c,36) + 10) for c in '16_10_13_x_6t_4_1o_9_1j_7_9_1j_1o_3_6_c_1o_6r'.split('_'))))))
... )
'P^SY\x8d~FqCsqCF\x7f|vF\x8f'
>>> ''.join(''.join(chr(123 ^ ord(c)) for c in (''.join(((chr(int(c,36) + 10) for c in '16_10_13_x_6t_4_1o_9_1j_7_9_1j_1o_3_6_c_1o_6r'.split('_'))))))
... )
'OUJP\x84u=h:jh:=vkm=\x86'
>>> ''.join(chr(ord(c) - 9) for c in 'OUJP\x84u=h:jh:=vkm=\x86')
'FLAG{l4_1a_14mbd4}'
>>>
```
はい。正直めっちゃ楽しかったです。欲を言えば継続渡し形式ならではとかの問題にはしてほしかったです。クロージャも渡してたし、β簡約しやすかったので満足ではあるんですけども。

## [Web] Bad_Woker
名前からservicewokerが関わってそうと考えて確認するとセキュリティポリシーが良くない
![woker.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090905/39605891-f6c7-6364-59df-95520074ddf2.png)
普通にデベロッパーツールでDUMMY.txtに置き換えられてる部分をFLAG.txtにしてリロードしてクリックでおｋ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090905/8600a399-09ca-d1cf-d1fc-aadb87b0c55d.png)
![該当箇所.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090905/25abbd9f-14f4-3ad8-1f86-bb97c9d8e7a6.png)
はい、問題の名前を確認するのは大事

## [Web] pow
ハッシュを計算し続けるとどれだけいいパソコンでもちょっと億年かかりそうなので、ちゃんと１億年ボタンを探します。
![web-pow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090905/b7fe70ff-c9ac-b891-2f38-043c7fbdaa87.png)
とりあえずapiの投げるやつを自動化して投げ続けます。ここで、一度通る値は何度も使えることがわかりました。
![web-pow-console-two.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090905/c85e33bc-71d2-aa0a-f61d-6a8654f37c08.png)
しかし、普通にリミットがありました。うーん適切。負荷対策は大事。
![web-pow-console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090905/104faeb7-9634-9eee-19d8-aacf04918015.png)
まあ王道に、配列の要素を0にしたり、ペイロードを入れたりしますが、普通に要素を2つやると一回で2の進捗を上げれることが判明しました。…なるほど。
![web-pow-postman.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090905/5eeb019a-c2fc-9e9e-891b-128d1f2dc209.png)
あとはやること一つです。これをこう！！！
![web-pow-postman-flag.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090905/06c33765-8aa8-c10a-dce8-1f227d7c4683.png)
これによって一回で増やせる量が50000なので20回くらいで到達します。

# 感想
フラグをメモってたり、メモってなかったり適当な記録をそろそろやめなきゃなあ…
難易度としては、ジャンルごとに大分違ったけど、まあ解けたほうが嬉しいみたいな難易度で、CTFを始めて実力をつけたいひとはBeginnerとeasyは解けるようになっておくとよさそう。
自分は得意ジャンルのRevがeasyどまりだったのでもうCTFをやりません。
writeupをここまで読んでくれた皆様お疲れさまでした。
良いCTFライフを。
改めまして、今回のCTFに関わった運営の皆様お疲れさまでした。
楽しかったです。