Windows认证原理浅析基础入门

 文章目录

0x01 前言简介

0x02 基本介绍

  1.本地登录认证

  2.网络登录认证

0x03 LM/NTLM 版本优缺

0x04 LM/NTLM 生成原理

  1.LM-Hashes 生成实例

  2.NTLM-Hashes 生成实例

0x05 LM/NTLM 挑战和响应机制原理

  1.LAN Manager Challenge/Response

  2.NTLM Challenge/Response

0x06 LM/NTLM C/R 协议分析

  1.NTLMv1 C/R

  2.NTLMv2 C/R

0x07 学习总结

0x08 参考来源


0x01 前言简介

本文借鉴安全界各位大佬所写的Windows认证入门科普(它们的站点我附在来源)对其中的知识点做了一个整理总结,同时复现里面的算法方便以后自己理解以及在其他域渗透/内网渗透方式中提供基础知识,这篇文章很适合小白入门Windows认证协议因为它简单明了;

本文实验模拟在Windows 7 、Windows 10 下进行验证主要内容:

Windows用户认证基础介绍

LM/NTLM Hashes 版本优缺

LM/NTLM Hashes 生成原理

LM/NTLM Hashes 加密流程实践

LM/NTLM 挑战和响应(C/R)机制原理

LM/NTLM C/R 协议分析

学习总结


0x02 基本介绍

描述:Hashes(散列)直接音译为“哈希-Hash”,是把任意长度的输入(又叫做预映射,pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。

简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。

回归到正题之中,有这样一个场景在您忘记您电脑密码的时候,我们常用的就是两种方式;

1.采用PE系统进行跳过原始系统用户密码进行登录;

2.进行PE系统中读取系统目录中SAM文件然后进行重新设置用户密码;

那SAM是什么呢?

SAM(Security Account Manage)是Windows系统中存放系统用户及密码的一种文件并采用Syskey(系统密钥)加密保护

而LM/NTLM 哈希存储在安全帐户管理器(SAM)数据库和域控制器的NTDS.dit数据库中

简单流程:用户登录的时候采用用户输入的密码进行NTLM Hashes加密然后与系统中SAM文件中存储的NTLM Hashes进行比对;

在这里不得不说一哈我们常用的NTLM Hashes的加密方式:

NTLM Hashes它采用的MD4加密方式,目前应用最广泛的Hashes算法 MD5 和 SHA1 它们也都是参考MD4加密原理为基础设计的,下面简单说一下:

1)MD4: (RFC 1320)是 MIT (麻省理工学院)的 Ronald L. Rivest 在 1990 年设计的,它是一种用来测试信息完整性的密码散列函数的实行。其MD(Message Digest)摘要长度为128位,一般128位长的MD4散列被表示为32位的十六进制数字。它适用在32位字长的处理器上用高速软件实现,它是基于 32 位操作数的位操作来实现的。

2)MD5: (RFC 1321)是 Rivest于1991年对MD4的改进版本。它仍以512位分组来输入,其输出是4个32位字的级联,与 MD4 相同。MD5比MD4来得复杂,并且速度较之要慢一点,但更安全,在抗分析和抗差分方面表现更好

3)SHA1: 由NIST NSA设计为同DSA一起使用的,它对长度小于264的输入,产生长度为160bit的散列值,因此抗穷举(brute-force)性更好。SHA-1 设计时基于和MD4相同原理,并且模仿了该算法。

回到正题由于当前PC常使用的系统版本基本都是Windows 7 / Windows 10,所以下认证情况都是基于该系统版本来说明的(作一个简单的了解):

1.本地登录认证

描述:当我们在本地登录认证时输入密码凭据登陆系统会首先将输入的凭据转换加密成NTLM Hashes(NT LAN Manager) 进行存储,这是由于Windows本身不存储用户的明文密码它将用户的明文密码经过加密算法后存储在SAM数据库(%SystemRoot%\System32\config\sam)中,此时操作系统会自动地读取Windows系统中的SAM文件中的对应用户的NTLM hashes值进行与我们凭据生成的NTLM Hashes进行比对认证,认证完成则登录成功否则提示账号或者密码错误;

Windows本地登录验证流程:

1.在我们注销或开机后将会弹出输入账号密码的界面用于接受用户输入由本地winlogon.exe进程进行管理;

本地进程winlogon.exe将账号密码给lsass.exe进程进行处理并将密码缓存在进程中;

本地进程lsass.exe将我们输入密码凭据转换为NTML Hashes读取SAM数据库与用户名进行比较;

2.若比较结果相同则将User SID与Group SID发给winlogon.exe,并准备登陆界面;若比较结果不同则登陆失败提示账号或者密码错误。

简单流程:

#Windows Logon Process winlogon.exe是 Windows NT 用户登陆程序用于管理用户登录和退出。#Lsass.exe 是 用于微软Windows系统的安全机制它用于本地/远程安全和登陆策略,它会与我们SAM进行相互作用将本地或者远程身份认证的用户信息都会保存在其内存地址中。winlogon.exe ->接收用户输入 ->lsass.exe ->if(认证){登录成功}else{登录失败}

