Block Write-up - TryHackMe
Extracting NTLM hashes from a memory dump and decrypting SMB3 traffic to find the flag.
Block
is a medium-level CTF challenge about decrypting SMB3 traffic.
Information Gathering
One of your junior system administrators forgot to deactivate two accounts from a pair of recently fired employees. We believe these employees used the credentials they were given in order to access some of the many private files from our server, but we need concrete proof. The junior system administrator only has a small network capture of the incident and a memory dump of the Local Security Authority Subsystem Service process. Fortunately, for your company, that is all you need.
I started by downloading the provided files and extracting them.
There were two files: lsass.DMP
and traffic.pcapng
.
I opened the traffic.pcapng
file with Wireshark to analyze the network traffic.
A lot of traffic was captured, mostly SMB3 packets. Since these packets are encrypted, I couldn’t see the contents of the packets. We need to find a way to decrypt these packets. The Random Session Key is used to encrypt the SMB3 packets.
I did some research and found this blog post: Decrypting SMB3 Traffic with just a PCAP? Absolutely (maybe.)
According to the blog post, to compute the session key, we need the following information:
- Unicode (utf-16le) of password
- MD4 hash of the above (This is also the NTLM Hash of the password)
- Unicode(utf-16le) and Uppercase of Username and Domain/Workgroup together
- Calculating the ResponseKeyNT via HMAC_MD5(NTLM Hash, Unicode of User/Domain above)
- NTProofStr (can be calculated but not needed as it is present in the PCAP)
- Calculating the KeyExchangeKey via HMAC_MD5(ResponseKeyNT,NTProofStr)
- Decrypt the Encrypted Session Key via RC4 and the Key Exchange Key to finally get the Random Session Key
Using lsass.DMP
file, we can extract the NTLM hash of the user’s password. I used mimikatz
to extract the NTLM hash.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
mimikatz # sekurlsa::minidump lsass.dmp
Switch to MINIDUMP : 'lsass.dmp'
mimikatz # sekurlsa::logonPasswords
Opening : 'lsass.dmp' file for minidump...
[...]
Authentication Id : 0 ; 1883025 (00000000:001cbb91)
Session : Interactive from 3
User Name : mrealman
Domain : BLOCK
Logon Server : WIN-2258HHCBNQR
Logon Time : 10/22/2023 7:53:54 PM
SID : S-1-5-21-3761843758-2185005375-3584081457-1104
msv :
[00000003] Primary
* Username : mrealman
* Domain : BLOCK
* NTLM : 1f9175a516211660c7a8143b0f36ab44
* SHA1 : ccd27b4bf489ffda2251897ef86fdb488f248aef
* DPAPI : 3d618a1fffd6c879cd0b056910ec0c31
[...]
Authentication Id : 0 ; 828825 (00000000:000ca599)
Session : Interactive from 2
User Name : eshellstrop
Domain : BLOCK
Logon Server : WIN-2258HHCBNQR
Logon Time : 10/22/2023 7:46:09 PM
SID : S-1-5-21-3761843758-2185005375-3584081457-1103
msv :
[00000003] Primary
* Username : eshellstrop
* Domain : BLOCK
* NTLM : 3f29138a04aadc19214e9c04028bf381
* SHA1 : 91374e6e58d7b523376e3b1eb04ae5440e678717
* DPAPI : 87c8e56bc4714d4c5659f254771559a8
I extracted the NTLM hashes of the users mrealman
and eshellstrop
.
Computing the Session Key
Fortunately, the blog post provided a Python script to compute the session key. I slightly modified the script to include the NTLM hashes of the users instead of the password.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import hashlib
import hmac
import argparse
#stolen from impacket. Thank you all for your wonderful contributions to the community
try:
from Cryptodome.Cipher import ARC4
from Cryptodome.Cipher import DES
from Cryptodome.Hash import MD4
except Exception:
LOG.critical("Warning: You don't have any crypto installed. You need pycryptodomex")
LOG.critical("See https://pypi.org/project/pycryptodomex/")
def generateEncryptedSessionKey(keyExchangeKey, exportedSessionKey):
cipher = ARC4.new(keyExchangeKey)
cipher_encrypt = cipher.encrypt
sessionKey = cipher_encrypt(exportedSessionKey)
return sessionKey
###
parser = argparse.ArgumentParser(description="Calculate the Random Session Key based on data from a PCAP (maybe).")
parser.add_argument("-u","--user",required=True,help="User name")
parser.add_argument("-d","--domain",required=True, help="Domain name")
parser.add_argument("-p","--ntlm",required=True,help="NTLM Hash of User")
parser.add_argument("-n","--ntproofstr",required=True,help="NTProofStr. This can be found in PCAP (provide Hex Stream)")
parser.add_argument("-k","--key",required=True,help="Encrypted Session Key. This can be found in PCAP (provide Hex Stream)")
parser.add_argument("-v", "--verbose", action="store_true", help="increase output verbosity")
args = parser.parse_args()
#Upper Case User and Domain
user = str(args.user).upper().encode('utf-16le')
domain = str(args.domain).upper().encode('utf-16le')
#Create 'NTLM' Hash of password
password = args.ntlm.decode('hex')
#Calculate the ResponseNTKey
h = hmac.new(password, digestmod=hashlib.md5)
h.update(user+domain)
respNTKey = h.digest()
#Use NTProofSTR and ResponseNTKey to calculate Key Excahnge Key
NTproofStr = args.ntproofstr.decode('hex')
h = hmac.new(respNTKey, digestmod=hashlib.md5)
h.update(NTproofStr)
KeyExchKey = h.digest()
#Calculate the Random Session Key by decrypting Encrypted Session Key with Key Exchange Key via RC4
RsessKey = generateEncryptedSessionKey(KeyExchKey,args.key.decode('hex'))
if args.verbose:
print "USER WORK: " + user + "" + domain
print "PASS HASH: " + password.encode('hex')
print "RESP NT: " + respNTKey.encode('hex')
print "NT PROOF: " + NTproofStr.encode('hex')
print "KeyExKey: " + KeyExchKey.encode('hex')
print "Random SK: " + RsessKey.encode('hex')
Okay, let’s collect the required information from the PCAP file. NTProofStr
, Encrypted Session Key
, and Domain
.
I ran the script with the following parameters:
1
2
3
┌──(kali㉿kali)-[~]
└─$ python2 random_session_key_calc.py --user MREALMAN --domain WORKGROUP --ntlm 1f9175a516211660c7a8143b0f36ab44 --ntproofstr 16e816dead16d4ca7d5d6dee4a015c14 --key fde53b54cb676b9bbf0fb1fbef384698
Random SK: 20a642c086ef74eee26277bf1d0cff8c
I repeated the same process for the user eshellstrop
.
1
2
3
┌──(kali㉿kali)-[~]
└─$ python2 random_session_key_calc.py --user eshellstrop --domain WORKGROUP --ntlm 3f29138a04aadc19214e9c04028bf381 --ntproofstr 0ca6227a4f00b9654a48908c4801a0ac --key c24f5102a22d286336aac2dfa4dc2e04
Random SK: facfbdf010d00aa2574c7c41201099e8
Decrypting the SMB3 Traffic
From the same packets, I extracted the Session ID
for both users.
Session ID for mrealman
is 0x0000100000000041
and for eshellstrop
is 0x0000100000000045
.
Now we have everything we need to decrypt the SMB3 traffic.
Edit -> Preferences -> Protocols -> SMB2 -> Edit
Notice that the Session ID
must be formatted as 4100000000100000
. We need to reverse the bytes because of the endianness.
And that’s it! We successfully decrypted the SMB3 traffic.
I exported SMB3 Objects to a file.
File -> Export Objects -> SMB
Questions & Flags
Now we can answer the questions.
Task 1
What is the username of the first person who accessed our server?
Answer: mrealman
Task 2
What is the password of the user in question 1?
Since we have the NTLM hash of the user’s password, I used crackstation.net to crack the hash.
Answer: Blockbuster1
Task 3
What is the flag that the first user got access to?
The flag was in the first file we exported.
1
2
sarp@IdeaPad:~/Desktop$ cat %5cclients156.csv | grep THM
Farris,Busst,THM{SmB_DeCrypTing_who_Could_Have_Th0ughT}
Answer: THM{SmB_DeCrypTing_who_Could_Have_Th0ughT}
Task 4
What is the username of the second person who accessed our server?
Answer: eshellstrop
Task 5
What is the hash of the user in question 4?
Answer: 3f29138a04aadc19214e9c04028bf381
Task 6
What is the flag that the second user got access to?
1
2
sarp@IdeaPad:~/Desktop$ cat %5cclients978.csv | grep THM
Tonye,Risebrow,THM{No_PasSw0Rd?_No_Pr0bl3m}
Answer: THM{No_PasSw0Rd?_No_Pr0bl3m}
Conclusion
This was an interesting challenge. I didn’t know how to decrypt SMB3 traffic until this challenge. I learned it by doing this challenge. Thanks for reading! Feel free to reach out to me on Twitter if you have any questions or feedback.