基于 Docker 的 AWD 平台搭建与使用完整教程(含环境修复与比赛操作)

AWD平台搭建与使用完整教程

一、AWD赛事规则

1. 赛事基础信息

(1)赛事定位

本赛事为 CTF 攻防对抗(AWD)模式,核心考察参赛队伍的实战攻防综合能力:参赛队伍需同步完成两项核心任务——自身靶机服务加固(防御端)其他队伍靶机漏洞利用(攻击端),最终以攻防表现综合计分排名。

(2)环境配置

配置项 详细说明
靶机部署 基于 Docker 容器化部署,采用官方稳定基础镜像(如 Ubuntu 20.04 LTS);每队分配 1-3 台靶机,以 Linux 系统为主,预装 Web 服务(Apache/Nginx)、中间件(Tomcat/PHP-FPM)、数据库(MySQL/MongoDB)等,初始环境完全一致。
访问权限 仅提供低权限账户(如 ctf 用户),通过 SSH(默认 22 端口)或 VNC 连接;禁止通过提权工具(如 sudo 滥用、内核漏洞提权)获取 root 权限,一经检测视为违规。
辅助环境 可选配流量分析虚拟机(预装 Wireshark、tcpdump 等工具),提供实时流量日志下载(路径由主办方赛前告知),仅用于本队攻防分析,禁止用于攻击其他队伍。
平台限制 赛事提交平台(含 API 接口)、裁判系统、网关/DNS 服务器均为 非攻击目标,禁止对其发起任何网络请求(含扫描、访问、攻击)。

2. 赛事流程

阶段 时长 核心任务及限制
赛前准备 10 分钟 1. 领取本队靶机 IP、账户密码、唯一身份 token 凭证;
2. 确认赛事提交平台 API 地址及测试提交有效性;
3. 禁止提前扫描任何网段或尝试连接其他队伍靶机。
服务发现 & 加固 30 分钟 1. 仅允许操作本队靶机:扫描端口(如 nmap)、审计源码、备份数据、修复漏洞;
2. 此阶段 不计分,且禁止对其他队伍靶机发起任何网络连接。
攻防对抗 180 分钟 1. 攻击端:利用漏洞获取其他队伍 Flag 并提交;
2. 防御端:维护自身服务可用性,拦截攻击并修复新漏洞;
3. 实时计分,每 2 分钟为 1 轮计分周期。
结果公示 10 分钟 1. 公布最终排名、总分及扣分详情;
2. 参赛队伍可现场提出分数异议,裁判需在 5 分钟内核查并答复。

3. 核心环节规则

(1)服务发现规范

允许操作
  • 端口扫描:使用 nmap 等工具扫描 本队靶机及赛事指定 C 段(如 nmap -sn 192.168.10.0/24),探测存活主机及开放端口;
  • 服务探测:通过 httpscan、dirsearch、gobuster 等工具,检测 Web 服务路径、备份文件(如 .sql.bak)、敏感目录(如 admin/);
  • 配置排查:查找靶机内服务配置文件(如 Nginx 的 nginx.conf、PHP 的 php.ini、MySQL 的 my.cnf),定位服务根目录及关键参数。
禁止行为
  • 提前攻击:在“服务发现 & 加固”阶段结束前,对其他队伍靶机发起漏洞利用、连接测试等攻击行为;
  • 跨网段扫描:禁止扫描非赛事指定的网段(如主办方办公网络、公网地址);
  • 攻击辅助环境:禁止扫描、访问或攻击流量分析虚拟机、赛事提交平台、裁判系统等非靶机设备。

(2)防御操作规则

基础加固要求
  1. 数据备份:必须备份 Web 源码(如 /var/www/html)及数据库(通过 mysqldump 等工具);允许 3 次一键恢复(因自身配置失误导致服务故障时使用),每次恢复扣 5 分,超过 3 次恢复不计分且需自行排查故障。
  2. 弱口令修复:修改所有默认账户密码(如 MySQL 默认 root/root、PHPStudy 默认 123456、Web 后台默认 admin/admin),密码需满足“8 位以上 + 字母大小写 + 数字 + 特殊符号”复杂度。
  3. 权限控制:禁用无用账户(如 guesttest);限制数据库仅本地登录(修改 my.cnfbind-address=127.0.0.1);设置 Web 目录权限为 755(文件为 644),禁止 www-data 等服务账户拥有执行权限。