2.网络登录认证

局域网工作组:缺少信托机构(银行:两者之间进行交易所必须信任的中间人)

工作组的环境是一个逻辑上的网络环境(工作区) ,隶属于工作组的机器之间无法互相建立一个完美的信任机制,只能点对点,是较为落后的认证方式没有信托机构。

假设A主机与B主机在一个工作主组环境,A想要访问B主机上的资源,需要将一个存在于B主机上的账户凭证发送至B主机,经过认证才能访问B主机上的资源。传输数据由协议来规范数据如何传递,最常见的服务:SMB服务端口445 / RPC服务(Remote Procedure Call,远程过程调用) 135端口。



0x03 LM/NTLM 版本优缺

Windows用户认证LM/NTLM Hashes发展流程:

1) LM Hashes

IBM设计的LM Hash算法在Windows XP 或 Windows Server 2003 等系统发行版本以及以下采用的加密方式(基本已经被淘汰了);

LM Hashes版本系列说明:

LM Hashes

LM :完整名称(LAN Manager Challenge/Response) 挑战和验证机制主要用于网络身份认证;

2) NTLM Hashes

NTLM简称NT LAN Manager,由于LM Hashes脆弱性和Windows认证需要协议来规范,以及微软在保持向后兼容性的同时提出了WindowsNT挑战/响应验证机此时NTLM Hash便应运而生。

在Windows Vista 与 Windows Server 2008 以上版本默认采用的加密方式, NTLM Hashes算法的前身是LM Hashes

NTLM Hashes版本系列说明:

NTLM Hashes (也称为 NT Hashes) 主要用于本地认证;

NTLMv1 Hashes (也称为Net-NTLMv1 Hashes) 运用了WindowsNT挑战与响应验证机制结合,主要用于网络身份认证;

NTLMv2 Hashes (也称为Net-NTLMv2 Hashes) 主要用于网络身份认证并且使用广泛;

NTLM session 用于在没有NTLMv2身份验证的情况下协商NTLM2会话安全性时

说明:为了后面方便引用C/R验证机制的时候统一采用NTLMv1 Hashes 、NTLMv2 Hashes 进行说明;

LM / NTLM Hashes 两者之间优缺点比较:

1.LM-Hashes

缺点:安全问题密码不区分大小写(因为最开始会把密码统一转换为大写) 、密码最长为14位(2*7B==112bit)、可通过加密后的值反推加密前的密码位数、DES加密强度较弱等。

2.NTLM-Hashes / Net-NTLM

缺点:可以用来获取不区分大小写的密码,以及用于查找NTLM响应使用的区分大小写密码的试错法,特别是NTLMv1版本容易被彩虹表进行碰撞检测得出密码的NTLM Hashes。

LM / NTLM / Net-NTLM Hashes 格式:

#(1) LM哈希(16B = 32字符 ) : NTLM哈希(16B = 32位)

aad3b435b51404eeaad3b435b51404ee : e19ccf75ee54e06b06a5907af13cef42

#(2) LM Pesponse(24B = 48位)

ca1200723c41d577ab18c764c6def34fa61bfa0671ea5fc8

#(3) NetNTLMv1 / NetNTLMv1+ESS

NTLM Server Challenge: f9c7fc816b991824

Lan Manager Response: c67ee888f6b41a4400000000000000000000000000000000

NTLM Response: 293b99da834c86c6e37c37a20920b41581be32740a5e062e

#(4) NET-NTLMv2(又名NTLMv2)哈希的示例

NTLM Server Challenge: f12d21c3e60843cc

Lan Manager Response: 000000000000000000000000000000000000000000000000

LMv2 Client Challenge: 0000000000000000

NTLMv2 Hashes: 6061d067efff612ae4f1c704f1a44f08 #(16 = 32位)

NTProofStr: 32a48adf53baf6ef888482d94e222001

NTLMv2 Response: 32a48adf53baf6ef888482d94e2220010101000000000000...#(128bit)



0x04 LM/NTLM 生成原理

1.LM-Hashes 生成实例

注意:如果需要复现需要将系统策略进行更改支持LM存储:控制面板>所有控制面板项>管理工具>本地安全策略(gpedit.msc)>本地策略>安全选项>网络安全:在下一次更改密码时不存储LAN管理器哈希值(LM) 设置禁用;

LM-Hashes生成原理三步骤详解:

Step0.由于这种密码生成规则要求用户的密码最多仅能为14个字符即14*8B=11bit长度

Step1.明文口令转换为其大写形式(Upper case)在有字母的情况下进行否者直接进行第二步

Step2.将转换后的口令进行转成Hex编码

Step3.生存的Hex编码如果不足112bit/8bit=14个字符要求用0补全

Step4.将补全后的14个字符112bit的数据分成2组每组7字节/B(56 bit)

Step5.将每组的十六进制转换成为二进制并且在转换后长度不足56bit使用0在左边补齐长度,再将二进制数据分7bit为一组末尾加0组成新的编码此时成为每组8B(64bit);

