搭建GZCTF平台及上传动态flag密码题目过程
平台的搭建
记得用桥接模式
在ubuntu上创建'GZCTF'文件夹,包含这些文件
这个ip地址貌似不能直接ifconfig得到,我忘记是怎么找到的了,如果你们搭建过程中报错可以问问ai原因
appsettings.json
{
"AllowedHosts": "*",
"ConnectionStrings": {
"Database": "Host=db:5432;Database=gzctf;Username=postgres;Password=Admin123"
},
"EmailConfig": {
"SendMailAddress": "a@a.com",
"UserName": "",
"Password": "",
"Smtp": {
"Host": "localhost",
"Port": 587
}
},
"XorKey": "Admin123",
"ContainerProvider": {
"Type": "Docker",
"PortMappingType": "Default",
"EnableTrafficCapture": false,
"PublicEntry": "你的ip",
"DockerConfig": {
"SwarmMode": false,
"Uri": "unix:///var/run/docker.sock"
}
},
"RequestLogging": false,
"DisableRateLimit": true,
"RegistryConfig": {
"UserName": "",
"Password": "",
"ServerAddress": ""
},
"CaptchaConfig": {
"Provider": "None",
"SiteKey": "<Your SITE_KEY>",
"SecretKey": "admin",
"GoogleRecaptcha": {
"VerifyAPIAddress": "https://www.recaptcha.net/recaptcha/api/siteverify",
"RecaptchaThreshold": "0.5"
}
},
"ForwardedOptions": {
"ForwardedHeaders": 5,
"ForwardLimit": 1,
"TrustedNetworks": ["你的ip/8"]
}
}
docker-compose.yml
version: "3.0"
services:
gzctf:
image: gztime/gzctf:latest
restart: always
environment:
- "LANG=zh_CN.UTF-8"
- "GZCTF_ADMIN_PASSWORD=Admin123"
ports:
- "80:8080"
volumes:
- "./data/files:/app/files"
- "./appsettings.json:/app/appsettings.json:ro"
- "/var/run/docker.sock:/var/run/docker.sock"
depends_on:
- db
db:
image: postgres:alpine
restart: always
environment:
- "POSTGRES_PASSWORD=Admin123"
volumes:
- "./data/db:/var/lib/postgresql/data"
在GZCTF文件夹下运行
docker-compose up -d
系统会在GZCTF文件夹里生成data文件夹
在win上输入你在json里写的ip,就可以进入平台
创建镜像
动态flag
docker-compose.yml
version: '3'
services:
chal:
build: .
environment:
FLAG: "flag{test_dummy}"
ports:
- "9999:9999"
restart: unless-stopped
Dockerfile
FROM python:3.10.12-slim-bullseye
# apt源换USTC
RUN sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list && \
sed -i 's/security.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
RUN apt-get update && apt-get install -y socat
# 安装python依赖
RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pycryptodome sympy
# 创建用户
RUN useradd -m ctf
WORKDIR /home/ctf
# 拷贝文件
COPY ./src/server.py /home/ctf/server.py
COPY ./service/docker-entrypoint.sh /docker-entrypoint.sh
RUN chmod +x /docker-entrypoint.sh
# 入口
ENTRYPOINT ["/bin/sh","/docker-entrypoint.sh"]
service/docker-entrypoint.sh
#!/bin/sh
# 获取flag优先级
if [ "$GZCTF_FLAG" ]; then
INSERT_FLAG="$GZCTF_FLAG"
export GZCTF_FLAG=no_FLAG
elif [ "$FLAG" ]; then
INSERT_FLAG="$FLAG"
else
INSERT_FLAG="flag{TEST_Dynamic_FLAG}"
fi
# 写入 /flag
echo $INSERT_FLAG > /flag
chmod 600 /flag
# socat启动python
# 监听9999端口
socat -s TCP-LISTEN:9999,reuseaddr,fork EXEC:"python3 -u /home/ctf/server.py"
src/server.py
#!/usr/bin/env python3
from Crypto.Util.number import *
from random import getrandbits
import sympy, os, sys
# 从文件读取 flag
def get_flag():
try:
with open("/flag","rb") as f:
return f.read().strip()
except:
return b"GZCTF_FLAG_NOT_SET"
FLAG = get_flag()
flag1 = FLAG[:len(FLAG)//2]
flag2 = FLAG[len(FLAG)//2:]
# 彩色 Banner(只展示一次)
print('''
\033[91m ____ __ _ ____ __ ___ __ __ ________ ______ ______
\033[92m / __ \ / / / | / / / / / |__ \ // / / / ____/ |/ / | / ____/
\033[93m / / / / / / / |/ / / / / __/ ///_/ / / / __/ /|_/ / /| | / __/
\033[93m / /_/ / / /___/ /| / /_/ / / __/ / / / /_/ / / / / ___ |/ /___
\033[94m \___\_\/_____/_/ |_/\____/ /____/ /_/ \____/_/ /_/_/ |_/_____/
\033[0m
''')
class V_cha:
def __init__(self):
self.P1 = getPrime(1036)
self.P2 = sympy.nextprime(self.P1)
assert self.P2 - self.P1 < 1000
self.Q1 = getPrime(512)
self.Q2 = sympy.nextprime(self.Q1)
self.e1 = getPrime(1024)
self.e2 = sympy.nextprime(self.e1)
self.N1 = self.P1 * self.P1 * self.Q1
self.N2 = self.P2 * self.P2 * self.Q2
def enc(self):
return self.N1, self.N2, self.e1, self.e2
def encrypt_flag(self):
m1 = bytes_to_long(flag1)
m2 = bytes_to_long(flag2)
c1 = pow(m1, self.e1, self.N1)
c2 = pow(m2, self.e2, self.N2)
return c1, c2
def keykey():
x1 = getrandbits(32)
x2 = getrandbits(32)
print("solve this: ", x1, "+", x2, "=?")
sys.stdout.flush()
try:
result = int(sys.stdin.readline())
except:
exit(0)
if result != x1 + x2:
print("wrong!")
exit(0)
else:
print("ok!")
def main():
print("welcome to V_Challenge")
A = V_cha()
coin = 5
while coin > 0:
print("1) verify")
print("2) get ciphertext")
print("3) get N & e")
print("4) exit")
sys.stdout.flush()
choose = sys.stdin.readline().strip()
if choose == "1":
keykey()
coin -= 1
elif choose == "2":
c1, c2 = A.encrypt_flag()
print(f"c1 = {c1}\nc2 = {c2}")
coin -= 1
elif choose == "3":
N1, N2, e1, e2 = A.enc()
print(f"N1 = {N1}\nN2 = {N2}\ne1 = {e1}\ne2 = {e2}")
coin -= 1
elif choose == "4":
print("bye~")
# 线上比赛可以选择不输出flag,或输出完整flag
try:
print(FLAG.decode())
except:
print(str(FLAG))
break
else:
print("wrong input")
sys.stdout.flush()
print("奥利给!!!!!")
if __name__ == "__main__":
main()
在V_cha文件夹下,也就是dockerfile文件所在地址运行命令
docker build -t v_challenge .
docker run -it --rm -p 9999:9999 \
-e GZCTF_FLAG="flag{TEST_DYNAMIC_LOCAL}" \
v_challenge
#这个命令的好处就是暂定flag,nc检查完后直接ctrl+c就可以关闭容器了,不用一个一个删掉测试容器
然后把镜像的名字复制到题目管理下的镜像下就可以了
ps:最好让ai帮你写,不累
有什么问题多问gpt,把报错发给它,一点一点试
保证你的题目docker正确,如果不确定,最好先用已经成功了的题目docker试试,心里有个底
这里还有模版