diff --git a/README.md b/README.md new file mode 100644 index 0000000..f0a4d7e --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# VrnCTF 6 Kids + + \ No newline at end of file diff --git a/images/.gitkeep b/images/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/images/scoreboard_1.png b/images/scoreboard_1.png new file mode 100644 index 0000000..bed4f07 Binary files /dev/null and b/images/scoreboard_1.png differ diff --git a/tasks/captcha/challenge.yml b/tasks/captcha/challenge.yml new file mode 100644 index 0000000..094e356 --- /dev/null +++ b/tasks/captcha/challenge.yml @@ -0,0 +1,76 @@ +# Манифест развертывания задачи на CTFd +# Полный пример можно посмотреть в документации -- https://github.com/CTFd/ctfcli/blob/master/ctfcli/spec/challenge-example.yml +# Необязательные, но нужные вам секции можно раскомментировать + +# Обязательные поля +# Имя задачи на CTFd +name: Captcha +# Никнейм в Telegram +author: "@kotz1k" +# Описание таска на платформе. +description: | + `@kotz1k` + + Кафиф гулял по цифровому простанству в поисках новых ресурсов, но наткнулся на капчу... +# Одна из следующих категорий: web, reverse, pwn, osint, joy, forensic, stegano, crypto +category: joy +# Оставляем как есть - цена таски +value: 100 +# Не трогаем - тип соревнования +type: dynamic + +extra: + # Стартовая цена + initial: 100 + # Сколько команд должны решить, чтобы цена упала до минимума + decay: 10 + # Минимальная цена + minimum: 10 + +# Опциональные настройки, включайте по мере необходимости +# Коннект к удаленной машине, может быть nc или URL к сайту +connection_info: cafmath.tasks.ctf.vrnctf.ru + +# Флаги. Их может быть очень много, но обычно делают один +flags: + - { + type: "static", + content: "vrnctf{y0u_p4553d_7h3_7357}", + data: "case_insensitive", + } + +# Примечания для админов, не видны участникам +# Разрешены строки + +# topics: +# - information disclosure +# - buffer overflow +# - memory forensics + +# Публичны, видят участники. Можно вешать теги на задачи +# tags: +# - web +# - sandbox +# - js + +# Секция с файликами, которые отдаются участниками. Относительный путь от папки public +# files: +# - public/task.zip + +# Подсказки. Можно передавать словари и строки +# hints: +# - { +# content: "This hint costs points", +# cost: 10 +# } +# - This hint is free + +# Если у вас задача зависит от другой, и не должна быть сдана до того, как решат первую - можно так сделать +# requirements: +# - "Warmup" +# - "Are you alive" + +# Отображение на платформе. visible/hidden +state: visible +# Версия вашей задачи +version: "0.1" \ No newline at end of file diff --git a/tasks/captcha/deploy/Dockerfile b/tasks/captcha/deploy/Dockerfile new file mode 100644 index 0000000..c79c809 --- /dev/null +++ b/tasks/captcha/deploy/Dockerfile @@ -0,0 +1,5 @@ +FROM python:alpine +WORKDIR /app +COPY . . +RUN pip install flask +CMD [ "python3", "main.py" ] \ No newline at end of file diff --git a/tasks/captcha/deploy/compose.yaml b/tasks/captcha/deploy/compose.yaml new file mode 100644 index 0000000..339e8b2 --- /dev/null +++ b/tasks/captcha/deploy/compose.yaml @@ -0,0 +1,8 @@ +version: '3.1' + +services: + captcha: + build: . + restart: always + ports: + - "86:8080" \ No newline at end of file diff --git a/tasks/captcha/deploy/main.py b/tasks/captcha/deploy/main.py new file mode 100644 index 0000000..c51abd2 --- /dev/null +++ b/tasks/captcha/deploy/main.py @@ -0,0 +1,45 @@ +from flask import Flask, request, render_template, session, url_for, redirect, send_file +from my_math import generate_expr, eval_expr + +app = Flask(__name__) +app.secret_key = "some_very_secret_key" +app.debug = False + +@app.route("/index", methods=["GET", "POST"]) +@app.route("/", methods=["GET", "POST"]) +def index(): + if not session: + session["count"] = 0 + if session["count"] == 1000: + return render_template("index.html", message = "vrnctf{y0u_p4553d_7h3_7357}") + if not session.get("captcha"): + session["captcha"] = generate_expr() + session["answer"] = eval_expr(session["captcha"]) + if request.method == "POST": + answer = request.form.get("answer") + try: + answer = int(answer) + except: + session["count"] = 0 + del session["captcha"] + return render_template("index.html", message = "You entered something bad! Will you try again?") + if int(answer) == session["answer"]: + session["count"] += 1 + session["captcha"] = generate_expr() + session["answer"] = eval_expr(session["captcha"]) + redirect(url_for("index")) + else: + session["count"] = 0 + del session["captcha"] + return render_template("index.html", message = "WRONG! Will you try again?") + return render_template("index.html", captcha = session["captcha"], count = session["count"]) + + +@app.route("/kafif.jpg", methods=["GET", "POST"]) +def download(): + path = "/app/templates/kafif.jpg" + return send_file(path, as_attachment=True) + + +if __name__=="__main__": + app.run(debug=True, host='0.0.0.0', port=8080) diff --git a/tasks/captcha/deploy/my_math.py b/tasks/captcha/deploy/my_math.py new file mode 100644 index 0000000..c9b51eb --- /dev/null +++ b/tasks/captcha/deploy/my_math.py @@ -0,0 +1,43 @@ +import random +import ast +import operator + +def generate_expr(): + ops = ["+", "-", "*"] + a = random.randint(1, 10) + b = random.randint(1, 10) + c = random.randint(1, 10) + d = random.randint(1, 10) + e = random.randint(1, 10) + op1 = random.choice(ops) + op2 = random.choice(ops) + op3 = random.choice(ops) + op4 = random.choice(ops) + expr = f"{a} {op1} {b} {op2} {c} {op3} {d} {op4} {e}" + + return expr + +def eval_expr(expr): + tree = ast.parse(expr, mode='eval') + + ops = { + ast.Add: operator.add, + ast.Sub: operator.sub, + ast.Mult: operator.mul, + ast.Div: operator.truediv, + ast.USub: operator.neg, + } + + def eval_node(node): + if isinstance(node, ast.Num): + return node.n + elif isinstance(node, ast.BinOp): + left = eval_node(node.left) + right = eval_node(node.right) + return ops[type(node.op)](left, right) + elif isinstance(node, ast.UnaryOp): + return ops[type(node.op)](eval_node(node.operand)) + else: + raise TypeError(f"Unsupported node type: {type(node)}") + + return eval_node(tree.body) \ No newline at end of file diff --git a/tasks/captcha/deploy/templates/index.html b/tasks/captcha/deploy/templates/index.html new file mode 100644 index 0000000..f72deb8 --- /dev/null +++ b/tasks/captcha/deploy/templates/index.html @@ -0,0 +1,40 @@ + + +
+ + + +{{ message | safe }}
+