ARTICLE DETAIL

资讯详情

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

Python渗透测试脚本合集整理指南:环境隔离与脚本改造

Python渗透测试脚本合集整理指南:环境隔离与脚本改造 简介这是一份面向安全初学者与渗透测试从业者的Python实战脚本合集围绕Python 3.9与Kali环境编写强调用编程替代工具依赖既可用于实战演练也可作为Python安全编程的学习范例。资源共64个文件以45个py脚本为主辅以txt说明、passwords、username、result等字典与结果文件压缩包约3.02MB结构按功能模块划分清晰。内容覆盖干扰测试中的POC与EXP脚本、被动与主动信息搜集DNS解析、域名与邮件爬取、ICMP/TCP/UDP/ARP主机发现、端口与服务识别、敏感目录探测、未授权访问与SQL盲注检测、SQLMap Tamper脚本编写、XXE与SSRF检测、Base64/AES/DES/MD5加解密、弱口令生成与爆破、DDOS与嗅探等方向。已有166人学习适合希望从脚本层面理解渗透流程、积累可复用代码与排错思路的读者参考。1. 拿到一个 Python 渗透测试脚本工具合集先别急着双击运行很多人第一次拿到「Python渗透测试脚本,工具合集.zip」这类压缩包第一反应是解压、找入口、双击运行然后被一堆ModuleNotFoundError、SyntaxError和杀软弹窗劝退。我见过太多人卡在这一步最后把包丢进回收站转头去搜「python安装教程」重新开始。其实问题不在你而在这个包本身——它大概率是某个从业者多年攒下来的脚本碎片目录结构混乱、依赖版本打架、Python 2 和 3 混着写甚至有些脚本是半成品。你要做的不是「运行它」而是「把它当成一个待整理的知识库」先分类、再隔离、最后逐个跑通。这篇笔记就是讲我怎么把这类合集拆成能用的东西哪些脚本值得留、依赖怎么锁、在什么环境里跑、跑不通时看哪里。适合手里已经有一个类似压缩包、想把它变成自己工具箱的人也适合刚学渗透测试、想通过读别人脚本快速入门的新手。2. 先给合集做一次「体检」目录分类与脚本筛选2.1 用三条命令摸清压缩包的家底拿到包之后不要用图形界面解压完就开跑。我一般先在 Linux 虚拟机里操作因为大部分渗透脚本对 Windows 的兼容性很差尤其是涉及 socket、raw packet、subprocess 调 shell 的那些。先解压到一个隔离目录然后跑三条命令看结构。# 解压到独立目录避免污染当前工作区 mkdir -p ~/tools/pt_collection cd ~/tools/pt_collection unzip ~/Downloads/Python渗透测试脚本,工具合集.zip -d . # 第一条看目录树只展开两层避免输出爆炸 find . -maxdepth 2 -type d | sort # 第二条统计文件类型分布心里有数 find . -type f | sed s/.*\.// | sort | uniq -c | sort -rn | head -20 # 第三条找出所有 Python 文件并标记 Python 2 特征 grep -rl print --include*.py . | head -20 grep -rl raw_input\|urllib2\|except Exception, e --include*.py .这三条命令分别解决三个问题目录结构是否按功能分比如scanner/、exploit/、crawler/文件类型是否以.py为主还是混了大量.exe、.jar以及有多少脚本是 Python 2 写的。第三条里print带空格、raw_input、urllib2、except Exception, e都是 Python 2 的典型特征命中越多说明这个包越老后面要花的迁移时间越长。参数说明-maxdepth 2控制目录展开深度太深会刷屏太浅看不到子模块sed s/.*\.//提取扩展名注意没有扩展名的文件会被算成整行可以再加grep \.过滤grep -rl的-l只输出文件名方便后续批量处理。2.2 按「能不能独立跑」给脚本分三档体检完你会得到一堆.py文件但它们的质量参差不齐。我习惯按依赖复杂度分三档这个分类直接决定后面怎么处理。档位特征处理策略典型例子A 档单文件自包含只 import 标准库或依赖极少requests、socket直接建虚拟环境跑端口扫描、目录爆破、简单爬虫B 档有 requirements 或明确依赖目录里有requirements.txt、setup.py或 import 了 scapy、paramiko 等单独建环境锁版本中间件探测、SSH 爆破、流量分析C 档半成品/缺依赖/写死路径import 了不存在的模块或硬编码/root/xxx路径先读代码能补则补不能补就归档各种test.py、demo.py、untitled.py分档不是靠猜用一条命令就能把 import 情况拉出来# 提取所有 py 文件的 import 语句统计第三方库出现频率 grep -rh ^import \|^from --include*.py . | \ sed s/^from \([a-zA-Z0-9_]*\).*/\1/; s/^import \([a-zA-Z0-9_]*\).*/\1/ | \ sort | uniq -c | sort -rn | head -30这条命令的输出就是你的「依赖热度榜」。排在前面的requests、socket、os、sys是标准库或常见库不用慌如果出现scapy、impacket、pwntools、paramiko说明这个包里有偏底层的脚本需要单独准备环境。注意sed那段的写法只提取第一个模块名from a.b import c会被归到a够用了不用追求完美解析。提示不要在这个阶段就pip install -r requirements.txt。很多合集的 requirements 是作者随手pip freeze出来的里面混了几百个无关包直接装会把你的环境搞乱。正确做法是逐个脚本看 import按需装。2.3 把 C 档脚本当「阅读材料」而不是「运行目标」C 档脚本里其实藏着最有价值的东西——作者的思路。我遇到过很多写死路径、缺模块的脚本但里面的 payload 构造、请求头伪造、编码绕过逻辑写得很巧。这类脚本不要急着修先读。读的时候重点看三处请求怎么发的、payload 怎么拼的、结果怎么判断的。把这三段摘出来改写成自己能用的函数比修一个跑不起来的脚本划算得多。比如一个跑不起来的 SQL 注入探测脚本核心可能就这几行# 从 C 档脚本里摘出来的核心逻辑重写成可复用函数 import requests def check_boolean_injection(url, param): 基于布尔盲注的简单探测比较真/假条件的响应长度差异 true_payload f{param}1 AND 11 false_payload f{param}1 AND 12 try: r_true requests.get(f{url}?{true_payload}, timeout5) r_false requests.get(f{url}?{false_payload}, timeout5) # 长度差异超过阈值认为存在布尔盲注特征 diff abs(len(r_true.text) - len(r_false.text)) return diff 50, diff except requests.RequestException as e: return False, str(e)这段代码的价值不在「能跑」而在它示范了布尔盲注的判定思路构造真条件和假条件比较响应差异。参数timeout5是必须的渗透脚本最怕卡死阈值50是经验值实际用的时候要根据目标页面大小调整页面本身波动大的话这个阈值要往上提。把这类逻辑抽出来你就有了自己的探测函数库比攒一堆跑不起来的脚本有用。3. 环境隔离为什么我坚持一个脚本一个 venv3.1 全局装依赖是翻车的开始新手最容易犯的错是在系统 Python 里pip install一切。渗透脚本依赖的库版本冲突极其常见scapy新版改了 API老脚本跑不了requests某些版本对 SSL 校验的行为不一样impacket不同版本模块路径都变过。你在全局环境里装 A 脚本的依赖可能就把 B 脚本搞挂了。血泪经验我早期图省事全局装结果一个pycryptodome的版本冲突让我排查了一下午最后发现是两个脚本要的版本差了一个大版本。正确做法是每个 B 档脚本或每组功能相近的脚本建一个独立 venv。命令不复杂但要养成习惯# 为单个脚本建独立环境Python 版本按脚本需要选 cd ~/tools/pt_collection/scanner python3 -m venv .venv source .venv/bin/activate # 先只装脚本明确 import 的库不装 requirements.txt pip install requests beautifulsoup4 # 跑通后把实际用到的版本冻结下来 pip freeze requirements.lock.txt # 退出环境 deactivate关键点在「先只装明确 import 的库」。很多脚本的requirements.txt是作者全量导出的里面几十个包你根本用不到。手动装三五个跑一遍报缺什么补什么最后pip freeze出来的requirements.lock.txt才是这个脚本真正的最小依赖集。lock这个命名是故意的提醒自己这是锁定版本换机器复现时用它而不是原始 requirements。参数说明python3 -m venv .venv里的.venv是目录名放在脚本同级目录方便识别source .venv/bin/activate是 Linux/macOS 写法Windows 下是.venv\Scripts\activatepip freeze输出的是包名版本格式适合复现。3.2 Python 2 脚本怎么办能迁则迁不能迁就容器化体检阶段标记出来的 Python 2 脚本处理方式分两种。逻辑简单、行数少的直接手动迁到 Python 3主要改这几处print加括号、raw_input换input、urllib2换urllib.request、except Exception, e换except Exception as e、字典的iteritems()换items()。用2to3工具能自动改一部分但别全信它改完必须人工过一遍。# 用 2to3 自动转换先备份原文件 cp old_script.py old_script.py.bak 2to3 -w old_script.py # 转换后重点检查这几类问题 grep -n print \|raw_input\|urllib2\|iteritems\|has_key old_script.py2to3 -w会直接改原文件所以先cp备份。转换后grep那行是查漏has_key这种老写法 2to3 有时处理不干净要手动换成in。如果脚本依赖的库本身就没有 Python 3 版本比如某些老旧的mechanize分支别硬迁用 Docker 跑一个 Python 2.7 镜像把脚本封进去用完即弃。# 用 python:2.7-slim 跑老脚本挂载当前目录 docker run --rm -it -v $(pwd):/work -w /work python:2.7-slim \ bash -c pip install -r requirements.txt python old_script.py--rm用完删容器不留垃圾-v $(pwd):/work把当前目录挂进去脚本读写都在宿主机可见-w /work设工作目录。这种方式适合一次性任务不适合长期维护但比在宿主机装 Python 2.7 干净得多。3.3 用目录约定管理多个环境避免「我到底在哪个 venv 里」脚本一多最容易出的玄学问题是你以为在 A 环境里其实终端还激活着 B 环境跑出来的结果对不上。我的做法是给每个环境配一个激活脚本并在提示符里显示当前环境名。# 在 ~/.bashrc 里加一段激活 venv 时提示符显示环境名 venv_activate() { source $1/bin/activate export PS1(venv:$(basename $(dirname $1))) $PS1 }这样每次venv_activate .venv之后提示符前面会带上目录名一眼就知道自己在哪个环境。别小看这个排查「为什么昨天能跑今天不行」的时候十次有三次是环境搞错了。另外跑脚本前养成which python和pip list | grep 关键库的习惯确认路径和版本比事后 debug 省时间。4. 逐个跑通从端口扫描到请求构造的实操路径4.1 先跑 A 档脚本建立信心再碰 B 档A 档脚本依赖少适合用来验证环境没问题。典型的是端口扫描和目录爆破。跑之前先读一遍代码确认它扫的是你授权的目标别拿公网 IP 乱扫。我一般用本地起的靶机或者scanme.nmap.org这类明确允许扫描的地址做验证。# 一个典型的 A 档端口扫描脚本核心逻辑用 socket 实现 import socket import concurrent.futures def scan_port(host, port, timeout1): 尝试连接指定端口返回 (port, is_open) try: with socket.create_connection((host, port), timeouttimeout) as sock: return port, True except (socket.timeout, ConnectionRefusedError, OSError): return port, False def scan_range(host, ports, workers100): 并发扫描端口范围workers 控制并发数 results [] with concurrent.futures.ThreadPoolExecutor(max_workersworkers) as executor: futures [executor.submit(scan_port, host, p) for p in ports] for future in concurrent.futures.as_completed(futures): port, is_open future.result() if is_open: results.append(port) return sorted(results) if __name__ __main__: open_ports scan_range(127.0.0.1, range(1, 1025)) print(f开放端口: {open_ports})这段代码的关键参数是timeout和workers。timeout1秒是内网扫描的常用值扫公网要适当加大但太大会拖慢整体速度workers100是并发线程数太高会被目标限流或触发防护内网可以到 200公网建议 50 以下。socket.create_connection比裸socket.connect好在它会自动处理 DNS 解析和超时异常捕获里ConnectionRefusedError和OSError要分开考虑前者是端口关闭后者可能是网络不可达排查时含义不同。跑通 A 档之后你对这个合集的质量就有判断了。如果连 A 档都跑不起来大概率是 Python 版本或基础库问题先解决环境再往下走。4.2 B 档脚本的依赖锁定与版本回退B 档脚本是合集的主体也是最容易出问题的地方。以scapy为例它不同版本对网卡权限、Python 版本的要求都不一样。我的流程是先看脚本 import 了什么查这个库的当前稳定版装上去跑报错就降版本。# 以 scapy 为例先装最新稳定版试跑 pip install scapy python arp_scan.py # 如果报 API 相关错误查脚本里用的方法在哪个版本存在 pip index versions scapy # 回退到指定版本 pip install scapy2.5.0pip index versions能列出所有可用版本比去 PyPI 网页翻快。回退版本时注意有些库的新版本改了模块路径比如scapy.all里的某些类被移走光降版本不够还要改 import。这种情况我一般先看脚本的注释或 README 里有没有写「基于 scapy x.x 开发」有就按那个版本装没有就试最近的两三个大版本。注意涉及 raw socket 的脚本scapy、socket 的SOCK_RAW需要 root 权限Linux 下用sudo跑但sudo会切换 Python 环境导致 venv 失效。解决办法是用sudo .venv/bin/python script.py指定解释器路径而不是sudo python script.py。4.3 请求构造类脚本的参数化改造合集里大量脚本是「请求构造 结果判断」的模式比如目录爆破、参数 fuzz、简单的注入探测。这类脚本原版往往把目标 URL、字典路径、并发数写死在代码里直接跑不灵活。我的做法是统一改成命令行参数用argparse包一层改完就能复用。# 把写死目标的脚本改造成命令行工具 import argparse import requests from concurrent.futures import ThreadPoolExecutor def check_path(base_url, path, timeout5): 请求拼接后的 URL根据状态码判断路径是否存在 url f{base_url.rstrip(/)}/{path.lstrip(/)} try: r requests.get(url, timeouttimeout, allow_redirectsFalse) # 200/301/302/403 都可能表示路径存在按需调整 return url, r.status_code, len(r.content) except requests.RequestException: return url, None, 0 def main(): parser argparse.ArgumentParser(description目录爆破脚本) parser.add_argument(-u, --url, requiredTrue, help目标基础 URL) parser.add_argument(-w, --wordlist, requiredTrue, help字典文件路径) parser.add_argument(-t, --threads, typeint, default20, help并发线程数) parser.add_argument(--timeout, typeint, default5, help单请求超时秒数) args parser.parse_args() with open(args.wordlist, encodingutf-8, errorsignore) as f: paths [line.strip() for line in f if line.strip()] with ThreadPoolExecutor(max_workersargs.threads) as executor: for url, code, size in executor.map( lambda p: check_path(args.url, p, args.timeout), paths ): if code and code ! 404: print(f[{code}] {url} ({size} bytes)) if __name__ __main__: main()改造的核心是argparse那几行把 URL、字典、线程数、超时都变成参数。check_path里allow_redirectsFalse是故意的爆破时 302 跳转往往意味着路径存在但需要认证跟着跳转反而看不到真实状态。状态码判断里404排除但403要保留它表示路径存在但禁止访问对渗透来说是有价值的信息。errorsignore处理字典文件里的编码问题实战中字典来源杂不加这个容易崩。参数说明-t默认 20 是保守值内网可以调到 50--timeout默认 5 秒目标响应慢就加大但会拖慢整体executor.map保持输入顺序输出可读性好如果追求速度可以用as_completed但输出会乱序。5. 避坑与排查那些让我加班到凌晨的坑5.1 现象脚本在终端能跑放进 cron 或后台就失败原因环境变量不同。终端里你source过 venvPATH和PYTHONPATH都对cron 用的是最小环境找不到你的 venv也找不到脚本里相对路径引用的字典文件。解决在 cron 里显式指定解释器绝对路径和工作目录或者写一个 wrapper 脚本先cd再source。# wrapper 脚本cron 调用这个而不是直接调 python #!/bin/bash cd /home/user/tools/pt_collection/scanner || exit 1 source .venv/bin/activate python scan.py -u http://target -w ./dict.txt /var/log/scan.log 21cd那行保证相对路径正确source激活环境日志重定向方便排查。cron 里写0 2 * * * /home/user/wrapper.sh即可。5.2 现象requests 请求 HTTPS 站点报 SSL 证书错误原因目标用了自签名证书或者你的 Python 环境缺少 CA 证书包。渗透场景下经常遇到自签名证书的内网系统。解决不要无脑verifyFalse那会引入中间人风险且掩盖问题。先确认是证书问题还是环境问题环境问题就装certifi并更新确认是自签名再针对性关闭校验同时关掉警告。import requests import urllib3 # 确认是自签名证书后局部关闭校验 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) r requests.get(https://self-signed.target, verifyFalse, timeout5)disable_warnings只是屏蔽警告不解决安全问题仅用于授权测试。生产环境或不确定的场景正确做法是把目标证书加到信任链而不是关校验。5.3 现象并发脚本跑一会儿就卡死或报「Too many open files」原因文件描述符耗尽。每个 socket 连接占一个 fd并发数高、连接不关闭就会撞上系统限制。解决先看当前限制ulimit -n临时提高ulimit -n 65535同时在代码里确保连接用完就关用with语句或显式close。线程池的max_workers不要设得比 fd 限制还高。# 查看当前限制 ulimit -n # 临时提高到 65535只对当前 shell 有效 ulimit -n 65535永久修改要改/etc/security/limits.conf但渗透测试一般临时提就行。代码层面requests用with requests.Session() as s能复用连接并自动管理比每次新建连接省 fd。5.4 现象脚本输出乱码或中文路径报错原因Windows 和 Linux 默认编码不同合集里很多脚本是 Windows 下写的读文件没指定编码。解决所有open()加encodingutf-8输出重定向时设置PYTHONIOENCODING。# 运行前设置环境变量强制 UTF-8 export PYTHONIOENCODINGutf-8 export LANGen_US.UTF-8 python script.py代码里读字典、读配置的地方统一加encodingutf-8, errorsignoreerrorsignore能跳过无法解码的字节避免整个脚本崩掉。5.5 现象杀软或 EDR 把脚本当恶意程序删了原因脚本里有subprocess调 shell、socket建连、写注册表等行为特征像恶意软件。解决在隔离的测试环境跑别在主力机上跑来源不明的脚本。虚拟机快照是后悔药跑之前先打快照。如果必须在本机跑把脚本目录加入杀软白名单但前提是你已经读过代码确认没有恶意逻辑。读代码这一步不能省合集来源不明时尤其要警惕有些脚本会偷偷外传数据。6. 把合集变成自己的工具箱脚本改造与验证的一个具体技巧跑通一批脚本之后真正的价值不在于「我有了这些脚本」而在于「我能按需改这些脚本」。我最后会做一件事给每个跑通的脚本写一个最小的验证用例放在同级目录的test_前缀文件里。这个习惯来自一次翻车——我改了一个爆破脚本的并发逻辑本地跑没问题换到目标环境因为超时设置不同把目标打挂了。从那以后任何改动我都先写验证用例。验证用例不需要复杂核心是「给定已知输入断言输出符合预期」。以端口扫描为例# test_scan.py验证 scan_range 在已知开放端口上的行为 from scan import scan_range def test_localhost_ssh(): 本地若开了 22 端口扫描结果应包含 22 result scan_range(127.0.0.1, [22], workers1) # 这里不断言一定开放因为环境不同只验证函数不抛异常且返回列表 assert isinstance(result, list) def test_closed_port(): 扫一个几乎不可能开放的端口结果应为空 result scan_range(127.0.0.1, [1], workers1) assert 1 not in resulttest_localhost_ssh故意不硬断言 22 一定开放因为不同机器环境不同硬断言会让测试在别人机器上失败。它只验证函数返回类型正确、不抛异常。test_closed_port扫端口 1这个端口几乎不会开放断言它不在结果里能验证扫描逻辑没有把关闭端口误报为开放。这种「弱断言 强边界」的写法适合渗透脚本这种依赖外部环境的场景。跑测试用pytest装一下就行pip install pytest pytest test_scan.py -v-v显示每个用例的名字和结果改完脚本跑一遍几秒钟就知道有没有改坏。这个习惯让我在后续改造脚本时放心很多不用每次手动跑一遍完整流程。另一个技巧是给脚本加--dry-run参数。涉及实际发包、写文件、改配置的脚本加一个 dry-run 模式只打印「将要做什么」而不真正执行。改造起来就是在关键操作前加判断if args.dry_run: print(f[DRY-RUN] 将请求 {url}) else: r requests.get(url, timeoutargs.timeout)这个参数在调试阶段极其有用能让你在不触碰目标的情况下验证逻辑分支对不对。我现在的习惯是任何要发到目标网络的脚本先 dry-run 跑一遍看输出确认无误再去掉这个参数正式跑。说到底一个「Python渗透测试脚本工具合集」的价值不在于它里面有多少个脚本而在于你能不能把其中三五个改造成自己顺手、可验证、有测试兜底的工具。我自己的工具箱里常年只维护十来个脚本每一个都有验证用例和 dry-run 模式比攒几百个跑不起来的碎片踏实得多。希望帮到你。本文还有配套的精品资源点击获取
返回列表