Step6.将上步得到的两组8B字节编码分别作为单向DES加密Key魔术字符串KGS!@#$%转换成为Hex(4B47532140232425)数据然后得到两组密文;

Step7.将两组DES加密后的数据进行拼接得到LM-Hash值;

实例验证LM-Hashes生成:

服务器密码:123456

LM-HASH值为:44EFCE164AB921CAAAD3B435B51404EE

1.由于服务器密码是纯数字转换任然为本身进行步骤跳过;

2.转换成为16进制的ASCII码不足14B采用0补齐并将补全结果分为两个7 Bytes部分即:31323334353600 00000000000000;

3.分别将两组7Bytes数据转换成为二进制进行补0操作后再分7bit一组在末尾+0,形成每组8B长度再将其转换成为16进制:

#二进制

第一组:31323334353600 == 110001001100100011001100110100001101010011011000000000

第二组:00000000000000 == 54 x 0

#左边补0(2bit)

第一组:00110001001100100011001100110100001101010011011000000000

第二组:56 x 0

#再分7bit为一组末尾加0 (形成每组8B)

#第一组 / #第二组(全为0) 0000000 0 x 7 

0011000 0

1001100 0

1000110 0

0110011 0

0100001 0

1010100 0

1101100 0

0000000 0

#对此时的密码字符串对应的8字节16进制编码(str_to_key()函数处理)

30988C6642A8D800

0000000000000000

4.将以上步骤得到的两组16进制字符串,分别作为DES加密key为魔术字符串KGS!@#$%(Hex:4b47532140232425)进行加密

44EFCE164AB921CA

AAD3B435B51404EE

5.拼接得到的密码即形成LM-Hashes:44EFCE164AB921CAAAD3B435B51404EE

Python3实现LM-HASH脚本(需要安装pyDes模块):

运行:LM-Hashes.py

#!/usr/bin/env python

# coding=utf-8

# Build Version: Python3

import base64

import binascii

import sys

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__":

    try:

      #将输入值进行Bytes转换

      print("Password : "+sys.argv[1])

      test_str = sys.argv[1].encode('utf-8')

    except Exception as e:

      print("Usage:Python LM-Hashes.py Password")

      print("[*] Error:"+str(e))

      sys.exit()

    # 用户的密码转换为大写,并转换为16进制ASCCI;

    test_str = test_str.upper()

    test_str = binascii.b2a_hex(test_str).decode();

    print("Hex: "+test_str)

    str_len = len(test_str)

    # 密码不足14字节将会用0来补全

    if str_len < 28:

        test_str = test_str.ljust(28, '0')

    # 固定长度的密码被分成两个7byte部分

    t_1 = test_str[0:14]

    t_2 = test_str[14:]

    # print(t_1 + " " + t_2)

    # 每部分转换成比特流,并且长度位56bit,长度不足使用0在左边补齐长度

    t_1 = bin(int(t_1, 16)).lstrip('0b').rjust(56, '0')

    t_2 = bin(int(t_2, 16)).lstrip('0b').rjust(56, '0')

    # 再分7bit为一组末尾加0,组成新的编码

    t_1 = Zero_padding(t_1)

    t_2 = Zero_padding(t_2)

    #print(t_1)

    t_1 = hex(int(t_1, 2))

    t_2 = hex(int(t_2, 2))

    t_1 = t_1[2:].rstrip('L')

    t_2 = t_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)

    # 上步骤得到的8byte二组,分别作为DES key为"KGS!@#$%"进行加密。

    LM_1 = DesEncrypt("KGS!@#$%", t_1)

    LM_2 = DesEncrypt("KGS!@#$%", t_2)

    # 将二组DES加密后的编码拼接,得到最终LM HASH值。

    LM = LM_1 + LM_2

    print("LM-Hashse Lower: "+LM.decode()+ "\nLM-Hashes Upper: "+LM.decode().upper())

执行结果:

[root@WeiyiGeek F:\]$ Python LM-Hashes.py 123456Password:123456Hex: 31323334353631323334353600 0000000000000000110000100110001000110001100110010000101010100011011000000000000x30988c6642a8d800 0x0LM-Hashse Lower: 44efce164ab921caaad3b435b51404eeLM-Hashes Upper: 44EFCE164AB921CAAAD3B435B51404EE

2.NTLM-Hashes 生成实例

NTLM-Hashes 生成原理步骤详解:

Step1:明文口令转换成16进制ASCII编码(Hex)

Step2:Unicode编码(ASCII转Unicode) 原本是在每个Hex编码前加上0x00nn,但是由于Window操作使用的是小端存储,所以得注意这里采用的是UTF-16小端序编码(LE,Little Endian|)即在每个字节之后添加00;

Step3:对Unicode字符串使用MD4消息摘要算法得到16字节的值即NTML-Hash

NT_Hash(password)=MD4(UTF-16-LE(password))NT_Hash("pass1")="8D7A851DDE3E7BED903A41D686CD33BE"

补充知识点:

大端序(Big-Endian,大尾序):高位字节放在内存的低地址,低位字节放在内存的高地址, 低地址 0x12 0x34 0x56 0x78 高地址, 可以看见是符合人们常规得理解顺序。

