Crunch.py:纯Python密码字典生成器的原理与应用

发布时间:2026/10/13 7:10:05
Crunch.py:纯Python密码字典生成器的原理与应用 简介Crunch 密码列表生成器的 Python 实现主要面向安全测试、渗透测试及密码恢复等需要快速生成自定义字典的场景。脚本支持通过 min/max 参数设定密码长度范围并通过字符集或掩码方式控制生成规则还提供后缀添加、输出重定向等实用选项便于直接管道传递给 aircrack-ng 等工具。相比原版 C 语言 Crunch该版本运行速度略慢但胜在代码轻量、易读适合学习与二次改造。资源包共 3 个文件以 Python 脚本为主体附带 Markdown 说明文档和一张演示 GIF压缩包整体大小 5.76MB结构简洁。目前已有 324 人学习下载适合熟悉基本命令行操作、希望用 Python 实现或定制密码字典生成逻辑的初学者与进阶用户。通过阅读源码和演示可掌握字符集组合、掩码生成、后缀注入等实现思路并能直接运行脚本产出自定义 wordlist也可作为进一步扩展多进程性能优化的基础。1. 一个密码字典生成需求一个 Python 解压方案某个口令合规评估里我需要按公司密码策略批量生成测试密码至少一个大写字母、一个数字、一个符号长度 8 到 12。手边的机器只有 Python3 环境而经典的 crunch 密码列表生成器是 C 写的光是交叉编译就够折腾。Crunch.py 正好补上这个缺口——它是一个等效于 crunch 的 wordlist-generator用纯 Python 复刻了 crunch 的参数体系和生成逻辑喂同样的字符集、长度区间和模式就能吐出同样的 passwordlist。适合那些不想折腾 C 编译、又想保留 crunch 习惯的密码测试人员也适合把字典生成流程塞进现有 Python 脚本里。2. Crunch.py 的生成内核从枚举组合到可打断的迭代器想用好这份工具先理解它背后到底在算什么东西。Crunch 以及它的 Python 复刻本质上做的事情只有一个把字符串的笛卡尔积按指定规则展开。2.1 Crunch 原版的统计模型先算总量再展开Crunch 原版接受几个核心参数最小长度min、最大长度max、字符集charset以及可选的模式串pattern。如果不给模式串生成器会遍历从 min 到 max 的所有长度对每个长度做字符集的全排列组合。注意是“有放回”的排列也就是允许aaa、aab这种重复字符出现因为现实里用户设置密码时本来就会重复使用相同字符。组合数的计算公式是字符集长度 ^ 当前密码长度。比如字符集是 26 个小写字母长度固定为 4生成的总行数就是26^4 456976行。这个预计算在 Crunch.py 里会被用来做两件事一是在生成前打印一个预估行数让你判断是不是该提前终止任务二是作为进度评估的基准。部分网上的使用教程喜欢说“用 Python 写个循环然后把字符串拼起来”实际操作会发现小长度没问题长度一超过 8、字符集一到 62 位普通列表推导会在内存里炸掉。Crunch.py 这类实现不会把所有结果一次性存到内存里它维护一个索引数组每一位记录当前字符在字符集里的位置通过进位逻辑逐条输出类似里程表的滚动过程。def generate_fixed_length(charset: str, length: int): n len(charset) index [0] * length total n ** length for _ in range(total): # 用索引数组映射出当前字符串 word .join(charset[i] for i in index) yield word # 从最低位开始进位 for pos in range(length - 1, -1, -1): index[pos] 1 if index[pos] n: break index[pos] 0这段代码对应 Crunch.py 里最核心的定长生成逻辑。它先初始化一个全 0 的索引列表每次迭代把索引映射成字符串然后模拟“进制加法”更新索引。这里有一个值得注意的设计生成器用了yield外部每请求一条它才计算一条所以不会像一次性构建大列表那样瞬间吃掉几百 MB 内存。参数上的含义也直接charset是展开后的字符集比如abcdefghijklmnopqrstuvwxyz0123456789很多实现里会自动去重length是固定长度。如果你要生成 6 到 8 位混合字符代码只需在外层再套一个长度循环。2.2 Python 实现里的模式占位符机制Crunch 原版有一个非常好用的模式串功能代表小写字母,代表大写字母%代表数字^代表特殊符号。举个例子模式%%%^会生成形如a123!的密码一位小写、四位数字、一个符号。Crunch.py 复刻这个机制时把这个模式串当成逐字符的模板来处理。处理流程是先扫描模式串遇到占位符则取对应字符集遇到普通字符则原样保留。比如模式Pss%P和ss是字面量会展开成 26 个小写字母%展开成 10 个数字。展开后的结果是 260 个候选串因为只有两个可变位置。实现里通常用笛卡尔积来组合这些位置而不是把所有可能先塞进内存。def generate_by_pattern(pattern: str, charset_map: dict) - str: segments [] for ch in pattern: if ch in charset_map: segments.append(charset_map[ch]) else: segments.append(ch) def rec(seg_idx, prefix): if seg_idx len(segments): yield prefix return seg segments[seg_idx] if len(seg) 1: # 普通字面量直接拼接 yield from rec(seg_idx 1, prefix seg) else: # 占位符逐字符展开 for c in seg: yield from rec(seg_idx 1, prefix c) return rec(0, )这个递归写法直观但有个性能隐患如果模式串里可变占位符太多递归深度会跟模式长度线性增长Python 默认递归上限是 1000正常密码模式不会超过 20 位所以实际上不会触顶。真正需要注意的是生成器对象被复用的问题某些粗糙的 Python 复刻版在generate_by_pattern里直接返回了字符串列表把几万条结果一次性载入内存那就丢掉了迭代器的优势。我看到某个折腾过的实现里作者把segments里的单个字符也当成可迭代对象处理导致字面量被拆成了单字符逐段展开生成的密码全部缺字。后来改成判断len(seg) 1就走原样拼接问题才消失。这个细节也提醒我们看导入的 wordlist-generator 代码时先盯模式展开这一段。2.3 为什么用 Python 重写而不用 C 扩展有人会问直接用 Crunch 原版不就行了问题在于现实环境。很多评估任务跑在容器里容器基础镜像只有 Python3 运行时没有 gcc也没有配套的 libc 开发文件。这时候一个纯 Python 实现就能直接拉起来不需要处理 glibc 版本、不需要安装编译链。Crunch.py 在功能上做了减法也做了加法。减法是指它去掉了一些 Crunch 里的交互式会话和部分算法参数保留最常见的min/max/charset/pattern/output选项。加法是指它把生成器做成了 Python 模块你可以在自己的脚本里import它直接把生成函数当库用。这一点对做自动化评估的人来说是关键差异因为它不再是一个黑盒命令行工具而是可以嵌入现有流程的组件。用 Python 复刻还解决了编码问题。Crunch 原版在部分语言环境下输出 UTF-8 字符会出乱码因为 C 字符串默认按单字节处理。而 Python3 的字符串是 Unicode 原生的你可以在字符集里直接放中文、日文字符生成结果落到文件里也是标准 UTF-8。在生成包含公司名拼音加生僻字的密码字典时这个特性非常实用。3. 部署 Crunch.py参数映射与第一条可用的字典这部分把 Crunch.py 当成一个命令行工具来用。我拆过的这个实现里入口脚本就一个crunch.py没有依赖第三方库启动方式就是py -3或python3直接调用。3.1 运行环境与入口参数概览前提是机器上有 Python 3.6 以上版本因为代码里用了 f-string 和yield from低于这个版本会直接语法报错。Windows、Linux、macOS 都能跑唯一注意点是 Windows 下输出重定向到文件时默认编码可能不是 UTF-8需要加环境变量或用--encoding参数强制指定。我一般会用下面这条命令确认脚本可用python3 crunch.py --help如果能打印出参数帮助列表说明脚本已经具备运行条件。接下来参数含义和 Crunch 原版几乎一一对应-m指定最小长度-M指定最大长度-c指定字符集-o指定输出文件-p指定模式串-d开启去重。没有额外依赖也不需要先编译。3.2 生成 4 位纯数字口令字典最常见的一个需求是生成某系统的临时验证码字典4 位或者 6 位纯数字。用 Crunch.py 可以这样干python3 crunch.py -m 4 -M 4 -c 0123456789 -o digits_4.txt-m 4 -M 4表示最小长度和最大长度都是 4生成定长序列-c 0123456789给出字符集代码内部会做去重-o digits_4.txt指定输出路径执行之后会先打印一行预估总数10000 行然后开始逐条写入。这里可以观察到一个细节脚本启动后是边生成边写文件不是全部算完再写。所以如果你在生成到一半时发现规模远超预期直接按 CtrlC 中断已经输出到文件里的部分仍然保留不会出现“要么全部成功、要么什么也没有”的尴尬。参数替代的做法也有不少比如有人喜欢用python3 crunch.py 4 4 0123456789 -o digits_4.txt在 Crunch 原版里min max charset是可以作为位置参数传的但 Crunch.py 这个实现只接受-m/-M/-c这种命名参数我一开始没看代码直接用位置参数传结果脚本把4当成了输出文件名导致生成了几十 MB 的垃圾文件。建议使用前先跑一遍--help不要盲目套 Crunch 的原始参数顺序。3.3 生成 6 到 8 位小写字母加数字混合字典现实里的密码很少是纯数字多数是字母数字混排。比如测试某个系统时需要覆盖 6 到 8 位、字符集为abcdefghijklmnopqrstuvwxyz0123456789的全部组合命令是python3 crunch.py -m 6 -M 8 -c abcdefghijklmnopqrstuvwxyz0123456789 -o mix_6_8.txt执行时脚本会先做一次预计算36^6 36^7 36^8结果是超过两万亿条。看到这个数字你就能判断该不该缩小范围。我一般会先跑一个只含 10 万条的小规模验证比如限制字符集为abc 123确保输出格式正确再用完整字符集跑正式任务。这里还要提一下-d去重参数。如果字符集里本来就包含重复字符比如-c aaaabc不去重的话生成结果里会出现大量相同项。Crunch.py 默认会对字符集做一次去重有些网友魔改版本会关掉这个默认行为以提升速度但代价是输出体积膨胀好几倍我在后面的避坑章节会专门展开。3.4 输出到标准流与压缩文件不是所有场景都需要把字典落盘。有的评估脚本直接把生成器和测试工具连起来用管道一条条消费这时候输出到标准输出反而更流畅。python3 crunch.py -m 6 -M 6 -c 0123456789 | python3 bruteforce_tool.py代码里对标准输出做了逐条 flush这样下游程序能实时收到数据。注意不要手动加-o /dev/stdout某些实现里对输出文件做了编码处理写/dev/stdout会额外产生一个stdout文件还是直接靠管道传递更干净。压缩存储也有对应参数部分 fork 版本支持-z gz自动把输出写入.gz文件。但基础版 Crunch.py 不带这个功能我在用的时候是手动走管道 gzip比如python3 crunch.py -m 8 -M 8 -c abcdefghijklmnopqrstuvwxyz | gzip eight_lower.txt.gz这样硬盘占用能缩小几十倍。8 位 26 字母全集总行数约为 2088 亿明文文件会超过 1 TB但 gzip 压缩后大约 6 GB。跑之前先算清楚别把磁盘塞满。4. 自定义字符集与复杂模式贴合真实口令策略生成默认的小写字母、数字、特殊符号分段方式够用但遇到真实口令策略就很僵硬。比如某系统要求“姓氏 手机号后四位 一个特殊符号”这种规则可以拆成模式串处理。4.1 字符集文件的格式与归并Crunch.py 支持从外部文件读字符集避免命令行里写一长串引号把 shell 搞晕。文件格式很简单明文、无分隔符、按行读取每一行作为一组字符。实现里会把所有行的内容拼接起来再整体去重。cat charset_custom.txt abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 !#$%^*()_调用方式python3 crunch.py -m 8 -M 10 -c charset_custom.txt -o custom_dict.txt这里有一个容易踩的坑-c参数既支持“直接传字符集字符串”也支持“传文件路径”。实现是靠判断参数是不是一个已存在文件来区分的。如果你当前目录正好有个文件叫a而你想用单个字符a做字符集脚本会误读文件内容。我一般会在脚本调用前pwd确认目录里没有同名文件或者用绝对路径指定字符集文件。文件里的换行符和空格会被原样纳入字符集吗这个实现里不会它会过滤掉\n、\r和空格。也就是说如果你想在字典里包含空格作为候选字符用字符集文件反而做不到只能靠模式串里的字面量空格或者手工改代码这是个边界情况。4.2 模式串规则%^ 展开与字面量转义模式串是按位定义的比如L%D代表一个大写字母L固定、一个数字、一个大写字母、一个小写字母。固定字符直接保留占位符展开。python3 crunch.py -c abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 -p Pss%2019 -o pattern_dict.txt这个命令里P和ss是字面量展开为小写字母%展开为数字2019是固定串。生成结果类似Passa2019、Pssb2019、Pssc2019这样的组合。实现底层会构造一个位置列表每个位置要么是长度为 1 的常量字符串要么是可变字符串集合。然后用递归或者迭代器逐条产出。注意如果模式里有两个连续可变占位符比如%生成量是26 * 26 * 10 6760行这个数量可以直接在预期统计里看到。转义的方式有点不直观因为、%、^本身就是占位符你想让字典包含一个字符时不能直接在模式串里写需要把映射表里的改成其他定义或者在代码里加一个转义前缀。这个实现在命令行里没有设计转义语法所以我的做法是先让字符集包含再用固定字符段的拼接方式实现比如-p ack%ss把%当可变数字想保留就得把代码里的charset_map临时改掉。这算是一个需要提前知道的限制。4.3 批量任务串联循环体里调用生成器对象命令行适合单次生成但实际评估经常是“一个规则生成一批、再来一个规则生成另一批”。这种场景下我倾向于把 Crunch.py 当成模块导入在自己的脚本里循环调用。import crunch # 定义几组字符集和模式 tasks [ {min_len: 6, max_len: 6, charset: 0123456789}, {min_len: 8, max_len: 8, charset: abcdefgh, pattern: a%a%a%a%} ] for t in tasks: gen crunch.generate(t) for word in gen: # 在这过滤掉不想要的结果 if 000 not in word: print(word)这里的关键是crunch.generate(t)返回一个生成器而不是列表。每次调用next()时才计算下一条密码循环体内你可以接任意处理逻辑比如 hash 计算、长度过滤、正则匹配。像这种“批混合规则生成不落盘只在线处理”的玩法是命令行工具做不到的也正是 Python 模块化的价值所在。5. 生成过程常见的坑与排查从内存爆掉到多余重复任何生成器跑大规模任务都会翻车这里列几个我踩过或帮人排查过的典型问题。5.1 现象生成到一半内存占用飙到 2GB 以上现象调用了固定长度生成函数跑了几万条后进程内存持续增长最终触顶被杀。原因正常实现里每次迭代只占用常量内存。内存狂涨通常是把生成器结果转成了列表或者代码里把每次生成的字符串存入了结果集用于后续去重。Crunch.py 在开启-d去重时如果作者用 set 收集所有输出数据集一大内存就失控。解决先用小规模测试复现比如把长度限制在 3 位以内观察内存是否线性增长。如果是 set 导致的可以去掉内存去重改用sort -u在生成完文件后再去重。因为 Crunch.py 的-d参数在原版实现里只对字符集做去重不负责对输出结果做全量去重你可以把-d理解成“字符集去重”而不是“输出去重”。5.2 现象输出行数和预计算的组合数对不上现象启动时预览显示10000 行最终文件里却只有 9000 行或 10010 行多出或缺少一部分。原因常见是因为模式串和字符集参数冲突。比如给了-p %%%但同时-c里只包含大写字母和符号没有数字导致%展开出来是空集合该位直接跳过另一种情况是字符集文件里包含重复字符脚本只做了部分去重导致输出中有相同的行。解决把问题定位到参数组合不要同时用-m/-M和-p。Crunch.py 的规则是给了-p就以模式串为准忽略 min/max。所以你也不需要同时传。检查方式是用 Python 交互式环境跑一下generate_by_pattern看看返回生成器的预估总数确认每位都有有效字符集。5.3 现象模式里的特殊符号被 shell 吃掉现象执行带!或$的命令时生成的字典里缺少某些字符甚至命令执行失败。原因shell 会把部分特殊字符解释成历史扩展或变量引用。比如双引号里的!在交互式 bash 里可能触发历史替换单引号里虽然没有变量扩展但某些交换环境下对$、反引号的处理依然会出问题。解决所有模式串全部用单引号包起来而不是双引号。同时在脚本开头执行set H关闭历史扩展。命令示范set H python3 crunch.py -p !$%2019 -o special.txt如果字符集里也有特殊符号建议走字符集文件而不是内联参数。我在一次评估上模式串里的^被 bash 解释成管道符号的一部分导致整条命令被切割成两段后面排查了很久才发现是参数解析问题。5.4 现象按文件续跑时首尾重复现象生成任务中途中断然后用追加的方式继续跑结果新文件的开头几十行和旧文件的结尾重复。原因Crunch.py 的进度记录只保存到长度不保存字符集的精确位置。比如断在 6 位数字的第 12345 行续跑时从 6 位数字的第 1 行重新开始共用一套字符集顺序所以重复了。解决不用脚本自带的续跑功能改用外部工具切分任务。把一个大任务按“长度首字符”拆成多个子任务比如a开头的全部组合、b开头的全部组合这样每个子任务独立中断后只需重跑对应子任务不会和别的任务重叠。参数上可以用模式串固定首字符python3 crunch.py -p a%%%% -c 0123456789 -o seg_a.txt python3 crunch.py -p b%%%% -c 0123456789 -o seg_b.txt这种做法把组合总数从 10 万切成了 1 万一个片续跑成本低得多。5.5 现象字符集重复造成大量冗余输出现象charSet 写成aaaabbbccc生成文件行数还是字符集长度的全排列但里面大量重复词条文件体积远超预期。原因代码按输入字符集逐个取字符没有自动去重。有些 Crunch.py 版本默认做了去重但我手头这份 fork 里把去重开关默认关掉了理由是生成速度更快。结果就是aaa、aaa这种明显重复行大量出现。解决事前规范化字符集。在调用前用一段简单脚本做去重或者使用-d参数。如果文件已经生成用sort -u收尾比重新生成更快。sort -u raw.txt final.txt但sort -u会打乱行的原始顺序如果后续测试工具依赖某种顺序宁可重新生成也不要事后排序。6. 验证与提效三个让字典更可控的测试习惯字典生成完了不代表能用生成结果要先做冒烟验证再投入正式测试否则几十 GB 的文件跑完才发现格式是错的损失的时间很难补。养成三个习惯之后这个大坑基本就避开了。先用最小规模冒烟。任何正式任务的前驱我会把长度和字符集缩小到一万行以内生成一小份验证字典人工抽查里面的规律。比如-m 3 -M 3 -c ab预期结果是aaa、aab、aba、abb这样 8 行如果输出里出现空行、乱码、重复项就是代码环境有问题不值得跑大任务去撞运气。其次按长度分片比单一大文件更好管理。大任务中渠道像-m 8 -M 8 -c 完整字符集会生成超过 2000 亿行任何编辑器都打不开。我习惯按固定字符长度拆成独立文件再用时间戳命名比如dict_len8_0913.txt方便统计和续跑。分片后还能把多片内容通过管道合并进测试工具不用手动处理一个巨型文件。最后我每次生成后会跑一段校验脚本统计行数、对比预估值、抽查文件头尾、确认没有空行。这个脚本很短但能快速发现问题。如果你有既有弱口令库也可以直接合并去重用cat加上awk去掉重复项这样最终字典是“基础字典 规则生成字典”的综合结果。有一个小习惯我坚持至今所有批量任务跑完后留一份完整的命令行参数记录。因为密码字典的可追溯性太重要一旦测试过程被复盘你得说清楚这批字典是怎么生成的、字符集从哪里来、模式串依据什么规则。Crunch.py 生成的字典文件名我从来不带final这种词而是直接把参数写进文件名比如dict_8_36char_setA_2019.txt确保任何时刻都能一眼看出生产配方。希望这个工具和这些工程习惯能帮你省下几小时的折腾时间。附常见参数速查参数含义示例-m最短长度-m 6-M最长长度-M 8-c字符集或字符集文件-c abc123-p模式串优先于长度参数-p %%-o输出文件-o out.txt-d开启字符集去重-d调用格式python3 crunch.py -m 6 -M 8 -c abcdefghijklmnopqrstuvwxyz0123456789 -o dict.txt注意这只是备忘录具体行为以你拿到的源码为准毕竟不同 fork 版本在细节实现上会有差异。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询