Skip to content

Commit

Permalink
VrnCTF-6 tasks
Browse files Browse the repository at this point in the history
  • Loading branch information
DeviJoe committed May 2, 2024
0 parents commit efa1d7a
Show file tree
Hide file tree
Showing 215 changed files with 29,509 additions and 0 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# VrnCTF 6 Kids

![](images/scoreboard_1.png)
Empty file added images/.gitkeep
Empty file.
Binary file added images/scoreboard_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
76 changes: 76 additions & 0 deletions tasks/captcha/challenge.yml
Original file line number Diff line number Diff line change
@@ -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"
5 changes: 5 additions & 0 deletions tasks/captcha/deploy/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM python:alpine
WORKDIR /app
COPY . .
RUN pip install flask
CMD [ "python3", "main.py" ]
8 changes: 8 additions & 0 deletions tasks/captcha/deploy/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
version: '3.1'

services:
captcha:
build: .
restart: always
ports:
- "86:8080"
45 changes: 45 additions & 0 deletions tasks/captcha/deploy/main.py
Original file line number Diff line number Diff line change
@@ -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! <a href='/'>Will you try again?</a>")
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! <a href='/'>Will you try again?</a>")
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)
43 changes: 43 additions & 0 deletions tasks/captcha/deploy/my_math.py
Original file line number Diff line number Diff line change
@@ -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)
40 changes: 40 additions & 0 deletions tasks/captcha/deploy/templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Prove that you are not a robot</title>
</head>
<body style="background-image:url('kafif.jpg'); background-size: cover; background-repeat: no-repeat;">
<div style="float: left; margin-right: 20px; margin-bottom: 20px; border: 1px solid; border-radius: 10px;">
<h3>Count: {%if count %} {{ count }} {% else %} 0 {% endif %} / 1000</h3>
</div>

{% if captcha %}
<div style="text-align: center;">
{{captcha}}
</div>
{% endif %}
<center>
<div style="text-align: center; margin-bottom: 20px;">
<form action="/" method="POST">
<label for="answer">Answer:</label>
<br>
<input type="text" name="answer" required>
<button type="submit">Submit</button>
</form>
</div>

{% if message %}
<div style="text-align: centerl;">
<p>{{ message | safe }}</p>
</div>
{% endif %}

</body>

</html>

</body>
</html>
Binary file added tasks/captcha/deploy/templates/kafif.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions tasks/captcha/solution/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Решение

sploit.py
43 changes: 43 additions & 0 deletions tasks/captcha/solution/my_math.py
Original file line number Diff line number Diff line change
@@ -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)
15 changes: 15 additions & 0 deletions tasks/captcha/solution/sploit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import requests
from my_math import eval_expr

curl = requests.session()
i = 0
url = <url>
port = <port>
req = curl.get(f"http://{url}:{port}")
expr = req.text.split('<div style="text-align: center;">\n')[1].split("\n")[0].strip()
while i != 1000:
req = curl.post(f"http://{url}:{port}", data={"answer": eval_expr(expr)})
expr = req.text.split('<div style="text-align: center;">\n')[1].split("\n")[0].strip()
i += 1
req = curl.post(f"http://{url}:{port}", data={"answer": eval_expr(expr)})
print(req.text)
39 changes: 39 additions & 0 deletions tasks/cat_site/challenge.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Обязательные поля
# Имя задачи на CTFd
name: We only have paws...
# Никнейм в Telegram
author: "@lumen_02"
# Описание таска на платформе.
description: |
`@lumen_02`
Хоть Кафиф и очень смышлённый кот, навыков вёрстки ему всё же не хватает. Сайт получился довольно кривым, но Кафифа можно понять - у него лапки)
category: web
# Оставляем как есть - цена таски
value: 100
# Не трогаем - тип соревнования
type: dynamic

connection_info: https://catlab.tasks.ctf.vrnctf.ru

extra:
# Стартовая цена
initial: 100
# Сколько команд должны решить, чтобы цена упала до минимума
decay: 10
# Минимальная цена
minimum: 10

# Флаги. Их может быть очень много, но обычно делают один
flags:
- {
type: "static",
content: "vrnCTF{samAya-blag0RodNaya-p0roDa-koShk3k}",
data: "case_insensitive",
}

# Отображение на платформе. visible/hidden
state: visible
# Версия вашей задачи
version: "0.1"
7 changes: 7 additions & 0 deletions tasks/cat_site/deploy/compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
services:
nginx:
image: nginx:latest
ports:
- "81:80"
volumes:
- .:/usr/share/nginx/html
36 changes: 36 additions & 0 deletions tasks/cat_site/deploy/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Сайт о кошках</title>
<link rel="stylesheet" href="styles.css">
</head>

<body>
<div id="header-line">
<div id="header">Добро пожаловать на сайт о кошках!</div>
<div id="hint"><a href="index1.html" class="text"><u>Подсказка</u></a></div>
</div>

<section id="registration-form">
<h2 id "labb">Введите породу:</h2>
<form id="registration" action="#" method="post">
<input type="text" id="username" name="username">
<button type="submit" id="butt">Ок</button>
</form>
</section>

<div id="breeds-line">
<div id="breeds-list"> <u>Список НЕ уникальных пород:</u></div>
<div id="breeds-list2"><u>Список уникальных пород:</u></div>
</div>

<div id="footer-line">
<div id="footer">Сайт делал НЕ РОБОТ, так что не судите строго, <br>у меня лапки..</div>
</div>
<script src="script.js"></script>
</body>

</html>
Loading

0 comments on commit efa1d7a

Please sign in to comment.