CTF新生赛Web题:出题逻辑与高频考点通关路径 第一次打开新生赛的 Web 题页面时大多数人看到的是同一幅画面一个输入框、一个提交按钮、一行提示语然后就没别的了。我第一次参加这类比赛时也这样翻来覆去地点提交浏览器开发者工具是打开过的但不知道要看什么最后那道签到题是靠队友一句话点醒才拿下的。后来自己出题、自己带人、自己复盘慢慢才明白新生赛的 Web 题不是靠运气解出来的它有一套相当稳定的出题逻辑和考察范围看懂了这套逻辑解题速度会有一个台阶式的提升。这篇内容围绕 2022 年一场高校新生赛的 Web 题展开把题目背后的考点设计、信息收集的正确顺序、高频漏洞的最短通关路径、以及我自己踩过的那些坑一条条拆开讲清楚。适合刚接触 CTF Web 方向、做过几道题但总觉得“靠猜”的新人也适合准备给下一届出题的同學参考——知道题是怎么被设计出来的解题时就少绕很多弯。所有内容仅针对比赛靶场和授权环境实际场景中的测试请务必取得书面授权。1. 新生赛 Web 题的“套路感”是从哪来的很多人做完一套新生赛题会有种奇怪的感觉题目好像都差不多。这不是错觉是赛制决定的。新生赛的定位是“筛人”而不是“筛高手”出题人往往是在校的高年级学生备赛周期短则两周、长则一个月还要同时兼顾平台部署、环境测试、题目文档。在这样的约束下题目必然会向“考点明确、环境简单、验证直观”三个方向收敛久而久之就形成了固定的套路感。理解这一点很重要因为它直接决定了你解题时的搜索方向——你不会在新生赛里遇到需要三天才能挖出来的复杂逻辑漏洞但你会反复遇到同一批经典考点。1.1 一道题的成本账出题人为什么偏爱这几类考点一个单文件 PHP 环境加上几行过滤逻辑就能构成一道完整的弱类型比较题而一个需要多模块协作的业务逻辑漏洞光是搭环境、写前端、保证逻辑自洽就要花掉好几天。出题成本决定了题目的形态。我参与过的一次出题经历里最后上线的六道 Web 题中有四道是单文件两道带简单的前后端分离工作量已经相当吃紧测试阶段还爆出过一个环境版本不一致的问题。从出题人视角算一笔账就很清楚了考点类型环境搭建成本出题耗时可验证性新生赛适配度源码泄露 / 信息泄露极低半小时强高常做签到题PHP 弱类型比较低1 小时强高文件包含低1 小时强高入门 SQL 注入中2 小时强高命令执行 / 过滤绕过低1-2 小时强高反序列化中半天中中常做压轴条件竞争中高半天到一天弱容易出意外低少见复杂业务逻辑高数天中极低这张表基本就是新生赛的题目分布图。看到一道题先在心里给它归个类你就知道大致该往哪个方向想而不是漫无目的地试参数。1.2 难度梯度签到题、常规题、压轴题的分层逻辑正规一点的新生赛都会做难度梯度通常是 1:3:1 或者 2:4:2 的分布。签到题的目的是让所有人都有分拿不至于开局就劝退常规题是区分度的主力压轴题用来选出能进校队的那几个人。签到题的形态非常固定页面源码里藏注释、响应头里放提示、robots.txt里写路径、cookie 里有 base64。这类题不需要工具F12 加一点观察力就够了。我带过的新人里有相当一部分卡在签到题上原因不是不会而是压根没想到去翻源码——他们默认“可见的页面就是全部”。常规题的典型特征是“有交互、有过滤、有反馈”。你提交一个参数页面会告诉你对或错过滤逻辑会拦掉一部分输入。反馈越明确说明出题人越希望你能通过试错找到路这类题往往是最容易通过系统地试出来的。压轴题通常是反序列化或者带一点绕过的注入需要读源码、构造 payload、验证链路的完整性。这类题的关键不在技巧而在耐心把类结构、魔术方法、可控属性一点点梳理清楚。1.3 读懂题干暗示题名、附件、提示语里的信息量这是很多人忽略的一块。新生赛的题名往往起得很直白easy_php、upload_me、guess_the_number这些名字本身就框定了考点范围。题面提示语里如果出现“flag 在 flag.php 中”那是直接告诉你文件包含的方向如果出现“管理员说他的密码很简单”那是暗示弱口令或字典爆破。还有一个细节附件。有些题会给一个源码压缩包很多人解压看一眼就扔在一边其实附件里往往藏着过滤器、正则、路径拼接方式的完整实现。读附件比在线上盲试快十倍。提示拿到题先花两分钟通读题名、题面、附件、提示语把能确定的信息写在草稿里。这一步花的钱后面能省回来。2. 开局三分钟比扫目录更重要的信息收集我见过太多新人拿到题的第一反应是打开扫描工具把一个大字典甩上去然后盯着进度条等。这个习惯在新生赛里经常是负收益一部分比赛平台对请求频率有监控扫得太凶会被临时限制另一方面真正的线索往往就摆在页面里而目录扫描的字典命中率对新生赛这种小环境并不高。信息收集应该有顺序感先手工再工具先静态再动态。2.1 页面本身能告诉你的东西打开页面后我会按固定顺序做几件事。第一看地址栏路径是什么有没有带参数参数名是什么。?fileindex这种参数名几乎就是在喊“文件包含”。第二看页面渲染出来的内容有没有表单、有没有隐藏字段、提交后返回什么。第三按 F12 看三样东西——元素里有没有注释和display:none的隐藏输入框、源码里有没有内联脚本暴露接口、网络面板里提交请求的完整形态是什么样的。隐藏输入框是个高频坑。有时候页面只显示一个用户名输入框但源码里还有一个roleuser的隐藏字段把它改成admin就是整道题的解。这种设计在出题人看来“很巧妙”在解题人看来则是“我要是没看源码就永远想不到”。再看响应头。Server和X-Powered-By能告诉你后端语言和大致版本这直接影响你选哪套 payload。PHP 7 和 PHP 8 在弱类型比较、字符串处理上有差异提前知道版本能避免很多无用尝试。最后看状态码和响应长度。同样是 200返回 30 字节和返回 3000 字节的含义完全不同。有些题的判断逻辑是“命中就返回不同内容”这时候对比响应长度比看内容更快。2.2 源码与备份文件的常见藏身处信息泄露类的题在新生赛里占了相当大的比重因为出题成本几乎为零。常见的藏身处有这么几类HTML 注释!-- flag.php --、!-- TODO: 记得删掉调试代码 --最朴素也最常见。前端脚本有些题把校验逻辑写在前端密钥、路径、判断条件全在 JS 里搜索关键字就能找到。robots.txt写一个Disallow: /secret_path等于直接把路径送给你。备份文件www.zip、web.rar、index.php.bak、index.php~、index.php.swp这些后缀在开发过程中会产生忘了删就上线了。版本控制残留.git/、.svn/一旦目录可访问整份源码都能还原出来。编辑器配置和日志.DS_Store、access.log前者能列出目录结构后者在某些场景下可以配合文件包含。备份文件这一类新手最容易漏的是命名规则。以 PHP 为例常见的备份后缀至少有bak、swp、save、old、tmp、copy这几种还有尾部加波浪号、加数字的写法。我在一次比赛里就是靠index.php.bak拿到源码的前面试了七八种都 404。这种时候不要急把后缀列表列出来批量试比手动一个个敲快得多。.git泄露的处理稍微复杂一点。目录能访问不代表文件能直接读需要把仓库结构按路径一个个拉下来再还原工具能自动化这个过程但理解原理仍然必要——你需要知道HEAD、config、objects分别对应什么才能在工具失败时手工补。2.3 目录扫描的节奏控制与字典取舍工具当然要用但要有节奏。我的习惯是三级推进先用最小的字典几十条就是常见的备份后缀和敏感目录名快速过一遍没结果再换中等字典一两千条包含常见的 CMS 路径和接口名最后才考虑大字典而且线程数要压下来。线程数的取舍有讲究。新生赛的靶场往往部署在配置一般的机器上或者放在带限速的网关后面你开 50 个线程打过去结果可能是一半超时、一半被拦还留下了一堆脏数据。我一般从 10 线程起步看到响应时间稳定再往上加。如果连续出现 429 或者连接被重置立刻停手等几分钟再试。字典选择上针对新生赛环境我优先关注这几类备份后缀、admin系列、api系列、upload系列、flag相关。很多题的 flag 文件名就叫flag.php或者flag.txt直接试一下不丢人。注意比赛平台的靶场是共享资源你扫得凶会影响别人。控制并发不只是为了自己不被封也是基本的比赛素养。3. 高频考点的最短通关路径前面铺垫了这么多真正落到解题上还是要靠对这些考点的熟悉程度。这一节按考点逐条拆每条都给出“怎么识别、怎么打、卡住了往哪想”三部分。需要声明的是以下内容全部基于靶场和比赛环境实际系统的测试必须获得授权。3.1 弱类型比较识别、绕过与常见变体PHP 的是松散比较两侧类型不同时会先做类型转换再比。这个特性在新生赛里几乎是必考项。最经典的形态是代码里有个if ($_GET[a] $_GET[b])但要求两个值不相等或者要求某个值的 md5 摘要等于另一个固定字符串。识别方法很简单看源码里用的是还是。宽松比较就有文章可做严格比较基本堵死了类型转换这条路。常见绕过手法有这么几种?php // 场景一0e 开头的“魔法哈希” // 两个不同字符串的 md5 值都是 0e 开头松散比较时会被当成 0 // 例如 md5(240610708) 与 md5(QNKCDZO) var_dump(md5(240610708) md5(QNKCDZO)); // true // 场景二数组绕过 // md5() 接收数组时返回 null两个 null 松散比较相等 var_dump(md5([]) md5([])); // true // 场景三数字与字符串 var_dump(1abc 1); // PHP 7 中为 true var_dump(abc 0); // PHP 8 中为 false7 中为 true ?这里有个非常关键的版本差异PHP 8 修改了字符串与数字比较的规则abc 0在 PHP 8 里是false在 PHP 7 里是true。如果你按 PHP 7 的思路构造 payload在 PHP 8 环境里会直接失败。这就是为什么前面强调要先看响应头确认版本。数组绕过是另一个高频点。除了md5strcmp、strpos、in_array都有类似问题。strcmp接收数组返回null而null 0为真于是判断被绕过。in_array在不传第三个参数时是松散比较in_array(1abc, [1])会返回真。还有一种题型是intval相关常见形态是要求输入值小于某个数但长度超过限制或者经过intval后变大。这类题的关键是把intval的转换规则搞清楚它从字符串开头解析数字遇到非数字字符停止科学计数法在部分版本里会被截断。3.2 文件包含伪协议读源码的正确姿势文件包含题的入口非常明显参数名通常叫file、page、path、include页面内容会随参数变化。确认存在包含后第一步不是急着找 shell而是把源码读出来——新生赛的题源码里往往就写着 flag 的位置。读源码的标准姿势是过滤器链# 读取 index.php 的源码base64 编码后返回避免被 PHP 解析 ?filephp://filter/convert.base64-encode/resourceindex.php拿到返回的 base64 串解码就能看到完整源码。这一步的价值在于你能直接看到过滤规则、能包含哪些文件、flag 是怎么被读出来的。很多人在这一步跳过直接各种伪协议乱试最后卡在“为什么 payload 不生效”上。常见的伪协议还有几个协议用途典型写法php://filter读源码、编码绕过php://filter/readconvert.base64-encode/resourceflag.phpphp://input从请求体读取内容POST 体里写 PHP 代码参数值填php://inputdata://直接内联数据data://text/plain;base64,PD9waHAg...phar://触发反序列化phar://upload/xxx.jpg要注意allow_url_include这个配置默认是关闭的php://input和data://在很多环境下用不了。相反php://filter不受这个限制所以在不确定环境配置时优先试 filter。如果伪协议被禁用还有日志包含这条路。把 PHP 代码写进 UA 或者请求路径然后包含日志文件。这条路的难点在于日志路径不一定固定需要试常见位置而且有些环境会裁剪日志内容。3.3 入门级 SQL 注入从探测到取数的完整链路新生赛的注入题通常过滤不严或者过滤规则有明显缺陷。标准流程是判断注入点、判断列数、确定回显位、取数据。判断注入点用单引号最简单观察报错或者页面变化。如果报错被关掉就用逻辑判断and 11和and 12返回内容应该有差异。判断列数用order by从 1 往上加直到报错或者页面异常上一次成功的数字就是列数。确定回显位用union select 1,2,3看哪个数字出现在页面上。取数据走information_schema-- 假设列数为 3回显位在 2 ?id-1 union select 1,database(),3 -- ?id-1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schemadatabase() -- ?id-1 union select 1,group_concat(column_name),3 from information_schema.columns where table_nameflag -- ?id-1 union select 1,group_concat(flag),3 from flag --这里有两个新手常踩的细节。第一union select前面要加一个不存在的 id比如-1这样前半句查不到数据页面只显示你的联合查询结果。第二注释符--里的加号是 URL 编码后的空格在 POST 请求里要用#或者--加空格。过滤绕过的基本思路空格被过滤用/**/或者%09、%0a关键字被过滤用大小写混写、双写、注释穿插引号被过滤就看能不能用数字型或者十六进制表示字符串。这些手段在新生赛里基本够用。3.4 命令执行黑名单绕过与输出回显命令执行的题通常给一个输入框输入的内容被拼进系统命令里。识别方法很直接输入127.0.0.1看是否有 ping 结果或者输入;ls看是否列出目录。黑名单绕过是这类题的核心。常见的过滤项和对应绕过方式被过滤内容绕过手法说明空格${IFS}、$IFS$9、%09、制表符和环境变量都能代替空格cattac、head、tail、more、less、nl换一个读取命令flagfl*、fla?、f[l]ag通配符和正则匹配和%0a、;、$()、反引号字母数字base64 编码后base64 -d执行需要管道没被封举个例子假设过滤了空格和cat要读flag.php# 原始意图cat flag.php # 绕过写法 ;tac${IFS}fl* ;more${IFS}fla?.php ;echo${IFS}ZmxhZy5waHA|base64${IFS}-d|xargs${IFS}cat命令执行题最怕的是没有回显。这时候就要考虑外带比如让目标机器把结果写到一个可访问的文件里或者通过 DNS 请求带出来。新生赛里有外带的题不多但遇到时不要慌先确认目标能不能出网。3.5 反序列化新生赛通常只考到这里反序列化在新生赛里一般作为压轴题出现难度不会太深核心是理解魔术方法的触发时机和属性可控性。基础形态是给你一个类里面有__destruct或__wakeup方法里执行了危险操作属性通过$_GET传入。你只需要构造好对象再序列化即可。?php class Demo { public $cmd whoami; public function __destruct() { system($this-cmd); } } // 构造 payload echo serialize(new Demo()); // O:4:Demo:1:{s:3:cmd;s:2:ls;} ?进阶一点的形态是 POP 链需要从一个类的魔术方法跳到另一个类的普通方法一步步把可控数据传到危险函数。新生赛的链一般只有两三层把每个类的方法列出来画出“谁调用谁”的图链就出来了。有个细节容易忽略私有属性和保护属性在序列化后的字符串表示不一样。私有属性是%00类名%00属性名保护属性是%00*%00属性名。如果属性是私有的你手写的 payload 里必须带上这些空字节在 URL 里要编码成%00。很多人的 payload 逻辑完全正确就是卡在这个不可见字符上。3.6 其他零星考点速查除了上面几类新生赛偶尔还会出现这些SSRF参数里能传 URL 的地方试file:///etc/passwd、dict://、gopher://。新生赛通常只考到内网探测不会让你构造复杂的 gopher 数据包。XXE有 XML 解析入口时试外部实体注入读文件或者探测内网。注意有些环境默认禁用外部实体。条件竞争上传或兑换类功能利用处理时间差。这类题在新生赛里不稳定遇到先看题面有没有暗示“并发”之类的词。PHP 伪随机mt_rand在同一进程内可预测如果题里有mt_srand(seed)且 seed 可控那基本就是考这个。Session 相关会话文件包含、会话固定通常和文件包含结合出题。4. 复盘时最耗时间的几个坑前面讲的是“该怎么打”这一节讲“为什么打不通”。我复盘自己那场比赛的过程真正卡住的时间几乎都不在思路上而在一些很琐碎的细节上。把这些坑列出来希望你遇到时能少花点时间。4.1 本地通了远程不通环境差异的系统性排查这是最气人的情况本地搭好环境payload 打得通提交到靶场就是不行。原因通常有三类。第一类是版本差异。前面提过 PHP 7 和 PHP 8 在松散比较上的区别。除此之外preg_match在遇到非法 UTF-8 时返回false而false在条件判断里等同于“不匹配”这可能导致过滤被意外绕过或者意外失效取决于你怎么写逻辑。如果题里用preg_match做黑名单而你的 payload 里有非 ASCII 字节行为就可能和本地不同。第二类是配置差异。allow_url_include、open_basedir、disable_functions这三个配置项能直接决定一条路走不走得通。本地环境往往是最宽松的默认配置靶场环境通常做了收紧。遇到 payload 不生效先想“是不是这个功能被禁了”。第三类是路径差异。本地你放在/var/www/html靶场可能是/app或者别的目录涉及绝对路径的 payload 全部要重新算。文件包含里用相对路径时当前工作目录也可能不同。排查方法很朴素把 payload 拆成最小单元一步步验证。先验证参数有没有传进去页面有没有变化再验证第一个过滤点有没有过报错信息最后验证执行结果回显内容。不要一上来就上完整 payload那样失败了你也不知道断在哪。4.2 过滤规则的误判读源码比猜规则靠谱有一次我卡在一道命令执行题上快一个小时凭经验判断过滤了空格和cat换了七八种绕过写法都不行。最后把源码读出来才发现题目过滤的是一个正则/[a-z]/i所有字母都被拦了我那些绕过全是白费功夫。正确解法是把命令做编码或者用纯符号构造。这个教训很直接能读源码就读源码。新生赛的题源码可读的概率相当高——文件包含、备份文件、Git 泄露三条路至少有一条通。花十分钟找源码比花一小时猜规则划算得多。读源码时重点看三个东西过滤函数、判断逻辑、输出路径。过滤函数决定你能输入什么判断逻辑决定你要满足什么条件输出路径决定 flag 在哪。很多人只看了第一个结果 payload 构造得完美但因为不满足某个前置判断根本没走到执行那一步。4.3 flag 格式与提交细节的连环坑这类坑看起来低级但每年都有人栽。常见的有这么几种flag 前缀和包裹格式有些平台是flag{xxx}有些是自定义前缀有些要求提交时不带包裹符号。题目页面一般会写明别凭习惯提交。大小写有些题目的 flag 内容是随机字符串大小写敏感从页面复制时注意别漏字符。不可见字符flag 里夹了换行、空格或者从 HTML 里复制时带上了标签。多段拼接有些题的 flag 分几部分藏在不同地方需要按顺序拼起来。提交次数限制部分平台限制提交错误次数别拿不确定的答案去试。我一般的做法是把 flag 复制到纯文本编辑器里去掉首尾空白确认格式后再提交。听起来啰嗦但确实能避免一些莫名其妙的失分。4.4 扫描和爆破的副作用被封了怎么办比赛平台对请求频率通常有监控。目录扫描开高并发、爆破密码试几百次很容易触发限制表现为全部请求超时或者返回统一的错误页。遇到这种情况第一件事是停下来。继续请求只会延长封禁时间。然后换一个思路如果当前路径被封看看题目有没有提供多个入口或者换用更少的请求把关键信息拿到。预防的办法是控制节奏。扫描时把线程压到 10 以内请求之间加一点延迟爆破时先分析密码规律能用逻辑推出来的就别跑字典。新生赛的弱口令题密码往往是admin、123456、password这种字典前一百条就能命中没必要上大字典。5. 把重复动作固化下来我的脚本和配置比赛时间有限把重复动作固化下来能省出大量时间。这一节分享我自己常用的一套配置和脚本都是很朴素的东西但胜在稳定。5.1 抓包工具的固定配置我习惯把所有请求都过一遍代理这样任何一次交互都能回看和重放。配置上有几个点值得固定下来拦截规则只针对目标域名避免把无关请求也拦下来影响浏览。提前设置好匹配替换规则比如把常见的 payload 片段存成替换项测试时一键套用。历史记录定期清理不然几百条请求里找一条很难。重放功能是排查的主力。一个请求改动一个参数对比响应差异这个流程比写脚本快得多尤其是在还不确定攻击面的时候。5.2 一个够用的请求脚本当需要批量测试或者处理编码问题时脚本就派上用场了。下面这个模板覆盖了我八成的需求发请求、处理编码、判断响应特征。import requests import base64 TARGET http://example-target/index.php HEADERS {User-Agent: Mozilla/5.0, Content-Type: application/x-www-form-urlencoded} def probe(payload, methodGET, paramfile): try: if method GET: r requests.get(TARGET, params{param: payload}, headersHEADERS, timeout5) else: r requests.post(TARGET, data{param: payload}, headersHEADERS, timeout5) return r.status_code, len(r.text), r.text except requests.exceptions.RequestException as e: return None, 0, str(e) # 示例批量测试备份后缀 suffixes [bak, swp, save, old, tmp, copy, ~, 1] for s in suffixes: code, length, body probe(findex.php.{s}) if code 200 and length 100: print(f[] hit: index.php.{s} len{length})脚本的价值在于批量对比。单个请求用手工工具更快但当你需要试几十种后缀、几十个参数组合时脚本能把结果整理成表格一眼就能看出差异。写脚本时有两个细节要注意一是超时一定要设不然一个卡住的请求会让整个脚本停摆二是异常要捕获网络抖动在比赛环境里很常见别让一个异常终止整个流程。5.3 手工优先自动化兜底工具再强也替代不了判断。我的原则是能用眼睛看出来的不用工具能用工具批量试的不用脚本需要逻辑推理的必须手工。自动化工具在你不理解原理时给出的结果往往是噪音你会得到一堆 200 响应但不知道哪个有意义。举个具体的例子。目录扫描出一堆 403新手可能会认为“这些路径存在但没权限”实际上很多环境对任意不存在的路径都返回 403这些结果全是假的。判断真假要看响应长度和内容特征而不是只看状态码。6. 赛后的训练路线与复盘方法比赛结束到下一次比赛之间才是真正拉开差距的阶段。我带过的新人里进步快的都有一个共同点每道题都写复盘不只是写“怎么解出来的”还写“当时为什么没想到”。6.1 一周一专题的练法贪多嚼不烂。我建议按专题推进一周一个每个专题做五到八道题做完之后合上题解自己再复现一遍。专题的划分可以参考前面的考点表周次专题目标第 1 周信息收集与源码泄露形成固定的检查清单第 2 周PHP 弱类型与特性能背出常见绕过手法第 3 周文件包含与伪协议熟练读源码理解协议差异第 4 周SQL 注入基础手注全流程不依赖工具第 5 周命令执行与绕过掌握黑名单绕过的通用思路第 6 周反序列化基础能独立构造简单 POP 链每个专题结束时做一次自测不看笔记从零开始做一道同类型的新题记录用时和卡点。卡点就是你下一周要补的地方。在线靶场是个好资源但要注意选择题目质量稳定的。有些平台上的题环境已经挂了或者题目描述和实际环境不符做这种题纯属浪费时间。判断方法是看题目的通过人数和最近提交时间环境正常的题一般有持续的通过记录。6.2 我的复盘笔记模板复盘笔记不追求长追求可检索。我自己的模板有固定几栏题目信息名称、考点、难度、用时。突破口第一眼看到什么、什么线索让你确定方向。卡点卡了多久、卡在哪个环节、当时是怎么想的、错在哪。正确路径完整步骤包括所有 payload。可复用的东西这道题里有什么手法能迁移到别的题上。其中“卡点”这一栏最有价值。技术手法网上到处都有但“我当时为什么没往那个方向想”只有你自己知道。把这些记录下来下次遇到类似场景你的第一反应会不一样。还有一个小习惯值得养成把常用的 payload、字典、脚本整理成一个自己的资料库按考点分类。比赛时直接调用不用现场回忆。这个库会随着做题越来越多是你个人的核心竞争力。6.3 关于比赛心态的一点个人体会新生赛最容易出现的情绪是焦虑看着排行榜上别人的分数往上涨自己的题还卡在第一步。我经历过一次前两个小时只拿下一道签到题后面越急越乱把已经想到的思路反复推翻。后来我给自己定了个规矩一道题卡超过四十分钟就换题回头再看。换个脑子往往能跳出死胡同而且做别的题拿到的分能缓解焦虑。比赛是限时的但限时之内怎么分配注意力是可以自己控制的。另外不要迷信“标准解法”。新生赛的题有时候会有意料之外的解法出题人自己都没想到。能拿到 flag 就是对的路径不唯一。当然前提是不影响其他选手、不破坏靶场环境。最后再分享一个实用的小技巧比赛开始前十分钟把所有会用到的工具、脚本、字典路径检查一遍代理设好浏览器书签整理好。这个准备动作看起来不起眼但能避免开局手忙脚乱——我见过有人比赛开始二十分钟还在折腾工具环境。