小端序(Little-Endian,小尾序):低位字节放在内存的低地址,高位字节放在内存的高地址0x78 0x56 0x34 0x12,笑话:计算机说我也要由自己得理解顺序。

实例验证NTLM-Hases生成:

# 1.查看lsass.exe进程信息;$tasklist|findstr"lsass.exe"lsass.exe                      676 Services                  0    35,172 K# 2.该程序在内存中的信息$procdump64.exe -ma -t 676ProcDump v9.0 - Sysinternals process dump utilityProcess:              lsass.exe(676)Process image:        C:\Windows\system32\lsass.exeCPU threshold:        n/aPerformance counter:  n/aCommit threshold:      n/aThreshold seconds:    n/aHung window check:    DisabledLog debug strings:    DisabledException monitor:    DisabledException filter:[Includes]*[Excludes]Terminate monitor:    EnabledCloning type:          DisabledConcurrent limit:      n/aAvoid outage:          n/aNumber of dumps:      1Dump folder:          C:\Users\Administrator\Downloads\Procdump\Dump filename/mask:    PROCESSNAME_YYMMDD_HHMMSSQueue to WER:          DisabledKill after dump:      Disabled#3.下载该应用程序在内存之中数据导出到本地以供mimikatz使用$procdump64.exe -accepteula -ma lsass.exe lsass.dmp[22:45:02]Dump 1 initiated: lsass.dmp[22:45:05]Dump 1 writing: Estimated dumpfilesize is 35 MB.[22:45:05]Dump 1 complete: 36 MB writtenin3.5 seconds[22:45:06]Dump count reached.#4.获取lsass.dmp文件内容并用mimikatz查看账户密码的NTML HASH值$mimikatz.exe"sekurlsa::minidump lsass.dmp""sekurlsa::logonPasswords full"exit>pass.txt$typepass.txtmimikatz(commandline)# sekurlsa::minidump lsass.dmpSwitch to MINIDUMP:'lsass.dmp'mimikatz(commandline)# sekurlsa::logonPasswords fullOpening:'lsass.dmp'fileforminidump...Logon Time:2020/3/8 11:30:23User Name:TestSID              :S-1-5-21-1802160877-2963370050-2309095339-500msv:[00010000]CredentialKeys* NTLM:26b5936a9a6b7cd2d589abd4c6c126de* SHA1:fa6fe7fab3f9920f1e97ebd148767776e07e55b6

手动实现密码加密:

根据NTML HASH的生成原理推算也同样得到7b86d7692a8b1de47817434f08671229;

第一步:将WeiyiGeek进行十六进制的转换后输出结果如下;

WeiyiGeek=57 65 69 79 69 47 65 65 6b

第二步:将ASCII转码为Unicode(小端序)得到结果如下;

#注意:如果是使用UltraEdit进行转换成Unicode会带有FF FE,开头的FF FE用于标识此文本文件为Unicode编码String to Hex Unicode :770065006900790069006700650065006b00

第三步:将570065006900790069004700650065006b00(注意需要进行设置为Hex String)进行MD4加密后得到结果如下;

第四步:与上面内存中的NTLM HASH进行比较验证完成,自己拿取了大佬们写的JS库写的一个小Demo演示(在线加密的有很多,自己只是学习了解其中的算法思路才写的):

