零基础学Python打CTF:从环境搭建到五大方向实战脚本
发布时间:2026/9/29 4:34:54来源:尧图网络
每年都会有人问我同一个问题想入门CTF但完全不会编程到底应该从哪里开始我的答案一直没变过先学Python然后在题目里学Python。CTFCapture The Flag夺旗赛的核心是在限时内解决一组安全挑战而Python是这个圈子里使用频率最高的语言。不管是Web、密码学、杂项还是逆向、PWN动手写脚本解题几乎是每天的日常Python就像一把万能螺丝刀什么场景都能拧两下。这篇文章就是按这个思路写的——从零基础开始把Python当成CTF的解题工具来学而不是当成一门课程来背。内容覆盖环境搭建、语法速成、五大方向实战脚本、报错排查最后给出一条能落地执行的进阶路线。希望你看完能做的第一件事就是打开终端开始跑第一个脚本。1. CTF入门与Python的定位为什么非它不可1.1 CTF五大方向与Python的用武之地很多新手第一次接触CTF都会被五花八门的方向搞晕。其实常规赛事的题目就五大类每一类都离不开编程能力而Python几乎在每个方向都能出力方向考察重点Python典型用途WebSQL注入、XSS、命令执行、文件上传、反序列化等构造HTTP请求、枚举参数、自动提取flagCrypto古典密码、AES/RSA、哈希、随机数快速实现加解密逻辑、大整数运算、破解弱密钥Misc编码转换、隐写术、流量分析、取证处理文件头、解析图片、分析pcapng流量Reverse逆向工程、算法还原、注册机编写模拟脚本、还原加密算法、与调试器配合PWN漏洞利用、栈溢出、堆利用用pwntools编写exploit、收发数据、接管交互你会发现即使不做纯开发CTF解题的每一个环节——从读题到拿flag——都需要写点东西。而Python语法简洁、库极其丰富是想法到脚本距离最短的语言。1.2 Python为什么是CTF圈子的通用语不是C不好也不是Go不优秀但在CTF这种几个小时内要出结果的比赛里Python有三个不可替代的优势。第一语法接近伪代码。你脑子里想的先尝试所有可能的位移量再用频率分析判断哪个是明文几乎可以逐行翻译成Python不需要被内存管理、指针、模板这些细节打断思路。第二生态太全了。requests处理HTTPPIL处理图片pwntools直接跟程序交互pycryptodome和gmpy2覆盖加解密和大整数运算scapy还能解析流量包。这些库一装等于赛前就把工具箱备好了。第三胶水特性。很多时候解题不是纯Python搞定一切而是用Python调起系统命令、处理临时文件、把工具链串起来。Python写这种胶水脚本是最顺手的。一个现实判断如果你准备参加三个月后的比赛与其花时间研究语言特性不如直接把Python放到题目里学。刷题碰到一个编码转换就写一个转换脚本碰到一道RSA就写一个数字分解的脚本。很快你就会发现语法慢慢熟了解题思路也通了。1.3 赛前环境准备从安装到常用库一次配齐先说Python安装。网上太多教程会让人去官网下载、一路点Next然后……没有然后因为环境变量没配命令行里python直接报不是内部或外部命令。我的建议是装新版3.8以上即可不必追最新安装时务必勾选Add Python to PATH装完打开命令行敲python --version验证一下。如果你在Windows上遇到也可以用微软商店直接搜Python安装那个会自动处理好环境变量省心很多。python --version # 配置国内镜像加速不然pip下载库会慢到怀疑人生 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple编辑器推荐VS Code安装Python插件后就能直接运行脚本。运行方式很简单新建一个.py文件右键在终端中运行Python文件。不需要配置复杂的调试器先把东西跑起来最重要。CTF常用的库一次装全pip install requests pycryptodome gmpy2 pwntools pillow pyzbar提示Windows上如果gmpy2安装失败不要硬扛编译报错直接到Visual Studio Code或Python官网对应的wheel文件页下载匹配Python版本的whl再pip install这个whl文件一分钟搞定。环境到位之后接下来的所有脚本都是这个基础上跑的。2. Python基础语法速成按CTF需求学不按教材学2.1 先搞懂三件事输入、输出与类型转换CTF解题脚本大多长成一个样子从题目给的参数出发经过一系列处理最后打印flag。所以输入输出和类型转换是最高频的操作。# input()拿到的永远是字符串 s input( ) print(type(s)) # class str # 需要当整数用时必须显式转换 n int(s) # 输出时Python的print会自动换行且多个参数间默认用空格隔开 print(flag, is, here)有一个点我会反复跟新人强调eval这个函数能直接执行字符串里的表达式网上很多代码示例喜欢用它来简洁地转数字或解析输入但在CTF方向里eval本身就经常是考点——它能让一段字符串变成代码执行很多Web注入题考的就是你如何利用类似的入口。平时练习千万别图省事在自己的工具脚本里用eval因为一旦脚本处理了不可信输入后果很难预料。养成显式转换类型的习惯后面会少踩很多坑。另外要理解int(x, base)这个用法处理十六进制、二进制字符串时非常常见print(int(ff, 16)) # 255 print(int(1010, 2)) # 102.2 字符串、字节与编码CTF里的文字游戏基础CTF题目的信息和flag绝大多数都需要经过编码转换才能读出来。拿到一段看似乱码的字符串实际上可能是十六进制、Base64、ASCII偏移、URL编码……这些都是Python里几行代码的事。先搞清楚Python3里最折磨新手的一对概念str和bytes。str是人能读的文本bytes是计算机存的原生字节。两者不能直接拼接中间靠encode/decode转换。# 字符与ASCII码互转 print(ord(f)) # 102 print(chr(102)) # f # 十六进制字符串转文本 bytes.fromhex(666c6167).decode() # flag flag.encode().hex() # 666c6167 # Base64解码 import base64 print(base64.b64decode(ZmxhZw).decode()) # flag # URL解码 from urllib.parse import unquote print(unquote(%66%6c%61%67)) # flag理解这些转换Misc方向的入门题就没那么可怕了。练得多了你会发现乱码只是还没找到正确的解码方式而已。2.3 循环与字典写第一把瑞士军刀循环解决的是重复问题。CTF里最常见的重复动作是枚举枚举凯撒位移、枚举异或密钥、遍历参数。字典则用来做统计和映射古典密码分析尤其依赖字符频率。写一个字符频率统计脚本是很多人的第一个解题工具from collections import Counter cipher iqfcf{vFt1TsXs91_98X_6291jX9f3s9} freq Counter(cipher) print(freq.most_common(5)) # [(9, 4), (f, 4), (1, 3), (X, 3), ...]再配一个循环把凯撒位移全试一遍cipher iqfcf{vFt1TsXs91_98X_6291jX9f3s9} for shift in range(26): result for ch in cipher: if a ch z: result chr((ord(ch) - ord(a) shift) % 26 ord(a)) elif A ch Z: result chr((ord(ch) - ord(A) shift) % 26 ord(A)) else: result ch if flag in result.lower(): print(shift, result)这个脚本用了两层循环外层枚举位移内层逐字符处理。类似这种枚举判断的组合在后面的RSA小指数攻击、简单异或解密里会反复出现。理解了它你就理解了多数CTF脚本的基本骨架。2.4 文件读写处理二进制数据的基本功Misc、Reverse方向经常要跟文件打交道。题目给一个图片、一个压缩包或者一个原始数据文件脚本里第一步通常是打开、看文件头、按字节处理。# 以二进制方式读取才能看到文件的真实内容 with open(secret.png, rb) as f: data f.read() print(data[:8]) # b\x89PNG\r\n\x1a\n这是PNG的标准文件头判断文件真实类型时文件头很关键。很多新手直接改后缀名打不开文件先用十六进制看头部再用Python判定真实类型def detect_type(data): if data[:8] b\x89PNG\r\n\x1a\n: return PNG if data[:4] b\x89JF: return JPEG if data[:2] bPK: return ZIP return unknown处理十六进制转储文件时经常要把十六进制字符串还原为二进制文件with open(dump.hex, r) as f: hex_str f.read().strip().replace( , ).replace(\n, ) with open(out.bin, wb) as g: g.write(bytes.fromhex(hex_str))文件操作的基本功其实就是以什么模式打开、读完是bytes还是str、写到哪里。这三步想清楚大多数跟文件有关的题就不会卡住。3. 五大方向解题中的Python实战从读题到拿flag3.1 Crypto题实战10行代码解一道入门RSA密码学方向的题目是最适合练Python的因为思路清晰、逻辑严密。拿一道入门级RSA题举例题目给了大整数n、公钥指数e和密文c。解题思路是分解n得到两个质数p和q算出欧拉函数求出私钥指数d再用pow(c, d, n)还原明文。from sympy import factorint from gmpy2 import invert n 90581 # 题目给的模数 e 65537 # 公钥指数 c 39167 # 密文 factors list(factorint(n).keys()) p, q factors[0], factors[1] print(fp {p}, q {q}) phi (p - 1) * (q - 1) d int(invert(e, phi)) # 求e关于phi的逆元 m pow(c, d, n) # 解密 # 把整数明文转成可见文本 flag m.to_bytes((m.bit_length() 7) // 8, big) print(flag)每一步的作用讲清楚分解模数是RSA破解的关键环节欧拉函数(p-1)(q-1)是计算私钥的基础invert是求乘法逆元相当于计算d最后用Python内置的pow做模幂运算这是大整数运算效率最高的方法别用**运算符自己算模。如果遇到更大的n硬分解就跑不动了思路会转向低加密指数攻击、共模攻击、padding预测等但脚本骨架几乎不变读参数、算密钥、解明文。这就是为什么我说把一类题的脚本写熟后面遇到变体能很快迁移思路。3.2 Web题实战用requests和正则自动提取flagWeb方向的核心是考察对漏洞原理的理解但很多步骤需要用脚本完成。最典型的动作是给一个URLPOST一个参数循环试探从返回内容里找flag。import requests import re # 注意这段脚本只在比赛平台/授权的靶场环境中使用 url http://target.example.com/query for i in range(1, 50): data {id: f{i}} r requests.post(url, datadata) if flag in r.text.lower(): print(f第{i}条记录返回了关键内容) flag re.search(rflag\{[^}]\}, r.text, re.I) if flag: print(fFlag: {flag.group(0)}) break这里用到三个知识点。requests.post发送表单数据r.text拿到响应文本re.search用正则从大段HTML里提取flag格式的内容。CTF里flag一般有固定格式比如常见的flag{...}正则写对就能精准捕获。实战中经常遇到响应内容很大、直接肉眼找不过来或者返回数据被编码的情况。这时候建议把每次响应的完整内容保存到本地文件再慢慢分析而不是每次都在脚本里打断点看输出。脚本里加一行with open(fresponse_{i}.html, w, encodingutf-8) as f: f.write(r.text)这样既方便复盘也避免响应太长把控制台刷爆。注意Web题一定要在题目指定靶场和授权范围内操作。CTF比赛是全新的、隔离的演练环境和真实系统完全是两码事。3.3 Misc题实战从图片、二维码和流量包里挖信息Misc在很多人眼里是杂货铺但高频套路其实就那么几类编码转换、图片隐写、二维码处理、流量分析。Python在这些地方很顺手。图片方向常常用到PIL。比如题给了一张图片怀疑低比特位隐写了信息LSB隐写那就需要逐像素读取RGB值的最低位from PIL import Image im Image.open(secret.png) width, height im.size bits text for y in range(height): for x in range(width): r, g, b im.getpixel((x, y))[:3] bits str(r 1) # 只取红色通道的最低位 if len(bits) 8: ch chr(int(bits, 2)) if 32 ord(ch) 127: # 只打印可见字符 text ch bits print(text)二维码处理更简单直接调用库解码from pyzbar.pyzbar import decode from PIL import Image data decode(Image.open(qr.png)) for item in data: print(item.data.decode())如果二维码上贴了遮挡物或背景不够干净可以先用图像处理把二维码区域提出来再做二值化再用这个库识别。这个技巧在做Misc题时很实用。流量分析是另一个高频考点尤其是热词里经常出现的pcapng和USB流量题。主流工具是Wireshark或者tshark但Python里用scapy可以快速做批量过滤from scapy.all import rdpcap packets rdpcap(capture.pcapng) for pkt in packets: if pkt.haslayer(Raw): print(pkt.summary(), pkt.load)USB流量题实际上是在解析纯数据流把USB HID键盘事件还原成按键。这类题用Python处理比手工翻Wireshark高效很多。核心思路是用tshark把usb相关包过滤出来提取HID Data段的键值字节再对照USB键盘映射表还原成字母。映射表网上能查到把它存成一个字典脚本跑完就是完整键盘输入记录。这里有个小教训拿到流量包先别急着写脚本先抓几个关键包看字段结构确认协议层次正确再写解析逻辑。上来就套模板很容易因为字段名不同白跑一遍。3.4 逆向与PWN题里的脚手架pwntools入门PWN方向是CTF里偏底层的方向核心是写expexploit利用脚本和远程程序交互。pwntools是最常用的库它的设计哲学就是让脚本跟程序对话。from pwn import * # 远程连接题目给的地址和端口 io remote(1.2.3.4, 10001) # 接收程序输出直到某个固定字符串出现 io.recvuntil(bPlease input your name:) # 发送payload io.sendline(bflag) # 持续交互方便手动查看程序其他输出 io.interactive()这段代码虽然短但完成了整个连接、接收提示、发送数据、保持交互的闭环。Reversing方向的题如果需要跟程序多次交互或者需要根据反馈调整参数pwntools这套交互框架也是首选。不要一上来就啃堆利用、shellcode这些超难内容。先把pwntools的收发数据、交互流程跑通能把题目跑起来再逐步深入。工具的使用门槛往往比想象中低很多。4. 常见报错与解题脚本中的避坑经验4.1 新手最容易翻车的五个Python报错写解题脚本的过程本质上是和报错打交道的过程。下面这些报错基本是每个新人都会中招的我把原因和解决办法整理成一个速查表报错信息常见原因解决方法ModuleNotFoundError库没安装pip install 对应库TypeError: cant concat str to bytes混用了str和bytes先统一调用encode/decodeUnicodeDecodeError以文本方式读二进制文件改用rb模式或指定encodingValueError: invalid literal for int()字符串里有空格或非数字字符先strip()清理再int()转换RecursionError递归太深改用循环或提高递归限制处理UnicodeDecodeError是我个人踩过最多次的坑。很多流量导出或文件转储用文本方式打开后会报错解决办法是明确按二进制读取或者指定编码。判断标准很简单文件内容里如果有大量非ASCII字符就用rb。4.2 一道Web题的启发Python脚本为什么会感觉好奇怪热词里有个很有意思的题目描述小小查询系统输入id即可查询到信息但是报错感觉好奇怪。这道题反映的是Web方向里很经典的一类现象输入正常参数返回正常内容输入特殊内容却返回异常的报错信息而这个报错本身就是解题线索。很多新手第一次在Python脚本里复现这个过程时会感觉脚本怎么跟浏览器表现不一样原因通常有三个。第一个是编码问题。requests拿到响应后自动猜测解码方式但猜错时页面里的中文会乱码。解决方案是手动指定编码r.encoding utf-8。第二个是响应内容里有特殊字符导致正则匹配失败。不要看到一段显示正常就直接用正则先打印r.text的repr版本看看是否有隐藏的换行、标签或不规则空格。第三个是会话状态问题。有些查询接口依赖Cookie或上一步的Token直接用requests.post发一次请求会失败需要用requests.session()保持状态。这类奇怪感觉其实是很好的训练信号——每当脚本行为和预期不符把现象拆解成输入、输出、环境三类再逐项排查比反复试错高效得多。4.3 写解题脚本的六个好习惯刷题多了以后我总结了一套自己写脚本的习惯分享出来每个脚本开头打印接收到的关键参数确认和解说一致再往下走。把请求、解密、文件处理等动作拆成函数复用时不用复制粘贴。网络请求一律加超时和重试题目服务器本来就容易卡顿。响应和中间结果及时存文件不只在控制台里看。用tqdm给循环加进度条大量枚举时心理压力小很多。赛后把脚本精简、加注释存进自己的exp_lib目录按方向分类。这六个习惯看起来简单但能在比赛高压环境下省出大量时间。脚本不是写给自己爽的是写给几小时后的自己看的——那时候你很可能已经忘了当时为什么这么写。5. 持续进阶从入门到常态化参赛的一条可行路径5.1 一条清晰的学习路线给零基础新人排一条不绕弯的学习路线大概四个阶段阶段目标具体做法第一阶段能用Python处理文本和编码拿一段Base64、hex、URL编码的字符串反复转换直到看见种类编码不慌第二阶段能照葫芦画瓢写解题脚本到CTF题库平台找Crypto和Misc方向的入门题看题解理解后自己复现第三阶段能独立分析题目并写完整exp做Web方向的模拟靶场练习requests、正则、会话管理第四阶段按兴趣专精方向喜欢Web就深入框架漏洞和绕过技巧喜欢二进制就啃pwntools和底层利用核心做法是永远不要先把Python学完再打CTF两件事要并行。语法学到能写循环和函数就可以开始找题目练手了。碰到不会的语法和函数直接查官方文档查完马上用到题里记忆会非常牢固。5.2 刷题平台、工具沉淀与合规实践刷题平台我推荐几个自己常用的BUUCTF题库量大适合系统练CTFshow有大量针对新人的低成本入门题攻防世界适合按方向分类刷polar CTF这类赛事官网也常有赛题归档赛后可以拿来复盘。多平台交叉刷的好处是能接触不同出题风格不会只熟悉某一家的偏好。工具沉淀方面很多选手会整理自己的编码工具箱比如圈子里常说的随波逐流CTF编码工具就是把Base64、URL、进制转换、古典密码等常用编码解码能力集中到一起比赛时当双保险用。但我始终建议工具可以辅助核心的转换逻辑一定要自己用Python写过一遍。因为比赛时网络环境、工具兼容性都不确定自己的脚本永远不会带不动。学有余力时还可以关注行业内的一些合规实践比如各类厂商的SRC漏洞报告渠道——在授权范围内向厂商提交你发现的安全问题。这跟CTF比赛不一样它面对的是真实系统必须严格遵守规则和边界。我见过不少CTF选手通过这条路积累了宝贵的实战经验但前提永远是合规和授权。5.3 从单打独斗到常态化参赛的个人体会参加常态化赛事以后我发现一个规律真正拉开差距的不是知识量而是脚本沉淀速度和临场心态。比赛是几个小时的连续作战临时去查库、查语法会让节奏断掉。所以我在比赛前一定会做两件事检查常用库是否都装好把过去整理的exp_lib目录拉到手边。写题解writeup也是特别重要的一环。每次比赛后把每道题的解题脚本浓缩成注释清晰的单文件附上自己的踩坑记录发到社区或个人博客。这个过程倒逼你理解题目本质同时也让后来的新人少走弯路。我自己很多经验都是从别人的writeup里学来的——这个圈子之所以高效正是因为大家都愿意把经验写下来传下去。我个人在带新人时反复强调的只有一句话别把Python当一门课来学把它当成一把螺丝刀。CTF里每一个需要你重复手工做的事都值得写脚本每一次报错都是你精进工具的契机。从今天的环境搭建开始到写出第一个能自动提取flag的脚本这段路我走过无数人也走过它没有想象中那么难但一定需要你亲手敲下第一行代码。
网站建设高端定制企业官网