Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
2022 HackTheBox Business CTF Rogue [Encrypted SMBv3 Decryption]
#!/usr/bin/env python3
"""
This function calculates the random secret key for SMB decryption.
This uses the NTLM hash or plaintext password of the user given a pre-existing packet capture.
"""
# Imports
from Cryptodome.Cipher import ARC4
from Cryptodome.Hash import MD4
import hashlib
import hmac
import argparse
from binascii import hexlify, unhexlify
def generateEncryptedSessionKey(keyExchangeKey, exportedSessionKey):
cipher = ARC4.new(keyExchangeKey)
cipher_encrypt = cipher.encrypt
sessionKey = cipher_encrypt(exportedSessionKey)
return sessionKey
def swap_bytes(x):
x = bytearray(unhexlify(x));
x.reverse();
return hexlify(x)
# Arguments
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", required=False,
help="Password of User")
parser.add_argument("-ph", "--ntlmpassword", required=False,
help="NTLM Password Hash of User")
parser.add_argument("-n", "--ntproofstr", required=True,
help="NTProofStr (hex). This can be found in PCAP via ntlmssp.ntlmv2_response.ntproofstr")
parser.add_argument("-k", "--sessionkey", required=True,
help="Encrypted Session Key (hex). This can be found in PCAP.")
parser.add_argument("-i", "--sessionid", required=True,
help="Session ID (hex). This can be found in PCAP.")
parser.add_argument("-v", "--verbose", action="store_true",
help="increase output verbosity")
args = parser.parse_args()
# Upper CaseUsername and Domain
Username = str(args.user).upper().encode('utf-16le')
Domain = str(args.domain).upper().encode('utf-16le')
# Create 'NTLM' Hash of password
if args.ntlmpassword:
NTLMPassword = unhexlify(args.ntlmpassword)
elif args.password:
Password = args.password.encode('utf-16le')
hash1 = MD4.new(Password)
NTLMPassword = hash1.hexdigest()
NTLMPassword = unhexlify(NTLMPassword)
else:
exit("Requires password or NTLM hash")
# Calculate the ResponseNTKey
h = hmac.new(NTLMPassword, digestmod=hashlib.md5)
h.update(Username+Domain)
ResponseNTKey = h.digest()
# Use NTProofSTR and ResponseNTKey to calculate Key Exchange Key
NTProofStr = unhexlify(args.ntproofstr)
h = hmac.new(ResponseNTKey, 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, unhexlify(args.sessionkey))
if args.verbose:
print("USER+DOMAIN: " + Username.decode() + "" + Domain.decode())
print("PASS HASH: " + hexlify(NTLMPassword).decode())
print("RESP NT: " + hexlify(ResponseNTKey).decode())
print("NT PROOF: " + hexlify(NTProofStr).decode())
print("KeyExKey: " + hexlify(KeyExchKey).decode())
print("Session ID: " + swap_bytes(args.sessionid).decode())
print('Random SK:', hexlify(RsessKey).decode())
@godylockz
Copy link
Author

godylockz commented Jul 17, 2022

Note, if there are multiple SMB sessions with the same Session ID, decryption only works with the first random session key inserted in Protocols, SMB in version Wireshark version 3.6.6 which is the latest version available at this time.
Filter: ntlmssp.ntlmv2_response.ntproofstr to get inputs for the script.
Also, older versions of Wireshark may not work.
Go to File, Exports, SMB to view any files decrypted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment