0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ctf upsolve by kodai Advent Calendar 2025(Day4)

Posted at

ctf upsolve by kodai Advent Calendar 2025のDay4の記事になります。

取り扱った問題

AlpacaHack Round 11 (Web) Jackpot
Author: Ark


upsolve

15個のスロットを全て7で揃えることができればFLAGをゲットできるという問題です。
image.png

単純に運で7を揃えることができる確率は以下のようになります。

\frac{1}{10^{15}}

現実的に運でどうにかなる問題ではないです。
そこで何とかして7を揃えるためにコードの実装を読んでみます。

from flask import Flask, request, render_template, jsonify
from werkzeug.exceptions import BadRequest, HTTPException
import os, re, random, json

app = Flask(__name__)
FLAG = os.getenv("FLAG", "Alpaca{dummy}")


def validate(value: str | None) -> list[int]:
    if value is None:
        raise BadRequest("Missing parameter")
    if not re.fullmatch(r"\d+", value):
        raise BadRequest("Not decimal digits")
    if len(value) < 10:
        raise BadRequest("Too little candidates")

    candidates = list(value)[:10]
    if len(candidates) != len(set(candidates)):
        raise BadRequest("Not unique")

    return [int(x) for x in candidates]


@app.get("/")
def index():
    return render_template("index.html")


@app.get("/slot")
def slot():
    candidates = validate(request.args.get("candidates"))

    num = 15
    results = random.choices(candidates, k=num)

    is_jackpot = results == [7] * num  # 777777777777777

    return jsonify(
        {
            "code": 200,
            "results": results,
            "isJackpot": is_jackpot,
            "flag": FLAG if is_jackpot else None,
        }
    )


@app.errorhandler(HTTPException)
def handle_exception(e):
    response = e.get_response()
    response.data = json.dumps({"code": e.code, "description": e.description})
    response.content_type = "application/json"
    return response


if __name__ == "__main__":
    app.run(debug=False, host="0.0.0.0", port=3000)

このコードを読んだときに分かった制約は以下です。

  • 文字列全体が1文字以上の0~9の数字だけで構成されていること
  • 文字に重複があってはいけないこと
  • 10文字目以降の数字は無視される

これらの制約の中で7を揃える方法を考えました。
\dにマッチする、かつreturnの中でユーザの入力をint型に変換してリストに入れているので、int型に変換した時に、7になれば良さそうです。

def validate(value: str | None) -> list[int]:
    if value is None:
        raise BadRequest("Missing parameter")
    if not re.fullmatch(r"\d+", value):
        raise BadRequest("Not decimal digits")
    if len(value) < 10:
        raise BadRequest("Too little candidates")

    candidates = list(value)[:10]
    if len(candidates) != len(set(candidates)):
        raise BadRequest("Not unique")

    return [int(x) for x in candidates]

\dについてPythonのreモジュールのドキュメントを見てみると以下のように書いてありました。

Matches any Unicode decimal digit (that is, any character in Unicode character category [Nd]). This includes [0-9], and also many other digit characters.

参考リンク: https://docs.python.org/3/library/re.html

なので数字の7を表すUnicode文字列を10種類探せばいいことが分かります。
探したものは7٧۷७৭୭൭૭7߇になります。これを入力してスロットを回すとFLAGがゲットできます。
FLAG : Alpaca{what_i5_your_f4vorite_s3ven?}

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?