Skip to content

Application Architecture

BlackSnufkin edited this page May 3, 2026 · 6 revisions

Application Architecture

LitterBox is a Flask app with server-rendered Jinja templates and vanilla-JS ES6 modules on the frontend (no build step). Analysis is performed by a registry of pluggable analyzer classes; the EDR pipeline is a separate orchestrator that talks to a remote agent over HTTP.


High-level dispatch

graph LR
    Upload[Operator uploads sample] --> Hash[Hash + metadata + entropy]
    Hash --> Type{Type}
    Type -->|.exe / .dll / .lnk / .docx / .xlsx / .bin| FileFlow[File analysis]
    Type -->|.sys| DriverFlow[Driver analysis]
    PID[Operator picks a PID] --> ProcessFlow[Process analysis]

    FileFlow --> StaticGroup[Static analyzers]
    FileFlow --> DynamicGroup[Dynamic analyzers]
    FileFlow --> EdrGroup[EDR profiles]
    DriverFlow --> Holygrail[HolyGrail BYOVD]
    ProcessFlow --> DynamicGroup

    StaticGroup --> Persist[(Saved JSON)]
    DynamicGroup --> Persist
    EdrGroup --> Persist
    Holygrail --> Persist

    Persist --> Risk[Risk scoring]
    Risk --> Render[Results pages]
Loading

Each rounded box is a separate JSON file under Results/<hash>_<original-name>/:

File Source
file_info.json written at upload β€” hashes, entropy, PE info, etc.
static_analysis_results.json YARA + CheckPlz + Stringnalyzer findings
dynamic_analysis_results.json YARA-mem + PE-Sieve + Moneta + Patriot + HSB + RedEdr
byovd_results.json HolyGrail driver analysis
edr_<profile>_results.json one per dispatched EDR profile (kind: elastic or kind: fibratus)
_summary_cache.json mtime-validated dashboard payload (auto-generated)

EDR dispatch (v5)

