mirror of
https://github.com/smittix/intercept.git
synced 2026-07-28 02:28:11 -07:00
Add verbose results option to TSCM sweeps and setup improvements
- Add verbose_results flag to store full device details in sweep results - Add non-interactive mode (--non-interactive) to setup.sh - Add ask_yes_no helper for interactive prompts with TTY detection - Update reports.py to handle new results structure with fallbacks Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
+92
-50
@@ -298,19 +298,20 @@ def _check_available_devices(wifi: bool, bt: bool, rf: bool) -> dict:
|
|||||||
|
|
||||||
|
|
||||||
@tscm_bp.route('/sweep/start', methods=['POST'])
|
@tscm_bp.route('/sweep/start', methods=['POST'])
|
||||||
def start_sweep():
|
def start_sweep():
|
||||||
"""Start a TSCM sweep."""
|
"""Start a TSCM sweep."""
|
||||||
global _sweep_running, _sweep_thread, _current_sweep_id
|
global _sweep_running, _sweep_thread, _current_sweep_id
|
||||||
|
|
||||||
if _sweep_running:
|
if _sweep_running:
|
||||||
return jsonify({'status': 'error', 'message': 'Sweep already running'})
|
return jsonify({'status': 'error', 'message': 'Sweep already running'})
|
||||||
|
|
||||||
data = request.get_json() or {}
|
data = request.get_json() or {}
|
||||||
sweep_type = data.get('sweep_type', 'standard')
|
sweep_type = data.get('sweep_type', 'standard')
|
||||||
baseline_id = data.get('baseline_id')
|
baseline_id = data.get('baseline_id')
|
||||||
wifi_enabled = data.get('wifi', True)
|
wifi_enabled = data.get('wifi', True)
|
||||||
bt_enabled = data.get('bluetooth', True)
|
bt_enabled = data.get('bluetooth', True)
|
||||||
rf_enabled = data.get('rf', True)
|
rf_enabled = data.get('rf', True)
|
||||||
|
verbose_results = bool(data.get('verbose_results', False))
|
||||||
|
|
||||||
# Get interface selections
|
# Get interface selections
|
||||||
wifi_interface = data.get('wifi_interface', '')
|
wifi_interface = data.get('wifi_interface', '')
|
||||||
@@ -348,12 +349,12 @@ def start_sweep():
|
|||||||
_sweep_running = True
|
_sweep_running = True
|
||||||
|
|
||||||
# Start sweep thread
|
# Start sweep thread
|
||||||
_sweep_thread = threading.Thread(
|
_sweep_thread = threading.Thread(
|
||||||
target=_run_sweep,
|
target=_run_sweep,
|
||||||
args=(sweep_type, baseline_id, wifi_enabled, bt_enabled, rf_enabled,
|
args=(sweep_type, baseline_id, wifi_enabled, bt_enabled, rf_enabled,
|
||||||
wifi_interface, bt_interface, sdr_device),
|
wifi_interface, bt_interface, sdr_device, verbose_results),
|
||||||
daemon=True
|
daemon=True
|
||||||
)
|
)
|
||||||
_sweep_thread.start()
|
_sweep_thread.start()
|
||||||
|
|
||||||
logger.info(f"Started TSCM sweep: type={sweep_type}, id={_current_sweep_id}")
|
logger.info(f"Started TSCM sweep: type={sweep_type}, id={_current_sweep_id}")
|
||||||
@@ -1193,16 +1194,17 @@ def _scan_rf_signals(sdr_device: int | None, duration: int = 30) -> list[dict]:
|
|||||||
return signals
|
return signals
|
||||||
|
|
||||||
|
|
||||||
def _run_sweep(
|
def _run_sweep(
|
||||||
sweep_type: str,
|
sweep_type: str,
|
||||||
baseline_id: int | None,
|
baseline_id: int | None,
|
||||||
wifi_enabled: bool,
|
wifi_enabled: bool,
|
||||||
bt_enabled: bool,
|
bt_enabled: bool,
|
||||||
rf_enabled: bool,
|
rf_enabled: bool,
|
||||||
wifi_interface: str = '',
|
wifi_interface: str = '',
|
||||||
bt_interface: str = '',
|
bt_interface: str = '',
|
||||||
sdr_device: int | None = None
|
sdr_device: int | None = None,
|
||||||
) -> None:
|
verbose_results: bool = False
|
||||||
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Run the TSCM sweep in a background thread.
|
Run the TSCM sweep in a background thread.
|
||||||
|
|
||||||
@@ -1470,21 +1472,61 @@ def _run_sweep(
|
|||||||
identity_summary = identity_engine.get_summary()
|
identity_summary = identity_engine.get_summary()
|
||||||
identity_clusters = [c.to_dict() for c in identity_engine.get_clusters()]
|
identity_clusters = [c.to_dict() for c in identity_engine.get_clusters()]
|
||||||
|
|
||||||
update_tscm_sweep(
|
if verbose_results:
|
||||||
_current_sweep_id,
|
wifi_payload = list(all_wifi.values())
|
||||||
status='completed',
|
bt_payload = list(all_bt.values())
|
||||||
results={
|
rf_payload = list(all_rf)
|
||||||
'wifi_devices': len(all_wifi),
|
else:
|
||||||
'bt_devices': len(all_bt),
|
wifi_payload = [
|
||||||
'rf_signals': len(all_rf),
|
{
|
||||||
'severity_counts': severity_counts,
|
'bssid': d.get('bssid') or d.get('mac'),
|
||||||
'correlation_summary': findings.get('summary', {}),
|
'essid': d.get('essid') or d.get('ssid'),
|
||||||
'identity_summary': identity_summary.get('statistics', {}),
|
'ssid': d.get('ssid') or d.get('essid'),
|
||||||
'baseline_comparison': baseline_comparison,
|
'channel': d.get('channel'),
|
||||||
},
|
'power': d.get('power', d.get('signal')),
|
||||||
threats_found=threats_found,
|
'privacy': d.get('privacy', d.get('encryption')),
|
||||||
completed=True
|
'encryption': d.get('encryption', d.get('privacy')),
|
||||||
)
|
}
|
||||||
|
for d in all_wifi.values()
|
||||||
|
]
|
||||||
|
bt_payload = [
|
||||||
|
{
|
||||||
|
'mac': d.get('mac') or d.get('address'),
|
||||||
|
'name': d.get('name'),
|
||||||
|
'rssi': d.get('rssi'),
|
||||||
|
'manufacturer': d.get('manufacturer', d.get('manufacturer_name')),
|
||||||
|
}
|
||||||
|
for d in all_bt.values()
|
||||||
|
]
|
||||||
|
rf_payload = [
|
||||||
|
{
|
||||||
|
'frequency': s.get('frequency'),
|
||||||
|
'power': s.get('power', s.get('level')),
|
||||||
|
'modulation': s.get('modulation'),
|
||||||
|
'band': s.get('band'),
|
||||||
|
}
|
||||||
|
for s in all_rf
|
||||||
|
]
|
||||||
|
|
||||||
|
update_tscm_sweep(
|
||||||
|
_current_sweep_id,
|
||||||
|
status='completed',
|
||||||
|
results={
|
||||||
|
'wifi_devices': wifi_payload,
|
||||||
|
'bt_devices': bt_payload,
|
||||||
|
'rf_signals': rf_payload,
|
||||||
|
'wifi_count': len(all_wifi),
|
||||||
|
'bt_count': len(all_bt),
|
||||||
|
'rf_count': len(all_rf),
|
||||||
|
'severity_counts': severity_counts,
|
||||||
|
'correlation_summary': findings.get('summary', {}),
|
||||||
|
'identity_summary': identity_summary.get('statistics', {}),
|
||||||
|
'baseline_comparison': baseline_comparison,
|
||||||
|
'results_detail_level': 'full' if verbose_results else 'compact',
|
||||||
|
},
|
||||||
|
threats_found=threats_found,
|
||||||
|
completed=True
|
||||||
|
)
|
||||||
|
|
||||||
# Emit correlation findings
|
# Emit correlation findings
|
||||||
_emit_event('correlation_findings', {
|
_emit_event('correlation_findings', {
|
||||||
@@ -1506,13 +1548,13 @@ def _run_sweep(
|
|||||||
})
|
})
|
||||||
|
|
||||||
# Emit device identity cluster findings (MAC-randomization resistant)
|
# Emit device identity cluster findings (MAC-randomization resistant)
|
||||||
_emit_event('identity_clusters', {
|
_emit_event('identity_clusters', {
|
||||||
'total_clusters': identity_summary['statistics'].get('total_clusters', 0),
|
'total_clusters': identity_summary.get('statistics', {}).get('total_clusters', 0),
|
||||||
'high_risk_count': identity_summary['statistics'].get('high_risk_count', 0),
|
'high_risk_count': identity_summary.get('statistics', {}).get('high_risk_count', 0),
|
||||||
'medium_risk_count': identity_summary['statistics'].get('medium_risk_count', 0),
|
'medium_risk_count': identity_summary.get('statistics', {}).get('medium_risk_count', 0),
|
||||||
'unique_fingerprints': identity_summary['statistics'].get('unique_fingerprints', 0),
|
'unique_fingerprints': identity_summary.get('statistics', {}).get('unique_fingerprints', 0),
|
||||||
'clusters': identity_clusters,
|
'clusters': identity_clusters,
|
||||||
})
|
})
|
||||||
|
|
||||||
_emit_event('sweep_completed', {
|
_emit_event('sweep_completed', {
|
||||||
'sweep_id': _current_sweep_id,
|
'sweep_id': _current_sweep_id,
|
||||||
@@ -2423,9 +2465,9 @@ def get_baseline_diff(baseline_id: int, sweep_id: int):
|
|||||||
import json
|
import json
|
||||||
results = json.loads(results)
|
results = json.loads(results)
|
||||||
|
|
||||||
current_wifi = results.get('wifi', [])
|
current_wifi = results.get('wifi_devices', [])
|
||||||
current_bt = results.get('bluetooth', [])
|
current_bt = results.get('bt_devices', [])
|
||||||
current_rf = results.get('rf', [])
|
current_rf = results.get('rf_signals', [])
|
||||||
|
|
||||||
diff = calculate_baseline_diff(
|
diff = calculate_baseline_diff(
|
||||||
baseline=baseline,
|
baseline=baseline,
|
||||||
|
|||||||
@@ -69,6 +69,18 @@ echo
|
|||||||
# ----------------------------
|
# ----------------------------
|
||||||
# Helpers
|
# Helpers
|
||||||
# ----------------------------
|
# ----------------------------
|
||||||
|
NON_INTERACTIVE=false
|
||||||
|
|
||||||
|
for arg in "$@"; do
|
||||||
|
case "$arg" in
|
||||||
|
--non-interactive)
|
||||||
|
NON_INTERACTIVE=true
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
cmd_exists() {
|
cmd_exists() {
|
||||||
local c="$1"
|
local c="$1"
|
||||||
command -v "$c" >/dev/null 2>&1 && return 0
|
command -v "$c" >/dev/null 2>&1 && return 0
|
||||||
@@ -76,6 +88,32 @@ cmd_exists() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ask_yes_no() {
|
||||||
|
local prompt="$1"
|
||||||
|
local default="${2:-n}" # default to no for safety
|
||||||
|
local response
|
||||||
|
|
||||||
|
if $NON_INTERACTIVE; then
|
||||||
|
info "Non-interactive mode: defaulting to ${default} for prompt: ${prompt}"
|
||||||
|
[[ "$default" == "y" ]]
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -t 0 ]]; then
|
||||||
|
warn "No TTY available for prompt: ${prompt}"
|
||||||
|
[[ "$default" == "y" ]]
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$default" == "y" ]]; then
|
||||||
|
read -r -p "$prompt [Y/n]: " response
|
||||||
|
[[ -z "$response" || "$response" =~ ^[Yy] ]]
|
||||||
|
else
|
||||||
|
read -r -p "$prompt [y/N]: " response
|
||||||
|
[[ "$response" =~ ^[Yy] ]]
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
have_any() {
|
have_any() {
|
||||||
local c
|
local c
|
||||||
for c in "$@"; do
|
for c in "$@"; do
|
||||||
@@ -111,6 +149,18 @@ detect_os() {
|
|||||||
[[ "$OS" != "unknown" ]] || { fail "Unsupported OS (macOS + Debian/Ubuntu only)."; exit 1; }
|
[[ "$OS" != "unknown" ]] || { fail "Unsupported OS (macOS + Debian/Ubuntu only)."; exit 1; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
detect_dragonos() {
|
||||||
|
IS_DRAGONOS=false
|
||||||
|
# Check for DragonOS markers
|
||||||
|
if [[ -f /etc/dragonos-release ]] || \
|
||||||
|
[[ -d /usr/share/dragonos ]] || \
|
||||||
|
grep -qi "dragonos" /etc/os-release 2>/dev/null; then
|
||||||
|
IS_DRAGONOS=true
|
||||||
|
warn "DragonOS detected! This distro has many tools pre-installed."
|
||||||
|
warn "The script will prompt before making system changes."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# ----------------------------
|
# ----------------------------
|
||||||
# Required tool checks (with alternates)
|
# Required tool checks (with alternates)
|
||||||
# ----------------------------
|
# ----------------------------
|
||||||
@@ -382,6 +432,15 @@ apt_try_install_any() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apt_install_if_missing() {
|
||||||
|
local pkg="$1"
|
||||||
|
if dpkg -l "$pkg" 2>/dev/null | grep -q "^ii"; then
|
||||||
|
ok "apt: ${pkg} already installed"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
apt_install "$pkg"
|
||||||
|
}
|
||||||
|
|
||||||
install_dump1090_from_source_debian() {
|
install_dump1090_from_source_debian() {
|
||||||
info "dump1090 not available via APT. Building from source (required)..."
|
info "dump1090 not available via APT. Building from source (required)..."
|
||||||
|
|
||||||
@@ -543,9 +602,17 @@ EOF
|
|||||||
install_debian_packages() {
|
install_debian_packages() {
|
||||||
need_sudo
|
need_sudo
|
||||||
|
|
||||||
# Suppress needrestart prompts (Ubuntu Server 22.04+)
|
# Keep APT interactive when a TTY is available.
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
if $NON_INTERACTIVE; then
|
||||||
export NEEDRESTART_MODE=a
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
export NEEDRESTART_MODE=a
|
||||||
|
elif [[ -t 0 ]]; then
|
||||||
|
export DEBIAN_FRONTEND=readline
|
||||||
|
export NEEDRESTART_MODE=a
|
||||||
|
else
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
export NEEDRESTART_MODE=a
|
||||||
|
fi
|
||||||
|
|
||||||
TOTAL_STEPS=18
|
TOTAL_STEPS=18
|
||||||
CURRENT_STEP=0
|
CURRENT_STEP=0
|
||||||
@@ -554,42 +621,59 @@ install_debian_packages() {
|
|||||||
$SUDO apt-get update -y >/dev/null
|
$SUDO apt-get update -y >/dev/null
|
||||||
|
|
||||||
progress "Installing RTL-SDR"
|
progress "Installing RTL-SDR"
|
||||||
# Handle package conflict between librtlsdr0 and librtlsdr2
|
if ! $IS_DRAGONOS; then
|
||||||
# The newer librtlsdr0 (2.0.2) conflicts with older librtlsdr2 (2.0.1)
|
# Handle package conflict between librtlsdr0 and librtlsdr2
|
||||||
if dpkg -l | grep -q "librtlsdr2"; then
|
# The newer librtlsdr0 (2.0.2) conflicts with older librtlsdr2 (2.0.1)
|
||||||
info "Detected librtlsdr2 conflict - upgrading to librtlsdr0..."
|
if dpkg -l | grep -q "librtlsdr2"; then
|
||||||
|
info "Detected librtlsdr2 conflict - upgrading to librtlsdr0..."
|
||||||
|
|
||||||
# Remove packages that depend on librtlsdr2, then remove librtlsdr2
|
# Remove packages that depend on librtlsdr2, then remove librtlsdr2
|
||||||
# These will be reinstalled with librtlsdr0 support
|
# These will be reinstalled with librtlsdr0 support
|
||||||
$SUDO apt-get remove -y dump1090-mutability libgnuradio-osmosdr0.2.0t64 rtl-433 librtlsdr2 rtl-sdr 2>/dev/null || true
|
$SUDO apt-get remove -y dump1090-mutability libgnuradio-osmosdr0.2.0t64 rtl-433 librtlsdr2 rtl-sdr 2>/dev/null || true
|
||||||
$SUDO apt-get autoremove -y 2>/dev/null || true
|
$SUDO apt-get autoremove -y 2>/dev/null || true
|
||||||
|
|
||||||
ok "Removed conflicting librtlsdr2 packages"
|
ok "Removed conflicting librtlsdr2 packages"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If rtl-sdr is in broken state, remove it completely first
|
||||||
|
if dpkg -l | grep -q "^.[^i].*rtl-sdr" || ! dpkg -l rtl-sdr 2>/dev/null | grep -q "^ii"; then
|
||||||
|
info "Removing broken rtl-sdr package..."
|
||||||
|
$SUDO dpkg --remove --force-remove-reinstreq rtl-sdr 2>/dev/null || true
|
||||||
|
$SUDO dpkg --purge --force-remove-reinstreq rtl-sdr 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Force remove librtlsdr2 if it still exists
|
||||||
|
if dpkg -l | grep -q "librtlsdr2"; then
|
||||||
|
info "Force removing librtlsdr2..."
|
||||||
|
$SUDO dpkg --remove --force-all librtlsdr2 2>/dev/null || true
|
||||||
|
$SUDO dpkg --purge --force-all librtlsdr2 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean up any partial installations
|
||||||
|
$SUDO dpkg --configure -a 2>/dev/null || true
|
||||||
|
$SUDO apt-get --fix-broken install -y 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# If rtl-sdr is in broken state, remove it completely first
|
apt_install_if_missing rtl-sdr
|
||||||
if dpkg -l | grep -q "^.[^i].*rtl-sdr" || ! dpkg -l rtl-sdr 2>/dev/null | grep -q "^ii"; then
|
|
||||||
info "Removing broken rtl-sdr package..."
|
progress "RTL-SDR Blog drivers"
|
||||||
$SUDO dpkg --remove --force-remove-reinstreq rtl-sdr 2>/dev/null || true
|
if cmd_exists rtl_test; then
|
||||||
$SUDO dpkg --purge --force-remove-reinstreq rtl-sdr 2>/dev/null || true
|
info "RTL-SDR tools already installed."
|
||||||
|
if $IS_DRAGONOS; then
|
||||||
|
info "Skipping RTL-SDR Blog driver installation (DragonOS has working drivers)."
|
||||||
|
else
|
||||||
|
echo "RTL-SDR Blog drivers provide improved support for V4 dongles."
|
||||||
|
echo "Installing these will REPLACE your current RTL-SDR drivers."
|
||||||
|
if ask_yes_no "Install RTL-SDR Blog drivers?"; then
|
||||||
|
install_rtlsdr_blog_drivers_debian
|
||||||
|
else
|
||||||
|
ok "Keeping existing RTL-SDR drivers."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
install_rtlsdr_blog_drivers_debian
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Force remove librtlsdr2 if it still exists
|
|
||||||
if dpkg -l | grep -q "librtlsdr2"; then
|
|
||||||
info "Force removing librtlsdr2..."
|
|
||||||
$SUDO dpkg --remove --force-all librtlsdr2 2>/dev/null || true
|
|
||||||
$SUDO dpkg --purge --force-all librtlsdr2 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Clean up any partial installations
|
|
||||||
$SUDO dpkg --configure -a 2>/dev/null || true
|
|
||||||
$SUDO apt-get --fix-broken install -y 2>/dev/null || true
|
|
||||||
|
|
||||||
apt_install rtl-sdr
|
|
||||||
|
|
||||||
progress "Installing RTL-SDR Blog drivers (V4 support)"
|
|
||||||
install_rtlsdr_blog_drivers_debian
|
|
||||||
|
|
||||||
progress "Installing multimon-ng"
|
progress "Installing multimon-ng"
|
||||||
apt_install multimon-ng
|
apt_install multimon-ng
|
||||||
|
|
||||||
@@ -650,8 +734,20 @@ install_debian_packages() {
|
|||||||
progress "Configuring udev rules"
|
progress "Configuring udev rules"
|
||||||
setup_udev_rules_debian
|
setup_udev_rules_debian
|
||||||
|
|
||||||
progress "Blacklisting conflicting kernel drivers"
|
progress "Kernel driver configuration"
|
||||||
blacklist_kernel_drivers_debian
|
echo
|
||||||
|
if $IS_DRAGONOS; then
|
||||||
|
info "DragonOS already has RTL-SDR drivers configured correctly."
|
||||||
|
info "Skipping kernel driver blacklist (not needed)."
|
||||||
|
else
|
||||||
|
echo "The DVB-T kernel drivers conflict with RTL-SDR userspace access."
|
||||||
|
echo "Blacklisting them allows rtl_sdr tools to access the device."
|
||||||
|
if ask_yes_no "Blacklist conflicting kernel drivers?"; then
|
||||||
|
blacklist_kernel_drivers_debian
|
||||||
|
else
|
||||||
|
warn "Skipped kernel driver blacklist. RTL-SDR may not work without manual config."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# ----------------------------
|
# ----------------------------
|
||||||
@@ -685,11 +781,42 @@ final_summary_and_hard_fail() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ----------------------------
|
||||||
|
# Pre-flight summary
|
||||||
|
# ----------------------------
|
||||||
|
show_install_summary() {
|
||||||
|
info "Installation Summary:"
|
||||||
|
echo
|
||||||
|
echo " OS: $OS"
|
||||||
|
$IS_DRAGONOS && echo " DragonOS: Yes (safe mode enabled)"
|
||||||
|
echo
|
||||||
|
echo " This script will:"
|
||||||
|
echo " - Install missing SDR tools (rtl-sdr, multimon-ng, etc.)"
|
||||||
|
echo " - Install Python dependencies in a virtual environment"
|
||||||
|
echo
|
||||||
|
if ! $IS_DRAGONOS; then
|
||||||
|
echo " You will be prompted before:"
|
||||||
|
echo " - Installing RTL-SDR Blog drivers (replaces existing)"
|
||||||
|
echo " - Blacklisting kernel DVB drivers"
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
if $NON_INTERACTIVE; then
|
||||||
|
info "Non-interactive mode: continuing without prompt."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
if ! ask_yes_no "Continue with installation?" "y"; then
|
||||||
|
info "Installation cancelled."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# ----------------------------
|
# ----------------------------
|
||||||
# MAIN
|
# MAIN
|
||||||
# ----------------------------
|
# ----------------------------
|
||||||
main() {
|
main() {
|
||||||
detect_os
|
detect_os
|
||||||
|
detect_dragonos
|
||||||
|
show_install_summary
|
||||||
|
|
||||||
if [[ "$OS" == "macos" ]]; then
|
if [[ "$OS" == "macos" ]]; then
|
||||||
install_macos_packages
|
install_macos_packages
|
||||||
@@ -702,4 +829,3 @@ main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|
||||||
|
|||||||
@@ -7860,6 +7860,7 @@
|
|||||||
const wifiInterface = document.getElementById('tscmWifiInterface').value;
|
const wifiInterface = document.getElementById('tscmWifiInterface').value;
|
||||||
const btInterface = document.getElementById('tscmBtInterface').value;
|
const btInterface = document.getElementById('tscmBtInterface').value;
|
||||||
const sdrDevice = document.getElementById('tscmSdrDevice').value;
|
const sdrDevice = document.getElementById('tscmSdrDevice').value;
|
||||||
|
const verboseResults = document.getElementById('tscmVerboseResults').checked;
|
||||||
|
|
||||||
// Clear any previous warnings
|
// Clear any previous warnings
|
||||||
document.getElementById('tscmDeviceWarnings').style.display = 'none';
|
document.getElementById('tscmDeviceWarnings').style.display = 'none';
|
||||||
@@ -7877,7 +7878,8 @@
|
|||||||
rf: rfEnabled,
|
rf: rfEnabled,
|
||||||
wifi_interface: wifiInterface,
|
wifi_interface: wifiInterface,
|
||||||
bt_interface: btInterface,
|
bt_interface: btInterface,
|
||||||
sdr_device: sdrDevice ? parseInt(sdrDevice) : null
|
sdr_device: sdrDevice ? parseInt(sdrDevice) : null,
|
||||||
|
verbose_results: verboseResults
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -10562,4 +10564,4 @@
|
|||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -23,6 +23,15 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div style="display: flex; align-items: center; gap: 8px;">
|
||||||
|
<input type="checkbox" id="tscmVerboseResults" style="margin: 0;">
|
||||||
|
<label for="tscmVerboseResults" style="flex: 1; margin: 0; font-size: 12px;">
|
||||||
|
Verbose results (store full device details)
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div style="border-top: 1px solid var(--border-color); padding-top: 12px; margin-top: 12px;">
|
<div style="border-top: 1px solid var(--border-color); padding-top: 12px; margin-top: 12px;">
|
||||||
<label style="display: block; font-size: 11px; font-weight: 600; margin-bottom: 8px; color: var(--text-secondary);">Scan Sources</label>
|
<label style="display: block; font-size: 11px; font-weight: 600; margin-bottom: 8px; color: var(--text-secondary);">Scan Sources</label>
|
||||||
<div class="form-group" style="margin-bottom: 8px;">
|
<div class="form-group" style="margin-bottom: 8px;">
|
||||||
|
|||||||
+21
-9
@@ -761,15 +761,27 @@ def generate_report(
|
|||||||
# Add findings from profiles
|
# Add findings from profiles
|
||||||
builder.add_findings_from_profiles(device_profiles)
|
builder.add_findings_from_profiles(device_profiles)
|
||||||
|
|
||||||
# Statistics
|
# Statistics
|
||||||
results = sweep_data.get('results', {})
|
results = sweep_data.get('results', {})
|
||||||
builder.add_statistics(
|
wifi_count = results.get('wifi_count')
|
||||||
wifi=len(results.get('wifi', [])),
|
if wifi_count is None:
|
||||||
bluetooth=len(results.get('bluetooth', [])),
|
wifi_count = len(results.get('wifi_devices', results.get('wifi', [])))
|
||||||
rf=len(results.get('rf', [])),
|
|
||||||
new=baseline_diff.get('summary', {}).get('new_devices', 0) if baseline_diff else 0,
|
bt_count = results.get('bt_count')
|
||||||
missing=baseline_diff.get('summary', {}).get('missing_devices', 0) if baseline_diff else 0,
|
if bt_count is None:
|
||||||
)
|
bt_count = len(results.get('bt_devices', results.get('bluetooth', [])))
|
||||||
|
|
||||||
|
rf_count = results.get('rf_count')
|
||||||
|
if rf_count is None:
|
||||||
|
rf_count = len(results.get('rf_signals', results.get('rf', [])))
|
||||||
|
|
||||||
|
builder.add_statistics(
|
||||||
|
wifi=wifi_count,
|
||||||
|
bluetooth=bt_count,
|
||||||
|
rf=rf_count,
|
||||||
|
new=baseline_diff.get('summary', {}).get('new_devices', 0) if baseline_diff else 0,
|
||||||
|
missing=baseline_diff.get('summary', {}).get('missing_devices', 0) if baseline_diff else 0,
|
||||||
|
)
|
||||||
|
|
||||||
# Technical data
|
# Technical data
|
||||||
builder.add_device_timelines(timelines)
|
builder.add_device_timelines(timelines)
|
||||||
|
|||||||
Reference in New Issue
Block a user