How bb-24/mars_static works
1. This is a desktop malware-analysis tool, not a server application.
The entry point is main.py, which boots a CustomTkinter GUI and ties it to a local analysis pipeline. The system runs entirely on the analyst’s machine and writes artifacts to a local workspace.
2. Bootstrap and configuration are centralized.
config/config.yaml drives the behavior of the whole app: workspace paths, allowed file extensions, unpack depth, file-size limits, entropy thresholds, suspicious import lists, and the YARA rules path. Startup also verifies required directories and compiles the local YARA ruleset from rules/rules.yar.
3. The GUI is a thin interaction layer.
gui/app.py provides the desktop dashboard for browsing a sample and starting analysis. It does not perform analysis itself; it delegates to the pipeline and displays results/events. The PyPubSub dependency suggests UI updates are event-driven rather than tightly coupled to analysis code.
4. core/pipeline.py is the orchestration boundary.
This is the central coordinator that connects intake, archive handling, static analysis, and reporting. Its job is to take a selected file, decide which processing path applies, and assemble the final results object that the GUI and report generator consume.
5. Intake is the first security gate.
core/intake.py validates the input before anything else happens: file existence, extension allowlist, size limits, hash computation, magic-byte/metadata checks, and basic sample identity. This protects later stages from unsupported or malformed inputs and creates the initial file fingerprint for reporting.
6. Archive/package handling is a separate subsystem.
core/package.py handles ZIP/MSI-style package inputs, recursive extraction, and extraction-depth limits. It also inventories extracted files and records SHA256 hashes plus flagged payload extensions. Extracted non-PE files are tracked, but only PE-like payloads continue into static analysis.
7. Static PE inspection is the main analysis engine.
core/static.py performs offline analysis of Windows binaries using pefile. It extracts PE metadata, section characteristics, entropy, imported APIs, manifest data, and mitigation flags. It also applies heuristics for packing/obfuscation and suspicious section permissions such as RWE.
8. Detection logic is layered, not monolithic.
The static analyzer combines several independent checks:
- mitigation presence/absence: DEP/NX, ASLR, CFG, SafeSEH, stack canaries, CET/shadow stack, force integrity, AppContainer
- import-based behavior signals: process injection, execution, networking, anti-analysis
- manifest execution intent
- regex artifact extraction for IPs, URLs, registry paths, emails, and password-like strings
This makes the output more explainable than a single “malicious/benign” score.
9. YARA scanning is a local enrichment step.
The repo uses yara-python and a single ruleset in rules/rules.yar. YARA is compiled at startup and then used during static analysis if available. If compilation fails, scanning is skipped rather than blocking the rest of the pipeline.
10. Reporting is an output boundary with two formats.
core/report.py turns the analysis result into both JSON and PDF reports. Outputs go to workspace/reports/ with a unique analysis ID prefix. This separates machine-readable results from analyst-friendly presentation.
11. The workspace is the main persistence boundary.
The app writes extracted archive contents and inventory logs to workspace/extracted/, and final reports to workspace/reports/. Nothing in the architecture suggests remote storage or cloud services; all state is local filesystem state.
12. Supported inputs are Windows-centric and static-only.
The default allowlist targets .exe, .dll, .msi, .sys, and .zip. The analysis never executes samples, so this repo’s architecture is centered on safe inspection of Windows executables and archive payloads in an isolated lab workflow.
13. Key architectural flow for a diagram:
User selects file in the GUI → pipeline triggers intake validation and hashing → archive inputs are unpacked/inventoried if needed → PE payloads undergo static/YARA analysis → results are aggregated → JSON/PDF reports are written to the workspace and surfaced back to the GUI.
14. Main dependency profile that matters architecturally:
customtkinter for the desktop UI, pefile for PE parsing, yara-python for signatures, fpdf2 for PDF generation, PyYAML for config loading, and PyPubSub for decoupled UI messaging. These libraries map directly to the major subsystem boundaries above.
Main entry points: pipeline.py Pipeline · static.py Static Analysis · app.py App UI · main.py main.py
Components 16
Desktop UI
CustomTkinter front-end and event-driven user interaction layer
- App UI · Analyst dashboard for selecting samples and viewing results
gui/app.py - Events · Decoupled UI update channel used between analysis and the GUI
- CustomTkinter · Provides the desktop UI toolkit
Analysis Core
Local orchestration, intake, package handling, static inspection, and reporting
- Pipeline · Coordinates intake, package handling, static analysis, and result assembly
core/pipeline.py - Intake · Validates sample identity, size, extension, and hashes before analysis
core/intake.py - Package Scan · Extracts and inventories ZIP/MSI-style inputs with depth limits
core/package.py - Static Analysis · Offline PE inspection, heuristics, import review, and artifact extraction
core/static.py - Report · Builds JSON and PDF analysis reports for the local workspace
core/report.py - pefile · Parses Windows PE structure and metadata
- yara-python · Runs compiled YARA signatures against samples
- fpdf2 · Generates analyst-friendly PDF reports
Bootstrap
Startup and configuration loading
Rules & Workspace
Local signature rules and filesystem output locations
- YARA Rules · Local ruleset compiled at startup and used as static enrichment
rules/rules.yar - Workspace · Filesystem area for extracted files, inventories, and reports
Connections 22
- main.py → PyYAML: load config · Startup reads centralized settings
- main.py → Config: bootstrap · Initializes app behavior from config
- main.py → App UI: launch UI · Starts the analyst dashboard
- App UI → CustomTkinter: renders with · Desktop widgets and layout
- App UI → Events: publishes · Sends UI events and status updates
- App UI → Pipeline: start analysis · Delegates selected sample to the analysis pipeline
- Pipeline → Intake: validate · Checks input before any deeper processing
- Pipeline → Package Scan: unpack if needed · Routes archive/package inputs to extraction
- Pipeline → Static Analysis: analyze · Performs offline PE inspection on eligible payloads
- Pipeline → Report: assemble result · Collects outputs into final analysis object and reports
- Intake → Workspace: fingerprint · Stores file identity and supporting artifacts locally
- Package Scan → Workspace: extract · Writes extracted payloads and inventory logs
- Package Scan → Static Analysis: pass payloads · Sends PE-like extracted files onward for analysis
- Static Analysis → pefile: parse PE · Reads headers, sections, imports, and mitigations
- Static Analysis → YARA Rules: scan · Applies local signature rules when available
- Static Analysis → yara-python: use engine · Uses compiled YARA runtime for matching
- Report → fpdf2: render PDF · Generates human-readable report output
- Report → Workspace: write reports · Persists JSON and PDF outputs under the local workspace
- YARA Rules → Workspace: loaded from · Rules are stored locally alongside the app
- Config → YARA Rules: points to · Configuration selects the active ruleset path
- Config → Workspace: defines paths · Config determines extraction and report locations
- Pipeline → Events: emit progress · Analysis progress can be surfaced asynchronously to the GUI