搭建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试试,心里有个底

这里还有模版

https://github.com/CTF-Archives/ctf-docker-template

posted @ 2025-09-09 16:29  FuPo1  阅读(2)  评论(0)    收藏  举报