Anti-Ransomware Module (AntiRansomwarePage)

Overview

The Anti-Ransomware module is implemented by the AntiRansomwarePage class. This module provides two complementary capabilities:

  • Manual scanning of a selected file or directory using YARA rules (local static detection)
  • Real-time event visibility by tailing a dedicated daemon log file and rendering relevant security events in the UI

Threat notifications are propagated via D-Bus using the BastionGuard alert interface, with a local GTK dialog used as a fallback when D-Bus is unavailable.


User Interface Structure

Header

The page uses a security-themed header bar consistent with other protection modules. The header is built using a horizontal Gtk::Box with the CSS class secure-headerbar, containing a centered label with the CSS class secure-header-title.

Displayed title:

Anti-Ransomware

Action Buttons

The module exposes four primary actions (buttons) in a single horizontal toolbar:

  • btnChooseFile – selects a file target (manual scan)
  • btnChooseFolder – selects a directory target (manual scan)
  • btnScan – executes the manual scan workflow
  • btnTest – sends a test alert to validate the notification path

Button labels (as defined in code):

📄 Scegli file
📂 Scegli cartella
🧪 Scansiona
🔔 Test notifica

Log Viewer

The module renders an operational log area used for both manual scan output and real-time event lines. It is implemented using:

  • Gtk::TextBuffer (textBuffer)
  • Gtk::TextView (textView)
  • Gtk::ScrolledWindow with a minimum height of 250px

The log view is read-only and word-wrapped.


Initialization Sequence

When AntiRansomwarePage is constructed, it performs the following high-level steps:

  1. Builds the UI layout (header, toolbar, log viewer)
  2. Registers button signal handlers
  3. Appends a “ready” line to the log
  4. Initializes and loads YARA rules via loadYaraRules()
  5. Starts the real-time log reader thread via startRealtimeLogReader()

Initial log line:

🔐 Anti-Ransomware pronto.

Manual Scan Workflow (YARA)

Target Selection

The user selects a scan target into selectedPath using standard GTK file chooser dialogs:

  • AntiRansomwarePage::onChooseFile() uses Gtk::FileChooserDialog with action OPEN
  • AntiRansomwarePage::onChooseFolder() uses Gtk::FileChooserDialog with action SELECT_FOLDER

On successful selection, the path is logged:

  • 📄 File selezionato: <path>
  • 📂 Cartella selezionata: <path>

Scan Dispatch Logic

Manual scanning is started by AntiRansomwarePage::onManualScan(). It validates selectedPath and dispatches based on filesystem type:

  • If selectedPath is a regular file: runYaraOnPath(selectedPath)
  • If selectedPath is a directory: scanDirectoryRecursively(selectedPath)
  • Otherwise: logs an invalid path message

Directory scanning enumerates files recursively using:

std::filesystem::recursive_directory_iterator(root)

YARA Engine Initialization and Rule Loading

The module initializes YARA during rule load:

yr_initialize()
yr_compiler_create(&yaraCompiler)

Rules are loaded from the fixed directory:

/usr/share/BastionGuard/data/yara

All files with extensions .yar or .yara are compiled using:

yr_compiler_add_file(yaraCompiler, f, nullptr, file.path().c_str())

After compilation, the ruleset is produced using:

yr_compiler_get_rules(yaraCompiler, &yaraRules)

If the directory does not exist, the module logs that no rules are available and does not perform YARA scans.


YARA Scan Execution

Each file is scanned using:

yr_rules_scan_file(yaraRules, path.c_str(), 0, yara_callback_gui, this, 0)

The scan logs the file being scanned:

🔍 Scansione: <path>

If YARA returns an error (non ERROR_SUCCESS), the error code is logged.


YARA Match Callback and Alert Triggering

YARA matches for manual scans are delivered via the callback:

static int yara_callback_gui(...)