<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><title>MD4 加密</title><scriptsrc="https://nf404.github.io/crypto-api/crypto-api.min.js"></script><scriptsrc="./md4.js"></script></head><body><p>请输入需要加密成NTLM的明文密码:</p><labelfor="src">明文密码:</label><inputtype="text"value=""id="src">&nbsp;&nbsp;<inputtype="button"value="转换"onclick="ntlm_encoder()"><hr><p>转换结果:</p><pid="result"></p><script>functionntlm_encoder(){varstr=document.getElementById("src").value;varhex="";for(i=0;i<str.length;i++){hex+=str.charCodeAt(i).toString(16)+"00";}resultASCII=CryptoApi.hash('md4',hex)resultUnicode=hex_md4(str);//采用16位 bits per input character 编码document.getElementById("result").innerHTML="<mark> String to Hex Unicode :"+hex+"<br> MD4 Text String : "+resultASCII+"<br> MD4 Hex String [NTLM]: "+resultUnicode+"</mark>";}</script></body></html>

0x05 LM/NTLM 挑战和响应机制原理

问什么是挑战/响应模式(鉴权协议)?

答:鉴权协议如下的鉴权协议又被称作挑战(认证模式),使用明文口令模式时,网络上传输的就是明文口令本身很容易被Sniffer捕获。而挑战/响应模式在传输信道也是是可被侦听Sniffer,但不可被篡改的情况下并且对密码进行分段加密,这是一种简单而安全的方法。

1.LAN Manager Challenge/Response

描述:LM验证机制方案比NTLM响应时间更早,安全性更低。

以SMB通讯A(Client)/B(Server)访问请求为例:

Step1.协商:通信连接请求TCP三次握手,采用SMB协议获取信息请求;

Step2.质询:质询的完整过程

(1) A向B发送需要登录的用户验证是否存在,存在则继续否则失败

(2) B找到该用户的缓存的LM-Hash密码并且随机生成8B(16位)的挑战数,随后发送给A;

(3) A收到该16位挑战数(LM Challenge)并且将输入的密码转换成为LM-Hashes(Client A缓存输入密码的哈希值,原始密码会被丢弃,“原始密码在任何情况下都不能被缓存”,这是一条基本的安全准则)

(4) A将LM-Hashes(16B = 32字符) 加上5B(0X00)凑成21B(42个字符)然后划分成三组每组7字节,之后再对每组7字节做为参数传递给str_to_key()函数,最终得到三组DESKEY得到每组8字节的Hex数据;

(5) A分别采用上面所得24B数据(3组*8B)依次对Challenge(8B)进行标准DES加密并将其进行拼接最终得到一个24字节的响应数据(这就是我们所说的LM Response),随后发送给B;

(6) B也是根据4-6步骤生成本地的LM Pesponse

Step3.响应验证:

(7) B收到A发送的Response后与本地生成的本地 LM Response进行比对,是则验证成功否则失败;

LM Challenge / Response 身份验证过程:

#1.假设我们登录的账户是admin密码是weiyigeek(此时B机器上存在admin账户正确密码的LM-Hashes值)[root@WeiyiGeek F:\]$ python LM-Hashes.py weiyigeekPassword:weiyigeekLM-Hashse Lower: 623e80a2f48abcf1b3a121027af9fe24LM-Hashes Upper: 623E80A2F48ABCF1B3A121027AF9FE24LM-Hashes("weiyigeek")=623e80a2f48abcf1b3a121027af9fe24;#2.B确认了Admin账户存在后之后生成8B的挑战并且向A进行发送;LM Challenge=0001020304050607#3.A收到B发送的Challenge开始进行一些列生成LM Response流程## 3.1 A输入的密码生成的LM-Hashse(16)+5B(0x00) = 21B623e80a2f48abcf1b3a121027af9fe24 0000000000## 3.2 将上步生成的21B数据平均分成三组(7B)623e80a2f48abc f1b3a121027af9 fe240000000000## 3.3 每组7字节做为参数传递给str_to_key()函数[就是将前面三组分别转成二进制然后7bit一组在后+0,最终形成8B数据再转回16进制]最终得到三组DESKEYDESKEY 1:621ea0142ea42a78DESKEY 2:f0d8e8241012eaf2DESKEY 3:fe12000000000000## 3.4 然后采用上面三组Key对进行Challenga加密后得到3组Hex字符拼接即可DESKEY 1:621ea0142ea42a78 ->对Challenge 0001020304050607 进行标准DES加密 ->5df3066f953edbd7DESKEY 2:f0d8e8241012eaf2 ->对Challenge 0001020304050607 进行标准DES加密 ->c1573fddf1430e6fDESKEY 3:fe12000000000000 ->对Challenge 0001020304050607 进行标准DES加密 ->2d124c5b2022bb6b## 3.5得到最终的Response同时发送给B,B服务端采用相同的方式生成的Local LM Response进行比对,如果匹配则身份验证通过否则失败Response Result:5df3066f953edbd7c1573fddf1430e6f2d124c5b2022bb6b

2.NTLM Challenge/Response

描述:NTLMv1 / NTLMv2 Hashes 是一种Challenge/Response 验证机制,由三种消息组成:通常称为类型1(协商),类型2(质询)和类型3(身份验证)。

NTLM版本1(“NTLMv1”)该方案解决了LM响应中的一些缺陷,但是同时自身由于NTLM响应几乎总是与LM响应一起发送所以比较薄弱(逆向推倒),在控制Challenge后可以在短时间内通过彩虹表还原出用户的ntlm hash;

NTLM版本2(“NTLMv2”)被用来解决NTLM中存在的安全问题。当启用NTLMv2时,NTLM响应被替换为NTLMv2响应,并且LM响应被替换为LMv2响应。

它们基本工作流程

Step1.协商:客户端向服务器发送类型1消息,确认协议版本是V1还是V2?

Step2.质询:质询的完整过程服务器进行响应(重点:进行响应)

(1) 服务器判断用户是否存在:

客户端向服务器端发送用户主机信息(必须包含用户名),服务器用客户端请求的用户名来判断服务器内是否有这个用户;

若没有这个用户那么认证过程就是失败的;若有则继续:

(2) 服务器生成16位Challenge:

服务器接受到请求之后生成一个16位随机数Challenge,服务器使用登录用户名对应的NTLM HASH;

(3) 服务器生成Net NTLM HASH便于比对:

服务器用本机SAM文件数据库内NTLM HASH 加密 16位随机数 Challenge生成本地Response 即“Net-NTML HASH”;

(4) 服务器返回16位Challenge:

服务器将之前生成的16位随机数Challenge再发送给客户端;

(5) 客户端生成传送给服务端的Response:

客户端接受到Challenge之后,使用将要登陆到账户对应的NTLM HASH加密Challenge生成Response,然后将Response发送到服务端 ;

Step3.类型验证:(最关键的部分因为它们向服务器证明客户端用户知道帐户密码)

(6) 服务端比对Response是否等于Net NTLM HASH:

比对服务器端收到客户端的Response后,比对NET NTLM HASH与Response是否相等,相等则通过。

1)NTLMv1 响应计算

