#!/bin/bash
# ==============================================================
# YARA Scanner
# ==============================================================
#
# Scans files in given path(s) using YARA rules.
# Supports fast scan, full scan, and delta scan (new/changed files).
# Optionally logs results to a file and runs inside a tmux session.
#
# Usage:
#   ./yara.sh -r <ruleset> -p <path>... [-f | -F | -n] [-l <logfile>] [-s] [-q]
#
# Required:
#   -r <ruleset>    Path to YARA rules file (.yar)
#   -p <path>...    One or more directories to scan (supports wildcards)
#
# Scan modes (pick one):
#   -f              Fast scan   - YARA stops after first match per rule
#   -F              Full scan   - YARA evaluates all rules completely
#   -n              New only    - Only scans files changed since last run
#                                 Uses /tmp/.yara_last_scan as timestamp
#                                 First run scans everything
#
# Optional:
#   -l <logfile>    Write matches and summary to logfile
#   -s              Run the scan inside a tmux session
#                   Detach with Ctrl+B, D — reattach with: tmux a -t yara_scan
#   -q              Quiet - suppress match output, only show summary at the end
#                   Without -q matches are printed live during scan
#
# Examples:
#   ./yara.sh -r /etc/rules/malware.yar -p /var/www/ -f
#   ./yara.sh -r /etc/rules/malware.yar -p /var/www/client*/web*/web/ -F -l /root/scan.log
#   ./yara.sh -r /etc/rules/malware.yar -p /var/www/ /opt/uploads/ -n -l /root/scan.log -s -q
#
# ==============================================================

LAST_SCAN_FILE="/tmp/.yara_last_scan"
SESSION="yara_scan"

usage() {
    echo "Usage: $0 -r <ruleset> -p <path>... (-f | -F | -n) [-l <logfile>] [-s] [-q]"
    echo ""
    echo "  -r   YARA rules file"
    echo "  -p   Path(s) to scan (supports wildcards)"
    echo "  -f   Fast scan (first match per rule)"
    echo "  -F   Full scan (all rules evaluated)"
    echo "  -n   New/changed files only since last scan"
    echo "  -l   Log output to file"
    echo "  -s   Run inside tmux session"
    echo "  -q   Quiet (only show summary)"
    exit 1
}

log() {
    [[ ${QUIET} -eq 0 ]] && echo "$1"
    [[ -n "${LOGFILE}" ]] && echo "$1" >> "${LOGFILE}"
}

ORIGINAL_ARGS=("$@")
SCAN_MODE=""
RULESET=""
SCAN_PATHS=()
LOGFILE=""
USE_TMUX=0
QUIET=0

while [[ $# -gt 0 ]]; do
    case "$1" in
        -r) shift; RULESET="$1" ;;
        -p)
            shift
            while [[ $# -gt 0 && ! "$1" =~ ^- ]]; do
                SCAN_PATHS+=("$1")
                shift
            done
            continue
            ;;
        -f) SCAN_MODE="fast" ;;
        -F) SCAN_MODE="full" ;;
        -n) SCAN_MODE="new" ;;
        -l) shift; LOGFILE="$1" ;;
        -s) USE_TMUX=1 ;;
        -q) QUIET=1 ;;
        *)  usage ;;
    esac
    shift
done

[[ -z "${RULESET}" || ${#SCAN_PATHS[@]} -eq 0 || -z "${SCAN_MODE}" ]] && usage
[[ ! -f "${RULESET}" ]] && { echo "Ruleset not found."; exit 1; }

# --- tmux: relaunch inside tmux session ---
if [[ ${USE_TMUX} -eq 1 ]]; then
    CLEAN_ARGS=()
    for arg in "${ORIGINAL_ARGS[@]}"; do
        [[ "${arg}" == "-s" ]] && continue
        CLEAN_ARGS+=("${arg}")
    done
    exec tmux new-session -s "${SESSION}" "bash $(readlink -f "$0") ${CLEAN_ARGS[*]}; bash"
fi

[[ -n "${LOGFILE}" ]] && : > "${LOGFILE}"

YARA_ARGS=()
[[ "${SCAN_MODE}" == "fast" ]] && YARA_ARGS+=("--fast-scan")

FIND_ARGS=("${SCAN_PATHS[@]}" -type f)
if [[ "${SCAN_MODE}" == "new" && -f "${LAST_SCAN_FILE}" ]]; then
    FIND_ARGS+=(-newer "${LAST_SCAN_FILE}")
fi

COUNT=0
HITS=0
START=$(date +%s)

while IFS= read -r file; do
    ((COUNT++))
    output=$(yara "${YARA_ARGS[@]}" "${RULESET}" "${file}" 2>/dev/null)
    if [[ -n "${output}" ]]; then
        ((HITS++))
        log "[MATCH] ${output}"
    fi
done < <(find "${FIND_ARGS[@]}")

END=$(date +%s)
ELAPSED=$((END - START))
MINS=$((ELAPSED / 60))
SECS=$((ELAPSED % 60))

touch "${LAST_SCAN_FILE}"

echo "Scanned: ${COUNT} | Matches: ${HITS} | Time: ${MINS}m ${SECS}s"
[[ -n "${LOGFILE}" ]] && echo "Scanned: ${COUNT} | Matches: ${HITS} | Time: ${MINS}m ${SECS}s" >> "${LOGFILE}"
