Files
spotdl-auto/dns-debunk.sh

140 lines
4.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# dns_bpf_correlate_fixed.sh
set -u
DOMAIN=$1
WINDOW_MS=2000
HALF_WINDOW_MS=$((WINDOW_MS/2))
BASE_TS="$(date +%Y%m%d_%H%M%S)"
DNSLOG="${DOMAIN}_${BASE_TS}_dns.log"
BPFLOG="bpftrace_${BASE_TS}.log"
INCIDENT_DIR="incidents_${BASE_TS}"
mkdir -p "$INCIDENT_DIR"
RED="\e[31m"; GREEN="\e[32m"; YELLOW="\e[33m"; BLUE="\e[34m"; RESET="\e[0m"
TCPDUMP_PID=""
BPF_PID=""
now_ms() { date +%s%3N; }
cleanup() {
echo -e "${BLUE}[*] Stopping background processes...${RESET}"
[[ -n "$TCPDUMP_PID" ]] && kill "$TCPDUMP_PID" 2>/dev/null || true
[[ -n "$BPF_PID" ]] && kill "$BPF_PID" 2>/dev/null || true
sleep 0.1
echo -e "${BLUE}[*] Done.${RESET}"
exit 0
}
trap cleanup SIGINT SIGTERM
echo -e "${BLUE}[*] Domain: ${YELLOW}$DOMAIN${RESET}"
echo -e "${BLUE}[*] DNS log: ${YELLOW}$DNSLOG${RESET}"
echo -e "${BLUE}[*] bpftrace log: ${YELLOW}$BPFLOG${RESET}"
echo -e "${BLUE}[*] Incidents directory: ${YELLOW}$INCIDENT_DIR${RESET}"
echo -e "${BLUE}[*] Window for correlation: ${YELLOW}${WINDOW_MS} ms (±${HALF_WINDOW_MS} ms)${RESET}"
echo ""
# Start tcpdump
tcpdump -n -i any port 53 -s0 -ttt -l 2>/dev/null >> "$DNSLOG" &
TCPDUMP_PID=$!
echo -e "${GREEN}[*] tcpdump started (PID $TCPDUMP_PID)${RESET}"
# Start bpftrace inline (correct syntax)
bpftrace -e '
tracepoint:syscalls:sys_enter_sendto
{
$s = time; $ms = nsecs/1000000 % 1000;
printf("%d.%03d PID=%d COMM=%s FD=%d\n", $s, $ms, pid, comm, args->fd);
}
' > "$BPFLOG" 2>/dev/null &
BPF_PID=$!
sleep 0.2
if ! kill -0 "$BPF_PID" 2>/dev/null; then
echo -e "${RED}[!] bpftrace failed to start!${RESET}"
cleanup
fi
echo -e "${GREEN}[*] bpftrace started (PID $BPF_PID)${RESET}"
sleep 1
echo ""
# Helper function: /proc info for PID
proc_info_for_pid() {
local pid="$1"
if [[ -r "/proc/$pid/cmdline" ]]; then
local exe=$(readlink -f "/proc/$pid/exe" 2>/dev/null || true)
local cmd=$(tr '\0' ' ' < "/proc/$pid/cmdline" 2>/dev/null || true)
echo "pid=$pid exe=${exe:-N/A} cmdline='${cmd:-N/A}'"
else
echo "pid=$pid (no /proc info)"
fi
}
# Tail tcpdump and correlate symmetrically
tail -Fn0 "$DNSLOG" | while IFS= read -r dnsline; do
if echo "$dnsline" | grep -qi -- "$DOMAIN"; then
detect_ms=$(now_ms)
echo -e "${RED}[!] Suspicious DNS request detected @${YELLOW}$detect_ms${RESET}"
echo -e "${YELLOW}$dnsline${RESET}"
echo ""
INCIDENT_TS="$(date +%Y%m%d_%H%M%S_%3N)"
INCIDENT_FILE="${INCIDENT_DIR}/incident_${INCIDENT_TS}.txt"
{
echo "=== INCIDENT ${INCIDENT_TS} ==="
echo "dns_line: $dnsline"
echo "detected_at_ms: $detect_ms"
} > "$INCIDENT_FILE"
# extract source IP/port
src_tok=$(echo "$dnsline" | awk '{for(i=1;i<=NF;i++) if($i=="IP" || $i=="IP6"){print $(i+1); exit}}' || true)
if [[ -n "$src_tok" ]]; then
srcPort="${src_tok##*.}"
srcIP="${src_tok%.*}"
echo -e "${GREEN}[+] Extracted source: IP=${YELLOW}$srcIP${RESET} PORT=${YELLOW}$srcPort${RESET}"
echo "extracted_src_ip: $srcIP" >> "$INCIDENT_FILE"
echo "extracted_src_port: $srcPort" >> "$INCIDENT_FILE"
fi
# Symmetric window: half before, half after
low_ms=$((detect_ms - HALF_WINDOW_MS))
high_ms=$((detect_ms + HALF_WINDOW_MS))
awk -v low="$low_ms" -v high="$high_ms" '
BEGIN{FS=" "; OFS=" "}
{
if ($1 ~ /^[0-9]+\.[0-9]{3}$/) {
split($1, a, ".")
t_s=a[1]; t_ms=a[2]; t=t_s*1000+t_ms
if (t >= low && t <= high) print $0
}
}' "$BPFLOG" | tee -a "$INCIDENT_FILE" > /tmp/_bpf_matches.$$ || true
if [[ -s /tmp/_bpf_matches.$$ ]]; then
echo -e "${GREEN}[+] bpftrace events found in ±${HALF_WINDOW_MS}ms window:${RESET}"
sed 's/^/ /' /tmp/_bpf_matches.$$
echo "bpftrace_matches:" >> "$INCIDENT_FILE"
cat /tmp/_bpf_matches.$$ >> "$INCIDENT_FILE"
pids=$(sed -n 's/.*PID=\([0-9]\+\).*/\1/p' /tmp/_bpf_matches.$$ | sort -u)
for pid in $pids; do
info=$(proc_info_for_pid "$pid")
echo " [*] $info"
echo " - $info" >> "$INCIDENT_FILE"
done
else
echo -e "${YELLOW}[!] No bpftrace events in window${RESET}"
echo "bpftrace_matches: NONE in ±${HALF_WINDOW_MS}ms" >> "$INCIDENT_FILE"
fi
echo "" >> "$INCIDENT_FILE"
echo "ss_snapshot:" >> "$INCIDENT_FILE"
ss -tulpn 2>/dev/null >> "$INCIDENT_FILE" || true
echo -e "${GREEN}[+] Incident saved to ${YELLOW}$INCIDENT_FILE${RESET}"
echo -e "${BLUE}------------------------------------------------------${RESET}"
echo ""
rm -f /tmp/_bpf_matches.$$
fi
done