Files
bigbrother/utils/logging.py
T
n0mad1k ccc6b729de Initial public release
Full BigBrother network implant - passive SOC + active exploitation.
Personal identifiers removed; all capabilities intact.
See README.md for setup and docs/deployment.md for detailed deployment.
2026-06-26 09:52:50 -04:00

147 lines
4.5 KiB
Python

#!/usr/bin/env python3
"""Encrypted log writer for SystemMonitor. Named bb_logging to avoid shadowing stdlib logging."""
import logging
import os
import time
from pathlib import Path
from typing import Optional
LOG_FORMAT = "[{timestamp}] [{module}] [{level}] {message}"
MAX_LOG_SIZE = 10 * 1024 * 1024 # 10MB default rotation size
LOG_DIR = "storage/logs"
class EncryptedLogHandler(logging.Handler):
def __init__(
self,
module_name: str,
log_dir: str = LOG_DIR,
max_bytes: int = MAX_LOG_SIZE,
encrypt: bool = False,
crypto_engine=None,
):
super().__init__()
self.module_name = module_name
self.log_dir = Path(log_dir)
self.log_dir.mkdir(parents=True, exist_ok=True)
self.max_bytes = max_bytes
self.encrypt = encrypt
self.crypto_engine = crypto_engine
self._log_path = self.log_dir / f"{module_name}.log"
self._file = None
self._current_size = 0
self._open_file()
def _open_file(self):
if self._file:
self._file.close()
mode = "ab" if self.encrypt else "a"
self._file = open(self._log_path, mode)
self._current_size = self._log_path.stat().st_size if self._log_path.exists() else 0
def _rotate(self):
if self._file:
self._file.close()
rotated = self._log_path.with_suffix(f".log.{int(time.time())}")
if self._log_path.exists():
self._log_path.rename(rotated)
self._open_file()
def emit(self, record):
try:
ts = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(record.created))
line = LOG_FORMAT.format(
timestamp=ts,
module=self.module_name,
level=record.levelname,
message=record.getMessage(),
)
if self.encrypt and self.crypto_engine:
data = self.crypto_engine.encrypt(line.encode("utf-8"))
length_prefix = len(data).to_bytes(4, "big")
self._file.write(length_prefix)
self._file.write(data)
self._current_size += 4 + len(data)
else:
line += "\n"
self._file.write(line)
self._current_size += len(line.encode("utf-8"))
self._file.flush()
if self._current_size >= self.max_bytes:
self._rotate()
except Exception:
self.handleError(record)
def close(self):
if self._file:
self._file.close()
self._file = None
super().close()
class BBLogger:
def __init__(
self,
module_name: str,
log_dir: str = LOG_DIR,
max_bytes: int = MAX_LOG_SIZE,
level: int = logging.INFO,
encrypt: bool = False,
crypto_engine=None,
suppress_stdout: bool = True,
):
self.module_name = module_name
self.logger = logging.getLogger(f"sensor.{module_name}")
self.logger.setLevel(level)
self.logger.propagate = False
# Clear existing handlers to prevent duplicates
self.logger.handlers.clear()
self._file_handler = EncryptedLogHandler(
module_name=module_name,
log_dir=log_dir,
max_bytes=max_bytes,
encrypt=encrypt,
crypto_engine=crypto_engine,
)
self._file_handler.setLevel(level)
self.logger.addHandler(self._file_handler)
if not suppress_stdout:
console = logging.StreamHandler()
console.setLevel(level)
fmt = logging.Formatter(
"[%(asctime)s] [%(name)s] [%(levelname)s] %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
console.setFormatter(fmt)
self.logger.addHandler(console)
def debug(self, msg: str, *args, **kwargs):
self.logger.debug(msg, *args, **kwargs)
def info(self, msg: str, *args, **kwargs):
self.logger.info(msg, *args, **kwargs)
def warning(self, msg: str, *args, **kwargs):
self.logger.warning(msg, *args, **kwargs)
def error(self, msg: str, *args, **kwargs):
self.logger.error(msg, *args, **kwargs)
def critical(self, msg: str, *args, **kwargs):
self.logger.critical(msg, *args, **kwargs)
def set_level(self, level: int):
self.logger.setLevel(level)
self._file_handler.setLevel(level)
def close(self):
self._file_handler.close()
self.logger.removeHandler(self._file_handler)