© VampSecure Studios — VampSecure Labs Security Research Division
🇬🇧 English
Self-service forensic queries over logs and user events, without requiring an LLM, that produce court-ready evidence on their own: a signed report, chain of custody (SHA-256 of sources), and a tamper-proof ZIP package (MANIFEST.sha256).
Designed to answer specific investigation questions — "how many distinct national IDs changed password in 2026, which ones and how many times?", "give me the exact timeline for this account" — in a deterministic and reproducible way.
How it works
- Ingests any tabular source (CSV/XLSX) into a normalized event model
(entity, type, action, datetime, IP, status, source). - Auto-classifies the entity:
DNI(8 digits+letter),NIE,CIF,email,IPv4. - Queries via CLI (no AI):
distinct,top,timeline,events,sql. - Generates evidence: for each query writes the result (CSV+JSON), a forensic HTML report
(with the reproducible query, methodology, chain of custody and legal notice) and, with
--evidence, a signed ZIP withMANIFEST.sha256for each artefact +cadena_de_custodia.json.
Queries
| Query | Returns |
|---|---|
distinct |
Distinct entities + occurrence count, first/last event, number of IPs, and type distribution |
top |
Like distinct but only repeat offenders (--min-count N) |
timeline |
Exact chronology (datetime + IP + status) for one entity (--entity) |
events |
All events matching the applied filters |
sql |
Free SELECT (read-only) over the events table |
Filters
--action, --entity, --entity-type {DNI,NIE,CIF,email,IPv4,otro}, --ip, --year,
--from/--to (YYYY-MM-DD), --min-count.
Column mapping
With --map role=column or a reusable profile (--profile client.json):
{ "sep": ";", "action_const": "password_change",
"map": { "entity": "Usuario", "ts": "CreatedAt", "ip": "Datos" } }
--action-const fixes the action for the entire source (useful when the file contains a single event type,
e.g. a password-change export). --sep re-splits sources whose fields arrive in a single column.
Examples
# How many distinct DNIs changed password in 2026 (+ signed evidence)
vamp_forensic_query.py Passwords.xlsx distinct \
--profile client.json --year 2026 --entity-type DNI \
--case "CASE-2026-001" --analyst "Expert — VampSecure Labs" --evidence
# Exact timeline for one account
vamp_forensic_query.py Passwords.xlsx timeline --profile client.json --entity 11723541G
# Repeat offenders (>=4 events) of all types, with evidence
vamp_forensic_query.py Passwords.xlsx top --profile client.json --action password_change \
--year 2026 --min-count 4 --evidence
# Free query
vamp_forensic_query.py Access.csv sql --map entity=Usuario ts=Fecha ip=IP \
--sql "SELECT ip, COUNT(DISTINCT entity) n FROM events GROUP BY ip HAVING n>=3 ORDER BY n DESC"
Evidence output
Each query with --evidence produces in --out:
query_<UTC>.json— result + metadata + reproducible query + chain of custodyquery_<UTC>.csv— tabulated resultquery_<UTC>.html— forensic reportquery_<UTC>_evidence.zip— sealed package (MANIFEST.sha256+cadena_de_custodia.json)
Integrity: any single-byte alteration to source files changes their SHA-256 and breaks the chain
of custody; any artefact alteration breaks its hash in the MANIFEST. Results are verifiable by
re-running the exact query over files with identical hashes.
Installation
pip install vamp-forensic-query
# or with Homebrew:
brew install vampsecure-labs/labs/vamp-forensic-query
Requirements
- Python 3.9+ (stdlib). For
.xlsxsources:pip install pandas openpyxl.
Finding prefix
Not applicable (this is a query/evidence tool, not a detection tool). It complements
vamp-log-analyzer (FORA-NNN detection) by providing the ad-hoc query + evidence layer.
Sample Output
$ vamp_forensic_query.py Passwords.xlsx distinct \
--profile client.json --year 2026 --entity-type DNI \
--case "CASE-2026-001" --analyst "Expert — VampSecure Labs" --evidence
vamp-forensic-query v1.4 — VampSecure Labs
Source: Passwords.xlsx (SHA-256: 3a9f...c204) | Rows ingested: 18 432
Profile: client.json | Entity type filter: DNI | Year: 2026
Case: CASE-2026-001 | Analyst: Expert — VampSecure Labs
Query: DISTINCT ─────────────────────────────────────────────────────────────────
Entity Type Events IPs First event Last event
─────────────────────────────────────────────────────────────────────────────────
11723541G DNI 14 5 2026-01-14 09:22:03 2026-09-30 17:41:10
28901234A DNI 9 3 2026-02-03 08:05:52 2026-08-11 16:30:07
47812345B DNI 7 1 2026-03-22 11:18:44 2026-09-01 09:55:30
52934812C DNI 4 2 2026-04-17 07:40:12 2026-07-29 14:22:03
63801234D DNI 3 1 2026-06-08 16:02:55 2026-09-12 10:41:57
74523018E DNI 2 1 2026-07-23 13:55:01 2026-09-28 08:17:44
─────────────────────────────────────────────────────────────────────────────────
Totals: 6 distinct DNI · 39 events · sources: 1
Evidence package written to ./CASE-2026-001/
query_20261008T091203Z.json
query_20261008T091203Z.csv
query_20261008T091203Z.html
query_20261008T091203Z_evidence.zip (MANIFEST.sha256 included)
Why vamp-forensic-query vs. Splunk · Elastic SIEM · manual SQL queries
| Capability | vamp-forensic-query | Splunk | Elastic SIEM | Manual SQL |
|---|---|---|---|---|
| Zero infrastructure — single Python script | ✅ | ❌ server required | ❌ cluster required | ⚠️ DB required |
| Chain-of-custody ZIP with SHA-256 manifest | ✅ | ❌ | ❌ | ❌ |
| ISO 27043 / RFC 3227 compliant evidence output | ✅ | ❌ | ❌ | ❌ |
| Auto-classification DNI / NIE / CIF / email / IPv4 | ✅ | ❌ manual regex | ❌ manual mapping | ❌ manual |
| Signed forensic HTML report | ✅ | ❌ | ❌ | ❌ |
| Ingest CSV + XLSX with column remapping | ✅ | ✅ | ✅ | ⚠️ import step |
| Streaming for sources >500 MB (zero RAM materialization) | ✅ | ✅ | ✅ | ⚠️ varies |
| Reproducible query embedded in evidence artefact | ✅ | ❌ | ❌ | ⚠️ manual |
- Court-ready by design: every
--evidencerun produces a sealed ZIP with aMANIFEST.sha256that cryptographically ties each artefact to the source files; any post-hoc alteration breaks the chain. - No infrastructure, no licence cost: Splunk and Elastic require servers, ingestion pipelines, and licence agreements that take days to procure in an incident response scenario.
vamp-forensic-queryruns on a laptop in under a minute. - Entity-type awareness: automatic classification of DNI, NIE, CIF, email, and IPv4 means investigators can ask "how many distinct DNIs?" without writing regex or custom ETL.
- Forensic report as first-class output: the generated HTML includes the exact query, methodology, legal disclaimer, and custody chain — ready to attach to a judicial proceeding without further editing.
Check Coverage
| Check ID | Description | Standard | Severity |
|---|---|---|---|
| FQ-001 | Source file SHA-256 computed and recorded in chain-of-custody | ISO 27043 §10, RFC 3227 §2.2 | INFO |
| FQ-002 | MANIFEST.sha256 generated and verified for all evidence artefacts | ISO 27043 §11 | INFO |
| FQ-003 | Entity auto-classification: DNI pattern (8 digits + checksum letter) | ISO 27043 §8 | INFO |
| FQ-004 | Entity auto-classification: NIE (X/Y/Z + 7 digits + letter) | ISO 27043 §8 | INFO |
| FQ-005 | Entity auto-classification: CIF (letter + 7 digits + control character) | ISO 27043 §8 | INFO |
| FQ-006 | Entity auto-classification: email address (RFC 5321 pattern) | ISO 27043 §8 | INFO |
| FQ-007 | Entity auto-classification: IPv4 address | ISO 27043 §8 | INFO |
| FQ-008 | Reproducible query string embedded in JSON evidence artefact | RFC 3227 §2.1 | INFO |
| FQ-009 | Streaming mode activated for sources ≥ 500 MB (zero RAM materialization) | ISO 27043 §9 | INFO |
| FQ-010 | --sql mode enforces SELECT-only (INSERT/UPDATE/DELETE/DROP rejected) |
ISO 27043 §10 | HIGH |
Version History
| Version | Main changes |
|---|---|
| v1.4 | Bilingual README (EN/ES) |
| v1.3 | Streaming mode for logs >500 MB: _read_rows is a generator (zero RAM materialization), automatic SQLite on disk when source ≥500 MB; --stream flag to force it |
| v1.2 | Binary analysis (PE/ELF/ZIP/MACH-O), improved chain of custody |
| v1.1 | Advanced queries, SHA-256 signed evidence ZIP package |
🇪🇸 Español
Consultas forenses self-service sobre logs y eventos de usuario, sin necesidad de un LLM,
que generan por sí solas la evidencia lista para peritaje: informe firmado, cadena de custodia
(SHA-256 de las fuentes) y paquete ZIP a prueba de manipulación (MANIFEST.sha256).
Pensado para responder preguntas concretas de una investigación —"¿cuántos DNI distintos cambiaron la contraseña en 2026, cuáles y cuántas veces?", "dame la cronología exacta de esta cuenta"— de forma determinista y reproducible.
Cómo funciona
- Ingesta cualquier fuente tabular (CSV/XLSX) a un modelo normalizado de eventos
(entidad, tipo, acción, fecha_hora, IP, estado, fuente). - Clasifica la entidad automáticamente:
DNI(8 díg.+letra),NIE,CIF,email,IPv4. - Consulta con la CLI (sin IA):
distinct,top,timeline,events,sql. - Genera evidencia: por cada consulta escribe resultado (CSV+JSON), informe pericial HTML
(con la consulta reproducible, metodología, cadena de custodia y nota legal) y, con
--evidence, un ZIP firmado conMANIFEST.sha256de cada artefacto +cadena_de_custodia.json.
Consultas
| Consulta | Qué devuelve |
|---|---|
distinct |
Entidades distintas + nº de veces, primero/último evento, nº de IPs, y distribución por tipo |
top |
Como distinct pero solo reincidentes (--min-count N) |
timeline |
Cronología exacta (fecha-hora + IP + estado) de una entidad (--entity) |
events |
Todos los eventos que cumplen los filtros |
sql |
SELECT libre (solo lectura) sobre la tabla events |
Filtros
--action, --entity, --entity-type {DNI,NIE,CIF,email,IPv4,otro}, --ip, --year,
--from/--to (YYYY-MM-DD), --min-count.
Mapeo de columnas
Con --map rol=columna o un perfil reutilizable (--profile cliente.json):
{ "sep": ";", "action_const": "password_change",
"map": { "entity": "Usuario", "ts": "CreatedAt", "ip": "Datos" } }
--action-const fija la acción para toda la fuente (útil si el fichero es de un solo tipo de evento,
p. ej. un export de cambios de contraseña). --sep re-divide fuentes cuyos campos vienen en una sola
columna.
Ejemplos
# Cuántos DNI distintos cambiaron contraseña en 2026 (+ evidencia firmada)
vamp_forensic_query.py Contrasenas.xlsx distinct \
--profile cliente.json --year 2026 --entity-type DNI \
--case "CASO-2026-001" --analyst "Perito — VampSecure Labs" --evidence
# Cronología exacta de una cuenta
vamp_forensic_query.py Contrasenas.xlsx timeline --profile cliente.json --entity 11723541G
# Reincidentes (>=4 eventos) de todos los tipos, con evidencia
vamp_forensic_query.py Contrasenas.xlsx top --profile cliente.json --action password_change \
--year 2026 --min-count 4 --evidence
# Consulta libre
vamp_forensic_query.py Acceso.csv sql --map entity=Usuario ts=Fecha ip=IP \
--sql "SELECT ip, COUNT(DISTINCT entity) n FROM events GROUP BY ip HAVING n>=3 ORDER BY n DESC"
Salida de evidencia
Cada consulta con --evidence produce en --out:
consulta_<UTC>.json— resultado + metadatos + consulta reproducible + cadena de custodiaconsulta_<UTC>.csv— resultado tabuladoconsulta_<UTC>.html— informe pericialconsulta_<UTC>_evidencia.zip— paquete sellado (MANIFEST.sha256+cadena_de_custodia.json)
Integridad: cualquier alteración de un byte de las fuentes cambia su SHA-256 y rompe la cadena
de custodia; cualquier alteración de un artefacto rompe su hash en el MANIFEST. Los resultados son
verificables reejecutando la consulta indicada sobre ficheros de idéntico hash.
Instalación
pip install vamp-forensic-query
# o con Homebrew:
brew install vampsecure-labs/labs/vamp-forensic-query
Requisitos
- Python 3.9+ (stdlib). Para fuentes
.xlsx:pip install pandas openpyxl.
Prefijo de hallazgos
No aplica (es una herramienta de consulta/evidencia, no de detección). Complementa a
vamp-log-analyzer (detección FORA-NNN) aportando la capa de consulta ad-hoc + evidencia.
Salida de ejemplo
$ vamp_forensic_query.py Contrasenas.xlsx distinct \
--profile cliente.json --year 2026 --entity-type DNI \
--case "CASO-2026-001" --analyst "Perito — VampSecure Labs" --evidence
vamp-forensic-query v1.4 — VampSecure Labs
Source: Contrasenas.xlsx (SHA-256: 3a9f...c204) | Rows ingested: 18 432
Profile: cliente.json | Entity type filter: DNI | Year: 2026
Case: CASO-2026-001 | Analyst: Perito — VampSecure Labs
Query: DISTINCT ─────────────────────────────────────────────────────────────────
Entity Type Events IPs First event Last event
─────────────────────────────────────────────────────────────────────────────────
11723541G DNI 14 5 2026-01-14 09:22:03 2026-09-30 17:41:10
28901234A DNI 9 3 2026-02-03 08:05:52 2026-08-11 16:30:07
47812345B DNI 7 1 2026-03-22 11:18:44 2026-09-01 09:55:30
52934812C DNI 4 2 2026-04-17 07:40:12 2026-07-29 14:22:03
63801234D DNI 3 1 2026-06-08 16:02:55 2026-09-12 10:41:57
74523018E DNI 2 1 2026-07-23 13:55:01 2026-09-28 08:17:44
─────────────────────────────────────────────────────────────────────────────────
Totals: 6 distinct DNI · 39 events · sources: 1
Evidence package written to ./CASO-2026-001/
consulta_20261008T091203Z.json
consulta_20261008T091203Z.csv
consulta_20261008T091203Z.html
consulta_20261008T091203Z_evidencia.zip (MANIFEST.sha256 included)
Por qué vamp-forensic-query frente a Splunk · Elastic SIEM · consultas SQL manuales
| Capacidad | vamp-forensic-query | Splunk | Elastic SIEM | SQL manual |
|---|---|---|---|---|
| Sin infraestructura — script Python único | ✅ | ❌ servidor requerido | ❌ cluster requerido | ⚠️ BD requerida |
| ZIP de cadena de custodia con manifiesto SHA-256 | ✅ | ❌ | ❌ | ❌ |
| Salida de evidencia conforme ISO 27043 / RFC 3227 | ✅ | ❌ | ❌ | ❌ |
| Auto-clasificación DNI / NIE / CIF / email / IPv4 | ✅ | ❌ regex manual | ❌ mapeo manual | ❌ manual |
| Informe pericial HTML firmado | ✅ | ❌ | ❌ | ❌ |
| Ingesta CSV + XLSX con remapeo de columnas | ✅ | ✅ | ✅ | ⚠️ paso de importación |
| Streaming para fuentes >500 MB (cero materialización en RAM) | ✅ | ✅ | ✅ | ⚠️ variable |
| Consulta reproducible embebida en artefacto de evidencia | ✅ | ❌ | ❌ | ⚠️ manual |
- Listo para el juzgado por diseño: cada ejecución con
--evidenceproduce un ZIP sellado conMANIFEST.sha256que vincula criptográficamente cada artefacto a los ficheros fuente; cualquier alteración posterior rompe la cadena. - Sin infraestructura, sin coste de licencia: Splunk y Elastic requieren servidores, pipelines de ingesta y contratos de licencia que tardan días en conseguirse en un escenario de respuesta a incidentes.
vamp-forensic-queryfunciona en un portátil en menos de un minuto. - Consciencia del tipo de entidad: la clasificación automática de DNI, NIE, CIF, email e IPv4 permite a los investigadores preguntar "¿cuántos DNI distintos?" sin escribir regex ni ETL personalizado.
- Informe pericial como salida de primer orden: el HTML generado incluye la consulta exacta, metodología, aviso legal y cadena de custodia — listo para adjuntar a un procedimiento judicial sin edición adicional.
Cobertura de checks
| Check ID | Descripción | Estándar | Severidad |
|---|---|---|---|
| FQ-001 | SHA-256 del fichero fuente calculado y registrado en la cadena de custodia | ISO 27043 §10, RFC 3227 §2.2 | INFO |
| FQ-002 | MANIFEST.sha256 generado y verificado para todos los artefactos de evidencia | ISO 27043 §11 | INFO |
| FQ-003 | Auto-clasificación de entidad: patrón DNI (8 dígitos + letra de control) | ISO 27043 §8 | INFO |
| FQ-004 | Auto-clasificación de entidad: NIE (X/Y/Z + 7 dígitos + letra) | ISO 27043 §8 | INFO |
| FQ-005 | Auto-clasificación de entidad: CIF (letra + 7 dígitos + carácter de control) | ISO 27043 §8 | INFO |
| FQ-006 | Auto-clasificación de entidad: dirección email (patrón RFC 5321) | ISO 27043 §8 | INFO |
| FQ-007 | Auto-clasificación de entidad: dirección IPv4 | ISO 27043 §8 | INFO |
| FQ-008 | Cadena de consulta reproducible embebida en artefacto JSON de evidencia | RFC 3227 §2.1 | INFO |
| FQ-009 | Modo streaming activado para fuentes ≥ 500 MB (cero materialización en RAM) | ISO 27043 §9 | INFO |
| FQ-010 | Modo --sql impone solo SELECT (INSERT/UPDATE/DELETE/DROP rechazados) |
ISO 27043 §10 | HIGH |
Historial de versiones
| Versión | Cambios principales |
|---|---|
| v1.4 | README bilingüe (EN/ES) |
| v1.3 | Modo streaming para logs >500 MB: _read_rows es generador (cero materialización en RAM), SQLite en disco automático cuando fuente ≥500 MB; flag --stream para forzarlo |
| v1.2 | Análisis binario (PE/ELF/ZIP/MACH-O), cadena de custodia mejorada |
| v1.1 | Consultas avanzadas, paquete ZIP de evidencia firmado SHA-256 |
Metadata
Release files for vamp-forensic-query 1.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| vamp_forensic_query-1.3.tar.gz | 42.6 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| vamp_forensic_query-1.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 74.8 kB
Release files / vamp_forensic_query-1.3.tar.gz
| Download URL | vamp_forensic_query-1.3.tar.gz |
|---|---|
| Size | 42.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4a89d3fcc626b59a7aed29aff94087c07dfc3bc382147b9004fb42e6a0b25777
|
|
BLAKE2b-256 checksum How to use checksums |
d9fbb27a92b66415d90c2dfee1182b41e3b07528c6d50ae175bc02086305cf06
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / vamp_forensic_query-1.3-py3-none-any.whl
| Download URL | vamp_forensic_query-1.3-py3-none-any.whl |
|---|---|
| Size | 32.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5d0b03ecd3d5e38113b20e15006a0cc4018528a13d5f11364ad38d4f495b6426
|
|
BLAKE2b-256 checksum How to use checksums |
f33cc943be4abf0c61a671c0b0bd297a1ccd5aff46a9dd8942c597816dd3d64a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Security for vamp-forensic-query 1.3
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.