ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

CTF备赛如何从乱刷到系统?一张知识地图厘清Web、隐写与PWN

CTF备赛如何从乱刷到系统?一张知识地图厘清Web、隐写与PWN 有段时间我刷 CTF 题完全是刷了个寂寞——今天看到隐写题教程就去看图片通道明天心血来潮又去折腾 PWN 环境配置结果比赛真打起来Web、Crypto、Misc、Reverse、PWN 五个方向全都要碰人直接懵在题目列表前面。后来我停下来把刷过的题按题型重新捋了一遍才发现真正的差距不是题量而是脑子里没有一张地图。这篇东西不是要给你一份复制粘贴就能交差的“全题型答案”而是把 CTF 备赛最该弄懂的那套底层流程讲清楚每个赛道考什么、按什么顺序学、遇到题怎么下手尤其是隐写和 PWN 这两个最容易劝退新手的模块。这两年各种数据安全赛、行业赛越来越多但扒开外壳看核心考点还是那些经典题型。这篇文章适合刚入门、刷题刷得很乱的人也适合赛前想快速理一遍框架的老手。1. 备赛不是比题量先给自己画一张 CTF 知识地图很多新人一上来就冲进“题海”今天刷一道 Web明天跟风看一道逆向看起来每天都在努力实际上知识点全是一盘散沙。CTF 备赛的第一步不是刷题是建立知识地图你得先知道这片战场上有哪几块阵地每块阵地的产出比是多少。1.1 五大题型各管一摊别让“全题型”变成空话CTF 的比赛题型通常分成五块每块背后的能力模型完全不同赛道典型考点上手难度新手阶段拿分效率Web代码审计、命令执行、SQL 注入、文件上传、源码泄露中等高思路可复制Misc/杂项图片隐写、流量分析、文件分离、压缩包、OSINT低高几乎是送分题Crypto/密码学编码转换、古典密码、现代密码、RSA 攻击面低到中高工具化明显Reverse/逆向程序分析、算法还原、注册机、脱壳高前期低学会后稳定PWN栈溢出、堆利用、格式化字符串、整型溢出最高前期低后期爆发这张表的核心结论是Misc 和 Crypto 是你第一阶段的“救命分”Web 是题量最大的主战场PWN 和 Reverse 是拉开差距的深水区。如果你只是备赛冲名次别一上来就死磕 PWN先把前三个赛道的常规分稳稳拿下这才是多数人的最优策略。1.2 新手阶段的优先级先拿稳定分再攻深水区我见过太多人备赛三个月Crypto 一道没刷PWN 的 gdb 却研究得贼深比赛一打PWN 没做出来Crypto 送分题也丢了。我自己后来定的节奏是这样的第 1 个月把 Python、Linux 基础命令练熟Web 的常见漏洞原理过一遍每天固定刷 2 到 3 道 Misc 题训练“看到文件先跑工具”的肌肉记忆。第 2 个月Crypto 系统刷一遍从 base64 套娃到凯撒、维吉尼亚、RSA 基础攻击顺手把 LSB 隐写、文件分离这类 Misc 高频考点巩固掉同时开始搭 PWN 环境。第 3 个月Reverse 入门和 PWN 栈溢出并行推进周末找一场模拟赛完整打一次感受真实比赛的时间压力。这个顺序的核心逻辑是先建立“看到题就能动手”的正反馈再进入需要长期积累的硬核赛道。新手最容易放弃的时刻往往是连续几天做不出题而 Misc 和 Crypto 恰恰是正反馈来得最快的方向。1.3 练习平台怎么选免费中文靶场加英文入门站搭配用平台这块没必要贪多我长期用的组合是ctfshow 练 Web 技能树和杂项buuoj 刷经典真题polar 平台拿来做比赛模拟攻防世界和 NSSCTF 作为补充题库。ctfshow 的技能树设计得很适合新手一个一个节点点过去Web 的整个知识体系能串起来polar 的题目命名经常套着故事情节但内核还是考点组合适合练“在花哨包装里识别真实考点”的能力。英文平台里 picoCTF 是很好的入门选择题目梯度设计得比很多国内靶场平滑。至于 Kali 系统备赛阶段直接用就行里面自带 binwalk、foremost、gdb、python3 这些常用工具省去大量装环境的痛苦。但注意一点看到一个题解里用了某个工具先确认版本再照做隐写和 PWN 工具不同版本的行为差异有时候非常大。2. Web 题从命令执行到 git 泄露最常见的得分点怎么抓Web 题是 CTF 里题量最大的板块也是新手最容易“看着答案都会自己做就废”的板块。原因很简单Web 题的考点非常依赖场景你不光要知道漏洞原理还得知道在过滤规则下怎么组合绕过。我挑三个高频方向展开这三个方向加起来能覆盖大部分新手期 Web 题。2.1 命令执行过滤绕过从 passthru 到空格、关键字全过滤命令执行类题目的经典入口是 PHP 的passthru、system、exec、shell_exec这几个函数还有反引号也算。很多题的代码长这样?php $ip $_GET[ip]; if (preg_match(/flag|cat|\/| /, $ip)) { die(no); } passthru(ping -c 1 . $ip); ?这道题把flag、cat、斜杠、空格全过滤了看起来没法读文件但绕过组合其实不少。先用分号截断命令?ip127.0.0.1;ls如果ls被过滤就换dir某些环境支持或者ls -la不行就试l\s。空格被过滤时用${IFS}或者$IFS$9代替因为 IFS 是 shell 的默认分隔符。斜杠被过滤时可以用相对路径进入目录读文件时用通配符cat${IFS}fla*、less${IFS}f*、tac${IFS}*lag*。cat被过滤了也别慌tac倒着读、less、more、nl、od、head、tail都可以读文件关键是你得知道这种题目在考“命令拼接 关键字黑名单绕过”。还有一类题是无回显的命令执行完你看不到输出这时候可以把结果写到 web 目录下再访问?ip127.0.0.1;ls${IFS}1.txt然后直接访问1.txt看结果。这个思路是我在比赛里用得非常频繁的招数比外带数据简单直接得多。2.2 文件读取与源码泄露php 伪协议和 git 泄露这两条路Web 题的第二个高频得分点是文件读取和源码泄露。看到?pageindex.php这类参数第一反应就是用 php 伪协议读源码?pagephp://filter/convert.base64-encode/resourceindex.php这个操作会把index.php的源码用 base64 编码后输出防止浏览器直接当作 HTML 解析导致页面空白。拿到一串 base64 后解出来就是源码剩下的漏洞点一眼就能看见。注意一个常见坑有时候页面确实输出了 base64但被浏览器解析成了乱码或者空白你要右键查看源代码才能看到完整内容我因为这个判断失误至少浪费过二十分钟。源码泄露的另一条高频路线是 git 泄露。很多开发者在服务器上执行过git init或者直接git clone部署把.git目录留在了 web 根目录下。你访问/.git/HEAD如果返回了内容说明存在 git 泄露。手动下载文件太折腾直接用工具一把梭githacker这类工具可以把整个 git 仓库 dump 下来然后你本地git log翻历史版本经常能翻到被删除的 flag 或者密钥。类似的还有.svn泄露、.DS_Store泄露、www.zip备份文件做题时留意一下这些敏感文件路径属于性价比极高的检查项。2.3 nginx 配置类题目别忽略中间件本身的安全细节最近两年 nginx 安全加固这类题出现频率明显上升它不直接考代码漏洞而是考你对中间件配置的理解。最常见的考点是alias路径拼接导致的目录穿越location /static/ { alias /var/www/html/static/; }如果 alias 后面的路径末尾少了一个斜杠访问/static../flag时实际解析路径就可能变成/var/www/html/static/../flag配合..就实现了目录穿越。这类题的判断思路是先拿到或推断出 nginx 配置再看 location 匹配规则里有没有路径拼接隐患。另一个常见考点是 location 匹配顺序。nginx 的匹配规则是精确匹配优先于前缀匹配如果管理员用前缀匹配写了安全规则又在后面加了一个更宽泛的 location就可能被绕过。做这类题别急着打先把配置读懂把“哪个 location 处理哪个请求”搞清楚漏洞自然就出来了。实际刷题时polar 和 ctfshow 都有专门的 nginx 专题挑几道仔细看题解比盲目刷十道普通 Web 题有用得多。3. 隐写题从看到题干就头大到建立自己的工具链隐写题是 Misc 里的大头也是新手最容易“拿着图看半天不知道干嘛”的板块。其实隐写题是有固定套路的把工具链和判断顺序建立起来之后大部分题都能在十分钟内解决。3.1 先做基础排雷file、strings、binwalk 三连拿到任何隐写文件第一件事不是用某个高大上的工具而是按顺序做基础排雷。先file看文件真实类型很多题表面是图片实际里面藏了压缩包再用strings提取可打印字符串配合关键字过滤file mystery.png strings mystery.png | grep -iE flag|ctf|key|password如果 strings 直接出了 flag那这题就是送分题。没出的话用binwalk -e分离文件binwalk 会扫描文件里的嵌入式文件把藏在图片末尾的 zip、rar、其他图片分离出来。foremost是另一个按文件类型分割的工具binwalk 分离失败时可以换它试试。还要养成看十六进制的习惯。文件头是判断格式的依据比如 PNG 的文件头是89 50 4E 47JPG 是FF D8 FFZIP 是50 4B 03 04。有时候 flag 就明文写在文件尾部或者藏在 EXIF 信息里用十六进制编辑器翻到最后一眼就能看到。这套三连动作做完隐写题已经能解决三成以上。3.2 LSB 隐写的原理和命令行提取别再只会点 StegSolve 的鼠标LSB 隐写是图片隐写里出镜率最高的手法。原理其实一句话就能讲明白图片每个像素的 RGB 三个通道各有 8 个 bit人眼对最低位的颜色变化几乎无感于是把隐藏数据的二进制位依次填入这些最低位图看起来没变化数据却藏进去了。很多新手只会用 StegSolve 手动点击提取点完 RGB 通道的勾选框碰运气。这种操作方式太慢而且容易漏。我更建议直接上命令行工具zsteg用一条命令就能扫出大部分常见 LSB 隐写结果zsteg -a flag.png如果想深入理解原理或者题目需要微调提取方式写个十几行的 Python 脚本更灵活。核心逻辑是遍历像素把每个通道的最低位取出来拼成二进制数据再转成字节最后在字节流里搜索 flag 头from PIL import Image img Image.open(flag.png).convert(RGB) pix img.load() bits for y in range(img.height): for x in range(img.width): r, g, b pix[x, y] bits str(r 1) bits str(g 1) bits str(b 1) data b for i in range(0, len(bits) - 7, 8): data bytes([int(bits[i:i8], 2)]) idx data.find(bflag{) print(data[idx:idx80])注意这段脚本的通道顺序是固定的 RGB 依次取最低位但实际题目可能用的是 RGBA、BGR甚至只取某个通道。遇到提取结果乱码就换一下通道顺序再跑这种“枚举通道组合”的思路比盲目猜要靠谱得多。3.3 图片宽高被改、压缩包伪加密这类花活怎么处理隐写题的另一大类是“图片显示不全”。拿到的 PNG 图片打开只有一部分内容提示信息写着“图片尺寸不对”。这是因为 PNG 的 IHDR 块里保存了宽高出题人把高度改小了真实内容被裁掉看不到。判断方法是用 pngcheck 或者看图工具检查图片是否报 CRC 错误如果报错十有八九就是宽高被改。爆破宽高的思路是PNG 前 8 字节是签名第 16 到 20 字节是宽度第 20 到 24 字节是高度第 29 到 33 字节是 IHDR 块的 CRC 校验值。正常图片修改高度后 CRC 会失效所以你保持宽度不变遍历可能的高度计算 CRC 和原图比对匹配上的就是真实高度import struct import zlib data open(broken.png, rb).read() width struct.unpack(I, data[16:20])[0] for h in range(1, 4000): ihdr_data bIHDR struct.pack(II, width, h) data[24:29] crc zlib.crc32(ihdr_data) 0xffffffff if crc struct.unpack(I, data[29:33])[0]: print(real height:, h) break跑出真实高度后把图片高度改回去隐藏内容就露出来了。压缩包伪加密也是高频考点。有些 zip 打开时要密码但文件头里的加密标志位其实是被出题人手动改过的数据本身并没有真正加密。判断方法很简单用十六进制工具看 zip 的目录结构如果文件头里加密标志位是01 00而不是00 00但又没有真正的加密头数据那就能绕过密码。直接把标志位改回00 00保存后重新打开文件直接就能解出来。这个技巧在比赛里救过我很多次。4. 密码学与杂项替换密码、编码混用和签到题的拿分姿势密码学这块对新手特别友好因为它的工具化程度极高很多时候你不需要完整理解算法原理只要识别出题目类型把密文丢进对应工具就能出答案。关键是“识别”这一步要快。4.1 替换密码与工具速查一眼认出凯撒、维吉尼亚和 Bacon密码学题的第一步永远是“判断加密类型”。高频出现的古典密码就那几类特征类型首选工具/方法字母整体偏移A 变成 C、B 变成 D凯撒密码循环试 25 次位移或 CyberChef 的 ROT13密钥重复出现比如 ABCABC 模式影响字母位移维吉尼亚密码CyberChef 的 Vigenere Decode / dcode.fr只由 A/B 或 0/1 组成长度是 5 的倍数Bacon 密码dcode.fr 的 Bacon cipher点划组合像摩斯电报摩斯电码CyberChef 的 Morse Code大小写字母加数字加 /base64CyberChef 的 From Base64全是 0x 开头的十六进制hexCyberChef 的 From Hex这里要特别提一下 quipqiup 这个工具它做替换密码的词频分析非常强。有些题目把密文做得像乱码每个字母被替换成了另一个字母没有规律可循这时候人肉分析会疯掉丢进 quipqiup 用词频统计自动破译往往几秒钟就能出可读文本。快捷键记不住没关系比赛时打开 CyberChef 页面把字符串丢进去用 Magic 功能自动识别编码和加密类型属于“无脑但有效”的兜底方案。4.2 编码套娃与压缩包密码从 base64 循环解码到爆破前先看提示编码套娃是 Crypto 入门必刷题型。一段密文可能是 base64、十六进制、URL 编码混合嵌套解了一层又是一层。遇到这种情况别手动画写个循环自动解import base64 data open(enc.txt, rb).read().strip() while bflag{ not in data: try: data base64.b64decode(data) except Exception: # 不是 base64试试 hex try: data bytes.fromhex(data.decode()) except Exception: print(data) break print(data)如果循环解到一半卡住看看是哪种编码换用 URL decode、ASCII85 继续解。这类题思路很简单就是反复尝试直到字节流里出现flag{关键字。压缩包密码题则要先看提示再爆破。很多题的压缩包文件名、备注、图片名里都有线索比如密码是“日期”“键盘位置”“题目名称”。先试这些弱密码不行再用fcrackzip或者john跑字典爆破。盲目暴力破解是最低效的方式我刷题时看到压缩包要密码第一反应永远是回头翻前面的题干和附件有没有隐藏信息。4.3 杂项题的决策树把零散思路变成可复用的判断流程杂项题范围很广但做题时其实可以形成一个“决策树”式的判断流程。拿到文件后先问自己几个问题文件真实类型是什么先file被改了后缀名就按真实类型处理。strings 里有没有直接可用的关键字有就直接出答案没有继续。binwalk 能不能分离出其他文件能就逐个分析经常藏着真正的压缩包。如果是图片是普通隐写、LSB、宽高被改还是图片尾部拼接了数据依次用 zsteg、宽高爆破脚本、十六进制检查。如果是音频听一遍打开频谱看看有些 flag 直接以文字形式画在频谱图上。如果是压缩包先试伪加密绕过再试提示密码最后才考虑爆破。这套决策树不是凭空想出来的是在刷了几十道杂项题之后总结出来的固定动作。比赛时照着顺序走能显著减少“拿着文件发呆”的时间。你也可以建立自己的决策树每做一道新题就更新一次三个月后你就是别人眼里的“杂项老手”。5. PWN 入门环境配置是第一道坎整型溢出是第一个突破口PWN 是 CTF 里门槛最高的赛道也是很多新手“想学但被环境劝退”的重灾区。我先说句实在话PWN 入门不需要你立刻搞懂堆利用你只需要把环境配好然后找一类“固定套路”反复练比如整型溢出练熟之后你就能拿到第一波 PWN 分了。5.1 环境准备做完这些你才算把 PWN 的门推开PWN 环境配置其实就三件事装 pwntools、装 gdb 插件、学会用 checksec 看保护。我用的是 Kali 或者 Ubuntu 20.04Python 3 环境下执行python3 -m pip install pwntools git clone https://github.com/pwndbg/pwndbg cd pwndbg ./setup.shpwntools 是写利用脚本的核心库里面自带了checksec、cyclic这些实用工具。pwndbg 是 gdb 的增强插件调试的时候能非常直观地看到栈布局、堆布局、寄存器状态对新手来说比裸 gdb 友好太多。环境装好后第一步是用file和checksec检查目标二进制file challenge checksec challengechecksec会告诉你程序开了哪些保护比如栈溢出保护Canary、地址随机化PIE、NX 保护。新手刷题优先找没有开 Canary、没有开 PIE 的题目这类题的栈溢出利用最简单直接返回地址覆盖就能拿分。比赛时看到 PWN 题先跑这条命令比瞎猜快得多。5.2 整型溢出为什么会发生从 C 的数据类型边界说起整型溢出是 CTF PWN 题里非常经典的一类入门考点它的本质是 C 语言数据类型宽度固定运算结果超出范围后会发生“回绕”。打个比方就像汽车里程表99999 公里再开一公里会跳回 00000。看一个典型的整型截断场景#include stdio.h #include stdlib.h #include unistd.h int main() { int n; char *buf; read(0, n, 4); if (n 0) return 0; unsigned short s n; buf malloc(s); if (buf NULL) return 0; read(0, buf, n); return 0; }这里程序先读入一个 4 字节整数n只检查了负数没有检查上界。接着把n截断成 2 字节的unsigned short s来分配堆空间但后续read用的却是原始的n字节长度判断和实际操作完全不一致。如果我发送n 65568也就是0x00010020这个数大于 0检查通过截断成unsigned short后低 16 位是0x0020也就是 32程序只会分配 32 字节的堆块但read(0, buf, n)会往这个 32 字节的堆块里读入 65568 字节堆溢出由此产生。题目里经常把这个过程包装成“菜单选择”“协议解析”“购物车结算”但核心永远是同一件事某个长度值在传递过程中因为类型宽度变化出了问题。5.3 从例题到利用脚本拿到一台靶机后按什么顺序打拿到一道 PWN 题按这个顺序走先file和checksec再运行程序看交互流程然后用 IDA 或者 Ghidra 反汇编定位漏洞点最后用 pwntools 写脚本。还是上面那道题利用脚本会是这样from pwn import * context.arch amd64 p process(./challenge) # n 65536 32截断后分配 32 字节 n 65536 32 p.send(p32(n)) # 构造溢出数据破坏相邻堆块 payload bA * 32 bB * 8 p64(0xdeadbeef) p.send(payload) p.interactive()第一次接触时你可能不会立刻 getshell这很正常。你先用 gdb 跑一下观察程序是不是在某个地址崩溃了崩溃的偏移是多少然后一步步调整 payload这个过程本身就是 PWN 入门最重要的训练。等你能稳定控制崩溃点再去学怎么通过栈溢出覆盖返回地址怎么调用 system 函数一扇门就打开了。这里提醒一个新手经常踩的坑本地打通的 exp到远程靶机上可能因为 libc 版本不同、opened flags 不同而失败。所以前期刷题优先找 No PIE、系统自带 libc 的简单栈溢出题把基本功练扎实再去碰堆题和远程版本适配的问题。6. 比赛日怎么打时间分配、抢分顺序和最容易翻车的细节平时的刷题储备再好比赛日的执行也能决定你最终排在第几名。CTF 夺旗赛的时间通常是 8 到 48 小时时间长度不同策略略有差别但底层逻辑是一样的先拿稳定分再攻坚难题避免在单道题上耗尽全部时间。6.1 从签到题到硬骨头一场比赛该按什么顺序推进我自己的节奏是这样的比赛开始的前半小时把所有题目列表扫一遍把“看一眼就知道怎么做”的题目先标记出来签到题立刻做掉这能快速建立心态优势。接下来第一个小时集中打 Web 和 Misc 的简单题这两块的稳定分到手后后面即使难题全卡住你的分数也不会难看。中期开始做 Crypto 和隐写先挑特征明显的题下手比如一眼是 base64 套娃、一眼是需要 binwalk 分离文件的这种题往往 10 分钟就能拿下一血。PWN 和 Reverse 放到后期集中攻坚但每道题给自己设一个 40 分钟的上限时间一到就果断换题。比赛里最常见的错误是“不甘心”在一道题上死磕三个小时最后既没做出来也错过了其他能拿的分数。6.2 flag 格式与提交陷阱格式错一次等于这道题白做这个细节我说再多都不为过题目做出来却提交不上比没做出来更让人崩溃。提交 flag 前先确认格式大多数平台是flag{}但有些赛事用ctf{}甚至像 polar 平台会用polar{}这种自定义格式。不要想当然从题目描述里找格式提示。还有几个非常容易踩的坑flag 区分大小写官方提交平台的输入框对大小写敏感所以要先原样复制不要手工敲有些 flag 里包含空格或者特殊符号手工输入很容易漏掉有的题目 flag 内容在附件里给了一段话里面有空格也要原样保留。做动态 flag 题目时更要注意题目会在服务端通过环境变量注入不同 flag网上题解里写死的那个 flag 是无效的你得自己到靶机环境里读取/flag或者指定路径的 flag 文件。6.3 赛后题解整理把“做过”变成“会做”的关键一步比赛结束不等于学习结束我个人认为赛后的题解整理比比赛本身更重要。每场比赛结束后 24 小时内趁记忆还热乎把每道题的解题过程复盘成固定格式的笔记【来源】polar / ctfshow / 某场比赛 【类型】Web | Misc | Crypto | PWN | Reverse 【考点】命令执行绕过 / LSB 隐写 / 整型溢出 【卡点】为什么没做出来没想到双编码 / 不知道用 zsteg 【解法】一句话用 zsteg 提取 RGB 三通道最低位 【命令】zsteg -a flag.png 【下次注意】PNG 通道不止 RGBA先跑工具再手写脚本这套笔记格式我坚持了三个赛季最大的感受是刷题量虽然没增加多少但“看到新题联想到旧题”的速度明显变快了。CTF 的知识点就那么多很多新题不过是旧考点的排列组合你的笔记库越完善比赛时的反应就越快。另外每隔三周左右把笔记里“卡点”比较多的题目重新做一遍不看题解看自己能不能独立打出来。这个“重做旧题”的动作比盲目刷十道新题都有用。最后再分享一个我自己的习惯每次比赛结束不管成绩好不好我都会把没做出来的题在三天内重新打一遍把 exp 和命令扔进本地仓库。坚持两三个赛季之后你会发现 CTF 备赛这件事题量可以不多路径一定要清晰。祝下次比赛你也能稳定输出。
返回列表