When a rule matches (CALLBACK_MSG_RULE_MATCHING):

  • The rule identifier is extracted from rule->identifier
  • If empty, the rule namespace (rule->ns->name) is used as a fallback identifier
  • A match line is appended to the GUI log
  • An alert is raised using AntiRansomwarePage::sendAlert(selectedPath, rule_name)

Alerting Mechanism (D-Bus + GUI Fallback)

Alerts are emitted via the session D-Bus interface:

Service:   org.BastionGuard.Ransomware.Alert
Path:      /org/BastionGuard/ransomware/alert
Interface: org.BastionGuard.Ransomware.Alert
Method:    ShowAlert(file, ruleName)

The alert call is constructed as a tuple containing:

  • file (string path)
  • ruleName (YARA rule identifier or event label)

If D-Bus fails, the module falls back to a modal warning dialog:

  • Gtk::MessageDialog
  • Type: Gtk::MessageType::WARNING
  • Buttons: Gtk::ButtonsType::OK

Test Alert Function

The notification pipeline can be validated using the “test alert” button, which invokes:

AntiRansomwarePage::onTestAlert()
sendAlert("/tmp/testfile", "TestRule")

This action does not perform scanning; it exists solely to verify that the D-Bus/GUI alert presentation path is functional.


Real-Time Log Reader (Daemon Visibility)

Purpose

In addition to manual scans, the page provides visibility into events generated by the Anti-Ransomware realtime daemon by tailing a log file and surfacing only relevant lines (match and alert signals).

Log File Source

The log reader tails:

/var/log/BastionGuard/antiransom_inotify.log

Threading Model

The log reader runs in a dedicated background thread started by startRealtimeLogReader(). The thread:

  • Opens the logfile
  • Seeks to end-of-file (tail behavior)
  • Polls for new lines every ~200ms when no new data is available
  • Marshals each new log line back to the GTK main loop using Glib::signal_idle().connect_once()

Important: UI updates are scheduled on the GTK main thread to preserve thread safety.

Lifecycle and Shutdown

The log reader is controlled by logThreadRunning. In the destructor (~AntiRansomwarePage()):

  • logThreadRunning is set to false
  • The thread is joined if joinable
  • YARA resources are released using yr_rules_destroy() and yr_compiler_destroy()

Log Line Parser (Real-Time Daemon Events)

Real-time log lines are processed by AntiRansomwarePage::processLogLine(const std::string& line), which intentionally extracts only security-relevant events.

1. Daemon “MATCH” Events

If a line contains the substring:

MATCH →

the parser extracts the rule name from the remainder of the line and logs:

⚠ MATCH realtime: <rule>

2. Daemon “Alert sent” Events

If a line contains:

Alert inviato:

the parser expects the format:

Alert inviato: <file> | <rule>

After trimming whitespace, the UI logs:

🚨 ALERT realtime: <rule> → <file>

All other log lines are ignored.


Design and Security Considerations

  • Manual scan uses YARA: local static analysis is performed entirely offline using rules deployed under /usr/share/BastionGuard/data/yara.
  • Centralized alert channel: both manual YARA matches and realtime daemon outcomes can be surfaced consistently through the same D-Bus alert interface.
  • Thread-safe GUI updates: background log reading never updates GTK widgets directly; all UI writes are marshaled via Glib::signal_idle().
  • Controlled parsing: the realtime log parser intentionally ignores non-critical lines, reducing UI noise and avoiding misleading output.
  • Graceful degradation: if D-Bus is not available, alerts fall back to a local warning dialog.

Key Files, Paths, and Interfaces

  • YARA rules directory: /usr/share/BastionGuard/data/yara
  • Realtime daemon log: /var/log/BastionGuard/antiransom_inotify.log
  • D-Bus alert interface:
org.BastionGuard.Ransomware.Alert
/org/BastionGuard/ransomware/alert
org.BastionGuard.Ransomware.Alert
Method: ShowAlert(file, ruleName)