Step1.首先本地生成输入密码的对应NTLM Hashes值;

Step2.其次与LM C/R响应的计算方式是相同的(只是生产LM / NTLM Hashes不同而已),也是将16字节(32个字符)的NTLM散列填充为21个字节,

Step3.分别将21Bytes分成3组7bit再将每组7字节做为参数传递给str_to_key()函数最终得到三组DESKEY(8bytes)

Step4.将从服务器端接收的Challenge(质询消息的挑战)分别采用上面三组DESKEY进行加密得到三组DES加密的结果;

Step5.将上面生成三组Des加密的结果进行拼接形成形成一个24字节的值这就是响应(Response)

说明:由于生成Response与LM C/R 一致所以这里不演示了,具体参考LM Challenge / Response 身份验证过程;

2)NTLMv2 响应计算

Step1.计算获取NTLM密码的Hashes参考前面实例验证NTLM-Hases生成;

Step2.计算NTLMv2哈希值流程;

1.先将用户名转换为大写然后和目标拼接在一起(目标为 domain or server name 的值,且区分大小写)组成字符串;

2.然后计算这个字符串的Unicode十六进制字符串,使用Step1中的16字节NTLM散列作为密钥;

3.将HMAC-MD5消息认证码算法应用于Unicode十六进制字符串,得到16字节的值即为NTLMv2-HASH

4.使用16字节NTLMv2散列作为密钥,将HMAC-MD5消息认证码算法应用于质询消息的挑战(Challenge)与blob连接字符串,此时会产生一个16字节的HASH输出值,然后该值与blob连接以形成NTLMv2响应(Response)。

构建被称为“blob”的数据块其简述如下:

在抓包中的关键字段是Blob目

实际流程验证:

目标DOMAIN:HACKONE用户名称:WeiyiGeek密码NTLM:fc348d696833ec7ea33e121e8c41b69c(我直接采用上面的NTLM工具生成Hashes)Challenge:a47b80ee3b16910eBlob:01010000000000009b09b1969ef7d50166ce6f7781f3d3670000000002001e004400450053004b0054004f0050002d004f004600510031004d0055004e0001001e004400450053004b0054004f0050002d004f004600510031004d0055004e0004001e004400450053004b0054004f0050002d004f004600510031004d0055004e0003001e004400450053004b0054004f0050002d004f004600510031004d0055004e00070008009b09b1969ef7d5010600040002000000080030003000000000000000000000000030000013b5d33a3c720a8cf7789ac2bfb7d9ef82d7d476d546a70be02087c0e11c979d0a001000000000000000000000000000000000000900200063006900660073002f003100390032002e003100360038002e0031002e003500000000000000000000000000

1.计算NTLMv2 Hashes值将用户名转换成为大写并且与domain(区分大小写)进行拼接,然后计算这个字符串的Unicode十六进制字符串(同样是小端序);

WEIYIGEEKHACKONE

570045004900590049004700450045004b004800410043004b004f004e004500

2.将密码NTLM Hashes作为密匙将HMAC-MD5消息认证码算法应用于Unicode十六进制字符串(运用于User+Domain)得到16字节的NTLMv2

#注意这里都必须将Unicode转换Hex String获取的值才可以否则这将是个坑(怎么都复现不了)6061d067efff612ae4f1c704f1a44f08

3.连接质询消息的挑战Challenge与blob得到字符串

a47b80ee3b16910e01010000000000009b09b1969ef7d50166ce6f7781f3d3670000000002001e004400450053004b0054004f0050002d004f004600510031004d0055004e0001001e004400450053004b0054004f0050002d004f004600510031004d0055004e0004001e004400450053004b0054004f0050002d004f004600510031004d0055004e0003001e004400450053004b0054004f0050002d004f004600510031004d0055004e00070008009b09b1969ef7d5010600040002000000080030003000000000000000000000000030000013b5d33a3c720a8cf7789ac2bfb7d9ef82d7d476d546a70be02087c0e11c979d0a001000000000000000000000000000000000000900200063006900660073002f003100390032002e003100360038002e0031002e003500000000000000000000000000

3.将上面的NTLMv2散列作为密匙,将HMAC-MD5消息认证码算法应用于此字符串(Blob值与Challenge)消息产生一个16字节的HASH输出值

379a24c5f7fb068a140397f6ca2fd3d5

4.将上步生成的Hash值与blob连接进行拼接形成NTLMv2响应:

