Very early test stage of scripts to extract ntlm and kerberos hashes from pcaps.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| if [ -z "$1" ] | |
| then | |
| echo "Usage: $0 <pcapfile>" | |
| exit 1 | |
| fi | |
| PCAP="$1" | |
| # Handle AS-REP and TGS-REP (using tshark) | |
| tshark -r "$PCAP" -Y "kerberos.msg_type == 11 || kerberos.msg_type == 13" -T fields \ | |
| -e frame.number \ | |
| -e kerberos.msg_type \ | |
| -e kerberos.realm \ | |
| -e kerberos.CNameString \ | |
| -e kerberos.etype \ | |
| -e kerberos.cipher | while IFS=$'\t' read -r frame msg_type crealm cname etype cipher; do | |
| [[ -z "$msg_type" || -z "$crealm" || -z "$cname" || -z "$etype" || -z "$cipher" ]] && continue | |
| realm_upper=$(echo "$crealm" | tr '[:lower:]' '[:upper:]') | |
| cname_clean=$(echo "$cname" | tr -d ' ,\r\n') | |
| etype_clean=$(echo "$etype" | cut -d',' -f1) | |
| cipher_clean=$(echo "$cipher" | tr -d ' ,\r\n') | |
| case "$msg_type" in | |
| 11) | |
| checksum="${cipher_clean:0:32}" | |
| encrypted_data="${cipher_clean:32}" | |
| echo "\$krb5asrep\$${etype_clean}\$${cname_clean}@${realm_upper}:${checksum}\$${encrypted_data}" | |
| ;; | |
| 13) | |
| service="krbtgt/${realm_upper}*" | |
| checksum="${cipher_clean:0:32}" | |
| encrypted_ticket="${cipher_clean:32}" | |
| echo "\$krb5tgs\$${etype_clean}\$*${cname_clean}\$${realm_upper}\$${service}\$${checksum}\$${encrypted_ticket}" | |
| ;; | |
| esac | |
| done | |
| # Handle AS-REQ (msg_type 10, using padata_value instead of cipher) | |
| tshark -r "$PCAP" -Y "kerberos.msg_type == 10" -T fields \ | |
| -e frame.number \ | |
| -e kerberos.msg_type \ | |
| -e kerberos.realm \ | |
| -e kerberos.etype \ | |
| -e kerberos.padata_value | while IFS=$'\t' read -r frame msg_type crealm etype padata; do | |
| [[ -z "$msg_type" || -z "$crealm" || -z "$etype" || -z "$padata" ]] && continue | |
| etype_name() { | |
| case "$1" in | |
| 1) echo "des-cbc-crc" ;; | |
| 3) echo "des-cbc-md5" ;; | |
| 16) echo "des3" ;; | |
| 17) echo "aes128" ;; | |
| 18) echo "aes256" ;; | |
| 23) echo "u5" ;; # RC4-HMAC | |
| *) echo "etype$1" ;; # fallback, unknown etype | |
| esac | |
| } | |
| realm_upper=$(echo "$crealm" | tr '[:lower:]' '[:upper:]') | |
| etype_clean=$(echo "$etype" | cut -d',' -f1 | tr -d '[:space:]') | |
| padata_clean=$(echo "$padata" | cut -d',' -f1 | tr -d '[:space:]') | |
| encryption_name=$(etype_name $etype_clean) | |
| final_hash=$(python3 ./extract-padata.py "$padata_clean") | |
| if [[ -n "$final_hash" ]] | |
| then | |
| echo "\$krb5pa\$${etype_clean}\$${encryption_name}\$${realm_upper}\$"dummy"\$${final_hash}" >> test-kerberos-hash.txt | |
| fi | |
| done |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Extract valid NTLMv1/v2 hashes from pcap using tshark | |
| # Usage: ./extract_ntlm_hashes.sh file.pcap | |
| pcap_file="$1" | |
| if [[ -z "$pcap_file" ]]; then | |
| echo "Usage: $0 <file.pcap>" | |
| exit 1 | |
| fi | |
| echo "[*] Extracting NTLMv2/v1 hashes from $pcap_file..." | |
| # Step 1: Get Challenge messages (Type 2) | |
| declare -A challenges | |
| while IFS=$'\t' read -r stream_id challenge; do | |
| if [[ "$challenge" =~ ^[a-fA-F0-9]{16}$ ]]; then | |
| challenges["$stream_id"]="$challenge" | |
| fi | |
| done < <(tshark -r "$pcap_file" \ | |
| -Y "ntlmssp.ntlmserverchallenge" \ | |
| -T fields \ | |
| -e tcp.stream \ | |
| -e ntlmssp.ntlmserverchallenge) | |
| # Step 2: Get Auth messages (Type 3) | |
| tshark -r "$pcap_file" \ | |
| -Y "ntlmssp.auth.username and ntlmssp.auth.ntresponse and ntlmssp.auth.lmresponse" \ | |
| -T fields \ | |
| -e tcp.stream \ | |
| -e ntlmssp.auth.username \ | |
| -e ntlmssp.auth.domain \ | |
| -e ntlmssp.auth.ntresponse \ | |
| -e ntlmssp.auth.lmresponse | | |
| while IFS=$'\t' read -r stream_id username domain nt_response lm_response; do | |
| challenge="${challenges[$stream_id]}" | |
| if [[ -z "$challenge" || -z "$username" || -z "$domain" ]]; then | |
| continue | |
| fi | |
| if [[ ! "$nt_response" =~ ^[a-fA-F0-9]+$ || ! "$lm_response" =~ ^[a-fA-F0-9]+$ ]]; then | |
| continue | |
| fi | |
| if [[ ${#nt_response} -gt 48 ]]; then | |
| version="NTLMv2" | |
| nt_proof="${nt_response:0:32}" | |
| blob="${nt_response:32}" | |
| hash="$username::$domain:$challenge:$nt_proof:$blob" | |
| elif [[ ${#nt_response} -eq 48 ]]; then | |
| version="NTLMv1" | |
| hash="$username::$domain:$lm_response:$nt_response:$challenge" | |
| else | |
| continue | |
| fi | |
| echo "[$version] $hash" | |
| echo "$hash" >> pcap-hashes.txt | |
| done |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import sys | |
| from impacket.krb5.asn1 import EncryptedData | |
| from pyasn1.codec.der.decoder import decode as der_decode | |
| def main(): | |
| if len(sys.argv) != 2: | |
| print(f"Usage: {sys.argv[0]} <padata_value_hex>") | |
| sys.exit(1) | |
| padata_hex = sys.argv[1] | |
| try: | |
| padata_bytes = bytes.fromhex(padata_hex) | |
| enc_data, _ = der_decode(padata_bytes, asn1Spec=EncryptedData()) | |
| cipher = bytes(enc_data['cipher']).hex() | |
| checksum = cipher[:32] | |
| encrypted_data = cipher[32:] | |
| final_hash = encrypted_data + checksum | |
| print(final_hash) | |
| except Exception as e: | |
| #print(f"Error decoding padata_value: {e}", file=sys.stderr) | |
| sys.exit(2) | |
| if __name__ == "__main__": | |
| main() |