vex-ioc 1.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. vex_ioc-1.1.0/LICENSE.md +21 -0
  2. vex_ioc-1.1.0/PKG-INFO +336 -0
  3. vex_ioc-1.1.0/README.md +307 -0
  4. vex_ioc-1.1.0/pyproject.toml +48 -0
  5. vex_ioc-1.1.0/setup.cfg +4 -0
  6. vex_ioc-1.1.0/vex/__init__.py +5 -0
  7. vex_ioc-1.1.0/vex/__main__.py +5 -0
  8. vex_ioc-1.1.0/vex/async_client.py +79 -0
  9. vex_ioc-1.1.0/vex/banner.py +64 -0
  10. vex_ioc-1.1.0/vex/batch.py +196 -0
  11. vex_ioc-1.1.0/vex/cache.py +82 -0
  12. vex_ioc-1.1.0/vex/client.py +136 -0
  13. vex_ioc-1.1.0/vex/config.py +125 -0
  14. vex_ioc-1.1.0/vex/defang.py +81 -0
  15. vex_ioc-1.1.0/vex/enrichers/__init__.py +1 -0
  16. vex_ioc-1.1.0/vex/enrichers/base.py +86 -0
  17. vex_ioc-1.1.0/vex/enrichers/domain.py +130 -0
  18. vex_ioc-1.1.0/vex/enrichers/hash.py +171 -0
  19. vex_ioc-1.1.0/vex/enrichers/ip.py +101 -0
  20. vex_ioc-1.1.0/vex/enrichers/protocol.py +35 -0
  21. vex_ioc-1.1.0/vex/enrichers/url.py +96 -0
  22. vex_ioc-1.1.0/vex/ioc_detector.py +75 -0
  23. vex_ioc-1.1.0/vex/knowledge/__init__.py +1 -0
  24. vex_ioc-1.1.0/vex/knowledge/api.py +27 -0
  25. vex_ioc-1.1.0/vex/knowledge/db.py +132 -0
  26. vex_ioc-1.1.0/vex/main.py +592 -0
  27. vex_ioc-1.1.0/vex/mitre/__init__.py +1 -0
  28. vex_ioc-1.1.0/vex/mitre/mapper.py +78 -0
  29. vex_ioc-1.1.0/vex/mitre/mapping.py +133 -0
  30. vex_ioc-1.1.0/vex/models.py +202 -0
  31. vex_ioc-1.1.0/vex/output/__init__.py +1 -0
  32. vex_ioc-1.1.0/vex/output/export.py +62 -0
  33. vex_ioc-1.1.0/vex/output/formatter.py +431 -0
  34. vex_ioc-1.1.0/vex/output/stix.py +172 -0
  35. vex_ioc-1.1.0/vex/plugins/__init__.py +1 -0
  36. vex_ioc-1.1.0/vex/plugins/loader.py +42 -0
  37. vex_ioc-1.1.0/vex/plugins/registry.py +47 -0
  38. vex_ioc-1.1.0/vex/plugins/virustotal.py +59 -0
  39. vex_ioc-1.1.0/vex/timeline.py +131 -0
  40. vex_ioc-1.1.0/vex/version_check.py +93 -0
  41. vex_ioc-1.1.0/vex_ioc.egg-info/PKG-INFO +336 -0
  42. vex_ioc-1.1.0/vex_ioc.egg-info/SOURCES.txt +44 -0
  43. vex_ioc-1.1.0/vex_ioc.egg-info/dependency_links.txt +1 -0
  44. vex_ioc-1.1.0/vex_ioc.egg-info/entry_points.txt +2 -0
  45. vex_ioc-1.1.0/vex_ioc.egg-info/requires.txt +6 -0
  46. vex_ioc-1.1.0/vex_ioc.egg-info/top_level.txt +1 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Christian Huhn
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
vex_ioc-1.1.0/PKG-INFO ADDED
@@ -0,0 +1,336 @@
1
+ Metadata-Version: 2.4
2
+ Name: vex-ioc
3
+ Version: 1.1.0
4
+ Summary: VirusTotal IOC Enrichment Tool for SOC/DFIR workflows
5
+ Author-email: Christian Huhn <duathron@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/duathron/vex
8
+ Project-URL: Repository, https://github.com/duathron/vex
9
+ Project-URL: Bug Tracker, https://github.com/duathron/vex/issues
10
+ Keywords: virustotal,ioc,threat-intelligence,dfir,soc,mitre-attack,stix
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Information Technology
14
+ Classifier: Topic :: Security
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Requires-Python: >=3.11
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE.md
22
+ Requires-Dist: httpx>=0.27.0
23
+ Requires-Dist: typer>=0.12.0
24
+ Requires-Dist: rich>=13.7.0
25
+ Requires-Dist: pydantic>=2.7.0
26
+ Requires-Dist: pyyaml>=6.0.1
27
+ Requires-Dist: python-dotenv>=1.0.0
28
+ Dynamic: license-file
29
+
30
+ <p align="center">
31
+ <img src="vex/vex.png" alt="vex logo" width="200"/>
32
+ </p>
33
+
34
+ <h1 align="center">vex</h1>
35
+
36
+ <p align="center">
37
+ <b>VirusTotal IOC enrichment for SOC triage and DFIR investigations, straight from your terminal.</b>
38
+ </p>
39
+
40
+ ```
41
+ ██╗ ██╗███████╗██╗ ██╗
42
+ ██║ ██║██╔════╝╚██╗██╔╝
43
+ ██║ ██║█████╗ ╚███╔╝
44
+ ╚██╗ ██╔╝██╔══╝ ██╔██╗
45
+ ╚████╔╝ ███████╗██╔╝ ██╗
46
+ ╚═══╝ ╚══════╝╚═╝ ╚═╝
47
+ ```
48
+
49
+ ---
50
+
51
+ ## Features
52
+
53
+ - **Auto-detection** of IOC types: MD5, SHA1, SHA256, IPv4, IPv6, Domain, URL
54
+ - **Two modes**: `triage` (fast, 1 API call) and `investigate` (deep, multiple calls)
55
+ - **Output formats**: JSON (default), Rich tables, plain console, CSV, STIX 2.1
56
+ - **MITRE ATT&CK mapping** from sandbox behaviors and VT tags
57
+ - **IOC defanging/refanging** for safe sharing (`hxxps[://]evil[.]com`)
58
+ - **Automation-ready**: exit codes, `--alert` filtering, `--summary` on stderr
59
+ - **Timeline enrichment**: chronological event reconstruction for DFIR
60
+ - **Local knowledge base**: tag, annotate, and watchlist IOCs in SQLite
61
+ - **Plugin architecture**: extensible enrichment sources via Protocol interface
62
+ - **Parallel batch processing** with progress bar for large IOC lists
63
+ - **STIX 2.1 export** for threat intelligence sharing
64
+ - **SQLite cache** with configurable TTL (default 24h)
65
+ - **Rate limiting**: token-bucket, free tier (4 req/min) and premium configurable
66
+
67
+ ---
68
+
69
+ ## Setup
70
+
71
+ ### Prerequisites
72
+
73
+ - Python 3.11+
74
+ - A [VirusTotal API key](https://www.virustotal.com/gui/my-apikey) (free tier works)
75
+
76
+ ### Installation
77
+
78
+ **From PyPI (recommended):**
79
+
80
+ ```bash
81
+ pip install vex-ioc
82
+ ```
83
+
84
+ **From source:**
85
+
86
+ ```bash
87
+ git clone https://github.com/duathron/vex.git
88
+ cd vex
89
+
90
+ python -m venv .venv
91
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
92
+
93
+ pip install -r requirements.txt
94
+ pip install -e .
95
+ ```
96
+
97
+ ### Upgrade
98
+
99
+ ```bash
100
+ # If installed from PyPI
101
+ pip install --upgrade vex-ioc
102
+
103
+ # If installed from git clone (editable)
104
+ cd vex
105
+ git pull
106
+ pip install -r requirements.txt
107
+ pip install -e .
108
+ ```
109
+
110
+ ### API Key
111
+
112
+ Set your API key using **one** of these methods (priority order):
113
+
114
+ ```bash
115
+ # Option 1: Per-command flag (highest priority)
116
+ vex triage 8.8.8.8 --api-key YOUR_KEY
117
+ vex investigate evil.com -k YOUR_KEY
118
+
119
+ # Option 2: Environment variable
120
+ export VT_API_KEY="your-virustotal-api-key"
121
+
122
+ # Option 3: Save permanently to ~/.vex/config.yaml
123
+ vex config --set-api-key YOUR_KEY
124
+
125
+ # Option 4: Manual config.yaml or .env
126
+ # api:
127
+ # key: "your-key"
128
+ ```
129
+
130
+ ---
131
+
132
+ ## Quickstart
133
+
134
+ ```bash
135
+ # Fast triage
136
+ vex triage 44d88612fea8a8f36de82e1278abb02f
137
+
138
+ # Rich terminal output
139
+ vex investigate evil-domain.com -o rich
140
+
141
+ # Batch from file, CSV export
142
+ vex triage -f iocs.txt --csv
143
+
144
+ # Pipe from another tool
145
+ echo "8.8.8.8" | vex triage -o rich
146
+
147
+ # Defanged IOC support
148
+ vex triage "hxxps[://]evil[.]com"
149
+
150
+ # STIX 2.1 export
151
+ vex investigate evil.com --stix > bundle.json
152
+
153
+ # Timeline reconstruction
154
+ vex investigate evil.com -o rich --timeline
155
+
156
+ # Automation: exit code + alert filter + summary
157
+ vex triage -f iocs.txt --alert SUSPICIOUS --summary
158
+ echo $? # 0=clean, 1=suspicious, 2=malicious
159
+ ```
160
+
161
+ ---
162
+
163
+ ## Documentation
164
+
165
+ ### Subcommands
166
+
167
+ | Command | Description |
168
+ |---------|-------------|
169
+ | `vex triage <ioc>` | Fast SOC triage (1 API call) |
170
+ | `vex investigate <ioc>` | Deep DFIR investigation (multiple calls) |
171
+ | `vex config` | Manage configuration (save API key, etc.) |
172
+ | `vex cache-clear` | Clear the SQLite result cache |
173
+ | `vex version` | Show version |
174
+ | `vex tag <ioc>` | Manage IOC tags in local knowledge base |
175
+ | `vex note <ioc>` | Manage IOC notes in local knowledge base |
176
+ | `vex watchlist <name>` | Manage IOC watchlists |
177
+
178
+ ### Triage / Investigate Options
179
+
180
+ | Flag | Description |
181
+ |------|-------------|
182
+ | `-k` / `--api-key` | VirusTotal API key (overrides env var & config) |
183
+ | `-q` / `--quiet` | Suppress the ASCII banner |
184
+ | `-o` / `--output` | Output format: `json` \| `rich` \| `console` (default: `console`) |
185
+ | `-f` / `--file` | File with one IOC per line |
186
+ | `-c` / `--config` | Custom config.yaml path |
187
+ | `--no-cache` | Bypass cache, force fresh lookup |
188
+ | `--csv` | CSV output (triage only) |
189
+ | `--defang` | Defang IOCs in output |
190
+ | `--stix` | Export as STIX 2.1 JSON bundle |
191
+ | `--alert <LEVEL>` | Only show results >= verdict level |
192
+ | `--summary` | Print verdict summary to stderr |
193
+ | `--timeline` | Show chronological timeline (investigate only) |
194
+
195
+ ### Configuration Command
196
+
197
+ Manage vex configuration:
198
+
199
+ ```bash
200
+ # Save API key permanently
201
+ vex config --set-api-key YOUR_KEY
202
+
203
+ # Show usage
204
+ vex config
205
+ ```
206
+
207
+ Saved config is stored at `~/.vex/config.yaml` with restricted permissions (0o600).
208
+
209
+ ### IOC Types
210
+
211
+ | Type | Example |
212
+ |------|---------|
213
+ | MD5 | `44d88612fea8a8f36de82e1278abb02f` |
214
+ | SHA1 | `3395856ce81f2b7382dee72602f798b642f14140` |
215
+ | SHA256 | `275a021bbfb6489e54d471899f7db9d1663fc695...` |
216
+ | IPv4 | `8.8.8.8` |
217
+ | IPv6 | `2001:4860:4860::8888` |
218
+ | Domain | `example.com` |
219
+ | URL | `https://example.com/malware.exe` |
220
+
221
+ Defanged IOCs are automatically refanged before lookup:
222
+ `hxxps[://]evil[.]com` becomes `https://evil.com`.
223
+
224
+ ### Verdict System
225
+
226
+ | Verdict | Condition | Exit Code |
227
+ |---------|-----------|-----------|
228
+ | **MALICIOUS** | >= 3 malicious detections | 2 |
229
+ | **SUSPICIOUS** | >= 1 malicious detection | 1 |
230
+ | **UNKNOWN** | Zero detections OR too few engines | 0 |
231
+ | **CLEAN** | Zero detections AND enough engines | 0 |
232
+
233
+ **Zero detections does not mean CLEAN.** If too few engines reported, the verdict is UNKNOWN.
234
+
235
+ ### MITRE ATT&CK Mapping
236
+
237
+ In `investigate` mode, vex maps sandbox behaviors and VT tags to MITRE ATT&CK techniques. Mappings cover 80+ keywords across all major tactics (Execution, Persistence, Defense Evasion, etc.) and appear in Rich output and STIX exports.
238
+
239
+ ### Knowledge Base
240
+
241
+ Manage local IOC metadata that persists across sessions:
242
+
243
+ ```bash
244
+ # Tag IOCs
245
+ vex tag 8.8.8.8 --add dns --add google
246
+ vex tag 8.8.8.8 # list tags
247
+
248
+ # Add notes
249
+ vex note evil.com --add "Seen in phishing campaign Q4"
250
+ vex note evil.com # list notes
251
+
252
+ # Watchlists
253
+ vex watchlist priority --add 8.8.8.8 --add evil.com
254
+ vex watchlist priority --list
255
+ ```
256
+
257
+ ### Plugin Architecture
258
+
259
+ vex uses a Protocol-based plugin system. The built-in VirusTotal plugin implements `EnricherProtocol`. Third-party sources (OTX, AbuseIPDB, etc.) can be added by implementing the same protocol.
260
+
261
+ ---
262
+
263
+ ## Config Reference
264
+
265
+ ```yaml
266
+ api:
267
+ # key: "your-key" # or set VT_API_KEY env var
268
+ tier: free # free | premium
269
+ rate_limit:
270
+ free:
271
+ requests_per_minute: 4
272
+ requests_per_day: 500
273
+ premium:
274
+ requests_per_minute: 1000
275
+ requests_per_day: 50000
276
+
277
+ thresholds:
278
+ malicious_min_detections: 3
279
+ suspicious_min_detections: 1
280
+ min_engines_for_clean: 10
281
+
282
+ cache:
283
+ enabled: true
284
+ ttl_hours: 24
285
+ # db_path: "/custom/path/cache.db" # default: ~/.vex/cache.db
286
+
287
+ output:
288
+ default_format: json
289
+ quiet: false # suppress banner (-q)
290
+ ```
291
+
292
+ ---
293
+
294
+ ## Project Structure
295
+
296
+ ```
297
+ vex/
298
+ ├── __init__.py # Package version (1.1.0)
299
+ ├── main.py # Typer CLI app with all subcommands
300
+ ├── banner.py # ASCII art banner (ffuf-style)
301
+ ├── client.py # Sync VT API v3 client + rate limiter
302
+ ├── async_client.py # Async VT API client for parallel ops
303
+ ├── config.py # Pydantic config from config.yaml
304
+ ├── cache.py # SQLite result cache with TTL
305
+ ├── ioc_detector.py # Regex auto-detection of IOC types
306
+ ├── defang.py # IOC defanging/refanging
307
+ ├── models.py # Pydantic v2 models + Verdict enum
308
+ ├── batch.py # Parallel batch processing
309
+ ├── timeline.py # Timeline event reconstruction
310
+ ├── vex.png # Logo
311
+ ├── enrichers/
312
+ │ ├── base.py # Shared enricher utilities
313
+ │ ├── protocol.py # EnricherProtocol interface
314
+ │ ├── hash.py # MD5/SHA1/SHA256 enrichment
315
+ │ ├── ip.py # IPv4/IPv6 enrichment
316
+ │ ├── domain.py # Domain enrichment
317
+ │ └── url.py # URL enrichment
318
+ ├── plugins/
319
+ │ ├── registry.py # Plugin discovery & registration
320
+ │ ├── loader.py # Plugin loading
321
+ │ └── virustotal.py # Built-in VT plugin
322
+ ├── mitre/
323
+ │ ├── mapping.py # VT behavior → ATT&CK technique dict
324
+ │ └── mapper.py # Result → ATT&CK mapping engine
325
+ ├── knowledge/
326
+ │ ├── db.py # SQLite knowledge base (tags/notes/watchlists)
327
+ │ └── api.py # High-level knowledge base API
328
+ └── output/
329
+ ├── formatter.py # Rich + console + timeline formatters
330
+ ├── export.py # JSON + CSV export
331
+ └── stix.py # STIX 2.1 bundle generation
332
+ ```
333
+
334
+ ---
335
+
336
+ *Built by [Christian Huhn](https://github.com/duathron) — [github.com/duathron/vex](https://github.com/duathron/vex)*
@@ -0,0 +1,307 @@
1
+ <p align="center">
2
+ <img src="vex/vex.png" alt="vex logo" width="200"/>
3
+ </p>
4
+
5
+ <h1 align="center">vex</h1>
6
+
7
+ <p align="center">
8
+ <b>VirusTotal IOC enrichment for SOC triage and DFIR investigations, straight from your terminal.</b>
9
+ </p>
10
+
11
+ ```
12
+ ██╗ ██╗███████╗██╗ ██╗
13
+ ██║ ██║██╔════╝╚██╗██╔╝
14
+ ██║ ██║█████╗ ╚███╔╝
15
+ ╚██╗ ██╔╝██╔══╝ ██╔██╗
16
+ ╚████╔╝ ███████╗██╔╝ ██╗
17
+ ╚═══╝ ╚══════╝╚═╝ ╚═╝
18
+ ```
19
+
20
+ ---
21
+
22
+ ## Features
23
+
24
+ - **Auto-detection** of IOC types: MD5, SHA1, SHA256, IPv4, IPv6, Domain, URL
25
+ - **Two modes**: `triage` (fast, 1 API call) and `investigate` (deep, multiple calls)
26
+ - **Output formats**: JSON (default), Rich tables, plain console, CSV, STIX 2.1
27
+ - **MITRE ATT&CK mapping** from sandbox behaviors and VT tags
28
+ - **IOC defanging/refanging** for safe sharing (`hxxps[://]evil[.]com`)
29
+ - **Automation-ready**: exit codes, `--alert` filtering, `--summary` on stderr
30
+ - **Timeline enrichment**: chronological event reconstruction for DFIR
31
+ - **Local knowledge base**: tag, annotate, and watchlist IOCs in SQLite
32
+ - **Plugin architecture**: extensible enrichment sources via Protocol interface
33
+ - **Parallel batch processing** with progress bar for large IOC lists
34
+ - **STIX 2.1 export** for threat intelligence sharing
35
+ - **SQLite cache** with configurable TTL (default 24h)
36
+ - **Rate limiting**: token-bucket, free tier (4 req/min) and premium configurable
37
+
38
+ ---
39
+
40
+ ## Setup
41
+
42
+ ### Prerequisites
43
+
44
+ - Python 3.11+
45
+ - A [VirusTotal API key](https://www.virustotal.com/gui/my-apikey) (free tier works)
46
+
47
+ ### Installation
48
+
49
+ **From PyPI (recommended):**
50
+
51
+ ```bash
52
+ pip install vex-ioc
53
+ ```
54
+
55
+ **From source:**
56
+
57
+ ```bash
58
+ git clone https://github.com/duathron/vex.git
59
+ cd vex
60
+
61
+ python -m venv .venv
62
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
63
+
64
+ pip install -r requirements.txt
65
+ pip install -e .
66
+ ```
67
+
68
+ ### Upgrade
69
+
70
+ ```bash
71
+ # If installed from PyPI
72
+ pip install --upgrade vex-ioc
73
+
74
+ # If installed from git clone (editable)
75
+ cd vex
76
+ git pull
77
+ pip install -r requirements.txt
78
+ pip install -e .
79
+ ```
80
+
81
+ ### API Key
82
+
83
+ Set your API key using **one** of these methods (priority order):
84
+
85
+ ```bash
86
+ # Option 1: Per-command flag (highest priority)
87
+ vex triage 8.8.8.8 --api-key YOUR_KEY
88
+ vex investigate evil.com -k YOUR_KEY
89
+
90
+ # Option 2: Environment variable
91
+ export VT_API_KEY="your-virustotal-api-key"
92
+
93
+ # Option 3: Save permanently to ~/.vex/config.yaml
94
+ vex config --set-api-key YOUR_KEY
95
+
96
+ # Option 4: Manual config.yaml or .env
97
+ # api:
98
+ # key: "your-key"
99
+ ```
100
+
101
+ ---
102
+
103
+ ## Quickstart
104
+
105
+ ```bash
106
+ # Fast triage
107
+ vex triage 44d88612fea8a8f36de82e1278abb02f
108
+
109
+ # Rich terminal output
110
+ vex investigate evil-domain.com -o rich
111
+
112
+ # Batch from file, CSV export
113
+ vex triage -f iocs.txt --csv
114
+
115
+ # Pipe from another tool
116
+ echo "8.8.8.8" | vex triage -o rich
117
+
118
+ # Defanged IOC support
119
+ vex triage "hxxps[://]evil[.]com"
120
+
121
+ # STIX 2.1 export
122
+ vex investigate evil.com --stix > bundle.json
123
+
124
+ # Timeline reconstruction
125
+ vex investigate evil.com -o rich --timeline
126
+
127
+ # Automation: exit code + alert filter + summary
128
+ vex triage -f iocs.txt --alert SUSPICIOUS --summary
129
+ echo $? # 0=clean, 1=suspicious, 2=malicious
130
+ ```
131
+
132
+ ---
133
+
134
+ ## Documentation
135
+
136
+ ### Subcommands
137
+
138
+ | Command | Description |
139
+ |---------|-------------|
140
+ | `vex triage <ioc>` | Fast SOC triage (1 API call) |
141
+ | `vex investigate <ioc>` | Deep DFIR investigation (multiple calls) |
142
+ | `vex config` | Manage configuration (save API key, etc.) |
143
+ | `vex cache-clear` | Clear the SQLite result cache |
144
+ | `vex version` | Show version |
145
+ | `vex tag <ioc>` | Manage IOC tags in local knowledge base |
146
+ | `vex note <ioc>` | Manage IOC notes in local knowledge base |
147
+ | `vex watchlist <name>` | Manage IOC watchlists |
148
+
149
+ ### Triage / Investigate Options
150
+
151
+ | Flag | Description |
152
+ |------|-------------|
153
+ | `-k` / `--api-key` | VirusTotal API key (overrides env var & config) |
154
+ | `-q` / `--quiet` | Suppress the ASCII banner |
155
+ | `-o` / `--output` | Output format: `json` \| `rich` \| `console` (default: `console`) |
156
+ | `-f` / `--file` | File with one IOC per line |
157
+ | `-c` / `--config` | Custom config.yaml path |
158
+ | `--no-cache` | Bypass cache, force fresh lookup |
159
+ | `--csv` | CSV output (triage only) |
160
+ | `--defang` | Defang IOCs in output |
161
+ | `--stix` | Export as STIX 2.1 JSON bundle |
162
+ | `--alert <LEVEL>` | Only show results >= verdict level |
163
+ | `--summary` | Print verdict summary to stderr |
164
+ | `--timeline` | Show chronological timeline (investigate only) |
165
+
166
+ ### Configuration Command
167
+
168
+ Manage vex configuration:
169
+
170
+ ```bash
171
+ # Save API key permanently
172
+ vex config --set-api-key YOUR_KEY
173
+
174
+ # Show usage
175
+ vex config
176
+ ```
177
+
178
+ Saved config is stored at `~/.vex/config.yaml` with restricted permissions (0o600).
179
+
180
+ ### IOC Types
181
+
182
+ | Type | Example |
183
+ |------|---------|
184
+ | MD5 | `44d88612fea8a8f36de82e1278abb02f` |
185
+ | SHA1 | `3395856ce81f2b7382dee72602f798b642f14140` |
186
+ | SHA256 | `275a021bbfb6489e54d471899f7db9d1663fc695...` |
187
+ | IPv4 | `8.8.8.8` |
188
+ | IPv6 | `2001:4860:4860::8888` |
189
+ | Domain | `example.com` |
190
+ | URL | `https://example.com/malware.exe` |
191
+
192
+ Defanged IOCs are automatically refanged before lookup:
193
+ `hxxps[://]evil[.]com` becomes `https://evil.com`.
194
+
195
+ ### Verdict System
196
+
197
+ | Verdict | Condition | Exit Code |
198
+ |---------|-----------|-----------|
199
+ | **MALICIOUS** | >= 3 malicious detections | 2 |
200
+ | **SUSPICIOUS** | >= 1 malicious detection | 1 |
201
+ | **UNKNOWN** | Zero detections OR too few engines | 0 |
202
+ | **CLEAN** | Zero detections AND enough engines | 0 |
203
+
204
+ **Zero detections does not mean CLEAN.** If too few engines reported, the verdict is UNKNOWN.
205
+
206
+ ### MITRE ATT&CK Mapping
207
+
208
+ In `investigate` mode, vex maps sandbox behaviors and VT tags to MITRE ATT&CK techniques. Mappings cover 80+ keywords across all major tactics (Execution, Persistence, Defense Evasion, etc.) and appear in Rich output and STIX exports.
209
+
210
+ ### Knowledge Base
211
+
212
+ Manage local IOC metadata that persists across sessions:
213
+
214
+ ```bash
215
+ # Tag IOCs
216
+ vex tag 8.8.8.8 --add dns --add google
217
+ vex tag 8.8.8.8 # list tags
218
+
219
+ # Add notes
220
+ vex note evil.com --add "Seen in phishing campaign Q4"
221
+ vex note evil.com # list notes
222
+
223
+ # Watchlists
224
+ vex watchlist priority --add 8.8.8.8 --add evil.com
225
+ vex watchlist priority --list
226
+ ```
227
+
228
+ ### Plugin Architecture
229
+
230
+ vex uses a Protocol-based plugin system. The built-in VirusTotal plugin implements `EnricherProtocol`. Third-party sources (OTX, AbuseIPDB, etc.) can be added by implementing the same protocol.
231
+
232
+ ---
233
+
234
+ ## Config Reference
235
+
236
+ ```yaml
237
+ api:
238
+ # key: "your-key" # or set VT_API_KEY env var
239
+ tier: free # free | premium
240
+ rate_limit:
241
+ free:
242
+ requests_per_minute: 4
243
+ requests_per_day: 500
244
+ premium:
245
+ requests_per_minute: 1000
246
+ requests_per_day: 50000
247
+
248
+ thresholds:
249
+ malicious_min_detections: 3
250
+ suspicious_min_detections: 1
251
+ min_engines_for_clean: 10
252
+
253
+ cache:
254
+ enabled: true
255
+ ttl_hours: 24
256
+ # db_path: "/custom/path/cache.db" # default: ~/.vex/cache.db
257
+
258
+ output:
259
+ default_format: json
260
+ quiet: false # suppress banner (-q)
261
+ ```
262
+
263
+ ---
264
+
265
+ ## Project Structure
266
+
267
+ ```
268
+ vex/
269
+ ├── __init__.py # Package version (1.1.0)
270
+ ├── main.py # Typer CLI app with all subcommands
271
+ ├── banner.py # ASCII art banner (ffuf-style)
272
+ ├── client.py # Sync VT API v3 client + rate limiter
273
+ ├── async_client.py # Async VT API client for parallel ops
274
+ ├── config.py # Pydantic config from config.yaml
275
+ ├── cache.py # SQLite result cache with TTL
276
+ ├── ioc_detector.py # Regex auto-detection of IOC types
277
+ ├── defang.py # IOC defanging/refanging
278
+ ├── models.py # Pydantic v2 models + Verdict enum
279
+ ├── batch.py # Parallel batch processing
280
+ ├── timeline.py # Timeline event reconstruction
281
+ ├── vex.png # Logo
282
+ ├── enrichers/
283
+ │ ├── base.py # Shared enricher utilities
284
+ │ ├── protocol.py # EnricherProtocol interface
285
+ │ ├── hash.py # MD5/SHA1/SHA256 enrichment
286
+ │ ├── ip.py # IPv4/IPv6 enrichment
287
+ │ ├── domain.py # Domain enrichment
288
+ │ └── url.py # URL enrichment
289
+ ├── plugins/
290
+ │ ├── registry.py # Plugin discovery & registration
291
+ │ ├── loader.py # Plugin loading
292
+ │ └── virustotal.py # Built-in VT plugin
293
+ ├── mitre/
294
+ │ ├── mapping.py # VT behavior → ATT&CK technique dict
295
+ │ └── mapper.py # Result → ATT&CK mapping engine
296
+ ├── knowledge/
297
+ │ ├── db.py # SQLite knowledge base (tags/notes/watchlists)
298
+ │ └── api.py # High-level knowledge base API
299
+ └── output/
300
+ ├── formatter.py # Rich + console + timeline formatters
301
+ ├── export.py # JSON + CSV export
302
+ └── stix.py # STIX 2.1 bundle generation
303
+ ```
304
+
305
+ ---
306
+
307
+ *Built by [Christian Huhn](https://github.com/duathron) — [github.com/duathron/vex](https://github.com/duathron/vex)*
@@ -0,0 +1,48 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "vex-ioc"
7
+ version = "1.1.0"
8
+ description = "VirusTotal IOC Enrichment Tool for SOC/DFIR workflows"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.11"
12
+ authors = [
13
+ { name = "Christian Huhn", email = "duathron@gmail.com" },
14
+ ]
15
+ keywords = ["virustotal", "ioc", "threat-intelligence", "dfir", "soc", "mitre-attack", "stix"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Environment :: Console",
19
+ "Intended Audience :: Information Technology",
20
+ "Topic :: Security",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.13",
24
+ "Programming Language :: Python :: 3.14",
25
+ ]
26
+ dependencies = [
27
+ "httpx>=0.27.0",
28
+ "typer>=0.12.0",
29
+ "rich>=13.7.0",
30
+ "pydantic>=2.7.0",
31
+ "pyyaml>=6.0.1",
32
+ "python-dotenv>=1.0.0",
33
+ ]
34
+
35
+ [project.scripts]
36
+ vex = "vex.main:main"
37
+
38
+ [project.entry-points."vex.plugins"]
39
+ # Third-party plugins register here. Example:
40
+ # my-plugin = "my_package.plugin:MyPlugin"
41
+
42
+ [project.urls]
43
+ Homepage = "https://github.com/duathron/vex"
44
+ Repository = "https://github.com/duathron/vex"
45
+ "Bug Tracker" = "https://github.com/duathron/vex/issues"
46
+
47
+ [tool.setuptools.packages.find]
48
+ include = ["vex*"]