379a24c5f7fb068a140397f6ca2fd3d501010000000000009b09b1969ef7d50166ce6f7781f3d3670000000002001e004400450053004b0054004f0050002d004f004600510031004d0055004e0001001e004400450053004b0054004f0050002d004f004600510031004d0055004e0004001e004400450053004b0054004f0050002d004f004600510031004d0055004e0003001e004400450053004b0054004f0050002d004f004600510031004d0055004e00070008009b09b1969ef7d5010600040002000000080030003000000000000000000000000030000013b5d33a3c720a8cf7789ac2bfb7d9ef82d7d476d546a70be02087c0e11c979d0a001000000000000000000000000000000000000900200063006900660073002f003100390032002e003100360038002e0031002e003500000000000000000000000000

我们可以与下面NTLMv2协议抓包的Response进行对比:

附录:小工具Console直接执行即可unicode转换:

varscript=document.createElement('script');script.src="https://nf404.github.io/crypto-api/crypto-api.js";//支持HMAC-MD5但是仅仅传入的是字符串(而非Bytes);document.getElementsByTagName('head')[0].appendChild(script);varhostname="HACKONE";varusername="WeiyiGeek";varntlmhashes="fc348d696833ec7ea33e121e8c41b69c";varstr=username.toUpperCase()+hostname;functionstringtoHex(str){varuhex='';for(i=0;i<str.length;i++){uhex+=str.charCodeAt(i).toString(16)+"00";}returnuhex;}console.log(stringtoHex(str));

0x06 LM/NTLM C/R 协议分析

1.NTLMv1 C/R

描述:自Windows Vista/Server2008开始,系统默认禁用Net-NTLMv1如果使用Net-NTLMv2仅修改客户端即可服务器不用修改;

修改注册表开启Net-NTLMv1:

reg add HKLM\SYSTEM\CurrentControlSet\Control\Lsa\ /v lmcompatibilitylevel /t REG_DWORD /d 0 /f

以下采用协议抓的包进行简单的分析,同样采用smb关键字进行过滤smb and ip.addr==192.168.199.210,做个大概的说明其实与NTLMv2流程差别不大,仅仅是加密算法以及C/R位数不同(所以主要的还是看NTLMv2为主);

1) 协商消息示例

NTLM Message Type: NTLMSSP_NEGOTIATE (0x00000001)

2) 质询消息示例

NTLM Message Type: NTLMSSP_CHALLENGE (0x00000002)

NTLM Server Challenge: f9c7fc816b991824

备注:在许多的文章中都会说到NTLMv1生成的是8位的Challenge而NTLMv2生成的是16位的Challenge但是根据实际抓包的情况来看都是8Bytes(16位)的挑战;

3) 身份验证消息示例

NTLM Message Type: NTLMSSP_AUTH (0x00000003)

Lan Manager Response: c67ee888f6b41a4400000000000000000000000000000000#如果采用了NTLMv2版本LM Response全为0NTLM Response: 293b99da834c86c6e37c37a20920b41581be32740a5e062e

备注:这里是区别采用是NTLMv1与NTLMv2版本进行认证的,值得注意一下;

2.NTLMv2 C/R

描述:NTLM响应由较新的客户端发送且NTLMv2为当前使用最为广泛的协议版本;

考虑到网络认证协议有多个版本以及现有的环境下面此处以NTLMv2为例进行实际分析

环境说明:

192.168.1.6 A客户端

192.168.1.5 B服务器

1) 协商消息示例

描述:协商消息从客户端发送到服务器以启动NTLM身份验证,其主要目的是通过FLAG指明支持的选项来建立认证的“基本规则”。(此处参考:来源3)

名称解释:

NTLMSSP: Microsoft NTLM Security Support Provider;

Wrieshark抓取协商消息数据包过滤条件(smb2 and ip.addr==192.168.1.5),查找关键字段NTLM Message Type: NTLMSSP_NEGOTIATE (0x00000001)

协商消息示例(十六进制):

4e544c4d53535000 -- NTLMSSP签名(不会变化)01000000 - NTLM消息类型1(谈判)mechToken: 4e544c4d5353500001000000978208e2000000000000000000000000000000000601b11d0000000f

示例说明:

#茜さす大佬的Hex我确实对应不上不知道是系统版本问题还是抓包工具不同的原因(求解-有知道的大佬可以在下面留个言)4e544c4d53535000010000000732000006000600330000000b000b0028000000050093080000000f574f524b53544154494f4e444f4d41494e

2) 质询消息示例

描述:质询消息由服务器发送到客户端以响应客户端的协商消息;它用于完成与客户的选择的谈判,并且向客户提供挑战,它可以选择包含有关认证目标的信息。

关键字段:NTLM Message Type: NTLMSSP_CHALLENGE (0x00000002)

质询消息示例(主要参数):

responseToken:0x4e544c4d535350000 -- NTLMSSP签名(不会变化)0x02000000 -- NTLM消息类型2(挑战)0x15828ae2 -- 谈判标志0x0a47b80ee3b16910e -- 服务器发的挑战#Security Bloba182010b30820107a0030a0101a10c060a2b06010401823702020aa281f10481ee4e544c4d53535000020000001e001e003800000015828ae2a47b80ee3b16910e000000000000000098009800560000000a00ba470000000f4400450053004b0054004f0050002d004f004600510031004d0055004e0002001e004400450053004b0054004f0050002d004f004600510031004d0055004e0001001e004400450053004b0054004f0050002d004f004600510031004d0055004e0004001e004400450053004b0054004f0050002d004f004600510031004d0055004e0003001e004400450053004b0054004f0050002d004f004600510031004d0055004e00070008009b09b1969ef7d50100000000