漏洞修复原则
  • 允许通过代码审计工具(如 Seay 代码审计系统、Burp Suite)定位漏洞,采用“过滤危险函数(如 PHP 的 eval()exec())、注释危险代码、添加输入验证”等方式修复;
  • 可部署自定义 WAF(Web 应用防火墙):通过 PHP 的 auto_prepend_file 加载 WAF 脚本,或在 Nginx 配置中添加拦截规则,需确保 WAF 不影响服务正常访问(如 HTTP 200 响应),且需记录攻击日志(供裁判核查)。
服务器停止工作处理
  • 自身原因宕机:因误删系统文件、配置错误(如 Nginx 配置语法错误)、加固过度(如关闭核心服务)导致靶机宕机,可联系技术支持重启靶机,每重启 1 次扣 10 分,且该轮服务可用分记为 0;
  • 他人违规攻击宕机:若因其他队伍发起 DoS/DDoS、删除关键文件等违规行为导致宕机,需在 5 分钟内提交流量日志、进程记录等证据,经裁判核实后:
    • 违规队伍按“恶意破坏服务”条款处罚;
    • 本队不扣除服务可用分,且恢复该轮应得分数。
禁止操作
  • 关闭核心服务:禁止停止 Apache、Nginx、MySQL、Docker Daemon 等赛事指定核心服务,导致主办方 Check 失败;
  • 删除必要文件:禁止删除赛事标记文件(如 /etc/ctf-marker)、靶机系统文件(如 /bin/bash)或服务依赖文件;
  • 过度防御:禁止部署“一刀切”拦截规则(如拦截所有 HTTP POST 请求),导致服务无法正常提供(主办方 Check 返回非 200 状态码)。

(3)攻击操作规则

