How dobin/avred works
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 scanning.py · plugin_office.py Office plugin · plugin_dotnet.py .NET plugin · file_model.py Outcome model
Components 26
Scan engine
Command-line scanning, verification, and reduction pipeline
- avred.py · Main single-file scan workflow
avred.py - scanning.py · Coordinates file slicing and scan passes
scanning.py - scanner.py · HTTP client boundary to the remote AMSI scanner
scanner.py - verifier.py · Confirms hits and tracks verification state
verifier.py - minimizer.py · Narrows matched ranges to smaller actionable slices
minimizer.py - reducer.py · Splits and ranks matches for reporting
reducer.py - filehelper.py · File handling and sample utilities
filehelper.py - config.yaml · Scanner endpoint and web authentication settings
config.yaml
Plugins
File-type specific parsing, analysis, and augmentation
- PE plugin · Windows executable parsing, analysis, and outflanking
plugins/pe/plugin_pe.py - Office plugin · Document and macro payload parsing and context extraction
plugins/office/plugin_office.py - .NET plugin · Assembly and metadata stream handling
plugins/dotnet/plugin_dotnet.py - Plain plugin · Unstructured file and script handling
plugins/plain/plugin_plain.py - PE augment · Disassembly and section-aware match context
plugins/pe/augment_pe.py - Office augment · Macro and embedded payload context
plugins/office/augment_office.py - .NET augment · Metadata and stream context for matches
plugins/dotnet/augment_dotnet.py
Web UI
Browser-facing upload, browsing, and result pages
- app/views.py · Main browse and file result pages
app/views.py - app/views_auth.py · Login and shared-password handling
app/views_auth.py - app/views_upload.py · Upload tracking and sample intake
app/views_upload.py - Templates · Rendered HTML for files, logs, matches, and upload flows
app/templates
Models & persistence
Persisted outcomes and file-backed result data
- Outcome model · File, match, verifier, and plugin outcome structures
model/file_model.py - Code matches · Persisted code-region match structures
model/model_code.py - Data matches · Persisted data-region match structures
model/model_data.py - Verification model · Verification status and outcomes
model/model_verification.py
Vendored parsers
Embedded third-party parsers used by plugins
- dotnetfile · Embedded .NET metadata parser library
dotnetfile/dotnetfile.py - pcodedmp · Embedded VBA/macro disassembly helper
pcodedmp/pcodedmp.py
Tools
Offline utilities for inspection and patching
- Tools · Pickle viewing, patching, and verification scripts
tools/viewer.py
Connections 29
- 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