深入解析Windows密码哈希与Kerberos密钥生成原理及实战

发布时间:2026/6/24 7:20:17

深入解析Windows密码哈希与Kerberos密钥生成原理及实战 1. 项目概述为什么我们需要深入理解Windows身份认证的“内功心法”在Windows域环境的安全评估、渗透测试甚至是日常的故障排查中我们经常会遇到一堆与密码相关的哈希值NT哈希、LM哈希还有Kerberos协议中那些神秘的密钥。很多工具能一键“转储”出这些哈希但知其然更要知其所以然。当你拿到一个NT哈希你知道它是如何从用户输入的密码一步步计算出来的吗LM哈希为什么被视为安全界的“活化石”而默认被禁用Kerberos票据加密所用的密钥又和用户密码有着怎样千丝万缕的联系这些问题直接关系到你对Windows身份认证体系的理解深度。DSInternals这个PowerShell模块就像一把打开Windows域数据库NTDS.dit内部世界的钥匙。它不仅能提取数据更能让我们以编程的方式亲手复现和验证这些核心安全组件的生成过程。这次我们不满足于简单的工具使用而是要深入“后厨”用DSInternals作为我们的实验台把NT哈希、LM哈希和Kerberos密钥的生成算法从头到尾、掰开揉碎地演练一遍。这对于安全研究人员、渗透测试工程师和系统管理员来说是构建底层知识体系不可或缺的一课。理解了这些“内功心法”你再看各种攻击手法如Pass-the-Hash、Kerberoasting和防御策略时会有一种豁然开朗的感觉。2. 核心概念与算法原理解析在动手操作之前我们必须先打好理论基础。Windows的密码存储和认证密钥生成是一套历史悠久、层层演进的体系。每个概念背后都有一段安全攻防的历史。2.1 NT哈希当前的主流与基石NT哈希也称为NTLM哈希是当今Windows系统存储用户密码凭证的主要方式。它的计算过程相对直接但每一步都值得深究。算法核心MD4没错NT哈希使用的是已经被证明不安全的MD4哈希算法。这本身就是一个历史包袱。计算过程可以概括为获取密码明文例如用户密码是Pssw0rd。转换为Unicode编码将密码字符串转换为UTF-16LE小端序格式的字节序列。这是关键一步因为一个英文字符在Unicode下会变成两个字节例如P变为0x50 0x00。计算MD4哈希对这个Unicode字节序列进行标准的MD4哈希运算。输出结果得到一个16字节128位的哈希值通常以32位的十六进制字符串表示如8846F7EAEE8FB117AD06BDD830B7586C。注意NT哈希是静态的。只要密码不变无论你在哪台计算机、哪个域上计算只要算法一致得到的NT哈希值都是相同的。这使得它成为“哈希传递”攻击的理想目标。为什么是MD4这要追溯到Windows NT早期设计时1990年代MD4是当时可用的、相对快速的哈希函数。尽管MD4早已被破解但出于巨大的向后兼容性考虑微软至今仍在身份认证协议中沿用其计算结果。2.2 LM哈希已被淘汰的“遗产”LM哈希是LAN Manager哈希的简称其历史比NT哈希还要古老源于早期的Windows和OS/2系统。它的设计存在严重的安全缺陷在现代Windows系统中默认已被禁用但你仍然可能在旧系统或某些特定配置中见到它。算法流程与安全缺陷密码大写将所有密码字符转换为大写。Pssw0rd变成PSSW0RD。这一步极大地减少了密码的熵不确定性。填充/截断至14字节密码不是14字节则用空字符填充超过14字节则截断。这限制了密码长度。拆分为两个7字节块将14字节的密码分成两个独立的7字节部分。各自生成DES密钥每个7字节块被用来生成一个8字节的DES密钥。这个转换过程将56位密钥扩展到64位是固定的进一步削弱了安全性。用固定字符串加密使用上一步生成的DES密钥对一个固定的、已知的字符串KGS!#$%进行DES加密。连接结果将两个8字节的加密结果连接起来形成一个16字节的LM哈希。LM哈希为何脆弱大小写不敏感直接降低爆破难度。分块独立加密攻击者可以分别破解两个7字符的密码相当于将难度从破解14个字符降低到破解两个7字符。弱DES密钥生成密钥生成算法简单易于预计算彩虹表。 正是这些缺陷使得LM哈希在多年前就已经被视作严重的安全风险。在安全要求高的环境中必须确保其被禁用。2.3 Kerberos密钥从密码到票据保护的桥梁Kerberos是Windows域环境默认的、更安全的网络认证协议。它不使用明文密码或静态哈希进行认证而是使用基于用户密码派生的加密密钥。核心关系密钥 f(密码, 盐, 迭代次数)Kerberos密钥不是直接由密码哈希而来而是通过一个更慢、更抗破解的密钥派生函数生成的最常见的是基于AES的。以AES密钥为例的生成过程输入密码用户密码Pssw0rd。确定盐在Kerberos中盐通常是域名和用户名的大写组合例如CONTOSO.COMAdministrator。加入盐是为了防止对相同密码的哈希进行跨用户预计算。选择迭代次数这是一个故意减慢计算过程的参数增加暴力破解的成本。Windows默认使用4096次或更多的迭代。执行PBKDF2函数将密码、盐和迭代次数输入到PBKDF2基于密码的密钥派生函数2中使用HMAC-SHA1或HMAC-SHA256作为伪随机函数。输出特定长度的密钥根据加密类型如AES-128、AES-256派生出一个特定长度的密钥16字节或32字节。这个密钥用于加密和解密Kerberos票据如TGT、服务票据。与NT哈希的关键区别动态性Kerberos密钥的生成引入了“盐”这意味着即使域中两个用户密码相同他们的Kerberos AES密钥也不同。计算成本高高迭代次数使得暴力破解Kerberos密钥远比破解NT哈希困难。协议专用这个密钥专用于Kerberos协议流程不用于NTLM认证。理解这三者的关系就理解了Windows认证从脆弱到相对坚固的演进脉络LM哈希已淘汰- NT哈希静态用于NTLM- Kerberos密钥动态派生用于Kerberos。3. 实战环境搭建与DSInternals工具链详解理论清楚了我们就要进入实战环节。工欲善其事必先利其器。我们将搭建一个安全的实验环境并深入理解DSInternals这个“瑞士军刀”。3.1 实验环境规划与安全须知绝对禁止在生产环境操作我们所有的实验都必须在隔离的虚拟实验室中进行。推荐使用VMware Workstation或Hyper-V创建一台Windows Server虚拟机如Windows Server 2022并配置为域控制器再创建一台Windows 10/11虚拟机加入该域。重要提示本文涉及密码哈希的生成和操作这些操作仅用于安全研究、教学和授权测试。在任何情况下都不应对未经授权的系统进行哈希提取或破解尝试。环境准备清单域控制器安装Windows Server提升为域控制器创建测试域如lab.local。成员服务器/客户端安装Windows 10/11加入上述域。管理工具在成员服务器上安装RSAT工具以便使用Active Directory管理工具。PowerShell环境确保PowerShell版本在5.1及以上并允许执行脚本Set-ExecutionPolicy RemoteSigned。3.2 DSInternals模块深度安装与配置DSInternals并非Windows原生组件需要通过PowerShell Gallery安装。安装步骤# 1. 检查并信任PowerShell Gallery首次可能需要 Get-PSRepository # 2. 安装DSInternals模块 Install-Module -Name DSInternals -Force -Scope CurrentUser # 使用 -Scope CurrentUser 可以避免需要管理员权限适合大部分场景。 # 3. 导入模块 Import-Module DSInternals安装常见问题与解决错误无法连接到远程服务器这通常是因为PowerShell Gallery被墙或网络问题。可以尝试指定国内的镜像源或者先下载模块再离线安装。# 方法一使用代理需自行配置 # 方法二离线安装推荐用于隔离环境 # 先在能联网的机器上保存模块 Save-Module -Name DSInternals -Path C:\Temp\Modules # 然后将整个DSInternals文件夹复制到实验机的模块目录下 # 个人模块目录%USERPROFILE%\Documents\WindowsPowerShell\Modules\ # 系统模块目录C:\Program Files\WindowsPowerShell\Modules\模块导入失败检查模块是否确实存在于正确的路径。使用Get-Module -ListAvailable -Name DSInternals查看。DSInternals核心Cmdlet预览安装成功后我们可以通过Get-Command -Module DSInternals查看其丰富的命令。与我们本次主题最相关的包括ConvertTo-NTHash: 计算NT哈希。ConvertTo-LMHash: 计算LM哈希。ConvertTo-KerberosKey: 根据密码和参数生成Kerberos密钥。Get-ADDBAccount/Get-BootKey用于从NTDS.dit文件中提取账户信息和解密密钥高级用法需要域数据库文件。4. 分步实操亲手计算三大哈希/密钥现在让我们进入最核心的环节使用DSInternals提供的Cmdlet从零开始生成这些哈希和密钥。我们将以一个测试用户labuser密码MySecPss123域lab.local为例。4.1 NT哈希的计算与验证计算NT哈希是最直接的一步。操作步骤# 1. 计算指定密码的NT哈希 $ntHash ConvertTo-NTHash -Password MySecPss123 $ntHash # 输出示例每次计算固定 # Hash NT : 2C7E4C5951B39B4D3F0456F7C5D5E3A7这个命令在内部完成了我们之前讲的所有步骤将密码转为Unicode计算MD4输出十六进制字符串。如何验证我们计算的NT哈希是正确的我们不能直接去域控上查看用户的密码哈希。但可以通过一个间接但可靠的方法使用DSInternals从本地SAM数据库计算一个已知密码的哈希并与我们的结果对比。在实验机上创建一个本地用户设置密码为MySecPss123。使用DSInternals提取该本地用户的哈希需要管理员权限# 获取本地用户的哈希需要管理员权限运行PowerShell $bootKey Get-BootKey -Online Get-SamAccount -All -BootKey $bootKey | Where-Object {$_.UserName -eq 你的本地用户名} | Select-Object UserName, NTHash对比提取的NTHash和我们用ConvertTo-NTHash计算的结果。它们应该完全一致。实操心得ConvertTo-NTHash的结果是大小写不敏感的十六进制字符串但在比较时最好统一大小写。这个哈希值就是你在Mimikatz的sekurlsa::logonpasswords或哈希转储工具中看到的NTLM字段。理解这一点就把工具输出和底层原理联系起来了。4.2 LM哈希的计算与历史回顾尽管不推荐使用但了解其计算过程对于理解旧系统遗留风险至关重要。操作步骤# 计算指定密码的LM哈希 $lmHash ConvertTo-LMHash -Password MySecPss123 $lmHash # 输出示例 # Hash LM : 7F8A2B3C4D5E6F7890A1B2C3D4E5F607深入分析输出你可以尝试用一些简单密码来计算LM哈希观察其弱点ConvertTo-LMHash -Password PASSWORD # 全大写 ConvertTo-LMHash -Password password # 全小写 ConvertTo-LMHash -Password Password # 首字母大写你会发现只要字母部分相同无论大小写计算出的LM哈希都是一样的。这就是“大小写不敏感”缺陷的直观体现。安全配置检查在真实的域安全评估中你需要检查是否还有任何账户或策略允许使用LM哈希。# 通过组策略或注册表检查但更直接的是查看提取的哈希是否存在LM部分 # 如果从SAM或NTDS.dit中提取账户信息时LMHash字段是 aad3b435b51404eeaad3b435b51404ee空值的占位符则说明LM哈希未存储或已禁用。这个占位符哈希是16字节的0xAAD3B435B51404EEAAD3B435B51404EE代表“空”或“禁用”。看到这个值比看到一个真实的LM哈希更让人安心。4.3 Kerberos密钥的生成与参数解析这是最复杂但也最体现现代密码学安全设计的一环。DSInternals的ConvertTo-KerberosKey命令功能强大需要我们理解其参数。基础生成# 生成基于AES-256的Kerberos密钥 $kerbKey ConvertTo-KerberosKey -Password MySecPss123 -Salt LAB.LOCALlabuser -Iterations 4096 -Aes256 $kerbKey # 输出示例 # KeyType : AES-256 # Key : 3F5A7B9C1D2E4F6A8B0C1D3E5F7A9B2C4D6E8F0A2B4C6D8E1F3A5B7C9D2E4F6A8 # Iterations : 4096 # Salt : LAB.LOCALlabuser-Salt必须与Kerberos域控制器使用的盐一致。标准格式是域名全大写 用户名中间无符号。这是最容易出错的地方。-Iterations迭代次数。Windows Server 2008以后默认是4096次但可以通过组策略调整。更高的次数更安全但登录时CPU开销也略大。-Aes256指定生成AES-256密钥32字节。还可以使用-Aes128、-DesCbcMd5、-DesCbcCrc等参数来生成旧加密类型的密钥。多加密类型支持一个用户密码可以派生出多种类型的Kerberos密钥以支持不同版本的客户端。# 一次性生成多种类型的Kerberos密钥 $allKeys ConvertTo-KerberosKey -Password MySecPss123 -Salt LAB.LOCALlabuser -Iterations 4096 -All $allKeys | Format-List这会输出一个列表包含AES-256、AES-128、RC4-HMAC即NT哈希用于Kerberos RC4加密类型等多种密钥。在Active Directory中用户的msDS-SupportedEncryptionTypes属性决定了支持哪些类型。验证生成的密钥直接验证Kerberos密钥比较困难因为它用于加密票据。一个间接验证的方法是如果你有权限访问域控制器的NTDS.dit文件并使用DSInternals的Get-ADDBAccount配合正确的BootKey进行解密你可以提取出账户存储的Kerberos密钥并与你计算的结果进行比对。这通常在离线分析取证时进行。5. 综合应用与高级场景分析掌握了单个计算后我们来看几个综合性的、更贴近实际工作场景的应用。5.1 从明文密码到完整凭证的批量生成在自动化测试或研究环境中我们可能需要批量生成测试账户的凭证。# 假设我们有一个CSV文件 users.csv包含三列UserName, Password, Domain # UserName,Password,Domain # alice,AlicePass123,lab.local # bob,BobSecure456,lab.local $userList Import-Csv -Path .\users.csv $results () foreach ($user in $userList) { $ntHash ConvertTo-NTHash -Password $user.Password # LM哈希通常不需要此处仅演示 $lmHash ConvertTo-LMHash -Password $user.Password $salt $($user.Domain.ToUpper())$($user.UserName) $aes256Key ConvertTo-KerberosKey -Password $user.Password -Salt $salt -Iterations 4096 -Aes256 $resultObj [PSCustomObject]{ UserName $user.UserName NTHash $ntHash.Hash NT LMHash $lmHash.Hash LM KerberosAES256Key $aes256Key.Key Salt $salt } $results $resultObj } $results | Export-Csv -Path .\user_hashes.csv -NoTypeInformation这个脚本展示了如何将DSInternals命令嵌入到自动化流程中生成一份包含多种凭证信息的报告。5.2 离线分析与NTDS.dit文件解密初探DSInternals的真正威力在于处理离线Active Directory数据库文件。这在应急响应和取证中极其有用。场景你获得了域控制器的NTDS.dit文件数据库和SYSTEM注册表配置单元文件包含解密所需的BootKey。操作流程概览获取BootKey# 从SYSTEM文件提取BootKey $bootKey Get-BootKey -SystemHiveFilePath C:\Forensic\SYSTEM解密NTDS.dit并提取账户# 连接到NTDS.dit文件并解密账户信息 $accounts Get-ADDBAccount -All -DBPath C:\Forensic\ntds.dit -BootKey $bootKey查看特定账户的哈希和密钥$targetAccount $accounts | Where-Object {$_.SamAccountName -eq administrator} $targetAccount | Select-Object SamAccountName, NTHash, LMHash, KerberosKeys此时你看到的NTHash和KerberosKeys就是域中存储的实际值。你可以用之前学到的ConvertTo-NTHash和ConvertTo-KerberosKey函数输入猜测的密码进行计算并与这些提取出来的值进行比对从而验证密码猜测是否正确。这就是离线密码破解的基本原理。重要警告此操作仅适用于你拥有合法权限的、属于你自己的实验环境或已获得明确授权的取证调查。非法获取和破解NTDS.dit文件是严重的犯罪行为。5.3 理解“哈希传递”与“Kerberoasting”的底层通过亲手计算你现在可以更深刻地理解两种常见攻击哈希传递攻击者获取了某个用户的NT哈希例如2C7E4C5951B39B4D3F0456F7C5D5E3A7。由于NTLM协议认证时直接使用这个哈希值进行挑战-响应而不需要明文密码攻击者就可以直接使用这个哈希值在网络上的其他机器进行认证仿佛他就是那个用户。这就是为什么保护NT哈希和禁用NTLM协议如此重要。Kerberoasting攻击者请求一个用RC4加密的服务票据因为RC4的密钥就是NT哈希。由于票据是用服务账户的哈希加密的攻击者可以将这个加密的票据离线暴力破解尝试还原出服务账户的密码。如果服务账户密码强度弱就很容易被破解。防御措施包括使用强密码、将服务账户设置为“使用仅限Kerberos的认证”不使用RC4以及启用AES加密。6. 常见问题、故障排查与安全加固建议在实际操作和原理理解中你可能会遇到以下问题。6.1 问题排查速查表问题现象可能原因解决方案ConvertTo-NTHash结果与工具提取的不一致1. 密码字符串包含隐藏字符如空格、换行。2. 编码问题计算时用的不是UTF-16LE。1. 检查密码输入是否绝对准确可在纯文本编辑器核对。2. 确保使用DSInternals命令它已处理正确编码。ConvertTo-KerberosKey生成的密钥无法用于验证1.盐值错误这是最常见原因。2. 迭代次数与域控不一致。3. 加密类型选择错误。1. 确认盐值格式为DOMAIN.UserName且域名部分大写。2. 在域控上检查或设置HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters下的IterationCount。3. 检查目标账户支持的加密类型。无法安装或导入DSInternals模块1. 网络问题无法访问PSGallery。2. PowerShell执行策略限制。3. 模块路径冲突。1. 使用-Repository指定其他源或离线安装。2. 以管理员身份运行Set-ExecutionPolicy RemoteSigned。3. 使用Get-Module -ListAvailable -Name DSInternals查看路径删除旧版本。从NTDS.dit提取的哈希全是NULL或占位符1. 使用的BootKey不正确。2. NTDS.dit文件损坏或不完整。3. 该账户的哈希确实为空如KRBTGT账户的NTHash。1. 确保SYSTEM文件与NTDS.dit文件来自同一台服务器、同一时间点。2. 尝试使用其他工具验证文件完整性。3. 对于KRBTGT账户这是正常现象其密钥基于密码派生。6.2 安全加固实操建议基于我们对这些哈希和密钥的理解可以提出直接落地的安全建议强制禁用LM哈希组策略计算机配置 - Windows 设置 - 安全设置 - 本地策略 - 安全选项 - 网络安全: 不要在下次更改密码时存储 LAN Manager 哈希值设置为“已启用”。效果新密码将不再计算和存储LM哈希。对于旧密码需要用户更改一次密码后才会清除。启用Kerberos AES加密弃用RC4组策略计算机配置 - 策略 - 管理模板 - 系统 - Kerberos - 支持的加密类型启用AES 256和AES 128禁用RC4。账户属性对于服务账户在AD中设置其msDS-SupportedEncryptionTypes属性为0x18十进制24即支持AES-128和AES-256。效果大幅增加Kerberoasting攻击的难度因为AES密钥比NT哈希RC4密钥难破解得多。实施强密码策略与定期轮换这是防御所有基于哈希/密钥攻击的基石。强密码能极大增加暴力破解和彩虹表攻击的成本。结合上述禁用LM和启用AES的策略即使哈希或密钥被窃取攻击者也难以在有效时间内破解出明文密码。限制NTLM的使用在域环境中通过组策略审计NTLM使用并逐步将应用迁移至仅支持Kerberos认证最终在可行的情况下禁用NTLM。这能从根源上消除“哈希传递”攻击的利用条件。通过DSInternals进行这些哈希和密钥的生成实验绝不仅仅是学习几个命令。它迫使你深入到Windows认证的“原子”层面去理解每一个字节的由来。当你再看到安全报告中的“检测到Pass-the-Hash攻击”或“Kerberoasting活动”时你脑海中浮现的不再是模糊的概念而是一串串具体的哈希值、密钥和它们背后的生成逻辑。这种从原理到实践的贯通是提升安全技术深度最扎实的路径。

相关新闻