- 為什麼有這篇文章呢,因為我們知道平常的Web系統有註冊、登入是依賴資料庫和後端的加密解密演演算法。那麼Windows系統登入的時候是如何進行身份驗證的呢,是否也有一個類似資料庫的東西,或者就是一個單純的文字呢?
- 參考--Windows內網協定學習NTLM篇之NTLM基礎介紹
- Windows也有一個類似於資料的東西,存放在
%SystemRoot%\system32\config\sam
,裡面存放著使用者的憑證資訊,當然這肯定不是明文,不然Windows這麼寫也太不安全了。這裡的加密演演算法不同於常見的MD5,加密後的資料有兩種分別為LM Hash
和NTLM Hash
。
LM Hash
- LM Hash全稱
LAN Manager Hash
,由IBM設計一般用於Windows XP
、Windows 2000
、Windows 2003
這一類系統中。加密演演算法如下。
- 密碼長度不能超過14個字元。
- 密碼轉換為大寫,再轉換成16進位制的字串,沒有28位元長度的,在右邊加0。
- 再將十六進位制的字串分為兩組14位元的字串。
- 再將這兩組14位元的字串進行十六進位制轉二進位制,轉換完成後不滿足56位的在左邊加0。
- 兩部分分別劃分為每組七位,在其末尾加0,再分別轉換為十六進位制。
- 最後將這兩組資料作為DES加密所需的Key,
KGS!@#$%
作為需加密的字元,將DES加密後的資料依次拼接。
- 這裡借用zjun的指令碼。
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 為"KGS!@#$%"進行加密。
LMOne = DesEncrypt("KGS!@#$%", binascii.a2b_hex(PartOne)).decode()
LMTwo = DesEncrypt("KGS!@#$%", binascii.a2b_hex(PartTwo)).decode()
print('兩組 DES 加密結果:', LMOne, LMTwo)
# 將二組 DES 加密後的編碼拼接,得到 LM HASH 值。
LM = LMOne + LMTwo
print('LM hash:', LM)
- 可以看出密碼長度小於7時,後面加密的資料是固定的,均為aad3b435b51404ee,因此其加密是不安全的。
NTML Hash
- NTML Hash全稱
NT LAN Manager
, 目前 Windows 基本都使用 NTLM hash ,一個32
位長度的字串。支援Net NTLM認證協定及本地認證過程中的關鍵憑據。加密演演算法如下:
- 密碼轉換為十六進位制
Unicode
編碼
MD4
加密
- Python指令碼如下:
import hashlib
import binascii
import sys
print(binascii.hexlify(hashlib.new("md4", sys.argv[1].encode("utf-16le")).digest()).decode())
123456
經過加密後則為32ed87bdb5fdc5e9cba88547376818d4
。
Windows本地認證
winlogon.exe
-> 接收使用者密碼 -> lsass.exe
-> 比對sam表。
- winlogon就是登陸介面,接受使用者密碼之後會傳送明文到
lsass.exe
,lsass.exe
會儲存一份明文,然後加密明文和sam表的hash做比對,判斷是否可以登陸。
- Windows Logon Process(即 winlogon.exe),是Windows NT 使用者登陸程式,用於管理使用者登入和退出。LSASS用於微軟Windows系統的安全機制。它用於本地安全和登陸策略。
- 這裡注意如果打了修補程式
KB2871997
,或者機器是win2012
之後,則不會儲存明文密碼了。
NTLM認證協定
- 什麼是
NTLM
認證協定呢?和NTLM Hash
又有什麼區別呢?NTLM
是一種網路認證協定,它是基於挑戰(Chalenge)/響應(Response)認證機制的一種認證模式。NTLM 網路認證協定是以 NTLM Hash
作為根本憑證進行認證的協定。
- 在內網滲透中,經常遇到工作組環境,而工作組環境是一個邏輯上的網路環境(工作區),隸屬於工作組的機器之間無法互相建立一個完美的信任機制,只能對等,是比較落後的認證方式, 沒有信託機構。
- 假設A主機與B主機屬於同一個工作組環境,A想存取B主機上的資料,需要將一個存在於B主機上的賬戶憑證傳送至B主機,經過認證才能夠存取B主機上的資源。
- 早期SMB協定在網路上傳輸明文口令。後來出現LAN Manager Challenge/Response驗證機制,簡稱LM,它是如此簡單以至很容易就被破解,現在又有了
NTLM
以及Kerberos
。
- 認證流程分為三部分,分別是:
協商
、質詢
、身份驗證
。
協商
- 使用者端向伺服器傳送協商請求,包含使用者名稱、密碼、認證協定版本等資訊。
質詢
- 伺服器接收到使用者端傳送到協商資訊,這時伺服器會生成一個亂數,叫做
challenge
,這裡的不同的協定亂數長度不同,NTLM V1是8位元,NTLM V2是16位元。
- 伺服器將登陸的使用者對應的
NTLM Hash
加密challenge
,得到Net NTLM Hash
,和生成的challenge
一起傳送給使用者端。
驗證
- 使用者端收到challenge後,將使用者的hash與challenge進行加密運算得到resposne,將username、response、challenge傳送給伺服器,最後伺服器進行校驗返回認證結果。
WireShark