Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

28 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Malware Scanner

A web-based scanner that checks if a downloaded file (.exe, .dll, .msi, .bin, .elf) is safe to run before you run it. The backend analyses uploads through multiple stages (PE structure, entropy, strings, YARA, VirusTotal) and combines the signals into a single CLEAN / SUSPICIOUS / MALICIOUS verdict with human-readable reasons.

⚠️ For educational and authorised security testing use only. See Disclaimer.

pipeline react license


Features

  • Multi-stage static analysis — PE structure, suspicious imports, section entropy, string extraction, YARA rules
  • VirusTotal lookup — cross-checks the file's SHA256 against 70+ AV engines (free-tier API key)
  • Weighted verdict engine — combines signals into a single score, explains every contributing reason
  • Local SQLite cache — same file, scanned twice, returns instantly
  • Drag-and-drop React UI — verdict badge, expandable analysis panels
  • Graceful fallbacks — missing API key, network errors, and malformed files never crash the pipeline
  • Rotating file logs — every scan, error, and VT lookup is recorded in logs/scanner.log

Architecture

┌─────────────────┐      multipart/form-data      ┌─────────────────────┐
│  React (Vite)   │  ───────────────────────────▶  │  FastAPI backend    │
│  localhost:5173 │                                │  127.0.0.1:8000     │
└─────────────────┘   ◀──────  JSON verdict  ───── └──────────┬──────────┘
                                                              │
                                ┌───────────┬─────────────────┼──────────────────┐
                                ▼           ▼                 ▼                  ▼
                          ┌──────────┐ ┌──────────┐    ┌──────────┐       ┌────────────┐
                          │ pefile + │ │  YARA    │    │ SQLite   │       │ VirusTotal │
                          │ entropy  │ │  rules   │    │  cache   │       │   API v3   │
                          │ + strings│ │          │    │          │       │            │
                          └──────────┘ └──────────┘    └──────────┘       └────────────┘

Quick start

Prerequisites

  • Python 3.12+ (3.14 tested)
  • Node.js 20+
  • Windows, macOS, or Linux (PE analysis works on any host; some test paths assume Windows)
  • A free VirusTotal API key — optional, the scanner runs without it but the verdict will lack the strongest signal

1. Clone and install backend

git clone https://github.com/POSTTTT/malware-scanner.git
cd malware-scanner

python -m venv venv
# Windows PowerShell:
.\venv\Scripts\Activate.ps1
# macOS/Linux:
source venv/bin/activate

pip install -r requirements.txt

2. Configure your VirusTotal key

cp .env.example .env
# then open .env and paste your key after VIRUSTOTAL_API_KEY=

The scanner also runs without a key — VT lookups will be skipped with a clear reason.

3. Install frontend dependencies

cd frontend
npm install
cd ..

4. Run it

You need two terminals open simultaneously.

Terminal 1 — backend:

cd backend
..\venv\Scripts\python.exe -m uvicorn main:app --reload

Terminal 2 — frontend:

cd frontend
npm run dev

Open http://localhost:5173 in your browser.

Usage

Drag a file onto the drop zone (or click to browse). The UI streams it to the backend, which:

  1. Validates the file (extension, size limit 50 MB)
  2. Computes SHA256 and checks the local cache
  3. If new: runs PE analysis, entropy, strings, YARA, then queries VirusTotal
  4. Combines all signals into a verdict with a 0–100 score
  5. Returns the result; the UI renders verdict + reasons + expandable details

You can also call the API directly:

curl -X POST http://127.0.0.1:8000/scan -F "file=@C:\Windows\System32\notepad.exe"

Interactive API docs are at http://127.0.0.1:8000/docs.

How the verdict is calculated

The verdict engine combines weighted signals from each scanner. Score thresholds:

Score Verdict
< 20 CLEAN
20–49 SUSPICIOUS
≥ 50 MALICIOUS

Selected signals (full list in backend/scanners/verdict.py):

Signal Points
VT: ≥ 10 engines flag the file +60
VT: ≥ 5 engines flag +40
VT: ≥ 1 engine flags +20
VT: 0 / many engines clean (well-known) −20
PE has Authenticode signature −20
PE imports the process-injection trio +25
Other suspicious imports +3 each, max +15
Section entropy ≥ 7.5 (likely packed/encrypted) +25
Section entropy ≥ 7.0 (possibly packed) +15
Suspicious keywords (bitcoin, decrypt, vssadmin, etc.) +5 each, max +15
YARA: high-severity match +40
YARA: medium-severity match +20
YARA: low-severity match +10

The response always includes a reasons[] array showing which signals contributed and their scores.

Project structure

malware-scanner/
├── backend/
│   ├── main.py                    # FastAPI app entry
│   ├── config.py                  # config.yaml loader
│   ├── database.py                # SQLite cache
│   ├── logger.py                  # rotating file logger
│   ├── api/
│   │   ├── health.py              # GET /health
│   │   └── scan.py                # POST /scan
│   ├── scanners/
│   │   ├── hasher.py              # SHA256
│   │   ├── pe_analyzer.py         # pefile-based PE parsing
│   │   ├── entropy.py             # Shannon entropy per section
│   │   ├── strings.py             # ASCII / UTF-16 string extraction
│   │   ├── yara_scan.py           # YARA rule matcher
│   │   ├── virustotal.py          # VT API v3 client
│   │   ├── static.py              # orchestrates all static stages
│   │   └── verdict.py             # weighted scoring engine
│   └── schemas/scan.py            # Pydantic response models
├── frontend/                      # Vite + React UI
├── rules/starter.yar              # bundled YARA rules
├── tests/test_pipeline.py         # end-to-end smoke test
├── config.yaml                    # central config (size limits, extensions, VT)
├── requirements.txt
├── PLAN.md                        # implementation plan + future work
└── IDEA.md                        # original concept

Running the smoke test

With the backend running:

python tests/test_pipeline.py

This uploads a clean Windows binary (notepad.exe) and a hand-crafted "fake ransomware" pattern, then asserts the verdicts are CLEAN and MALICIOUS respectively. Set SCANNER_URL to point at a different host/port if needed.

Configuration

Most knobs live in config.yaml:

uploads:
  max_size_mb: 50
  allowed_extensions: [.exe, .dll, .msi, .bin, .elf]

virustotal:
  rate_limit_per_minute: 4   # matches free-tier quota

Secrets (VIRUSTOTAL_API_KEY) live in .env, which is gitignored.

Future enhancements

Tracked in PLAN.md:

  • capa integration — map binary behaviour to MITRE ATT&CK techniques
  • MalwareBazaar — second threat-intel source
  • Authenticode publisher trust list — auto-CLEAN files signed by known vendors
  • Async pipeline — only needed when adding slow analyzers (capa, sandbox)
  • Sandbox (Phase 10) — run in a Docker container, observe behaviour

Disclaimer

This tool is for educational and authorised security testing purposes only. Do not use it on files you don't have permission to analyse. The authors are not responsible for misuse.

License

GPL-3.0

About

Multi-stage malware scanner. Combines PE analysis, entropy, YARA rules, and VirusTotal into a single explainable verdict (CLEAN / SUSPICIOUS / MALICIOUS).

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages