# dobin/avred architecture

> Architecture diagram of the GitHub repository dobin/avred, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-23). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/dobin/avred
- Repository: https://github.com/dobin/avred

## Overview

1. **What this repository is**
   avred is a two-part system: a command-line scanning/reduction engine and a small web UI for managing uploaded samples and viewing results. Its core job is to probe an antivirus/AMSI backend, find which byte ranges trigger detection, and then enrich those ranges with file-structure context.

2. **Primary execution entry points**
   `avred.py` is the main CLI workflow for scanning a single file end-to-end. `avredweb.py` is the web server entry point. The `app/` directory contains the web application layer: templates, static assets, and Flask-style view modules for browsing files, upload/login, and per-file result pages.

3. **Core scan pipeline**
   The scan path starts with file identification and parser selection, then feeds byte ranges into the configured scanner backend. The repo distinguishes between whole-file handling and structure-aware scanning, so PE sections, Office macro payloads, and .NET streams can be tested independently rather than only as one blob.

4. **Scanner/backend boundary**
   The actual detection engine is external: avred talks to an AMSI server over HTTP, configured in `config.yaml`. This makes the antivirus boundary explicit: avred does local analysis and orchestration, while the remote Windows/AMSI service decides whether a sample or byte slice is malicious.

5. **File-type plugin architecture**
   The `plugins/` tree is the main architectural extension point. There are specialized plugins for:
   - `pe/` for Windows executables
   - `office/` for Word/macros and embedded `vbaProject.bin`
   - `dotnet/` for .NET assemblies and metadata streams
   - `plain/` for unstructured files/scripts  
   Each plugin has a `file_*` module for file-specific parsing, an `analyzer_*` module for interpreting hits, and in some cases `augment_*` / `outflank_*` modules for extra context and reduction strategies.

6. **Verification and reduction workflow**
   After initial detection, the system does not stop at “something matched.” `verifier.py`, `minimizer.py`, `reducer.py`, and `scanner.py` work together to confirm that matches are real, narrow them down, and rank or split them into smaller actionable regions. This is what enables avred to show multiple verified matches instead of a single coarse hit.

7. **Model and persistence layer**
   The `model/` package defines the persisted outcome structures: files, code/data matches, verification state, and plugin-specific metadata. Results are stored as pickled `.outcome` files alongside `.log` files in the upload directory, which is why the README warns that model changes can invalidate older results.

8. **Augmentation and disassembly context**
   A major differentiator is match augmentation. For PE files, disassembly/context can come from radare2; for .NET, the repo vendors `dnfile/dotnetfile` plus `dncil`-based parsing; for Office macros, it vendors `pcodedmp`. These tools are used to explain a match in terms of code, sections, streams, and references rather than raw offsets only.

9. **Web application responsibilities**
   The web UI in `app/` is presentation and file management, not the scanning engine. It renders uploaded files, file info, match lists, logs, verifier status, and upload tracking. Authentication is optional and appears to be simple shared-password protection configured in `config.yaml`.

10. **Storage and operational model**
   The system is intentionally file-centric: uploaded samples live under `app/upload/`, examples under `app/examples/`, and all derived data stays on disk next to the sample. That keeps the architecture stateless from the web server’s perspective, but means the filesystem is the persistence boundary for outcomes, logs, and patched artifacts.

11. **Tooling and offline utilities**
   The `tools/` directory contains helper scripts for viewing pickles, patching files, and verifying outputs outside the main app flow. The `tests/` tree exercises the scanners, parsers, model logic, and verifier behavior using sample PE, Office, and .NET artifacts, which reflects the repo’s modular, file-type-driven design.

12. **Big-picture data flow**
   Input file → file-type detection → plugin-specific parsing/context extraction → HTTP scan against AMSI → match collection → verification/minimization → augmentation with disassembly/structure metadata → persisted outcome/logs → optional web UI display and offline tooling.  
   The key architectural boundaries are: local analysis vs remote antivirus, generic scan orchestration vs file-type plugins, and engine logic vs web presentation.

