
Hashcat的掩码攻击是我做授权渗透测试和密码安全评估时最常用的密码恢复手法之一。很多朋友刚接触Hashcat时习惯一上来就跑纯暴力破解遇到8位数字还好一旦碰上大写字母、小写字母、数字混合的密码纯暴力破解的候选空间能到几千亿甚至万亿级哪怕挂着高端显卡等上几天都是常事。掩码攻击的思路完全不同它假定密码存在某种可推断的结构用?d、?l、?u这类占位符把每一位的字符类型直接画出来让破解器只在一个大幅缩小的空间里枚举。想要快速搞定8位混合密码掩码攻击往往就是最优解。这篇文章围绕一个很具体的实战需求展开用Hashcat掩码攻击破解8位混合密码。我会把掩码语法、掩码设计思路、性能估算、常用掩码模板和踩坑排查整个讲透。适合刚接触Hashcat的渗透测试新手也适合已经会跑字典、想正式把掩码攻击纳入武器库的进阶用户。全文只讨论授权范围之内的安全测试与密码恢复场景所有操作请务必先确认自己拥有对应的合法授权。1. 掩码攻击是什么为什么它比纯暴力破解高效1.1 从暴力破解的算力账说起先看一组数字。一个8位密码假设字符集是95个可打印ASCII字符候选空间是95^8约6.63万亿亿……准确说是6.63×10^15也就是6630万亿种组合。显卡对当前哈希算法的破解速度如果是10 GH/s每秒百亿次全部跑完需要大约6.63×10^5秒差不多7.7天。而实际渗透测试和时间窗口往往只有几小时加密文档恢复的场景里用户更没有耐心等一周。暴力破解天然有个浪费算力的问题它把每个位置的字符都当成完全随机、独立分布的变量。但人设出来的密码根本不是随机的绝大多数密码都遵循高度可预测的结构比如首字母大写、后接小写、再跟两三位数字。暴力破解这种无差别枚举把大量算力消耗在永远不可能出现的组合上比如Zzzzzzzz或者这类没人会用的密码。1.2 掩码攻击的核心理念掩码攻击mask attack是Hashcat三种核心攻击模式之一另外两种是字典攻击和规则攻击。它通过占位符描述密码每一位的字符类型把一个巨大的搜索空间切分成若干个小得多的子空间。以8位混合密码为例你不需要知道具体是哪几个字符只需要判断出它是大写小写数字还是小写小写数字特殊符号这类结构GPU就只需要在一个受限的范围内枚举。打个比方暴力破解像在全城挨家挨户敲门找一个人掩码攻击则是根据这个人住东区、三层、带阳台的线索先划出一个片区再在片区内找。搜索范围小了五六个数量级速度自然不可同日而语。实际算一下完全暴力的8位全字符空间是6.63×10^15而一个?u?l?l?l?l?l?d?d掩码首字母大写、5位小写、2位数字的候选空间只有大约3.09×10^10两者差了五个数量级。同一个设备时间从几天直接压到几十秒。1.3 掩码攻击的典型适用场景掩码攻击适合以下场景我在实际项目中用得比较多授权渗透测试的离线哈希破解拿到哈希后快速验证弱密码、检验密码策略是否形同虚设。CTF比赛的安全题目题目里往往直接暗示了密码格式掩码几乎是最优解。企业内部密码策略审计考察员工密码是否落在常见结构里掩码模板可以量化检测覆盖率。取证与个人数据恢复自己忘记密码的加密压缩包、文档、磁盘镜像如果能回忆起部分格式掩码可以直接缩小范围。无论哪种场景前提都是合法授权。对不归你管的哈希做破解尝试不只是合规问题也是安全从业者的基本职业底线。2. 掩码语法完全拆解?d、?l、?u、?s 与自定义字符集2.1 内置字符集Hashcat定义了一套非常简洁的占位符体系核心就这几个占位符含义字符范围单个位置候选数?d数字0-910?l小写字母a-z26?u大写字母A-Z26?s特殊符号空格和!#等可打印符号33?a以上全部混合?l?u?d?s95?b全部可打印二进制字节0x00-0xff256另外还有?h小写十六进制0-9a-f和?H大写十六进制0-9A-F日常破解常规密码用得不多但处理某些设备默认密钥、或者特定系统生成的恢复码时会用到了解即可。?a是最常用的通配等价于把大小写字母、数字、符号全部混在一起这也是暴力破解在Hashcat里的本质写法。2.2 自定义字符集的高阶玩法内置占位符不够用的时候可以用自定义字符集。Hashcat的命令行参数里-1、-2、-3、-4分别对应四组自定义字符集掩码中用?1、?2、?3、?4来引用。写法非常灵活# 自定义字符集只包含 abc123 hashcat -m 1000 -a 3 -1 abc123 hashes.txt ?1?1?1?1?1?1 # 第一组字符集是小写字母数字掩码组合使用 hashcat -m 1000 -a 3 -1 ?l?d hashes.txt ?1?1?u?u?d?d?d?d第二个例子表达的结构是前2位是小写字母或数字、中间2位必须是大写字母、后4位必须是数字。自定义字符集里的内容可以叠加内置占位符这个能力非常实用。比如目标系统的密码策略明确只允许字母和数字、不允许特殊符号直接用-1 ?l?u?d就能把符号过滤掉避免在无效空间里浪费算力。2.3 从攻击模式到完整命令行掩码攻击对应的攻击模式是-a 3。一个典型的完整命令长这样hashcat -m 1000 -a 3 -w 3 hashes.txt ?u?l?l?l?l?l?d?d -o cracked.txt逐参数拆开看-m哈希类型。1000是NTLM0是MD5100是SHA11400是SHA25622000是WPA-PBKDF2-PMKID。拿不准时先识别哈希类型再跑。-a 3指定掩码攻击模式。-a 0是字典-a 1是字典组合-a 6和-a 7是字典与掩码的混合模式。-w 3工作负载。默认是1或23会占满显卡。如果机器上还跑着其他任务建议留在2。-o指定结果输出到文件避免终端滚动刷屏看不清。掩码本身用双引号包起来。这一步有讲究后面马上说。这里有个新手必踩的坑在bash或zsh里?是glob通配符。如果不加引号shell会把?u?l?l?l?l?l?d?d当成文件匹配模式展开轻则掩码变成一堆文件名重则直接报错找不到掩码。所以掩码永远要放在双引号里这是掩码攻击的第一条纪律。3. 实战用掩码攻击破解8位混合密码3.1 拿到哈希后的第一步确认哈希类型哈希类型搞错一切都白搭。我见过太多人拿个MD5哈希用-m 1000NTLM去跑跑了半天当然一无所获。常见的判断方法32位十六进制字符串大概率是MD5或NTLM64位十六进制大概率是SHA256带$分隔符的多段式字符串基本是各类Unix shadow哈希格式。新版本的Hashcat有--identify命令可以辅助识别老版本或者拿不准时直接查看Hashcat自带的示例哈希列表hashcat --example-hashes -m 0把输出里的示例和手头的哈希放一起逐段比对格式特征确认了再选-m。这一步错不得选错哈希类型掩码跑得再快也没有意义。3.2 根据密码策略设计掩码结构确认哈希类型之后下一步不是急着敲命令而是推断密码结构。假设目标系统的密码策略是8位以上、必须包含大写字母、小写字母和数字那么用户最可能按什么习惯设置我做了那么多密码审计观察到的规律高度一致首字母大写、后面跟几个小写字母、最后加一到两位数字比如Abcdef12、Happyday9这类。基于这个判断优先跑的掩码应该是?u?l?l?l?l?l?d?d首字母大写、5位小写、2位数字?u?l?l?l?l?l?l?d首字母大写、6位小写、1位数字?u?u?l?l?l?l?d?d前两位大写、4位小写、2位数字对比一下候选空间和耗时就能直观感受到掩码的价值。为了计算统一我按NTLM哈希在主流显卡上常见的10 GH/s下限来估算掩码候选空间10 GH/s耗时?a?a?a?a?a?a?a?a纯暴力6.63×10^15约7.7天?u?l?l?l?l?l?d?d3.09×10^10约3秒?u?l?l?l?l?l?l?d8.03×10^10约8秒?l?l?l?l?d?d?d?d1.76×10^10约2秒同一台机器同一个哈希类型纯暴力破解要跑一周掩码攻击只需要几秒。如果哈希算法更慢比如某些SHA变体速度只有1 GH/s甚至更低掩码结构的优势会进一步放大。结构信息的价值就在这里。3.3 先跑基准测试再估算时间正式开跑之前强烈建议先给当前设备跑一次基准测试搞清楚自己的硬件在不同哈希算法上的真实速度hashcat -b -m 1000输出里会给出每秒尝试数H/s。拿到这个数之后时间估算就很直白了时间 掩码候选空间 ÷ 每秒速度。比如基准测试显示当前设备对NTLM是12 GH/s那么?u?l?l?l?l?l?d?d3.09×10^10大约2.6秒就跑完。如果是一个慢哈希设备试验速度只有500 KH/s那同样掩码要跑8小时这时候就得重新评估掩码是否还有收窄空间。另外有个小技巧可以用--stdout参数把Hashcat当成候选生成器直接数一数某个掩码到底会产生多少组合hashcat -a 3 --stdout ?u?l?l?l?d?d?d?d | wc -l这个输出数量就是精确的候选空间比手算更靠谱也方便你验证掩码有没有拼错结构。3.4 完整执行与结果读取确认结构和速度都合理之后正式执行hashcat -m 1000 -a 3 -w 3 -o cracked.txt hashes.txt ?u?l?l?l?l?l?d?d跑完以后用--show直接从potfile里读取已破解结果hashcat -m 1000 --show hashes.txt--show不会重新破解而是读取Hashcat的potfile缓存秒出结果。这里有一个实际项目里很实用的习惯哈希文件最好按用户名:哈希的格式组织破解后输出才能对应回具体账号。如果只丢一串哈希进去破出来就是孤零零的明文没法落地到哪个账号用了弱密码。4. 常用掩码模板整理4.1 模板速查表Hashcat自带的masks目录里就有一批.hcmask格式的模板文件可以直接用-a 3 masks/passwords_8.hcmask调用。我自己整理了一份按场景分类的常用8位掩码表比官方那个更贴合实际审计需求模板名称掩码候选空间约典型场景8位纯数字?d?d?d?d?d?d?d?d1.00×10^8初始密码、设备默认密码8位纯小写?l?l?l?l?l?l?l?l2.09×10^11无策略约束的老系统首大写7小写?u?l?l?l?l?l?l?l2.09×10^11大写开头但后面不带数字首大写5小写2数字?u?l?l?l?l?l?d?d3.09×10^10强密码策略下的典型习惯首大写6小写1数字?u?l?l?l?l?l?l?d8.03×10^10数字只加一位的保守用户2大写4小写2数字?u?u?l?l?l?l?d?d3.09×10^10前两位固定大写的习惯3小写5数字?l?l?l?d?d?d?d?d1.76×10^10单词前缀数字后缀经典弱密码变体?u?s?l?l?l?d?l?d3.92×10^10匹配Pssw0rd这类结构8位全字符暴力?a?a?a?a?a?a?a?a6.63×10^15完全未知结构的兜底方案4.2 模板背后的概率逻辑这些模板不是拍脑袋写出来的背后是对大量真实密码样本的统计。人设密码有一个非常强的规律当系统强制要求大小写数字组合时绝大多数人会选择把大写放在开头、数字放在结尾中间的字母尽量用小写因为这样最好记、最好打。?u?l?l?l?l?l?d?d这类模板赌的正是这个习惯。而完全没有策略约束的系统里纯数字、纯小写的比例极其高?d和?l模板跑第一轮往往就有收获。另一个值得注意的模板是?u?s?l?l?l?d?l?d它对应的是Pssw0rd这棵经典弱密码树上的所有变体首字母大写、紧跟一个特殊符号、几个小写、一个数字替换字母o、再补一个小写和数字。这类密码看起来复杂实际上命中率极高在不少企业的密码审计里这一类能捞出一大把。4.3 字典、规则与掩码的叠加组合掩码攻击不是孤立的它可以和字典、规则灵活组合覆盖更多场景-a 6字典在前、掩码在后比如hashcat -m 1000 -a 6 words.txt ?d?d?d?d适用于已知基础词4位数字尾巴的结构。-a 7掩码在前、字典在后比如hashcat -m 1000 -a 7 ?u?u words.txt适用于两位大写前缀常见单词。规则叠加先用-r best64.rule对字典做常见变形大小写替换、尾号追加再配合掩码把同一份字典吃干榨净。多个掩码文件把模板写进.hcmask文件放进masks目录之后一句命令直接调用不用每次手敲长串掩码。经验之谈先跑字典加规则再跑掩码模板最后才上全字符暴力。这个优先级能帮你省下大量时间因为实际目标里能被字典命中的比例远高于你的直觉掩码是字典失效后的第二梯队。5. 常见问题与排查技巧实录5.1 速度远低于预期掩码空间明明很小却跑得很慢问题通常出在几个地方。首先看工作负载参数。-w 3和默认的-w 1跑出来的速度差几倍都很正常如果显卡没有跑满先试着把-w拉高。其次确认是不是真的在用GPU跑老机器或者驱动配置不当的时候Hashcat可能会退化到CPU上。用-d参数指定设备编号配合--benchmark对比理论速度一目了然。还有一个很现实的原因哈希算法本身就很慢。MD5、NTLM这类快哈希在GPU上每秒几十亿次但bcrypt、scrypt、Argon2这类慢哈希每秒只有几百到几千次是刻意设计成抗GPU破解的。遇到这种哈希再大的显卡也救不回来唯一能做的就是让掩码更精确把候选空间压到尽量小。5.2 常见报错信息怎么处理我自己整理了一份高频报错速查新手对照着看能少走很多弯路报错现象常见原因处理方式No devices foundOpenCL驱动缺失或版本过旧更新显卡驱动检查平台枚举用-I查看可用设备Separator unmatched哈希文件格式错误一行塞了多个哈希检查哈希文件确保每行一个条目且格式和-m匹配Token length exception哈希长度和所选-m类型对不上重新识别哈希类型换-mOut of memory自定义字符集过大、掩码过长导致生成器内存溢出拆分掩码分段跑或改用-O优化内核候选空间数了半天卡住生成启动时构造掩码内部结构耗时掩码别写得太复杂过多的固定字符和自定义集会影响初始化5.3 掩码写对了却不输出结果排除Hashcat本身报错之后最常见的没结果其实是这三个原因。第一个是potfile缓存干扰。同一份哈希如果之前跑过且命中了potfile里已经有记录再跑一次Hashcat不会重复输出因为默认认为已经完成了。想干净重跑用--potfile-disable或者指定一个新的--potfile-path。第二个是掩码结构与实际密码差距太大。你赌?u?l?l?l?l?l?d?d但目标密码实际是?l?l?l?l?d?d?d?d跑完整个空间也不会有结果。这时候别死磕一个模板换一份结构假设多试几个。第三个是长度问题。说是8位密码实际上可能有些账号是7位、有些是9位。这时候用增量模式hashcat -m 1000 -a 3 --increment --increment-min 8 --increment-max 8 hashes.txt ?u?l?l?l?l?l?d?d--increment会按min到max的区间自动扩展掩码位数把长度变化也覆盖进去。实战里我一般直接--increment-min 6 --increment-max 10配合一个通用模板先把长度区间扫一遍。5.4 合理排序与进度监控完全不知道结构的8位混合密码我的默认处理顺序是这样的先跑?d?d?d?d?d?d?d?d纯数字几秒十几秒先捞一波初始密码。再跑纯小写?l?l?l?l?l?l?l?l覆盖无策略约束的老系统。然后跑?u?l?l?l?l?l?l?l和?u?l?l?l?l?l?d?d这类大写开头结构。接着是?u?s?l?l?l?d?l?d这类经典弱密码变体。最后才考虑?a?a?a?a?a?a?a?a全字符暴力这通常已经是最后手段。长任务执行期间可以用--status-timer 60让Hashcat每60秒打印一次当前进度和剩余时间配合--restore断点续跑宕机或中断都不至于白跑。这个习惯在跑几十亿候选空间的模板时尤其重要。6. 实操心得与几个容易忽略的细节整个掩码攻击流程走下来我个人体会最深的是掩码攻击的瓶颈从来不是显卡而是你对密码结构的判断。自定义字符集和内置占位符都是死工具真正拉开差距的是猜结构的能力——这需要对目标系统密码策略、用户习惯和常见弱密码模式有足够的敏感度。几个容易被忽略的细节最后统一提醒一下每次破解前先跑benchmark把自己设备在不同哈希上的实测速度记成一张表。以后遇到任何估算直接查表代入不用每次重新摸索性能。这个习惯帮我省了很多时间。potfile里存的是明文密码属于高度敏感的数据。不要在共享目录、临时目录里留potfile审计项目结束后该清理的清理该加密保存的加密保存。很多安全测试项目出问题往往不是破解不了而是结果文件管理不当。我自己习惯把所有常用掩码写成.hcmask文件按8位数字8位混合日期后缀弱密码变体分类归档配合-a 3 masks/xxx.hcmask直接调用。积累一段时间之后这套模板库就是针对不同客户、不同系统策略最快出活的基础设施。掩码攻击从入门到熟练区别就在于你有没有自己的模板积累以及遇到跑不出结果时能不能冷静地换一个结构假设。希望这篇文章能让你少踩几个坑尽快把这一套流程用顺。