LitterBox host                              EDR-instrumented Windows VM
                                                                                 
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  ElasticEdrAnalyzer  /          β”‚         β”‚  Whiskers.exe (Rust HTTP)   β”‚
β”‚  FibratusEdrAnalyzer            β”‚ ──HTTP─►│   /api/info                 β”‚
β”‚  β”Œβ”€ Phase 1 (sync) ─┐           β”‚ ◄───────   /api/lock/{acquire,...}    β”‚
β”‚  β”‚ get_info         β”‚           β”‚         β”‚   /api/execute/exec (XOR)   β”‚
β”‚  β”‚ lock_acquire     β”‚           β”‚         β”‚   /api/logs/execution       β”‚
β”‚  β”‚ exec (XOR'd)     β”‚           β”‚         β”‚   /api/alerts/fibratus/...  β”‚
β”‚  β”‚ wait_for_exit    β”‚           β”‚         β”‚                             β”‚
β”‚  β”‚ kill (idempotent)β”‚           β”‚         β”‚   ↑ same VM ↑               β”‚
β”‚  β”‚ get_logs         β”‚           β”‚         β”‚                             β”‚
β”‚  β”‚ lock_release     β”‚           β”‚         β”‚   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜           β”‚         β”‚   β”‚ Elastic Defend agent β”‚  β”‚
β”‚        ↓ returns Phase 1 dict   β”‚         β”‚   β”‚      OR              β”‚  β”‚
β”‚        ↓ status=polling_alerts  β”‚         β”‚   β”‚ Fibratus (ETW)       β”‚  β”‚
β”‚  β”Œβ”€ Phase 2 (daemon thread)──┐  β”‚         β”‚   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚  β”‚ poll alerts every 2s      β”‚  β”‚         β”‚            ↓                β”‚
β”‚  β”‚ early-return on first hit β”‚  β”‚         β”‚     Application event log   β”‚
β”‚  β”‚ settle window for bursts  β”‚  β”‚         β”‚       (Provider=Fibratus)   β”‚
β”‚  β”‚ save final findings JSON  β”‚  β”‚         β”‚            ↓                β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚         └─── Whiskers wevtutil-queriesβ”‚
β”‚        ↓                         β”‚                                       β”‚
β”‚  Frontend polls saved JSON       β”‚         OR    Elastic stack           β”‚
β”‚  every 2-15s (adaptive)          β”‚                  ↑ HTTP to            β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                   ElasticClient.fetch_alerts

Two-phase split keeps the agent lock window tight: Phase 1 holds the lock through exec β†’ log fetch β†’ release (~1-7s typical); Phase 2 runs unlocked so back-to-back dispatches don't queue. Time-bounded queries keep concurrent runs from polluting each other.

See EDR Integration for the full discussion.


Backend layout

litterbox.py                # admin-check + Flask app.run(); entry point
config/config.yaml          # all paths, tool configs, timeouts, enable flags
app/
β”œβ”€β”€ __init__.py             # create_app() β€” wires AnalysisManager + RouteHelpers
β”œβ”€β”€ helpers.py              # RouteHelpers β€” load_analysis_data, calculate risk
β”œβ”€β”€ blueprints/             # one Flask blueprint per concern
β”‚   β”œβ”€β”€ upload.py           # GET / (dashboard) + GET /upload + POST /upload
β”‚   β”œβ”€β”€ analysis.py         # /validate, /analyze/*, /analyze/all, /analyze/edr,
β”‚   β”‚                       # /holygrail, /whiskers
β”‚   β”œβ”€β”€ results.py          # /results/<type>/<target>, /results/edr/<profile>/<target>,
β”‚   β”‚                       # /summary, /files
β”‚   β”œβ”€β”€ doppelganger.py     # /doppelganger
β”‚   β”œβ”€β”€ management.py       # /cleanup, /health, DELETE /file/<target>
β”‚   └── api.py              # /api/results/..., /api/edr/..., /api/system/scanners,
β”‚                           # /api/report/<target>
β”œβ”€β”€ services/
β”‚   β”œβ”€β”€ rendering.py        # render_pid_results, render_file_results
β”‚   β”œβ”€β”€ summary.py          # process_pid_summary, process_file_summary
β”‚   β”œβ”€β”€ summary_cache.py    # mtime-validated per-sample cache
β”‚   β”œβ”€β”€ tool_check.py       # check_analysis_tool, check_holygrail_tool
β”‚   β”œβ”€β”€ edr_health.py       # TTL-cached agent reachability + background poller
β”‚   └── error_handling.py   # @error_handler decorator
β”œβ”€β”€ utils/
β”‚   β”œβ”€β”€ file_io.py          # FileTypeDetector, save_uploaded_file, get_pe_info
β”‚   β”œβ”€β”€ validators.py
β”‚   β”œβ”€β”€ path_manager.py     # find_file_by_hash (mtime-cached)
β”‚   β”œβ”€β”€ risk_analyzer.py    # RiskCalculator + calculate_risk
β”‚   β”œβ”€β”€ forensics.py        # SecurityAnalyzer (MalAPI), entropy
β”‚   β”œβ”€β”€ json_helpers.py
β”‚   └── reporting.py        # generate_html_report
β”œβ”€β”€ analyzers/
β”‚   β”œβ”€β”€ base.py             # BaseAnalyzer + BaseSubprocessAnalyzer
β”‚   β”œβ”€β”€ manager.py          # AnalysisManager β€” parallel static, parallel dynamic + serial hsb
β”‚   β”œβ”€β”€ blender.py          # system-process baseline comparison
β”‚   β”œβ”€β”€ fuzzy.py            # ssdeep-style fuzzy matching DB
β”‚   β”œβ”€β”€ holygrail.py        # BYOVD driver analysis
β”‚   β”œβ”€β”€ static/             # yara, checkplz, stringnalyzer
β”‚   β”œβ”€β”€ dynamic/            # yara, pe_sieve, moneta, patriot, hsb, hollows_hunter, rededr
β”‚   └── edr/                # NOT a subprocess β€” talks to remote Whiskers + alert source
β”‚       β”œβ”€β”€ profile.py             # EdrProfile dataclass + load_profiles
β”‚       β”œβ”€β”€ agent_client.py        # AgentClient β†’ Whiskers HTTP API
β”‚       β”œβ”€β”€ elastic_client.py      # ElasticClient β†’ security alerts indices
β”‚       β”œβ”€β”€ elastic_edr_analyzer.py    # kind=elastic orchestrator
β”‚       β”œβ”€β”€ fibratus_edr_analyzer.py   # kind=fibratus orchestrator
β”‚       └── registry.py            # init() + dispatch_split() β€” kind dispatch
└── templates/
    β”œβ”€β”€ base.html, dashboard.html, upload.html, agents.html,
    β”œβ”€β”€ analyze_all.html, edr_info.html, results.html, file_info.html,
    └── …

Frontend layout

Vanilla JS, ES6 modules, no bundler. Loaded via <script type="module">.

app/static/js/
β”œβ”€β”€ base.js                 # universal β€” sidebar, modals, status, cleanup
β”œβ”€β”€ summary.js              # /summary page
β”œβ”€β”€ blender.js, fuzzy.js    # /doppelganger tabs
β”œβ”€β”€ results/
β”‚   β”œβ”€β”€ core.js             # AnalysisCore + DOMContentLoaded entry
β”‚   β”œβ”€β”€ managers.js         # TabManager, PayloadManager, ModalHandler
β”‚   β”œβ”€β”€ tools.js            # registry of per-tool modules
β”‚   β”œβ”€β”€ renderers.js
β”‚   β”œβ”€β”€ edr-saved.js        # /results/edr/<profile>/<target> bootstrap
β”‚   └── tools/              # one module per scanner β€” all consume `_shared.js` helpers
β”‚       β”œβ”€β”€ _shared.js
β”‚       β”œβ”€β”€ yara.js, checkplz.js, stringnalyzer.js
β”‚       β”œβ”€β”€ pe_sieve.js, moneta.js, patriot.js, hsb.js, rededr.js
β”‚       β”œβ”€β”€ edr.js          # diff-aware re-render, lazy detail, adaptive poll
β”‚       └── summary.js
β”œβ”€β”€ dashboard/core.js       # / dashboard
β”œβ”€β”€ agents/core.js          # /whiskers
β”œβ”€β”€ analyze-all/core.js     # /analyze/all/<target>
└── utils/                  # escape, formatters, severity, fetch, modals, dom

All polling JS pauses on document.visibilityState === 'hidden' and resumes (with one immediate refresh) on visible.


Whiskers Rust agent

Whiskers/                   # separate Rust crate, single binary
β”œβ”€β”€ Cargo.toml, Cargo.lock
β”œβ”€β”€ README.md               # install, CLI flags, endpoints, build-from-source
└── src/
    β”œβ”€β”€ main.rs             # CLI: --port / --bind / --samples-dir / --install / --uninstall
    β”œβ”€β”€ api/
    β”‚   β”œβ”€β”€ info.rs         # /api/info β€” hostname + telemetry_sources detection
    β”‚   β”œβ”€β”€ lock.rs         # single-occupancy gate
    β”‚   β”œβ”€β”€ execute.rs      # multipart exec, chunked-XOR write, rundll32 for DLLs
    β”‚   β”œβ”€β”€ logs.rs         # execution + agent log buffers
    β”‚   └── alerts.rs       # /api/alerts/fibratus/since β€” wevtutil queries Application log
    β”œβ”€β”€ state.rs            # AppState + RunState
    β”œβ”€β”€ file_writer.rs      # chunked-XOR (64 KiB working buffer)
    └── agent_log.rs

Built with cargo build --release β†’ target/release/Whiskers.exe (~1.6 MB, no runtime deps). See Whiskers Agent.

πŸ“Œ LitterBox Β· self-hosted payload analysis sandbox

Release


πŸš€ Getting Started

πŸ“Š Pipelines & Pages

πŸ”¬ Scanners Β· 4 modules

πŸ›°οΈ EDR Integration
πŸ”Œ API & Clients
βš™οΈ Configuration & Dev

Releases Β· CHANGELOG Β· Issues Β· README

Clone this wiki locally