简介:《ctf-all-in-one.pdf》是一份面向CTF(夺旗赛)学习者与安全爱好者的系统性指南,覆盖从入门到进阶所需的核心知识。文档从CTF概念、比赛形式和规则讲起,逐步展开Reverse、Pwn、Web、Crypto、Misc、Mobile等主流题型,并梳理虚拟机、调试器、反汇编器等常用工具链,帮助读者快速建立完整认知。后续章节深入Linux与Windows下的二进制分析、格式化字符串漏洞、栈溢出、堆利用、ROP等利用技术,还包含Fuzz测试、符号执行、反调试等高级专题,适合希望系统提升解题能力的选手。全包仅1个PDF文件,大小6.69MB,目录结构清晰,方便按需查阅。文档配有大量真实赛题案例与参考资料,既有理论讲解也有实战演示,可直接用于日常训练与备赛复盘。目前已有593人学习浏览,是实用性较强的CTF入门与进阶资料。
1. CTF-All-In-One 是什么:一份把 CTF 学习路径收拢的文档资料
想入坑 CTF(Capture The Flag)的人,最不缺的就是资料,最缺的是一张能照着走的地图。你搜"CTF 入门",能得到几百个博客、几十个 PDF、十几个平台,但每份资料的版本、方向、难度参差不齐,有人让你先刷 Pwn,有人让你先学密码学,结果新手第一周就卡在环境上。CTF-All-In-One 这类聚合型文档资料,正是冲着这个痛点来的:它把 CTF 竞赛里最常见的五个方向——Web、Pwn(二进制利用)、Reverse(逆向工程)、Crypto(密码学)、Misc(杂项)——连同工具安装、基础理论、例题思路整理成一套从零开始的目录。适合在校学生、刚转安全方向但缺实战经历的从业者,也适合想带竞赛队伍但又不想自己从零攒讲义的人。它的价值不在于某一道题讲得多深,而在于把"先学什么、后学什么、学完去哪验证"这条主线理顺了。
2. 把 CTF-All-In-One 的内容拆成一张可落地的学习地图
2.1 五个方向考的是五种不同的能力
很多人把 CTF 理解成"黑客比赛",以为学会了就能渗透一切,其实 CTF 更像一场限时的工程能力考试。文档之所以按方向拆章,是因为每个方向考察的心智模型完全不同,混在一起学只会两头都抓不住。我按自己带新人的经验,把这五个方向的核心差异列成一张表:
| 方向 | 核心考察 | 典型题型 | 入门门槛 |
|---|---|---|---|
| Misc 杂项 | 信息收集、编码识别、隐写、流量分析 | 图片隐写、pcap 包分析、各种奇葩编码 | 最低,会看文件、会装工具就能上手 |
| Web | 对 HTTP 协议的理解、服务端逻辑漏洞、注入类问题 | SQL 注入、XSS、文件包含、反序列化 | 中低,懂请求响应就能开始 |
| Reverse 逆向 | 读汇编、还原算法、对抗混淆 | 破解序列号、还原 flag 生成器、脱壳 | 中高,需要耐心看反汇编 |
| Crypto 密码学 | 数学建模、识别算法、求解约束 | 古典密码、RSA 变种、分组密码 | 中,难在把题目翻译成数学结构 |
| Pwn 二进制利用 | 程序内存布局、漏洞触发、构造 payload | 栈溢出、堆利用、格式化字符串 | 最高,需要同时懂汇编、系统与调试器 |
文档里每个方向都会配一个"前置知识"章节,这是我最看重的地方。它告诉你学 Reverse 之前至少要会看 x86 指令,学 Pwn 之前要知道进程虚拟内存长什么样。把这些前置知识过一遍,再往下读就顺很多。反过来,如果一上来就死磕 Pwn 的堆利用,大概率三天之内失去兴趣。
2.2 为什么值得当主教材而不是字典
我刚接触 CTF-All-In-One 时的第一反应是:这东西不就是把网上的 writeup 汇总了一下吗?等真按它学完一轮才发现,汇总和体系化是两码事。它最大的特点是"跟着读就能走",而不是"遇到问题时翻一下"。比如讲栈溢出,它会从函数调用约定讲起,讲到返回地址怎么被覆盖,再给一道例题让你本地复现;讲 RSA,它会先讲模运算和欧拉函数,再给脚本让算 flag。这种线性结构让初学者不用自己拼图。
第二个理由是它的交叉引用做得好。文档里提到某个工具时,会顺带告诉你它出现的上下文和典型用法,比如用 GDB 调试时遇到 PIE 开启该怎么处理,用 ROP 之前为什么先关 ASLR 做验证。对于自学的人来说,这种"上下文里的知识"比孤立的命令列表有用得多。第三个理由是版本问题被集中处理了。CTF 圈里大量老博客的例题还在用 Python 2,跑起来全是编码错误,而这类聚合文档一般会给出更现代的替代写法,省掉你到处找兼容方案的时间。
当然要承认它的边界:它是学习资料,不是题库。想达到比赛能出分的水平,至少还要搭配一个在线靶场练习平台,把文档里每一章的例题当作业去刷。文档的意义是让你少走弯路,不是替你走路。
2.3 需要先补齐的底子:二进制、汇编与密码学基础
CTF-All-In-One 虽然从零讲起,但它的"零"是"零 CTF 经验",不是"零编程基础"。我建议动手前的第一周把这四块底子补上:C 语言基础要会,不用写多好,能看懂指针、数组、函数调用就行;十六进制与二进制换算要熟练,因为所有隐写和逆向的入手点都是字节;Linux 基本命令要会,特别是 file、strings、xxd、readelf 这类分析命令;最后是基础的数论知识,包括模运算、公约数、逆元,这决定了你能不能看懂 RSA 的解题脚本。
这块底子对应的章节,在文档里往往被放在"准备篇"或"基础篇"。不要跳过,也不要用"先用再学"的心态糊弄。实战里你会反复遇到这些概念:一个逆向题卡住,往往不是不会反汇编,而是看不懂某个位运算在干什么;一个 Crypto 题卡住,往往是不知道欧拉函数怎么用。把基础看两遍,比盲目刷二十道题更高效。
3. 用本地环境把 CTF-All-In-One 里的知识点跑成复现结果
3.1 最小三件套:容器、Pwntools 与调试器
自学 CTF 最容易翻车的地方在环境。文档给的例题大多涉及编译、调试和 exploit,如果直接在物理机上折腾 32 位依赖,装完系统也差不多该重装了。我的做法是准备一个独立的虚拟化环境,作为跑题的"沙盒",坏了就重置,完全不心疼。
最常见的方式是用 Docker 起一个 Ubuntu 容器,把 CTF 常用工具装进去。下面这一组命令能让你快速得到一个可用的 pwn 环境:
# 拉一个长期支持的 Ubuntu 镜像并进入交互式容器 docker pull ubuntu:22.04 docker run -it --cap-add=SYS_PTRACE --name ctf-box ubuntu:22.04 /bin/bash # 进入容器后安装基础编译与调试工具 apt update apt install -y gcc gdb binutils python3-pip file net-tools vim # 安装 Pwntools 并验证版本 pip3 install pwntools python3 -c "from pwn import *; print('pwntools ok')"参数说明:--cap-add=SYS_PTRACE是很多新手会漏掉的关键项,它允许容器内的 GDB 附加到被调试进程上。没有这个权限,你在容器里调试子进程时会遇到ptrace: Operation not permitted,文档里的调试步骤全部失效。--name ctf-box给容器起了名字,后面要用docker start ctf-box和docker exec -it ctf-box /bin/bash重新进入时方便。Pwntools 是 Pwn 题脚本的必备库,里面集成了进程交互、payload 构造和 ELF 解析功能,装好后用一行 Python 验证导入是否成功,避免后面写 exploit 时才发现环境坏的窘境。
除了容器,我还建议再装一个 32 位运行库,因为文档里很多老例题是 32 位程序。在 Ubuntu 22.04 上执行:
dpkg --add-architecture i386 apt update apt install -y libc6-dev-i386 libc6-dbg:i386这两行是给系统加 32 位架构支持。如果不装,遇到cannot execute binary file: Exec format error别奇怪,不是文件坏了,是你的系统根本跑不了 32 位程序。
3.2 跑通第一个 Pwn 例题:64 位栈溢出与 payload 模板
文档里 Pwn 方向的第一个实战例题,几乎都是栈溢出。别觉得它简单,整个堆利用体系都是建立在"你能稳定控制返回地址"这件事上的。我先写一个本地自测用的脆弱程序,用它把最小模板跑通:
// vuln.c:一个存在栈溢出的最小程序,仅在本地练习环境使用 #include <stdio.h> #include <string.h> void win() { puts("you win!"); } void vuln() { char buf[64]; gets(buf); // 不检查长度,允许溢出覆盖返回地址 } int main() { vuln(); return 0; }编译时关掉默认防护,方便本地验证:
gcc -o vuln vuln.c -fno-stack-protector -no-pie参数说明:-fno-stack-protector去掉栈保护(canary),-no-pie让程序加载地址固定,这样win()的函数地址在每次运行中都不会变。对于刚起步的学习,这两个选项把你暂时不想碰的干扰因素去掉,先看清楚溢出的本质。接下来写 exploit:
from pwn import * # 加载目标程序并解析 ELF,拿到 win 函数地址 elf = ELF('./vuln') win_addr = elf.symbols['win'] # 启动本地进程作为攻击目标 p = process('./vuln') # 64 位下:缓冲区 64 字节 + rbp 8 字节,返回地址偏移为 72 payload = b'A' * 72 + p64(win_addr) p.sendline(payload) # 切换到交互模式,观察是否输出 you win p.interactive()逻辑说明:在 x86_64 架构下,函数调用时栈布局从低地址到高地址依次是局部变量、保存的 rbp、返回地址。buf[64]占了 64 字节,gets()写入的数据会继续向上覆盖保存的 rbp 和返回地址,所以偏移量是 72。p64(win_addr)把地址按小端序拼进 payload,这是 x86 系 CPU 的统一字节序,写反了程序会直接跳到一个不存在的地址。跑通这个用例后,文档里后面那些"控制返回地址"的章节就都好理解了:方式千变万化,内核都是这一条。
3.3 用 Z3 把 Crypto/逆向里的数学约束变成可求解代码
CTF 的 Crypto 方向和部分 Reverse 题,表面上是让你"解密"或"找 flag",实际上是在解一组数学约束。手工推导非常吃力,用约束求解器可以大幅省时间。Z3 是微软出品的定理证明器,CTF 圈的通用做法是先把题目条件翻译成变量和等式,再交给它跑。
from z3 import * # 声明两个整数变量,代表题中未知的 flag 片段 x = Int('x') y = Int('y') # 把题目里能读到的条件建模为等式 s = Solver() s.add(x + y == 6) s.add(x - y == 2) # 检查是否有解并输出 if s.check() == sat: m = s.model() print(f"x = {m[x]}, y = {m[y]}") else: print("no solution")逻辑说明:Int('x')创建符号变量,Solver收集约束,s.check()返回sat表示可满足,s.model()给出满足所有条件的赋值。实际题目里约束往往来自字节比较:比如一个函数对输入做了加减异或,最后和某个数组比对,你只需要把每一步逆运算写成等式即可。我把这个模板保存成本地的solve_template.py,遇到任何需要解方程的题都先套它,比手写暴力遍历快得多。Z3 也支持位向量(BitVec),处理二进制位运算时用位向量声明确保结果符合整数溢出语义,这是另一个值得记下来的细节。
4. 五大方向的学习顺序与每周时间分配
4.1 推荐顺序:Misc → Web → Reverse → Crypto → Pwn
文档可以线性读,但做题不能线性刷。我的推荐顺序是 Misc 先行。原因是 Misc 门槛最低,一两天就能出成绩,能快速建立"我确实在做 CTF"的正反馈,同时它使用的 file、strings、binwalk 等工具也是其他方向的基础技能。随后进入 Web,因为 Web 题的调试反馈最快:你发一个请求,服务器立刻告诉你对不对,适合用来理解"漏洞是逻辑缺陷,不是玄学"。
之后再看 Reverse。逆向需要耐着性子看汇编,如果一上来就学,容易因为挫败感放弃。有了 Web 和 Misc 的实战经验后,你至少熟悉了"通过输入输出猜测内部逻辑"的思路,这对逆向很重要。Crypto 放在第四位,它的难点在数学而不在工具,建议先掌握文档里 RSA 的几个经典攻击模型再去刷题,否则你会觉得每个题都是新题,永远总结不出规律。门槛最高的 Pwn 放最后,因为栈溢出、堆利用需要前面方向积累的调试能力和脚本编写能力作为支撑。这个顺序不一定适合所有人,但培养新手时几乎没有例外。
4.2 每天两小时的配比:读文档和刷题不是一回事
很多人"看了一个月文档,上赛场还是不会做题",因为读和做之间差着一条巨大的鸿沟。读文档时你跟随作者的思路,每一步都觉得理所当然;真正动手时没人帮你把坑填平,差一个变量都能让你卡半小时。所以每章读完,至少要留出同等时间去练习平台做同方向题目。
我建议的时间配比是:周一到周五每天只保证两小时,一小时读文档新章节,一小时做前一章对应的练习题,周末用半天专门复盘错题。下面这个周计划表是我带新人时常用的模板:
| 时间 | 内容 | 目标 |
|---|---|---|
| 周一 | 读文档 Misc 章前半部分 | 学会识别常见文件头与编码 |
| 周二 | 刷 Misc 隐写题 2 道 | 独立完成 binwalk 分析 |
| 周三 | 读 Web 章:HTTP 与注入基础 | 理解请求与响应的结构 |
| 周四 | 刷 SQL 注入题 1 道 | 能手工判断注入点 |
| 周五 | 回顾本周笔记,整理工具命令 | 把零散知识点压缩成卡片 |
| 周末 | 文档例题全复现 + 错题重做 | 每个题至少本地跑通一次 |
这里有个容易被忽略的原则:文档里的例题,照着读一遍不算数,一定要亲手敲进本地环境跑出结果。我见过太多人用"眼睛学会了"骗自己,结果在比赛现场连exploit.py都跑不起来。
4.3 用能力差值表决定下周主攻哪个方向
每周日我会做一件事:把当前五个方向各挑一道代表题,记录"读完题目到写出第一版脚本的时间"和"是否一次通过"。这两个数据直接反映熟练度。比如 Reverse 如果总是要 30 分钟才能摸清程序流程,说明汇编快速阅读还不过关,下周就集中补这个薄弱项;如果 Web 题基本一次过,说明这块已经够用,把时间让给其他方向。
这个做法其实也很适合借助文档的目录来实现:每学完一个章节,就在能力表里对应位置打分。CTF-All-In-One 这样的文档给自己提供了清晰的章节边界,天然就是现成的进度条。当你在某个方向的分数明显落后时,优先级不是去刷难题,而是回到文档把对应基础章节重新精读一遍,找到自己漏掉的那个点。
5. 新手自学 CTF-All-In-One 的五个高发问题排查单
5.1 32 位程序跑不了:缺的是 multilib,不是缺系统
现象:从文档例题或老题集中下载的 ELF 文件,一运行就提示cannot execute binary file: Exec format error,部分环境还会弹No such file or directory。
原因:程序是 32 位编译的,而你的系统是 64 位环境且没有安装 32 位运行库。注意Exec format error并不代表文件损坏,它只是内核不认识这个二进制格式。
解决:按第 3 章的方法启用 i386 架构并安装运行库。装完后用file命令确认一下输出里包含ELF 32-bit LSB executable再执行,基本就能跑起来了。
5.2 偏移对也打不通:PIE 与 ASLR 把栈地址挪了
现象:调试器里看到的偏移量算得一点没错,返回地址也拼进了 payload,但一执行就段错误。更诡异的是,同一段 exploit 偶尔能通,偶尔崩。
原因:程序开启了 PIE(位置无关可执行文件),或者系统 ASLR 生效。这两种机制都会让函数地址在每次运行时变化,你写死的0x4011b6在这一次运行中对应的并不一定是win()。
解决:本地练习时可以用setarch $(uname -m) -R ./vuln临时关闭地址随机化,先确保 payload 逻辑本身正确;远程题目环境无法关闭 ASLR,就要走"泄漏地址—计算基址—拼动态地址"的路线,这也是文档里后续章节讲 ROP 时必然遇到的内容。先分清是逻辑错还是地址随机化,能省掉大量无意义的调试时间。
5.3 py2 时代例题只报编码错:bytes 和 str 混用
现象:文档或老 writeup 里的 Python 脚本,一运行就报TypeError: can't concat str to bytes或者UnicodeDecodeError,明明代码逻辑没错。
原因:CTF 圈很多经典例题诞生于 Python 2 时代,那时候str本质上是字节串,和现在 Python 3 的bytes混在一起,各种隐式转换行为完全不一样。
解决:统一入口,把所有外部读入的数据都用bytes处理,只在输出到终端时才decode()。比如:
# 读入二进制数据,保持 bytes 类型 data = open('flag.png', 'rb').read() # 需要和字符串拼接时,encode 成 bytes 再拼 prefix = b'CTF{' result = prefix + data[:4]逻辑说明:Python 3 里b'CTF{'是 bytes,'CTF{'是 str,两者不能直接用+连接。很多隐写题脚本需要把固定头字节和文件内容拼在一起,写成上面这种格式就不会报错。补一个# -*- coding: utf-8 -*-注释虽然不能解决这个类型问题,但能避免源码里的中文注释在某些终端下乱码。
5.4 复现 Web 题 404/500:容器状态不是新的
现象:在练习平台复现文档里的 Web 例题时,Payload 完全按照题解写,但服务器返回 404 或者 500。换一个浏览器访问页面却正常。
原因:CTF 平台为了隔离用户,通常会为每个会话动态创建容器。你拿到题目时的容器状态是"干净"的,但某些依赖(比如数据库)没有自动初始化;还有不少题的容器会在空闲一段时间后被回收,重新开题时 session 变了,旧 Payload 自然失效。
解决:先确认题目容器是否已经重置。常见做法是重新点击"开启环境"按钮,拿到新的访问 URL 后再试;带 Cookie 的题目先清空浏览器 Cookie 和新容器匹配。另一个高频原因是 Payload 里的 URL 编码不完整,尤其是空格和引号,建议所有注入类参数都先用 Burp 的编码功能处理一遍。记得看容器日志,如果平台提供的话,500 错误十有八九是内部执行异常,不是你的 Payload 语法错。
5.5 看时会,合上就空白:笔记抄成题解库才有效
现象:读文档的时候觉得全懂了,但关上页面做新题,连第一步从哪下手都忘了。笔记记了好几页,比赛时根本来不及翻。
原因:你是在"抄"笔记,不是在"转化"笔记。抄下来的是作者的思路,不是你的思路,大脑没有真正参与加工。CTF 题型的相似性极高,但变化也多,抄来的笔记遇到变体就失效。
解决:强迫自己用"题型卡"格式记笔记,每个方向一张卡,只写四行:题目特征、核心考点、最小命令、一句口诀。比如栈溢出题型卡写"缓冲区+返回地址覆盖;偏移计算;p64 拼地址"就够用了。这样记录的本子,比赛前十分钟能快速过一遍,才能真正变成你的战斗力。
6. 把文档变成你自己的知识资产:三个习惯与一个复盘模板
CTF-All-In-One 这类资料,最好的用法不是从头到尾背一遍,而是把它当作骨架,往上长你自己的题解和经验。我的做法有三条:每学完一个章节,就用自己话把例题的考点压缩成一句话写进笔记;每用到一个新命令,就顺手把它归档到本地一个叫bin-notes.md的文件里,下次遇到同样场景直接 grep;每月底挑一个之前做不出来的题目重新做一遍,跑不通就回头改笔记,确保笔记里记录的步骤自己还能执行。这三条坚持下来,文档会从"别人的知识"慢慢变成"你的工具手册"。
复盘模板我也固定下来:按方向建目录,每个题目以"考点_题名.md"命名,正文固定三段——一句题干、一段关键思路、一段踩坑记录。这个习惯来自一次让我印象深刻的翻车:有次比赛遇到一道看似常见的逆向题,我抄过题解却从没本地复现过,结果现场发现自己的偏移计算完全错了,浪费了一个多小时才调通。从那以后,我的规矩就是"任何脚本只有本地跑通一遍,才允许写进笔记"——看懂不稀罕,能复现才是自己的。
如果你正在犹豫要不要按 CTF-All-In-One 投入时间,我的建议是:先把文档的目录通读一遍,找到自己最感兴趣的两个方向,用两周时间跑通第 3 章的基础环境,再决定是否深入。CTF 这条路很长,但它的正反馈来得也很快:第一次成功 getshell、第一次解出别人解不出的 RSA,那种成就感足以支撑你走完前面最枯燥的基础阶段。希望帮到你。
本文还有配套的精品资源,点击获取