3) 身份验证消息示例

该消息包含客户端对上一步挑战的响应,这表明客户知道账户密码而不直接发送密码;并且还指示身份验证目标(域或服务器名称)和身份验证帐户的用户名以及客户端工作站名称。

关键字段:NTLM Message Type: NTLMSSP_AUTH (0x00000003),此处根据NTLMv2 Response字段能判断出采用v2协议:

身份验证消息结构示例(主要参数):

responseToken:4e544c4d53535000 -- NTLMSSP签名(不会变化)03000000 -- NTLM消息类型3(认证)000000000000000000000000000000000000000000000000 -- Lan Manager Response(对于老式系统认证使用)0000000000000000 -- NTLMv2 Client Challenge:#NTLM Response / NTLMv2 Response379a24c5f7fb068a140397f6ca2fd3d501010000000000009b09b1969ef7d50166ce6f7781f3d3670000000002001e004400450053004b0054004f0050002d004f004600510031004d0055004e0001001e004400450053004b0054004f0050002d004f004600510031004d0055004e0004001e004400450053004b0054004f0050002d004f004600510031004d0055004e0003001e004400450053004b0054004f0050002d004f004600510031004d0055004e00070008009b09b1969ef7d5010600040002000000080030003000000000000000000000000030000013b5d33a3c720a8cf7789ac2bfb7d9ef82d7d476d546a70be02087c0e11c979d0a001000000000000000000000000000000000000900200063006900660073002f003100390032002e003100360038002e0031002e00350000000000000000000000000066ce6f7781f3d367 -- NTLMv2 Client Challenge

从上面身份验证消息结构示例可以看到A客户端创建一个或多个挑战的响应,大概有六种类型的回应:

1.LM(LAN Manager)响应 - 由大多数较早的客户端发送,这是“原始”响应类型。

2.NTLM 响应 - 这是由基于NT的客户端发送的,包括Windows 2000和XP。

3.NTLMv2 响应 - 在Windows NT Service Pack 4中引入的一种较新的响应类型。它替换启用了NTLM版本2的系统上的NTLM响应。

4.LMv2响应 - 替代NTLM版本2系统上的LM响应。

5.NTLM2会话响应 - 用于在没有NTLMv2身份验证的情况下协商NTLM2会话安全性时,此方案会更改LM和NTLM响应的语义。

5.匿名响应 - 当匿名上下文正在建立时使用; 没有提供实际的证书,也没有真正的身份验证。“存根”字段显示在类型3消息中。

4) 认证成功与失败示例

0x07 学习总结

描述:通过上面的学习以及加密原理的了解,可以针对于LM/NTLM有一个简单的入门了解,当我们在进行PTH攻击以及理解的时候是非常有用,并且有助于我们了解其他的Windows认证协议;

Net认证的Hash比较总结:

选项LM-HashesNTLMv1NTLMv2

密码区分大小写否是是

散列密钥长度56 bit + 56 bit(112)--

密码散列算法DES(mode=ECB)MD4MD4

散列值的长度64+64=128bit128 bit128 bit

C/R 密钥长度56bit + 56bit + 18bit56bit + 56bit + 18bit128 bit

C/R 算法DES(mode=ECB)DES(mode=ECB)HMAC_MD5

C/R 长度64bit + 64bit + 64bit64bit + 64bit + 64bit128 bit

0x08 参考来源

1) 参考资料

1.https://docs.microsoft.com/en-us/windows/win32/secauthn/microsoft-ntlm

2.https://docs.microsoft.com/en-us/windows/win32/secauthn/microsoft-kerberos

3.https://byt3bl33d3r.github.io/practical-guide-to-ntlm-relaying-in-2017-aka-getting-a-foothold-in-under-5-minutes.html

4.https://www.insecurity.be/blog/2018/01/21/retrieving-ntlm-hashes-and-what-changed-technical-writeup/

5.https://xz.aliyun.com/t/2445

6.https://3gstudent.github.io/3gstudent.github.io/Windows下的密码hash-Net-NTLMv1介绍/

2) 文中工具

1.进程内存数据提取:https://docs.microsoft.com/zh-cn/sysinternals/downloads/procdump

2.MD4加密:https://nf404.github.io/crypto-api/crypto-api.min.js

3.DEC编码加密:http://www.slavasoft.com/hashcalc/

4.JS之MD4加密编码算法:https://www.iteye.com/blog/neil-yang-703462

5.LM-NTLM脚本: https://xz.aliyun.com/t/2445

6.Hashcat-Hashes破解格式:https://hashcat.net/wiki/doku.php?id=example_hashes

7.自己: https://github.com/WeiyiGeek/SecOpsDev/tree/master/Cryption/DES/Python

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342