Block

Encryption? What encryption? - by hadrian3689

The following post by 0xb0b is licensed under CC BY 4.0


The Challenge provides us with a PCAP file and a dump of LSASS. We start by analyzing the PCAP file and finding encrypted SMB traffic. The description of the room indicates that it needs to be decrypted. The questions of the challenge ask us to find the username, password, or password hash and the flag (possibly the content of the transferred files) of the respective users. This should all be possible via the PCAP file and the LSASS dump.

Investigation On First User

Getting Usernames

We find the first username in the 11th packet, the Session Setup Request. We could have also queried for the ntlmssp packet, which reveals us both Session Setup Request happening.

The filter ntlmssp in Wireshark is used to display only packets that contain NTLM (NT LAN Manager) Security Support Provider (SSP) protocol data. NTLMSSP is a security protocol used in various Microsoft network authentication protocols, particularly in environments where Kerberos cannot be used. We are able to identify the users mrealman and eshellstrop.

Retrieving The Password

For the password, the LSASS dump was first examined using pypykatz. Unfortunately, this did not give a positive result for the first user - more on that later. Neither hash nor plain text passwords were available for the first user in the dump. We will therefore probably obtain these from the PCAP. We have the option of doing this manually and by taking a closer look at the session setup requests. Or using a tool to extract the hashes.

Manual approach:

Extract the following:

  • Username: The user's account name. [found in 11th packet]

  • Domain: The domain or workgroup name (often referred to as the target name). [found in 11th packet]

  • Server Challenge: The 8-byte challenge sent by the server. [found in 10th packet]

  • NT Proof String (NTLMv2 Response): The first 16 bytes of the NTLMv2 response, which is the HMAC-MD5 hash. [found in 11th packet]

  • Challenge Blob: The remaining part of the NTLMv2 response, including the timestamp, client challenge, target information, etc. [found in 11th packet - NTLM Response]

Then concatenate the the necessary items to a NTLMv2 structure:

<username>::<domain>:<server_challenge>:<nt_proof_string>:<blob>

Tool

The PCredz tool allows us to extract the hashes from the PCAP file.

We just need to provide the PCAP file and be able to retrieve the NTLMv2 hashes of mrealman and eshellstrop.

With Hashcat we are able to retrieve the password of mrealman. Unfortunately, the hash of eshellstrop is not crackable with the rockyou.txt wordlist.

Retrieving The Flag

We now have to decrypt the encrypted SMB traffic to get to the transferred artifacts and extract and view them. Here I came across the following source: a very good writeup on decrypting SMB traffic using only the information we have available in a PCAP.

The encrypted session key found in the packet can be decrypted by using the key exchange key, which can be derived from the contents of the PCAP file.

The following list of items is necessary to generate the session key (and shows the general approach), which can then be inserted into Wireshark with the matching session ID to decrypt the traffic. We have to do this for each user. The writeup also provides us with a Python script to calculate it. We already have the username, password and domain. We still need the NTProofStr and the response key

-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

The NTProofString can also be found in the ntmlssp packet...

... as well as the encrypted session key.

We use the Python script from Maveris Labs for this, but adapt it so that it runs for Python3 and extend it so that not only passwords but also the hashes can be used directly. This is relevant for the second user, as we were unable to crack the hash for this user.

The following shows the modified script:

calc_smb_session_key.py
import hashlib
import hmac
import argparse
import binascii

# 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 as e:
    print("Warning: You don't have any crypto installed. You need pycryptodomex")
    print("See https://pypi.org/project/pycryptodomex/")
    raise e

def generate_encrypted_session_key(key_exchange_key, exported_session_key):
    cipher = ARC4.new(key_exchange_key)
    cipher_encrypt = cipher.encrypt
    session_key = cipher_encrypt(exported_session_key)
    return session_key

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", "--password", help="Password of User")
parser.add_argument("-ph", "--passwordhash", help="NTLM Hash of the Password (in Hex)")
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()

# Validate that either password or password hash is provided
if not args.password and not args.passwordhash:
    parser.error("You must provide either --password or --passwordhash")

# Upper Case User and Domain
user = str(args.user).upper().encode('utf-16le')
domain = str(args.domain).upper().encode('utf-16le')

# If password is provided, calculate the NTLM hash
if args.password:
    passw = args.password.encode('utf-16le')
    hash1 = hashlib.new('md4', passw)
    password_hash = hash1.digest()
else:
    # Use provided password hash (in hex) instead of calculating it
    password_hash = binascii.unhexlify(args.passwordhash)

# Calculate the ResponseNTKey
h = hmac.new(password_hash, digestmod=hashlib.md5)
h.update(user + domain)
resp_nt_key = h.digest()

# Use NTProofSTR and ResponseNTKey to calculate Key Exchange Key
nt_proof_str = binascii.unhexlify(args.ntproofstr)
h = hmac.new(resp_nt_key, digestmod=hashlib.md5)
h.update(nt_proof_str)
key_exch_key = h.digest()

# Calculate the Random Session Key by decrypting Encrypted Session Key with Key Exchange Key via RC4
r_sess_key = generate_encrypted_session_key(key_exch_key, binascii.unhexlify(args.key))

if args.verbose:
    print("USER WORK: " + user.decode('utf-16le') + domain.decode('utf-16le'))
    if args.password:
        print("PASS HASH: " + binascii.hexlify(password_hash).decode())
    print("RESP NT:   " + binascii.hexlify(resp_nt_key).decode())
    print("NT PROOF:  " + binascii.hexlify(nt_proof_str).decode())
    print("KeyExKey:  " + binascii.hexlify(key_exch_key).decode())
print("Random SK: " + binascii.hexlify(r_sess_key).decode())

Next, we just need to run it with our extracted information and be able to retrieve the session key.

python3 calc_smb_session_key.py -u mrealman -d WORKGROUP -p <REDACTED> -n 16e816dead16d4ca7d5d6dee4a015c14 -k fde53b54cb676b9bbf0fb1fbef384698

To decrypt the encrypted SMB traffic, we also need the related session ID. This can also be extracted from the ntlmssp packet.

Now, we only have to insert the session ID and the calculated session key into the protocol settings at Edit->Preferences->Protocols->SMB2. But the option expects a different representation than the one in the packet, as shown below.

After applying the settings, the packets related to the user mrealman are decrypted.

We are then are able to extract the transmitted files using File -> Export Objects -> SMB.

In this CSV file, we find the first flag.

Investigation On Second User

Getting Usernames

Recalling the investigation of the first user, we are able to retrieve the username and all the later necessary information from the ntlmssp packet.

Retrieving The Hash

Recalling the hash retrieval from the first user, we were not able to crack the hash, so we need the NTLM hash to decrypt the SMB traffic. For this, we can make use of pypykatz to analyze the LSASS dump.

There we will find the NThash of eshellstrop.

Retrieving The Flag

We recall the steps taken on retrieving the flag of the first user and trying to decrypt the SMB traffic of eshellstrop to retrieve the transmitted files.

We retrieve the NTProofStr ...

... And the encrypted session key.

As already mentioned, we modified the script to also accept hashes, not only passwords. This was a simple modification, since the script just hashed the provided password. We provide the hash via the parameter -ph.

python3 calc_smb_session_key.py -u eshellstrop -d WORKGROUP -ph <REDACTED> -n 0ca6227a4f00b9654a48908c4801a0ac -k c24f5102a22d286336aac2dfa4dc2e04

We now then need the session ID of eshellstrop's session.

And repeat the steps as already known of first user.

The SMB traffic gets decrpypted.

We find another CSV file.

Which contains the second flag.

Last updated