Main entry points: [`scanning.py`](https://github.com/dobin/avred/blob/main/scanning.py) (scanning.py), [`plugins/office/plugin_office.py`](https://github.com/dobin/avred/blob/main/plugins/office/plugin_office.py) (Office plugin), [`plugins/dotnet/plugin_dotnet.py`](https://github.com/dobin/avred/blob/main/plugins/dotnet/plugin_dotnet.py) (.NET plugin), [`model/file_model.py`](https://github.com/dobin/avred/blob/main/model/file_model.py) (Outcome model)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_core["Scan engine"]
  node_avred_py["avred.py<br/>CLI entrypoint<br/>[avred.py]"]
  node_scanning_py["scanning.py<br/>scan orchestration<br/>[scanning.py]"]
  node_scanner_py["scanner.py<br/>backend client<br/>[scanner.py]"]
  node_verifier_py["verifier.py<br/>verification<br/>[verifier.py]"]
  node_minimizer_py["minimizer.py<br/>reduction<br/>[minimizer.py]"]
  node_reducer_py["reducer.py<br/>ranking/reduction<br/>[reducer.py]"]
  node_filehelper_py["filehelper.py<br/>file ops<br/>[filehelper.py]"]
  node_config_yaml["config.yaml<br/>runtime config<br/>[config.yaml]"]
end

subgraph group_plugins["Plugins"]
  node_plugin_pe["PE plugin<br/>PE analysis<br/>[plugin_pe.py]"]
  node_plugin_office["Office plugin<br/>Office analysis<br/>[plugin_office.py]"]
  node_plugin_dotnet[".NET plugin<br/>.NET analysis<br/>[plugin_dotnet.py]"]
  node_plugin_plain["Plain plugin<br/>generic file analysis<br/>[plugin_plain.py]"]
  node_augment_pe["PE augment<br/>context enrichment<br/>[augment_pe.py]"]
  node_augment_office["Office augment<br/>context enrichment<br/>[augment_office.py]"]
  node_augment_dotnet[".NET augment<br/>context enrichment<br/>[augment_dotnet.py]"]
end

subgraph group_web["Web UI"]
  node_views_py["app/views.py<br/>web views<br/>[views.py]"]
  node_views_auth_py["app/views_auth.py<br/>auth views<br/>[views_auth.py]"]
  node_views_upload_py["app/views_upload.py<br/>upload views<br/>[views_upload.py]"]
  node_templates["Templates<br/>presentation"]
end

subgraph group_data["Models & persistence"]
  node_file_model[("Outcome model<br/>persistence model<br/>[file_model.py]")]
  node_model_code[("Code matches<br/>match model<br/>[model_code.py]")]
  node_model_data[("Data matches<br/>match model<br/>[model_data.py]")]
  node_model_verification[("Verification model<br/>state model")]
end

subgraph group_vendored["Vendored parsers"]
  node_dotnetfile_pkg["dotnetfile<br/>vendored parser<br/>[dotnetfile.py]"]
  node_pcodedmp_pkg["pcodedmp<br/>vendored parser<br/>[pcodedmp.py]"]
end

subgraph group_tools["Tools"]
  node_tools_pkg["Tools<br/>offline utilities<br/>[viewer.py]"]
end

node_avred_py -->|"drives"| node_scanning_py
node_scanning_py -->|"loads"| node_filehelper_py
node_scanning_py -->|"selects"| node_plugin_pe
node_scanning_py -->|"selects"| node_plugin_office
node_scanning_py -->|"selects"| node_plugin_dotnet
node_scanning_py -->|"selects"| node_plugin_plain
node_scanning_py -->|"probes"| node_scanner_py
node_scanner_py -->|"reads"| node_config_yaml
node_scanning_py -->|"verifies"| node_verifier_py
node_verifier_py -->|"narrows"| node_minimizer_py
node_verifier_py -->|"splits"| node_reducer_py
node_plugin_pe -->|"enriches"| node_augment_pe
node_plugin_office -->|"enriches"| node_augment_office
node_plugin_dotnet -->|"enriches"| node_augment_dotnet
node_plugin_pe -->|"writes"| node_model_code
node_plugin_office -->|"writes"| node_model_data
node_plugin_dotnet -->|"writes"| node_model_code
node_scanning_py -->|"stores"| node_file_model
node_file_model -->|"contains"| node_model_verification
node_views_py -->|"reads"| node_file_model
node_views_py -->|"renders"| node_templates
node_views_auth_py -->|"renders"| node_templates
node_views_upload_py -->|"renders"| node_templates
node_views_upload_py -->|"checks"| node_config_yaml
node_plugin_dotnet -->|"uses"| node_dotnetfile_pkg
node_plugin_office -->|"uses"| node_pcodedmp_pkg
node_tools_pkg -->|"inspects"| node_file_model
node_tools_pkg -->|"uses"| node_config_yaml
node_avred_py -->|"configures"| node_config_yaml

click node_avred_py "https://github.com/dobin/avred/blob/main/avred.py"
click node_scanning_py "https://github.com/dobin/avred/blob/main/scanning.py"
click node_scanner_py "https://github.com/dobin/avred/blob/main/scanner.py"
click node_verifier_py "https://github.com/dobin/avred/blob/main/verifier.py"
click node_minimizer_py "https://github.com/dobin/avred/blob/main/minimizer.py"
click node_reducer_py "https://github.com/dobin/avred/blob/main/reducer.py"
click node_filehelper_py "https://github.com/dobin/avred/blob/main/filehelper.py"
click node_config_yaml "https://github.com/dobin/avred/blob/main/config.yaml"
click node_plugin_pe "https://github.com/dobin/avred/blob/main/plugins/pe/plugin_pe.py"
click node_plugin_office "https://github.com/dobin/avred/blob/main/plugins/office/plugin_office.py"
click node_plugin_dotnet "https://github.com/dobin/avred/blob/main/plugins/dotnet/plugin_dotnet.py"
click node_plugin_plain "https://github.com/dobin/avred/blob/main/plugins/plain/plugin_plain.py"
click node_augment_pe "https://github.com/dobin/avred/blob/main/plugins/pe/augment_pe.py"
click node_augment_office "https://github.com/dobin/avred/blob/main/plugins/office/augment_office.py"
click node_augment_dotnet "https://github.com/dobin/avred/blob/main/plugins/dotnet/augment_dotnet.py"
click node_file_model "https://github.com/dobin/avred/blob/main/model/file_model.py"
click node_model_code "https://github.com/dobin/avred/blob/main/model/model_code.py"
click node_model_data "https://github.com/dobin/avred/blob/main/model/model_data.py"
click node_model_verification "https://github.com/dobin/avred/blob/main/model/model_verification.py"
click node_views_py "https://github.com/dobin/avred/blob/main/app/views.py"
click node_views_auth_py "https://github.com/dobin/avred/blob/main/app/views_auth.py"
click node_views_upload_py "https://github.com/dobin/avred/blob/main/app/views_upload.py"
click node_templates "https://github.com/dobin/avred/tree/main/app/templates"
click node_dotnetfile_pkg "https://github.com/dobin/avred/blob/main/dotnetfile/dotnetfile.py"
click node_pcodedmp_pkg "https://github.com/dobin/avred/blob/main/pcodedmp/pcodedmp.py"
click node_tools_pkg "https://github.com/dobin/avred/blob/main/tools/viewer.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_avred_py,node_scanning_py,node_scanner_py,node_verifier_py,node_minimizer_py,node_reducer_py,node_filehelper_py,node_config_yaml toneBlue
class node_plugin_pe,node_plugin_office,node_plugin_dotnet,node_plugin_plain,node_augment_pe,node_augment_office,node_augment_dotnet toneAmber
class node_views_py,node_views_auth_py,node_views_upload_py,node_templates toneMint
class node_file_model,node_model_code,node_model_data,node_model_verification toneRose
class node_dotnetfile_pkg,node_pcodedmp_pkg toneIndigo
class node_tools_pkg toneTeal
```

## Components

### Scan engine

Command-line scanning, verification, and reduction pipeline

- [avred.py](https://github.com/dobin/avred/blob/main/avred.py): CLI entrypoint · Main single-file scan workflow · `avred.py`
- [scanning.py](https://github.com/dobin/avred/blob/main/scanning.py): scan orchestration · Coordinates file slicing and scan passes · `scanning.py`
- [scanner.py](https://github.com/dobin/avred/blob/main/scanner.py): backend client · HTTP client boundary to the remote AMSI scanner · `scanner.py`
- [verifier.py](https://github.com/dobin/avred/blob/main/verifier.py): verification · Confirms hits and tracks verification state · `verifier.py`
- [minimizer.py](https://github.com/dobin/avred/blob/main/minimizer.py): reduction · Narrows matched ranges to smaller actionable slices · `minimizer.py`
- [reducer.py](https://github.com/dobin/avred/blob/main/reducer.py): ranking/reduction · Splits and ranks matches for reporting · `reducer.py`
- [filehelper.py](https://github.com/dobin/avred/blob/main/filehelper.py): file ops · File handling and sample utilities · `filehelper.py`
- [config.yaml](https://github.com/dobin/avred/blob/main/config.yaml): runtime config · Scanner endpoint and web authentication settings · `config.yaml`

### Plugins

File-type specific parsing, analysis, and augmentation

- [PE plugin](https://github.com/dobin/avred/blob/main/plugins/pe/plugin_pe.py): PE analysis · Windows executable parsing, analysis, and outflanking · `plugins/pe/plugin_pe.py`
- [Office plugin](https://github.com/dobin/avred/blob/main/plugins/office/plugin_office.py): Office analysis · Document and macro payload parsing and context extraction · `plugins/office/plugin_office.py`
- [.NET plugin](https://github.com/dobin/avred/blob/main/plugins/dotnet/plugin_dotnet.py): .NET analysis · Assembly and metadata stream handling · `plugins/dotnet/plugin_dotnet.py`
- [Plain plugin](https://github.com/dobin/avred/blob/main/plugins/plain/plugin_plain.py): generic file analysis · Unstructured file and script handling · `plugins/plain/plugin_plain.py`
- [PE augment](https://github.com/dobin/avred/blob/main/plugins/pe/augment_pe.py): context enrichment · Disassembly and section-aware match context · `plugins/pe/augment_pe.py`
- [Office augment](https://github.com/dobin/avred/blob/main/plugins/office/augment_office.py): context enrichment · Macro and embedded payload context · `plugins/office/augment_office.py`
- [.NET augment](https://github.com/dobin/avred/blob/main/plugins/dotnet/augment_dotnet.py): context enrichment · Metadata and stream context for matches · `plugins/dotnet/augment_dotnet.py`

### Web UI

Browser-facing upload, browsing, and result pages

- [app/views.py](https://github.com/dobin/avred/blob/main/app/views.py): web views · Main browse and file result pages · `app/views.py`
- [app/views_auth.py](https://github.com/dobin/avred/blob/main/app/views_auth.py): auth views · Login and shared-password handling · `app/views_auth.py`
- [app/views_upload.py](https://github.com/dobin/avred/blob/main/app/views_upload.py): upload views · Upload tracking and sample intake · `app/views_upload.py`
- [Templates](https://github.com/dobin/avred/tree/main/app/templates): presentation · Rendered HTML for files, logs, matches, and upload flows · `app/templates`

### Models & persistence

Persisted outcomes and file-backed result data

- [Outcome model](https://github.com/dobin/avred/blob/main/model/file_model.py): persistence model · File, match, verifier, and plugin outcome structures · `model/file_model.py`
- [Code matches](https://github.com/dobin/avred/blob/main/model/model_code.py): match model · Persisted code-region match structures · `model/model_code.py`
- [Data matches](https://github.com/dobin/avred/blob/main/model/model_data.py): match model · Persisted data-region match structures · `model/model_data.py`
- [Verification model](https://github.com/dobin/avred/blob/main/model/model_verification.py): state model · Verification status and outcomes · `model/model_verification.py`

### Vendored parsers

Embedded third-party parsers used by plugins

- [dotnetfile](https://github.com/dobin/avred/blob/main/dotnetfile/dotnetfile.py): vendored parser · Embedded .NET metadata parser library · `dotnetfile/dotnetfile.py`
- [pcodedmp](https://github.com/dobin/avred/blob/main/pcodedmp/pcodedmp.py): vendored parser · Embedded VBA/macro disassembly helper · `pcodedmp/pcodedmp.py`

### Tools

Offline utilities for inspection and patching

- [Tools](https://github.com/dobin/avred/blob/main/tools/viewer.py): offline utilities · Pickle viewing, patching, and verification scripts · `tools/viewer.py`

## Connections

- avred.py → scanning.py: drives · CLI invokes the end-to-end scan pipeline
- scanning.py → filehelper.py: loads · Reads and prepares the target file
- scanning.py → PE plugin: selects · Routes PE samples to the PE plugin
- scanning.py → Office plugin: selects · Routes Office documents to the Office plugin
- scanning.py → .NET plugin: selects · Routes .NET assemblies to the .NET plugin
- scanning.py → Plain plugin: selects · Falls back to plain-file handling
- scanning.py → scanner.py: probes · Sends byte ranges to the remote AMSI backend
- scanner.py → config.yaml: reads · Uses configured scanner endpoint
- scanning.py → verifier.py: verifies · Confirms that detections are real
- verifier.py → minimizer.py: narrows · Reduces matched ranges during verification
- verifier.py → reducer.py: splits · Produces smaller ranked regions
- PE plugin → PE augment: enriches · Adds disassembly and structure context
- Office plugin → Office augment: enriches · Adds macro and embedded object context
- .NET plugin → .NET augment: enriches · Adds metadata and stream context
- PE plugin → Code matches: writes · Persists code-region match information
- Office plugin → Data matches: writes · Persists document/data match information
- .NET plugin → Code matches: writes · Persists assembly match information
- scanning.py → Outcome model: stores · Builds the overall outcome object
- Outcome model → Verification model: contains · Carries verification status
- app/views.py → Outcome model: reads · Displays persisted file outcomes
- app/views.py → Templates: renders · Uses HTML templates for file pages
- app/views_auth.py → Templates: renders · Uses login templates
- app/views_upload.py → Templates: renders · Uses upload and tracker templates
- app/views_upload.py → config.yaml: checks · Applies optional authentication rules
- .NET plugin → dotnetfile: uses · Delegates parsing to vendored .NET parser
- Office plugin → pcodedmp: uses · Delegates macro disassembly to vendored helper
- Tools → Outcome model: inspects · Reads persisted outcomes and pickles
- Tools → config.yaml: uses · Shares runtime configuration assumptions
- avred.py → config.yaml: configures · Initializes scanning behavior from config
