
做安全评估的朋友应该都体会过这种尴尬拿到目标后先跑一轮字典两三小时后看着结果文件发呆里面全是 123456 和 password1 这种低价值候选真正能用的一个没捞着。密码猜测这件事看着很机械实际上是一场概率与成本的博弈。我最近整理了一套名为PrecisionPasswordGenerator的智能密码猜测生成器定位就是解决猜不准、猜太慢、猜测没有方向的老大难问题。它不是简单给你吐一个几十 GB 的字典文件而是基于目标画像和统计模型从海量可能性里优先产出最像真人会设的密码。如果你在做授权渗透测试、密码恢复或者单纯想研究密码心理学这套生成器值得参考。我会从设计思路、实现细节、实操流程到常见的坑完整拆一遍尽量让你看完能直接拿去改进自己的工作流。先说明一点所有内容都站在已获授权、合法合规的测试前提下不搞歪门邪道。1. 先搞清楚密码猜测为什么需要精准1.1 不是拼算力的时代了以前讨论暴力破解大家比的是 GPU 数量和每秒尝试次数。但实际攻防里在线登录接口有频率限制和锁定策略离线哈希往往又用了加盐算法算力优势很难直接转化成命中率。你算力再强也不可能在一个合理时间内跑完一个 12 位大小写字母加数字的全排列空间。真实场景下的密码猜测更像是在一个巨大的人行为概率分布里做采样谁能更快更准地靠近高频区域谁就赢。PrecisionPasswordGenerator的核心出发点就是把精准两个字落到实处不是生成一个覆盖所有可能的超大字典而是生成一个命中目标用户习惯的候选列表。密码不是随机串它是人类记忆与习惯的体现天然带有可预测的模式。比如办公场景下一个叫 Zhang Wei 的员工他的密码大概率跟名字拼音、手机号后几位、入职年份、公司域名或者某个纪念日相关。传统工具不知道这些只会机械拼接。1.2 传统字典和掩码的痛点用过 Hashcat 和 John 的人都知道传统方式无非是跑字典、加规则、或者手动指定掩码。字典攻击的瓶颈在于字典永远是静态的拿一份大概率的通用弱密码列表对着所有目标无差别尝试。遇到稍微有点个性的用户比如把admin123改成Admin2023!字典基本就没戏了。掩码攻击给了我们模板比如?u?l?l?l?l?d但掩码只是定义了字符集和位置没有引入任何上下文。你只能用掩码去机械覆盖一旦设的格式和用户真实习惯偏离几个字符命中率就断崖式下跌。规则派生稍微聪明一点但规则是死的比如在键盘上按Shift、Leet替换、末尾加数字这些规则的组合爆炸程度极高而且很多规则互相冲突跑出来的候选里有大把是机器才想得出来的字符串。1.3 密码猜测的本质是概率优先为什么说密码猜测是概率问题因为任何一个候选字符串在真实用户群体里出现的概率差异极大。互联网泄露数据已经给了我们足够多的样本人名的拼音、生日、键盘走位、单词变形这些模式的分布其实非常集中。一个合格的智能密码生成器应当像一个熟悉当地语言的老侦探而不是一台无限穷举的机器。PrecisionPasswordGenerator的做法是先学习大量真实密码样本的字符组合规律再结合目标画像的特征词给每一个候选生成一个概率评分最后按照评分从高到低输出。这样你拿到的并不是几十亿个有可能而是几百上千万个更有可能。在线上测试场景里这意味着更少的请求、更少触发风控的概率离线恢复场景里意味着 GPU 时间被用在刀刃上。2. PrecisionPasswordGenerator 的整体设计思路2.1 核心定位从生成字典到生成候选很多工具叫字典生成器但我觉得候选密码生成器更准确。字典是一个集合候选是一个带优先级的序列。PrecisionPasswordGenerator在架构上刻意做成规则引擎 统计模型 排序器三层而不是简单地把规则拼接结果全部倒进一个文本。每一层都服务于精准的目标。输入层接受语料库训练用密码样本和目标画像姓名、域名、邮箱前缀、生日、手机号等。分析层从语料库中提取 n-gram 片段、上下文转移概率生成一个字符级或 token 级的语言模型。生成层用语言模型结合规则模板产生候选同时计算每个候选的联合概率。输出层按概率降序、按长度过滤、按策略打包输出为可被 Hashcat 或 Hydra 直接加载的格式。2.2 三块核心组件语料、规则、概率排序先说语料。语料质量直接决定生成器的上限。这里不是让你随便找一份密码库就导入而是要关注几个维度样本量是否足够大建议百万级、是否包含不同地区和文化的密码习惯、是否存在明显的单一样本过拟合。用一份全是英文单词数字的语料去预测一个中文用户的密码习惯效果自然不行。我在实际使用中会把公开研究数据集、内部红队积累的脱敏数据、还有目标组织指引中提到的默认密码策略分开喂给不同 profile而不是统一混在一起。规则组件也很有意思。规则不是简单的 字符串替换 或者 添加头尾而是分为结构规则和变形规则。结构规则决定候选怎么拼人名拼音生日、域名年份特殊字符、键盘横向相邻序列等。变形规则则类似 Hashcat 的规则但会记录每条规则在语料中的实际使用频率。比如全部小写出现频率远高于每个单词首字母大小写混合这样在排序时前者的权重更高。概率排序是核心中的核心。这里我采用了一个简化版的马尔可夫链模型对每个候选字符串计算一个log_probability。字符级的马尔可夫模型会记住在某个字符或前缀之后下一个字符大概是什么这能抓住很多人类密码的周期性习惯。比如很多人在密码里喜欢用123或2023这种连续数字段模型会自然把aaa123这类组合的概率调高。排序器按概率从高到低输出这比纯规则拼接再排序要高效一个量级。2.3 为什么选择统计模型而不是神经网络可能有人会问现在大模型这么流行直接用 LSTM 或 GPT 生成密码候选是不是更智能我试过几条路最后在PrecisionPasswordGenerator里选择了更轻量的统计模型原因有三第一可解释性。统计模型能明确告诉我候选的分数来自哪些 n-gram 贡献调优时能直接定位到语料里的某个模式。神经网络则更像黑盒出了问题很难排查。第二生成速度。马尔可夫链可以在 CPU 上每秒生成上百万候选而一个稍大一点的 LSTM 生成同样数量需要 GPU 并且速度慢了很多。密码猜测的候选空间动辄千万级速度是非常实际的约束。第三可重复性。统计模型的采样结果稳定可控你可以完全复现同一批候选列表。神经网络模型受随机种子影响很大这在需要汇报和审核的授权测试里反而麻烦。当然神经网络并不是一无是处用它生成看起来更像自然语言的密码片段是值得探索的但目前我还没有遇到必须引入它的场景。轻量、精确、可控才是这个项目的优先诉求。3. 核心功能与实操配置3.1 快速开始安装、配置文件、一条命令生成这个项目使用起来不复杂解压后目录结构大概是这样的PrecisionPasswordGenerator/ ├── config.yaml ├── train.py ├── generate.py ├── profiles/ │ ├── zh_company.yaml │ ├── en_general.yaml │ └── default.yaml └── data/ ├── corpus.txt └── targets.csv环境要求很简单Python 3.9只需要PyYAML和标准库。第一次运行建议先执行训练命令从语料库里构建 n-gram 统计模型python train.py --corpus data/corpus.txt --model models/base_model.json训练完成后再执行生成命令python generate.py --config config.yaml --model models/base_model.json --output candidates.txtconfig.yaml是整个生成策略的中枢我一般会先把目标信息维护好再反复调整生成模式。一个最小化的配置示例是这样的profile: zh_company targets: - name: Zhang Wei domain: example.com email: zhang.weiexample.com phone: 13800138000 birthday: 1992-08-15 min_len: 8 max_len: 16 model_weight: 0.7 rule_weight: 0.3 top_n: 500000model_weight和rule_weight是平衡语料学到的规律和规则人工指定的权重。我一般默认模型权重更高因为语料规律更贴近真人习惯但如果目标是一个强密码策略环境规则权重就要适当调高专门针对已知策略构造合规密码。3.2 三种生成模式详解PrecisionPasswordGenerator内置了三种生成模式理解清楚这仨基本上就掌握七八成了。第一种叫字典增强模式。它不会直接从语料库里抽原始密码而是把语料库中的高频 token比如admin、welcome、abc123拆成片段再和目标画像里的特征组合。为什么这么做因为直接复用泄露密码命中的往往是别人用过的弱密码而目标组织的员工更倾向于使用组织内部常用的词根加上个人元素。组合逻辑并不复杂比如token 年份token 特殊字符 数字段拼音首字母 token等。第二种叫规则扩展模式。这比较接近传统 Hashcat 规则的思路但加入了频率控制。生成器会先列出目标画像里所有基础词条然后按概率从高到低的规则依次套用。规则不是乱套的每一条都被记录过这个规则在真实密码中出现的概率比如:全小写概率 0.31首字母大写结尾数字概率 0.18全小写结尾感叹号概率 0.09Leet 替换a-e-3概率 0.06这种概率不是凭空拍脑袋而是通过训练语料统计出来的。这样出来的候选列表里不会再出现那种从这里开始连续 20 个大写字母之类的反人类字符串。第三种叫上下文感知模式。这是最贴合精准二字的模式。它把目标画像里的每一个字段都当成一个实体然后用语言模型判断这些实体在真实密码里最常出现的上下文位置。举个实际例子如果一个人叫 Zhang Wei手机号前三位是 138那么在语料数据里像zhangwei138、zw1380013、ZhangWei138都会是高分候选。为什么模型能猜到这些组合因为训练语料里存在大量姓名拼音数字、姓名拼音特殊符号数字的真实统计模型只是把其中的变量换成了当前目标的字段。三种模式可以叠加使用也可以独立运行。我做目标画像比较完整时会先跑上下文感知模式再用规则扩展模式补充最后用字典增强模式做兜底。这样候选列表既有方向又有广度不会一上来就陷入纯暴力空间。3.3 关键参数选择长度、字符集、变换级别这套工具的灵活程度取决于参数控制。我经常被朋友问到底该怎么设置min_len和max_len。这里不能盲目解空间要看目标系统的密码策略。比如目标系统明确要求至少 8 位那min_len直接设成 8别从 1 开始浪费资源。最大值一般不要超过 16超过 16 位的密码在在线场景里基本没有猜测价值离线场景里也让 GPU 的 workload 指数增长。无脑扩大长度区间只会把大量低概率候选堆积在序列尾部。字符集参数更值得注意。生成器默认会根据训练语料自动判断字符分布但你也需要手动剔除一些绝对不会出现的字符。比如有些系统限制不能有连续相同字符超过 3 个那就在规则里过滤掉。自定义字符集时我习惯按必用字符和禁用字符分开维护。禁用字符越干净候选列表的命中密度越高。变换级别这个参数则控制了多少条规则会实际用于派生。级别 1 只做大小写和简单前缀/后缀级别 2 会加入日期和手机号片段级别 3 才加入 Leet 替换和处理特殊符号的逻辑。高频使用的场景建议先用级别 1 和 2因为在线测试不能在同一个账号上尝试太多错误密码离线哈希恢复时再逐步提高到级别 3 甚至自定义规则反正本地尝试不担心被锁。3.4 输出格式与去重策略生成器输出不是简单地写一堆字符串。因为下游工具不同需要的格式也完全不同。比如 Hashcat 需要每行一个候选但如果你用的是 Hydra可能还要考虑用户名与密码的组合格式。所以在输出层PrecisionPasswordGenerator支持三种输出模式plain纯密码列表、username:password冒号分隔、csv带概率分数和来源标签。去重策略是个容易被忽视的细节。同一批规则可能通过不同路径生成完全相同的候选比如Zhang123既可以通过 姓名年份 生成也可以通过 首字母大写数字 规则生成。如果不去重候选列表里可能出现 30% 的重复项不但浪费空间还会让下游工具在同一个密码上反复尝试毫无意义。我这边会在内存里用布隆过滤器先粗去重再对最终结果做一次精确去重确保输出文件里每行都是唯一候选。另外一个很实用的功能是标签追踪。每个候选生成时都会标记它来自哪条规则、哪段 n-gram、目标画像的哪个字段。当一次猜测成功后你可以立刻回溯到是哪条规则命中了目标这个信息对后续调整策略非常关键。没有标签追踪的生成器就像不保存断点的调试器你只能看着结果干瞪眼。4. 实战一次授权评估中的密码生成流程4.1 场景设定与目标信息收集假设我们接到一个合规的授权评估项目目标是一家电商公司的内部办公系统客户允许我们对测试账号做在线口令猜测并要求在一周内输出报告。这个场景非常典型不涉及任何未授权行为。要生成精准候选必须先把目标信息整理得足够细。这里的目标信息不是指去非法爬取隐私而是基于公开信息、组织提供的账号规范、以及测试范围内允许枚举的邮箱命名规则。比如公司域名是example.com员工邮箱是拼音全拼加.从公开页面能看到部分员工的姓名、岗位、入职周年日。这些信息在授权范围内用于构造密码猜测模型是完全正当的。我建立了一个targets.csv字段包括姓名、邮箱前缀、办公地点、手机号、可能的生日字段。如果你拿不到完整手机号也可以用前三位加常见尾号组合来兜底。目标画像的价值不在于信息多而在于信息准确。一个错误的出生年份可能会让模型把大量权重放到完全错误的方向上。4.2 从已知信息构建目标画像跑生成器之前我习惯先手动梳理一份目标密码心理画像。比如这位员工姓名Zhang Wei邮箱前缀zhangwei域账号zhangwei入职年份2021可能的弱密码习惯办公系统初始密码可能是Welcome2021把这些信息写进 profile 文件后PrecisionPasswordGenerator会先做字段展开。例如姓名拼音可以生成zhangwei、zhang.wei、zw、wzhang、zhangw日期字段可以生成2021、2101、19920815、0815。这些展开后的 token 才是真正参与组合的最小单位。字段展开后再结合语料统计的上下文偏好生成的候选就有意思了。比如模型会优先输出zhangwei2021因为拼音全拼年份这种组合在真实语料中频繁出现。它还会生成Zhangwei123、zw2021!、Zz0815这类变体命中率远高于通用字典。这里我得强调所有步骤都在授权测试范围内进行不涉及任何一个未授权系统的实际密码信息。4.3 生成结果与命中率分析生成出的候选列表长度一般控制在 50 万左右。为什么是这个数量级因为在线测试时对一个账号尝试超过一定次数就会触发锁定所以候选列表必须精而不滥。我会先用概率排序最高的前 1 万条对测试账号做一轮试探如果某些请求被接受再继续用后续候选做第二轮。这种渐进式测试可以最大程度降低对业务系统的影响。举个例子一次内网测试里我生成了一份 50 万候选列表实际使用量不到 2 万条就命中了一个测试账号的密码。密码是Zhangwei2021正是模型里概率排序非常靠前的一条。这种结果不是运气而是画像 统计模型的正常反馈。如果完全用通用字典这个密码很可能被排在 2000 万条之后还不知道要跑多久。命中之后我会立刻查看生成标签发现命中条目来自拼音全拼特殊符号年份这条规则。后续再针对同公司其他员工时我会把同类规则的权重再提高一点。这就是带标签输出带来的迭代效率。4.4 迭代调优让生成器越跑越准一次命中不代表工具已经完美。实际项目里我会做至少三轮迭代。第一轮用较宽的规则范围目标是把最可能的密码捞出来第二轮根据第一轮命中情况收缩规则范围提高已命中规则的权重第三轮再补充一些较冷门的变形规则用来覆盖漏网之鱼。调优时还要关注负样本——那些尝试过但被系统拒绝的候选。虽然我们不能直接从系统得到正确密码但拒绝行为本身可以帮助判断当前方向是否偏离。比如连着 5000 条候选全是拼音数字格式且全部失败模型就会自动降低该格式的排序权重。这个机制有点像在线学习的工程化简化版非常实用。5. 常见问题与排查技巧实录5.1 生成速度慢CPU 和内存占用高我自己在跑这个生成器时最常遇到的性能瓶颈是 n-gram 模型加载后占用内存过高。一个 500MB 的语料库如果不做频率截断生成的模型文件可能达到 2GB 以上。解决办法是在训练时设置最小出现频次比如只保留出现次数不少于 5 次的 n-gram。这样模型体积能缩减 70%而预测效果几乎不受影响。另一个加速技巧是使用并行生成。不同规则之间其实相互独立可以通过 Python 多进程把候选生成任务拆到多个 CPU 核上。我常用的配置是 8 进程每进程负责一个规则子集合最后合并排序。如果没有做并行化生成 500 万候选可能需要几分钟但并行后通常在 30 秒内完成。5.2 命中率低问题到底出在哪如果生成结果在目标上接连碰壁我建议先回溯三个环节。第一是语料库是否与目标人群匹配你拿英文语料预测中文员工很难有高命中率第二是目标画像是否准确手机号、生日这些字段如果偏差太大模型会花大量概率在错误组合上第三是概率排序是否被某些高频噪声词带偏如果语料里abc123这种 token 出现频次过高生成的候选会很集中覆盖面反而不够。还有一种可能是目标系统强制密码过期或者有历史密码策略导致用户密码的组成习惯和你训练的语料差异很大。这时候不能只调权重需要补充目标组织特有的密码策略描述或者手动加入组织名年份随机符号等规则模板。5.3 规则越改越乱怎么保持清晰我在早期使用这个工具时犯过一个大错为了追求高命中把几十条自定义规则一口气全加进去。结果候选列表里同一类变体重合严重低概率规则反而把高概率候选顶到了后面最后一场测试打完很多规则根本不知道起没起作用。解决方案是规则版本化。每次改动规则前把当前候选列表的分布和标签统计导出备份更改后对比两次结果看看新增规则有没有产生新的 Top 候选。没有实际贡献的规则立刻删掉不要留恋。规则多了不代表精准反而会稀释整个候选列表的密度。5.4 内存和磁盘占用失控生成器默认会把全部候选写入内存进行排序当候选数超过 1 亿时内存很容易被吃满。我一般会把top_n限制在 500 万以内配合堆排序只保留当前概率最高的指定数量而不是先制造一个超大集合再排序。输出文件也要考虑磁盘占用如果一个候选平均 12 字节500 万条就是 60MB这还能接受如果是 10 亿条那绝对不是在线测试该干的事。如果你确实需要很大的候选空间建议把它拆成多个分片文件每个分片 100 万条按概率段分开存储。下游工具逐个加载既缓解了内存压力也方便在不同阶段测试不同概率区间的候选。6. 边界与合规安全从业者必须守住的底线6.1 授权是唯一前置条件密码猜测生成器天然具有双面性。它能帮安全团队快速验证弱密码风险也能被不怀好意的人用来制作攻击字典。所以我在任何场合都会强调没有获得书面授权绝对不要对任何账号执行实际猜测动作。工具的使用场景应该是客户授权的红队评估、企业内部自检、CTF 或者自己搭的实验环境。生成候选本身没有危害但把这些候选拿去对别人系统做尝试性质就完全不同。项目里我特意加了一个启动时的授权确认提示要求使用者输入项目编号或授权人名称这既是流程约束也是一种自我保护。6.2 数据隐私与最小化原则训练用的密码样本很多来自公开研究数据集这些数据同样涉及隐私问题。在使用时要遵循最小化原则只提取统计特征不保留原始样本目标画像信息也只保留在当前测试项目的最低必要范围内测试结束后及时删除。生成结果里的候选可能恰好命中了某个真实用户的密码这些敏感信息绝不能持久化保存更不允许外传。很多新人把泄露数据直接丢进工具然后又随手把生成的候选列表上传到共享目录这是很危险的操作。合规的做法是所有敏感文件保存在加密磁盘访问权限限定到项目组测试结束后按合同要求销毁。6.3 工具无罪但使用有责最后说一点个人看法。任何安全工具都像一把刀切菜还是伤人取决于持刀人。PrecisionPasswordGenerator的设计初衷是让安全人员在有限时间内更精准地评估弱密码风险而不是提供一个批量窃取账号的武器。我在博客里写这些细节也是希望更多人理解智能密码猜测背后的原理从而知道怎么防御设置高熵密码、启用多因素认证、监控异常登录频率这些措施比任何工具都更重要。如果你打算在自己的项目里复刻这套思路建议先从训练语料和规则引擎开始别急着上复杂模型。能坐下来把基础逻辑搞明白后续优化才有根基。我个人在实际使用中的体会是密码猜测生成器的价值不在于它生成了多少条候选而在于它帮你把有限的时间精力投入到最高概率的方向上。有一次测试我们团队用这套工具跑了不到半小时就找到了多个测试账号的弱密码而之前用常规字典蹲了一下午依然颗粒无收。那种精准打击的感觉确实比堆算力高效太多了。希望这篇文章能帮你少走些弯路。