Skip to content

Instantly share code, notes, and snippets.

@cicero343
Forked from khr0x40sh/random_session_key_calc.py
Last active August 19, 2024 21:14
Show Gist options
  • Save cicero343/b8eac1a5e5ac46d15ac8dee805388fc4 to your computer and use it in GitHub Desktop.
Save cicero343/b8eac1a5e5ac46d15ac8dee805388fc4 to your computer and use it in GitHub Desktop.
Get Session Key for encrypted traffic in PCAP (Interactive)
#!/usr/bin/env python3
"""
This is a Python3 improved/interactive version of the script made by khr0x40sh for decrypting encrypted session keys in a PCAP file to view encrypted traffic.
If you don't specify the parameters, it should ask you for the parameter values.
It will check to see if pycryptodomex is installed, and if not, it will install it.
It can also accept NTML hashes directly as well as passwords.
Usage:
python3 script_name.py -u USER -d DOMAIN -p PASSWORD -n NT_PROOF_STR -k ENCRYPTED_SESSION_KEY
Example:
python3 script_name.py -u alice -d EXAMPLE -p secret123 -n aabbccddeeff00112233445566778899 -k aabbccddeeff00112233445566778899
Description:
This script calculates the Random Session Key based on data extracted from a PCAP file (possibly).
It uses the NTLM hash of the user's password, NTProofStr, and an encrypted session key to generate a session key via RC4 encryption.
"""
import sys
import subprocess
import hashlib
import hmac
import argparse
import binascii
# Add user's local site-packages to sys.path
import site
site.addsitedir(site.getusersitepackages())
# Function to install pycryptodomex
def install_pycryptodomex():
try:
# Check if pip is installed
subprocess.check_call([sys.executable, "-m", "pip", "--version"])
except subprocess.CalledProcessError:
print("Error: pip is not installed. Please install pip first.")
sys.exit(1)
# Attempt to install pycryptodomex
try:
subprocess.check_call([sys.executable, "-m", "pip", "install", "--user", "pycryptodomex"])
except subprocess.CalledProcessError:
print("Failed to install pycryptodomex. Please install it manually using 'pip install pycryptodomex'.")
sys.exit(1)
# Attempt to import Cryptodome, install if missing
try:
from Cryptodome.Cipher import ARC4
from Cryptodome.Hash import MD4
except ImportError:
print("pycryptodomex is not installed. Attempting to install it now...")
install_pycryptodomex()
# Try importing again after installation
try:
from Cryptodome.Cipher import ARC4
from Cryptodome.Hash import MD4
except ImportError:
print("Failed to import pycryptodomex after installation. Please install it manually.")
sys.exit(1)
def generateEncryptedSessionKey(keyExchangeKey, exportedSessionKey):
cipher = ARC4.new(keyExchangeKey)
cipher_encrypt = cipher.encrypt
sessionKey = cipher_encrypt(exportedSessionKey)
return sessionKey
def md4_hash(data):
"""Calculate MD4 hash using pycryptodomex."""
hash_obj = MD4.new()
hash_obj.update(data)
return hash_obj.digest()
# Argument parser
parser = argparse.ArgumentParser(description="Calculate the Random Session Key based on data from a PCAP (maybe).")
parser.add_argument("-u", "--user", help="User name (prompted if not provided)")
parser.add_argument("-d", "--domain", help="Domain name (prompted if not provided)")
parser.add_argument("-p", "--password", help="Password of User or NTLM hash (prompted if not provided)")
parser.add_argument("-n", "--ntproofstr", help="NTProofStr (Hex Stream) (prompted if not provided)")
parser.add_argument("-k", "--key", help="Encrypted Session Key (Hex Stream) (prompted if not provided)")
parser.add_argument("-v", "--verbose", action="store_true", help="Increase output verbosity")
args = parser.parse_args()
# Prompt interactively if arguments are missing
if not args.user:
args.user = input("What is the username of the user? ").strip()
if not args.domain:
args.domain = input("What is the workgroup (domain)? ").strip()
if not args.password:
args.password = input("What is the password of the user or NTLM hash? ").strip()
if not args.ntproofstr:
args.ntproofstr = input("What is the NTProofStr (Hex Stream)? ").strip()
if not args.key:
args.key = input("What is the Encrypted Session Key (Hex Stream)? ").strip()
# Determine if password is provided as NTLM hash or plaintext password
if len(args.password) == 32 and all(c in '0123456789abcdefABCDEF' for c in args.password):
# Use provided NTLM hash
password = binascii.unhexlify(args.password)
else:
# Treat as plaintext password
passw = args.password.encode('utf-16le')
password = md4_hash(passw)
# Convert NTProofStr and Key from hex to binary data
try:
NTproofStr = binascii.unhexlify(args.ntproofstr)
key = binascii.unhexlify(args.key)
except binascii.Error:
print("Error: NTProofStr or Encrypted Session Key is not a valid hex string.")
sys.exit(1)
# Calculate the ResponseNTKey
h = hmac.new(password, digestmod=hashlib.md5)
h.update(args.user.upper().encode('utf-16le') + args.domain.upper().encode('utf-16le'))
respNTKey = h.digest()
# Use NTProofStr and ResponseNTKey to calculate Key Exchange Key
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, key)
# Print results
if args.verbose:
print("USER WORK: ", args.user.upper() + args.domain.upper())
print("PASS HASH: ", binascii.hexlify(password).decode())
print("RESP NT: ", binascii.hexlify(respNTKey).decode())
print("NT PROOF: ", binascii.hexlify(NTproofStr).decode())
print("KeyExKey: ", binascii.hexlify(KeyExchKey).decode())
print("Random SK: ", binascii.hexlify(RsessKey).decode())
@cicero343
Copy link
Author

Thanks to @khr0x40sh

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