LM-Hash && NTLM-Hash
字数 3406 2025-08-29 08:32:19

Windows 认证机制详解:LM-Hash 与 NTLM-Hash

1. LM-Hash 详解

1.1 LM-Hash 生成原理

LM-Hash (LAN Manager Hash) 是 Windows 早期使用的密码哈希算法,由 IBM 设计,存在多个安全弱点。

生成步骤

  1. 密码处理

    • 密码被限制为最多14个字符
    • 转换为大写形式
    • 转换为16进制字符串,不足14字节用0补全
  2. 分割处理

    • 16进制字符串分成两个7字节部分
    • 每部分转换为56位比特流,不足左边补0
    • 分7bit为一组,每组末尾加0,组成新编码(str_to_key函数处理)
  3. 加密处理

    • 得到的8字节二组分别作为DES密钥
    • 对魔术字符串"KGS!@#$%"进行DES加密
    • 将两组DES加密结果拼接,得到最终LM-Hash

示例:密码"123456"的LM-Hash生成过程

  1. 转换为大写:"123456" → "123456"
  2. 转换为16进制:313233343536
  3. 补全14字节:3132333435360000000000000000
  4. 分割为两部分:
    • 第一部分:31323334353600
    • 第二部分:00000000000000
  5. 分别处理并加密后得到:44EFCE164AB921CAAAD3B435B51404EE

1.2 LM-Hash 的弱点

  1. 密码强制转换为大写,降低安全性
  2. 固定分割为两部分,独立加密
  3. 使用弱DES密钥和固定魔术字符串
  4. 最大密码长度限制为14字符
  5. 第二部分对于短密码总是固定值(AA...)

2. NTLM-Hash 详解

2.1 NTLM-Hash 生成原理

NTLM-Hash 是微软提出的改进算法,解决了LM-Hash的部分安全问题。

生成步骤

  1. 将密码字符串转换为ASCII字符串
  2. ASCII字符串转换为16进制字符串
  3. 16进制字符串转换为Unicode字符串
  4. 对Unicode字符串使用MD4消息摘要算法
  5. 得到16字节的NTLM-Hash值

示例:密码"123456"的NTLM-Hash生成过程

  1. ASCII表示:49 50 51 52 53 54
  2. 16进制表示:31 32 33 34 35 36
  3. Unicode表示:310032003300340035003600
  4. MD4哈希:32ed87bdb5fdc5e9cba88547376818d4

2.2 NTLM-Hash 的优势

  1. 保留密码大小写敏感性
  2. 不使用固定分割和魔术字符串
  3. 使用更强的MD4算法
  4. 支持更长密码(最多256字符)
  5. 生成单一块哈希,而非两部分拼接

3. 挑战/响应认证协议

3.1 LM 挑战/响应流程

  1. Server → Client: 发送8字节挑战
  2. Client:
    • 计算密码的LM-Hash
    • 在LM-Hash后补5个0x00变为21字节
    • 分割为三组7字节
    • 每组7字节转换为DES密钥(8字节)
    • 用三组DES密钥分别加密挑战
    • 拼接三个8字节密文得到24字节响应
  3. Client → Server: 发送24字节响应
  4. Server: 用相同方法计算并验证响应

3.2 NTLM 响应计算

  1. 计算密码的NTLM-Hash
  2. 补全为21字节(加5个0x00)
  3. 分割为三组7字节
  4. 每组转换为DES密钥
  5. 用三组DES密钥分别加密挑战
  6. 拼接三个8字节密文得到24字节NTLM响应

示例:密码"SecREt01",挑战"0x0123456789abcdef"

  1. NTLM-Hash: cd06ca7c7e10c99b1d33b7485a2ed808
  2. 补全21字节: cd06ca7c7e10c99b1d33b7485a2ed8080000000000
  3. 分割三组:
    • cd06ca7c7e10c9
    • 9b1d33b7485a2e
    • d8080000000000
  4. 加密挑战得到:
    • 25a98c1c31e81847
    • 466b29b2df4680f3
    • 9958fb8c213a9cc6
  5. 最终NTLM响应: 25a98c1c31e81847466b29b2df4680f39958fb8c213a9cc6

3.3 NTLMv2 响应计算

  1. 计算NTLM-Hash
  2. 计算NTLMv2-Hash:
    • 用户名转大写与目标(domain/server)拼接
    • 计算拼接字符串的Unicode表示
    • 用NTLM-Hash作为HMAC-MD5的密钥计算哈希
  3. 构建"blob"数据块(包含时间戳等)
  4. 计算响应:
    • 将挑战与blob连接
    • 用NTLMv2-Hash作为HMAC-MD5密钥计算哈希
    • 将此哈希与blob拼接形成NTLMv2响应

示例:用户名"testapp",密码"123456789",domain"DESKTOP-DVIA6R3"

  1. NTLM-Hash: C22B315C040AE6E0EFEE3518D830362B
  2. NTLMv2-Hash:
    • 拼接字符串: "TESTAPPDESKTOP-DVIA6R3"
    • Unicode: 54004500530054004100500050004400450053004B0054004F0050002D004400560049004100360052003300
    • HMAC-MD5结果: a92765662d236c31c620d365c89540d1
  3. 构建blob并计算最终响应

4. NTLM 消息流程

NTLM验证包含三种消息类型:

4.1 类型1 - 协商消息

从客户端发送到服务器,包含:

  • 客户端支持的功能列表
  • 服务器请求的功能列表

4.2 类型2 - 质询消息

从服务器发送到客户端,包含:

  • 服务器支持的功能列表
  • 服务器生成的挑战(8字节随机数)
  • 可选的目标信息

4.3 类型3 - 身份验证消息

从客户端发送到服务器,包含:

  • 客户端域和用户名
  • 对挑战的响应(LM/NTLM/NTLMv2)
  • 客户端工作站名称

5. 实际应用与安全

5.1 Hashcat 破解示例

使用Hashcat破解NTLMv2响应的命令:

hashcat64.exe -m 5600 testapp::DESKTOP-DVIA6R3:4e783a49fe733dce:03b4e9129fbe586e457d55412b39f324:010100... pwd.txt -o found.txt --force

5.2 安全建议

  1. 禁用LM-Hash(在组策略中设置)
  2. 强制使用NTLMv2
  3. 使用长复杂密码
  4. 考虑使用Kerberos替代NTLM
  5. 在网络层面限制NTLM流量

6. 实现代码示例

6.1 Python LM-Hash 计算

import base64
import binascii
from pyDes import *

def DesEncrypt(str, Des_Key):
    k = des(Des_Key, ECB, pad=None)
    EncryptStr = k.encrypt(str)
    return binascii.b2a_hex(EncryptStr)

def Zero_padding(str):
    b = []
    l = len(str)
    num = 0
    for n in range(l):
        if (num < 8) and n % 7 == 0:
            b.append(str[n:n+7] + '0')
            num = num + 1
    return ''.join(b)

if __name__ == "__main__":
    test_str = "123456"
    # 转换为大写和16进制
    test_str = test_str.upper().encode('hex')
    # 补全14字节
    str_len = len(test_str)
    if str_len < 28:
        test_str = test_str.ljust(28, '0')
    # 分割两部分
    t_1 = test_str[0:len(test_str)/2]
    t_2 = test_str[len(test_str)/2:]
    # 转换为比特流并处理
    t_1 = bin(int(t_1, 16)).lstrip('0b').rjust(56, '0')
    t_2 = bin(int(t_2, 16)).lstrip('0b').rjust(56, '0')
    t_1 = Zero_padding(t_1)
    t_2 = Zero_padding(t_2)
    t_1 = hex(int(t_1, 2))[2:].rstrip('L')
    t_2 = hex(int(t_2, 2))[2:].rstrip('L')
    if '0' == t_2:
        t_2 = "0000000000000000"
    t_1 = binascii.a2b_hex(t_1)
    t_2 = binascii.a2b_hex(t_2)
    # DES加密
    LM_1 = DesEncrypt("KGS!@#$%", t_1)
    LM_2 = DesEncrypt("KGS!@#$%", t_2)
    # 拼接结果
    LM = LM_1 + LM_2
    print LM

7. 总结对比

特性 LM-Hash NTLM-Hash NTLMv2
算法 DES(两次) MD4 HMAC-MD5
密码处理 转大写,分割两部分 保留大小写 保留大小写,加入用户名/目标
最大长度 14字符 256字符 256字符
安全性 非常弱 较弱 较强
响应类型 LM响应 NTLM响应 NTLMv2响应
兼容性 最广泛 NT系统以上 NT SP4以上

现代Windows系统应禁用LM-Hash,优先使用NTLMv2或更安全的Kerberos认证协议。