Flag 机制
  • 生成规则:Flag 每 2 分钟刷新 1 轮,存放于靶机 固定指定路径(如 /tmp/flag/var/www/flag.txt),格式为 flag{随机 32 位字符串}(如 flag{8a3f2d7c9e1b4567890a1b2c3d4e5f6g});
  • 提交要求:通过赛事平台 API 提交(格式:https://[平台域名]/submit?token=[本队 token]&flag=[获取的 Flag]),重复提交无效(仅首次有效提交计分),提交虚假 Flag(非靶机生成)视为违规。
允许攻击手段
  • 漏洞利用:通过 SQL 注入、XSS、文件上传、反序列化、命令注入、PWN(缓冲区溢出)等漏洞,获取靶机低权限或读取 Flag;
  • 权限维持:可在靶机内种植“不死马”(如循环生成隐藏脚本、定时任务反弹 Shell),但需确保 不破坏服务可用性(如不占用 80% 以上 CPU/内存、不删除 Web 源码);
  • 信息收集:通过攻击获取的低权限,收集其他队伍靶机内的服务配置、漏洞信息,用于后续攻击。
严格禁止行为(含 DDoS 细化禁止)
  • 任何形式的 DoS/DDoS 攻击
    1. 流量压制:通过 TCP/UDP 洪水、ICMP ping 风暴、SYN Flood 等方式,占用靶机带宽(如每秒发包超 1000 个);
    2. 资源耗尽:高频访问靶机服务(如每秒请求超 10 次)、运行挖矿脚本、创建大量空文件,导致 CPU/内存/磁盘占用超 90%;
    3. 进程破坏:杀死靶机核心进程(如 apache2mysqlddocker)、停止服务(如 systemctl stop nginx);
  • 暴力破解:禁止使用工具(如 Hydra、Medusa)对其他队伍靶机的 SSH、MySQL、Web 后台等账户进行暴力破解(仅允许利用已知弱口令登录);
  • 恶意破坏:篡改其他队伍 Web 源码(如删除 index.php、替换为恶意页面)、格式化靶机磁盘、删除 Docker 容器,导致服务 永久宕机且无法快速恢复
  • 攻击非靶机目标:禁止对赛事提交平台、裁判系统、其他队伍的流量分析虚拟机发起任何攻击(含扫描、访问、漏洞利用)。

4. 计分与排名规则

(1)基础计分(每 2 分钟 1 轮,实时累计)

计分项目 分值 详细说明
服务可用 +1 分 主办方通过脚本 Check 本队靶机核心服务(如 Web 服务返回 HTTP 200、MySQL 可正常连接),响应正常则得分。
服务不可用 -1 分 服务宕机、无响应或 Check 返回非指定状态码(如 404、502);该扣分由 本轮所有服务正常的队伍均分(例:本轮 10 队中 2 队不可用,8 队正常,每正常队均分 2×1/8=0.25 分)。
提交有效 Flag +2 分 每成功提交 1 个其他队伍的有效 Flag 得 2 分,同一 Flag 重复提交不累计(仅首次有效提交计分)。
自身 Flag 被获取 -2 分 本队 Flag 被其他队伍获取并成功提交;该扣分由 所有获取该 Flag 的队伍均分(例:本队 Flag 被 3 队获取,每获取队均分 2/3≈0.67 分)。

(2)排名规则

  1. 优先按 总分降序 排名;
  2. 若总分相同,比较 有效 Flag 获取总数(获取越多排名越靠前);
  3. 若总分与 Flag 数量均相同,比较 服务可用率(服务可用轮数 / 总攻防轮数,可用率越高排名越靠前);
  4. 若上述三项均相同,比较 最后一轮得分(得分高者排名靠前)。

5. 违规处罚

违规行为 处罚措施
首次实施 DoS/DDoS 攻击、恶意破坏服务 扣除当前总分的 50%,在赛事群内通报批评,记录违规一次。
二次违规(含重复 DoS、攻击平台) 直接取消赛事资格,清空所有分数,禁止参与本次赛事后续环节。
提交虚假 Flag 干扰裁判 每提交 1 次扣 10 分;累计 3 次提交虚假 Flag,取消赛事资格。
攻击赛事平台/辅助环境/非靶机目标 视为严重违规,直接取消资格,通报所有参赛队伍,并禁止参与主办方后续赛事。
提权获取 root 权限/使用未授权工具(如木马) 取消赛事资格,清空分数,且需配合裁判核查工具来源。
导致靶机永久无法恢复(如格式化磁盘) 取消资格,通报批评,并需承担靶机重建的技术成本(视情况追偿)。

6. 附则

  1. 赛事技术支持仅协助解决 环境故障(如 Docker 容器崩溃、靶机无法连接),不提供漏洞提示、加固建议等技术指导;
  2. 参赛队伍需自行记录攻防操作日志(如攻击脚本执行记录、防御配置修改记录),裁判有权要求提交日志核查,拒绝提交视为违规
  3. 主办方拥有规则最终解释权,可根据现场情况(如大规模环境故障、违规行为频发)调整计分权重、攻防时长,调整后将第一时间通知所有队伍;
  4. 赛事期间禁止抄袭其他队伍的攻防方案(如复制攻击脚本、抄袭 WAF 规则),一经发现,扣除当前总分的 30%,抄袭累计 2 次取消资格。

二、AWD平台搭建步骤

1. 克隆AWD平台资源

执行以下命令克隆官方仓库到本地:

1
sudo git clone https://github.com/zhl2008/awd-platform.git

2. 安装Docker与Docker Compose

通过 APT 包管理器安装基础依赖工具:

1
apt install docker && apt install docker-compose

3. Docker换源(提升镜像下载速度)

使用 LinuxMirrors 提供的脚本一键换源,命令如下:

1
bash <(curl -sSL https://linuxmirrors.cn/docker.sh)

换源后效果:脚本会自动配置国内 Docker 镜像源(如阿里云、网易云),后续下载镜像速度显著提升(从 KB/s 级提升至 MB/s 级)。

4. 查看AWD平台目录结构

克隆完成后,进入 awd-platform 目录并查看核心文件:

1
2
cd awd-platform
ls -l # 列出目录下所有文件

核心目录结构(截图说明):

(包含 batch.py(队伍配置生成脚本)、start.py(环境启动脚本)、check_server(裁判机目录)等关键文件)

5. 下载AWD靶机镜像

执行以下命令拉取指定版本的靶机镜像(基于 Ubuntu 14.04,预装 Web 服务):

1
docker pull zhl2008/web_14.04

镜像下载效果(截图说明):

(镜像大小约 500MB,下载完成后可通过 docker images 查看)

6. 初始化队伍与环境

6.1 创建队伍配置(以3支队伍为例)

执行 batch.py 脚本生成 3 支队伍的基础配置文件:

1
python2 batch.py web_yunnan_simple 3

执行效果(截图说明):

(脚本会生成 team1team2team3 目录,每个目录包含靶机启动配置)

6.2 修正镜像名称(关键步骤)

由于后续脚本依赖默认镜像名 web_14.04,需执行以下命令重命名镜像:

1
sudo docker tag zhl2008/web_14.04 web_14.04

6.3 生成队伍运行环境

基于上述配置,执行 start.py 创建实际的靶机容器与裁判机环境:

1
python2 start.py ./ 3

执行效果(截图说明):

(初始化完成后,会自动启动 3 台靶机容器 + 1 台裁判机容器,可通过 docker ps 查看运行状态)

7. 启动裁判机与Check服务

裁判机负责周期性检测各队伍靶机存活状态、服务可用性并实时计分,启动步骤如下:

  1. 连接裁判机容器(容器名通常为 check_server):
    1
    docker attach check_server
  2. 激活交互环境:进入容器后,需先按 回车键 唤醒命令行,再执行 Check 脚本:
    1
    python2 check.py
    启动效果(截图说明):

    (Check 服务每 5 分钟(300 秒)检测一轮,输出各靶机“存活/宕机”状态)

8. 关闭AWD环境(资源清理)

如需停止所有靶机、裁判机并释放资源,执行清理脚本:

1
python2 stop_clean.py

清理效果(截图说明):

(脚本会自动停止并删除所有相关 Docker 容器,避免占用 CPU/内存资源)

三、靶机问题修复(必做步骤)

默认搭建的靶机存在 Check 服务异常Flag 重复提交漏洞 等问题,需按以下步骤修复,否则无法正常计分。

1. 修改Check脚本(修复服务检测逻辑)

编辑裁判机内的 check.py 文件(路径:awd-platform/check_server/check.py),替换为以下完整代码(修复服务检测失败问题):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#!/usr/bin/env python
# -*- coding:utf8 -*-
import hashlib
import base64

sleep_time = 300 # 检测周期(秒),默认5分钟
debug = True
headers = {"User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"}

import time
import httplib
import urllib2
import ssl

my_time = 'AAAA'
__doc__ = 'http(method,host,port,url,data,headers)'
flag_server = '172.17.0.1' # Flag服务器默认IP(Docker桥接地址)
key = '744def038f39652db118a68ab34895dc' # 计分密钥(与平台一致)
hosts = open('host.lists','r').readlines() # 读取靶机列表
user_id = [host.split(':')[0] for host in hosts]
hosts = [host.split(':')[1] for host in hosts]
port = 80 # Web服务默认端口

def http(method,host,port,url,data,headers):
con=httplib.HTTPConnection(host,port,timeout=2)
if method=='post' or method=='POST':
headers['Content-Length']=len(data)
headers['Content-Type']='application/x-www-form-urlencoded'
con.request("POST",url,data,headers=headers)
else:
headers['Content-Length'] = 0
con.request("GET",url,headers=headers)
res = con.getresponse()
if res.getheader('set-cookie'):
pass
if res.getheader('Location'):
print "Your 302 direct is: "+res.getheader('Location')
a = res.read()
con.close()
return a

def https(method,host,port,url,data,headers):
url = 'https://' + host + ":" + str(port) + url
req = urllib2.Request(url,data,headers)
response = urllib2.urlopen(req)
return response.read()

def get_score():
res = http('get',flag_server,8080,'/score.php?key=%s'%key,'',headers)
print res
user_scores = res.split('|')
print "******************************************************************"
res = ''
print res
print "******************************************************************"
return user_scores

def write_score(scores):
scores = '|'.join(scores)
res = http('get',flag_server,8080,'/score.php?key=%s&write=1&score=%s'%(key,scores),'',headers)
if res == "success":
return True
else:
print res
raise ValueError

class check():
def index_check(self):
res = http('get',host,port,'/index.php?file=%s'%str(my_time),'',headers)
if 'perspi' in res: # 检测Web页面特征值(确保服务正常)
return True
if debug:
print "[fail!] index_fail"
return False

def server_check():
try:
a = check()
if not a.index_check():
return False
return True
except Exception,e:
print e
return False

game_round = 0
while True:
scores = get_score()
scores = []
print "--------------------------- round %d -------------------------------"%game_round
for host in hosts:
print "---------------------------------------------------------------"
host = host[:-1] # 去除换行符
if server_check():
print "Host: "+host+" seems ok"
scores.append("0") # 服务正常,不扣分
else:
print "Host: "+host+" seems down"
scores.append("-10") # 服务宕机,扣10分
game_round += 1
write_score(scores)
time.sleep(sleep_time)

2. 修复Flag重复提交漏洞

替换 awd-platform/flag_server/flag_file.php 文件(限制同一Flag仅首次提交有效),内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<?php
require 'config.php';
$now_time = time();
$flag_file = 'xxxxxxxx_flag'; # Flag存储文件

// 限制提交频率(防止高频提交)
function check_time($attack_uid,$victim_uid){
global $time_file;
global $min_time_span;
global $now_time;
global $team_number;
$old_times = explode('|' , file_get_contents($time_file));
$id = $attack_uid * $team_number + $victim_uid;
if ($now_time - $old_times[$id] < $min_time_span){
die("error: submit too quick ". ($min_time_span + $old_times[$id] - $now_time). " seconds left");
}else{
return True;
}
}

// 更新提交时间
function update_time($attack_uid,$victim_uid){
global $time_file;
global $now_time;
global $team_number;
$old_times = explode('|' , file_get_contents($time_file));
$id = $attack_uid * $team_number + $victim_uid;
$old_times[$id] = $now_time;
$now_times = $old_times;
file_put_contents($time_file,implode('|' , $now_times));
}

// 验证Flag有效性
function match_flag($flag,$flag_file){
$flags = explode("\n",file_get_contents($flag_file));
foreach ($flags as $real_flag) {
$tmp = explode(":",$real_flag);
$host = $tmp[0];
$real_flag = $tmp[1];
if($flag==$real_flag){
return $host;
}
}
return '';
}

// 检查Flag是否已提交(防止重复提交)
function check_flag($attack_id,$flag){
$flags = explode("\n",file_get_contents('submit_flag.txt'));
foreach ($flags as $sub_flag) {
$tmp = explode(":",$sub_flag);
$attacker = $tmp[0];
$real_flag = $tmp[1];
if($flag==$real_flag && $attack_id == $attacker){
return ''; # 已提交过,返回空
}
}
return $flag; # 未提交过,返回原Flag
}

// 处理Flag提交请求
if(isset($_REQUEST['token']) && isset($_REQUEST['flag'])){
$token = $_REQUEST['token'];
$flag = $_REQUEST['flag'];
// 验证Token有效性
if(!array_key_exists($token , $token_list)){
die('error: no such token');
}
// 验证Flag有效性
$ip = match_flag($flag,$flag_file);
if(!$ip){
die('error: no such flag');
}
// 防止自攻自防
$attack_id = $token_list[$token];
$victim_id = $ip_list[$ip];
if($attack_id === $victim_id){
die('error: do not attack yourself');
}
// 防止重复提交
$flag_validity = check_flag($attack_id,$flag);
if(!$flag_validity){
die('error: The flag has already been submitted');
}
// 记录提交记录
file_put_contents('submit_flag.txt',$attack_id . ':' . $flag . "\n", FILE_APPEND);
// 计算分数(攻击方+2分,防守方-2分)
for($i=0;$i<$team_number;$i++){
$scores[$i] = 0;
}
$scores[$attack_id] = 2;
$scores[$victim_id] = -2;
// 检查提交频率
check_time($attack_id,$victim_id);
// 写入分数
$score = implode('|',$scores);
file_put_contents('result.txt',$user_list[$attack_id] . ' => ' . $user_list[$victim_id]."\n", FILE_APPEND);
$cmd = 'curl "127.0.0.1/score.php?key='.$key.'&write=1&score='.$score.'"';
system($cmd);
// 更新提交时间
update_time($attack_id,$victim_id);
}else {
die("error: empty token or empty target");
}
?>

3. 创建Flag提交记录文件并修复权限

执行以下命令,确保计分文件可读写(避免裁判机权限不足):

1
2
3
4
# 1. 创建Flag提交记录文件
touch /awd-platform/flag_server/submit_flag.txt
# 2. 设置计分相关文件权限为777(读写执行权限)
chmod 777 /awd-platform/flag_server/score.txt /awd-platform/flag_server/result.txt /awd-platform/flag_server/submit_flag.txt

权限修改效果(截图说明):

4. 查看靶机SSH密码

各队伍靶机的 SSH 登录密码存储在 pass.txt 中,执行以下命令查看:

1
cat awd-platform/pass.txt

密码查看效果(截图说明):

(每队密码唯一,格式为 team1:xxxxxx,对应 SSH 登录的 ctf 用户密码)

四、AWD比赛操作指南

1. Web界面访问(靶机前台)

各队伍靶机的 Web 服务通过 不同端口 区分,访问地址格式如下(需替换 <虚拟机IP> 为搭建平台的 Linux 虚拟机 IP):

  • Team1:http://<虚拟机IP>:8801
  • Team2:http://<虚拟机IP>:8802
  • Team3:http://<虚拟机IP>:8803

访问示例(Team1)(截图说明):

(成功访问则显示靶机默认 Web 页面,证明服务正常)

2. SSH访问(靶机后台)

各队伍靶机的 SSH 登录信息如下(密码从 pass.txt 中获取):

队伍 SSH连接地址 登录用户名 密码来源
Team1 <虚拟机IP>:2201 ctf awd-platform/pass.txt
Team2 <虚拟机IP>:2202 ctf awd-platform/pass.txt
Team3 <虚拟机IP>:2203 ctf awd-platform/pass.txt

登录步骤(以Team1为例):

  1. 执行 SSH 命令连接靶机:

    1
    ssh ctf@192.168.173.134 -p2201  # 替换IP为实际虚拟机IP

    输入 pass.txt 中对应 Team1 的密码,成功登录后效果(截图说明):

  2. 补全交互Shell(默认SSH环境可能缺少命令补全,执行以下命令修复):

    1
    python -c 'import pty;pty.spawn("/bin/bash")'

    补全效果(截图说明):

    (修复后支持 tab 命令补全、上下箭头查看历史命令)

3. 提交Flag(攻击得分)

当通过漏洞获取其他队伍靶机的 Flag 后,通过以下 URL 提交 Flag(需替换 <虚拟机IP>teamXFlag值):

1
http://<虚拟机IP>:8080/flag_file.php?token=teamX&flag=xxxx
  • teamX:当前攻击队伍的标识(如 Team1 提交则为 team1,需与 config.php 中配置一致);
  • flag=xxxx:从目标队伍靶机中获取的 Flag 值(格式为 flag{32位随机字符串})。

提交示例(Team1攻击Team2):

假设 Team1 获取 Team2 的 Flag 为 flag{85c58b085a949c1eb61125ceed70599c},提交 URL 如下:

1
http://192.168.173.134:8080/flag_file.php?token=team1&flag=flag{85c58b085a949c1eb61125ceed70599c}

提交成功效果(截图说明):

(页面无报错则为提交成功,若重复提交会提示 error: The flag has already been submitted

4. 查看比赛数据

4.1 查看实时分数

通过以下 URL 查看各队伍当前总分(实时更新):

1
http://<虚拟机IP>:8080/score.txt

分数查看效果(截图说明):

(示例中 Team1 得 2 分(攻击成功),Team2 扣 2 分(Flag 被获取),Team3 得 0 分)

4.2 查看攻击记录

通过以下 URL 查看所有 Flag 提交记录(含攻击方、防守方):

1
http://<虚拟机IP>:8080/result.txt

攻击记录效果(截图说明):

(记录格式为 攻击方 => 防守方,可追溯每一次有效攻击行为)