Windows 认证机制详解:LM-Hash 与 NTLM-Hash 1. LM-Hash 详解 1.1 LM-Hash 生成原理 LM-Hash (LAN Manager Hash) 是 Windows 早期使用的密码哈希算法,由 IBM 设计,存在多个安全弱点。 生成步骤 : 密码处理 : 密码被限制为最多14个字符 转换为大写形式 转换为16进制字符串,不足14字节用0补全 分割处理 : 16进制字符串分成两个7字节部分 每部分转换为56位比特流,不足左边补0 分7bit为一组,每组末尾加0,组成新编码(str_ to_ key函数处理) 加密处理 : 得到的8字节二组分别作为DES密钥 对魔术字符串"KGS !@#$%"进行DES加密 将两组DES加密结果拼接,得到最终LM-Hash 示例 :密码"123456"的LM-Hash生成过程 转换为大写:"123456" → "123456" 转换为16进制:313233343536 补全14字节:3132333435360000000000000000 分割为两部分: 第一部分:31323334353600 第二部分:00000000000000 分别处理并加密后得到:44EFCE164AB921CAAAD3B435B51404EE 1.2 LM-Hash 的弱点 密码强制转换为大写,降低安全性 固定分割为两部分,独立加密 使用弱DES密钥和固定魔术字符串 最大密码长度限制为14字符 第二部分对于短密码总是固定值(AA...) 2. NTLM-Hash 详解 2.1 NTLM-Hash 生成原理 NTLM-Hash 是微软提出的改进算法,解决了LM-Hash的部分安全问题。 生成步骤 : 将密码字符串转换为ASCII字符串 ASCII字符串转换为16进制字符串 16进制字符串转换为Unicode字符串 对Unicode字符串使用MD4消息摘要算法 得到16字节的NTLM-Hash值 示例 :密码"123456"的NTLM-Hash生成过程 ASCII表示:49 50 51 52 53 54 16进制表示:31 32 33 34 35 36 Unicode表示:310032003300340035003600 MD4哈希:32ed87bdb5fdc5e9cba88547376818d4 2.2 NTLM-Hash 的优势 保留密码大小写敏感性 不使用固定分割和魔术字符串 使用更强的MD4算法 支持更长密码(最多256字符) 生成单一块哈希,而非两部分拼接 3. 挑战/响应认证协议 3.1 LM 挑战/响应流程 Server → Client: 发送8字节挑战 Client: 计算密码的LM-Hash 在LM-Hash后补5个0x00变为21字节 分割为三组7字节 每组7字节转换为DES密钥(8字节) 用三组DES密钥分别加密挑战 拼接三个8字节密文得到24字节响应 Client → Server: 发送24字节响应 Server: 用相同方法计算并验证响应 3.2 NTLM 响应计算 计算密码的NTLM-Hash 补全为21字节(加5个0x00) 分割为三组7字节 每组转换为DES密钥 用三组DES密钥分别加密挑战 拼接三个8字节密文得到24字节NTLM响应 示例 :密码"SecREt01",挑战"0x0123456789abcdef" NTLM-Hash: cd06ca7c7e10c99b1d33b7485a2ed808 补全21字节: cd06ca7c7e10c99b1d33b7485a2ed8080000000000 分割三组: cd06ca7c7e10c9 9b1d33b7485a2e d8080000000000 加密挑战得到: 25a98c1c31e81847 466b29b2df4680f3 9958fb8c213a9cc6 最终NTLM响应: 25a98c1c31e81847466b29b2df4680f39958fb8c213a9cc6 3.3 NTLMv2 响应计算 计算NTLM-Hash 计算NTLMv2-Hash: 用户名转大写与目标(domain/server)拼接 计算拼接字符串的Unicode表示 用NTLM-Hash作为HMAC-MD5的密钥计算哈希 构建"blob"数据块(包含时间戳等) 计算响应: 将挑战与blob连接 用NTLMv2-Hash作为HMAC-MD5密钥计算哈希 将此哈希与blob拼接形成NTLMv2响应 示例 :用户名"testapp",密码"123456789",domain"DESKTOP-DVIA6R3" NTLM-Hash: C22B315C040AE6E0EFEE3518D830362B NTLMv2-Hash: 拼接字符串: "TESTAPPDESKTOP-DVIA6R3" Unicode: 54004500530054004100500050004400450053004B0054004F0050002D004400560049004100360052003300 HMAC-MD5结果: a92765662d236c31c620d365c89540d1 构建blob并计算最终响应 4. NTLM 消息流程 NTLM验证包含三种消息类型: 4.1 类型1 - 协商消息 从客户端发送到服务器,包含: 客户端支持的功能列表 服务器请求的功能列表 4.2 类型2 - 质询消息 从服务器发送到客户端,包含: 服务器支持的功能列表 服务器生成的挑战(8字节随机数) 可选的目标信息 4.3 类型3 - 身份验证消息 从客户端发送到服务器,包含: 客户端域和用户名 对挑战的响应(LM/NTLM/NTLMv2) 客户端工作站名称 5. 实际应用与安全 5.1 Hashcat 破解示例 使用Hashcat破解NTLMv2响应的命令: 5.2 安全建议 禁用LM-Hash(在组策略中设置) 强制使用NTLMv2 使用长复杂密码 考虑使用Kerberos替代NTLM 在网络层面限制NTLM流量 6. 实现代码示例 6.1 Python LM-Hash 计算 7. 总结对比 | 特性 | LM-Hash | NTLM-Hash | NTLMv2 | |------------|-----------------------------|-----------------------------|-----------------------------| | 算法 | DES(两次) | MD4 | HMAC-MD5 | | 密码处理 | 转大写,分割两部分 | 保留大小写 | 保留大小写,加入用户名/目标 | | 最大长度 | 14字符 | 256字符 | 256字符 | | 安全性 | 非常弱 | 较弱 | 较强 | | 响应类型 | LM响应 | NTLM响应 | NTLMv2响应 | | 兼容性 | 最广泛 | NT系统以上 | NT SP4以上 | 现代Windows系统应禁用LM-Hash,优先使用NTLMv2或更安全的Kerberos认证协议。