
Punteggio dei percorsi di attacco di BloodHound consapevole del rilevamento - trova il percorso più silenzioso verso il tuo obiettivo, calibrato sui livelli di audit/EDR/SIEM.

Punteggio dei percorsi di attacco Active Directory consapevole del rilevamento. DreadHost Research | complemento di OffsetInspect (PowerShell) e OffsetScan (Rust)
BloodHound (e PlumHound sopra di esso) trova un percorso verso l'obiettivo. NoiseHound acquisisce gli stessi dati del grafo e riordina i percorsi in base al costo di rilevamento atteso invece che al numero di hop, così un operatore può chiedersi "qual è il modo più silenzioso per arrivare a Domain Admin" invece che solo "qual è un modo".
Nuovo qui? Inizia con la Procedura guidata per l'operatore — un tutorial pratico e guidato da screenshot che ti porta dall'installazione a una prova di concetto live con BloodHound CE (i punteggi vengono riscritti nell'interfaccia di BloodHound UI), al motore DeadAir e al report delle lacune di rilevamento per il blue team.
Stato del progetto (v1.0): stabile e testato su dati BloodHound reali in più domini. 30 dei 57 archi del corpus sono ora misurati in laboratorio su quattro livelli di rilevamento (audit, Defender for Endpoint, Elastic SIEM e postura MDI) - distribuiti come profili plug-and-play in
profiles/, con prova a ciclo chiuso che cambiano le classifiche dei percorsi (docs/VALIDATION.md). I restanti ~28 archi hanno ancora stime di esperti; la suite di calibrazione (noisehound-calibrate,docs/CALIBRATION.md) è il modo in cui essi, e il vostro ambiente, vengono misurati. Trattate le classifiche non calibrate come indicazioni ben motivate, non come verità assoluta.
Solo per attività autorizzate. Questo strumento valuta i percorsi di attacco per la pianificazione OPSEC contro sistemi per cui hai il permesso scritto di testare.
NoiseHound è un progetto comunitario indipendente. Non è affiliato a, approvato da o associato a SpecterOps o al progetto BloodHound; consuma il formato dati aperto di BloodHound.
.zip), un file JSON grezzo o una directory
di esportazioni in un grafo interno. Viene accettato anche un formato JSON normalizzato {nodes, edges}
per analisi offline e test. Gli archi di escalation AD CS ESC1-8
vengono sintetizzati al caricamento dai fatti sui modelli di certificato e sulle CA
che BloodHound raccoglie (vedi sotto).effective_noise_score (0-100). Quando più diritti collegano la stessa coppia
di nodi, viene scelto il più silenzioso. I tipi di arco assenti dal corpus hanno come
predefinito un punteggio conservativo (60), così le lacune falliscono in sicurezza invece di sotto-segnalare.
Un profilo ambientale facoltativo adatta i punteggi alla postura di rilevamento dichiarata del bersaglio
(vedi sotto).Il rumore del percorso non è, di proposito, una semplice somma. Attivare la stessa rilevazione due volte non è due volte più rumoroso (triage SOC, non conteggio grezzo di eventi). NoiseHound usa:``` path_score = max(edge_scores) * 0.6 + mean(edge_scores) * 0.4
Questo approccio tende a dare più peso al singolo passo più rumoroso (un passo sbagliato spesso brucia l'intera operazione) pur tenendo conto dell'esposizione cumulativa. I pesi sono configurabili (`--max-weight` / `--mean-weight`) così da poter essere tarati empiricamente una volta che i dati di rilevamento reali saranno disponibili da un laboratorio APT29/Caldera.
Ogni percorso riporta anche una **probabilità di rilevamento** - la probabilità che inneschi un avviso correlato - combinando l'arco più rumoroso con il noisy-OR cumulativo di tutti gli archi (regolato tramite `--correlation`). Risponde a una domanda diversa rispetto al punteggio di rumore: un percorso breve ma rumoroso può avere una probabilità complessiva *inferiore* di essere scoperto rispetto a uno lungo ma silenzioso. Classifica in base a essa con `--rank-by probability`.
### Motore a due livelli (DeadAir)
Per i grafi di grandi dimensioni la risoluzione viene affidata a [DeadAir](https://github.com/warpedatom/DeadAir), un motore Rust complementare (il livello OffsetScan-to-OffsetInspect). NoiseHound rimane il frontend ricco di funzionalità - ingestione, corpus, ambiente/Sigma, vincoli, reporting - e passa il grafo preparato a qualunque motore lo risolva, quindi i risultati sono identici in entrambi i casi.
- `--engine auto` (predefinito): DeadAir quando il suo binario viene trovato *e* il grafo è grande (>= 5000 nodi); altrimenti il solver Python integrato.
- `--engine python`: forza il solver integrato (nessun binario necessario).
- `--engine rust`: forza DeadAir (errore se il binario manca).
DeadAir viene individuato tramite `$NOISEHOUND_DEADAIR`, poi `PATH`, quindi la build nella cartella sorella `../deadair/target/{release,debug}/`. È da 10 a 100 volte più veloce su grafi di grandi dimensioni (un grafo da 250.000 nodi si risolve in ~2s contro ~30s in Python) producendo classifiche byte per byte identiche. L'output registra quale motore è stato eseguito.
### Percorsi multi-obiettivo e vincolati
Rumore, numero di hop e probabilità di rilevamento spingono in direzioni diverse, quindi `--pareto` restituisce la **frontiera di Pareto** - ogni percorso che nessun altro supera su tutti e tre i criteri contemporaneamente - invece di imporre un unico vincitore. E le operazioni reali hanno vincoli: `--avoid NODE` mantiene un percorso lontano da un host specifico (un jump box monitorato da EDR, un honeypot), e `--avoid-edge TYPE` rifiuta una tecnica (es. `--avoid-edge DCSync`). Entrambi sono ripetibili e rieseguono la risoluzione al volo.```bash
python -m noisehound -i export.zip -s jdoe -o "Domain Admins" --pareto
python -m noisehound -i export.zip -s jdoe -o "Domain Admins" --avoid FILESERVER01 --avoid-edge HasSession
La pathfinding ponderata di BloodHound non è una novità, quindi ecco il posizionamento onesto:
Il contributo di NoiseHound è la combinazione: un corpus leggibile da macchina che collega gli archi di BloodHound alla telemetria di rilevamento, una nuova risoluzione ponderata per il rumore inquadrata come OPSEC dell'operatore ("il modo più silenzioso per arrivare a DA"), un modello di ambiente che si adatta alla postura dichiarata di un target e un ciclo di calibrazione che trasforma le rilevazioni di laboratorio in punteggi misurati. La matematica dei grafi è una commodity; il corpus e la struttura concettuale sono il punto. Il suo valore è pari a quello del corpus, motivo per cui calibrazione e contributo della community sono di prim'ordine: vedi sotto.
cd NoiseHound python -m pip install -r requirements.txt # networkx>=3.0
noisehound command on PATH:python -m pip install -e .
Richiede Python 3.10+.
## Utilizzo```bash
# Text summary (default)
python -m noisehound --input export.zip --objective "Domain Admins" --source jdoe
# JSON, for downstream tooling / correlation across the DreadHost suite
python -m noisehound -i export.zip -o "Domain Admins" -s jdoe -f json --out paths.json
# Self-contained HTML report
python -m noisehound -i export.zip -o "Domain Admins" -s jdoe -f html --out report.html
Innanzitutto, controlla la correttezza del parser sul tuo export (istogrammi + copertura del corpus, senza pathing) - il modo più rapido per validare NoiseHound su dati reali:```bash noisehound-inspect -i export.zip
### Live BloodHound CE / Neo4j
Invece di uno zip, punta `--input` al database Neo4j che BloodHound CE popola
e NoiseHound legge il grafo (già analizzato) direttamente tramite Bolt:```bash
pip install 'noisehound[neo4j]'
export NEO4J_PASSWORD=bloodhoundcommunityedition # match your BHCE compose
noisehound-inspect -i bolt://localhost:7687
python -m noisehound -i bolt://localhost:7687 -s jdoe -o "Domain Admins"
Avvia BloodHound CE (include Neo4j sulla porta 7687) con la sua compose ufficiale:
curl -L https://ghst.ly/getbhce | docker compose -f - up.
Provalo con i sample inclusi:```bash python -m noisehound -i samples/sample_graph.json -s jdoe -o "Domain Admins" -d CONTOSO.LOCAL python -m noisehound -i samples/sample_bloodhound_ce.zip -s jdoe -o "Domain Admins" python -m noisehound -i samples/sample_adcs_ce.zip -s jdoe -o "Domain Admins" # ADCS ESC1
python -m noisehound -i samples/sample_fullspectrum_ce.zip -s ALICE -o "Domain Admins" -d CONTOSO.LOCAL -k 3
Quell'ultimo è la demo più chiara della tesi: la via più silenziosa verso i Domain Admins è il percorso di sessione a 4 hop, classificato *sopra* il percorso RDP a 3 hop e il percorso ADCS ESC1 a 1 hop - più hop, meno rumore.
L'esempio dimostra il valore principale: la via più silenziosa è un percorso di sessione a 4 hop (punteggio 19.9), classificato *sopra* una scorciatoia ForceChangePassword a 2 hop (36.4). Meno hop non significa più silenzioso.
### Modalità di rilevamento dei gap per il blue team
Il percorso più silenzioso è quello in cui il rilevamento è più debole, quindi aggiungi `--defensive` per invertire l'output per i difensori: segnala i collegamenti che sono silenziosi solo perché la loro telemetria è disattivata o assente, associa ciascuno al controllo che lo rileverebbe e classifica questi controlli in base a quanto aumentano il punteggio del percorso più silenzioso.```bash
python -m noisehound -i export.zip -s jdoe -o "Domain Admins" --defensive
Sul campione full-spectrum rileva che il percorso più silenzioso verso Domain Admins
dipende da un accesso LSASS non rilevato (HasSession, 20 -> 65 se instrumentato) e
raccomanda di distribuire Sysmon Event 10: chiudere quella singola lacuna porta il
percorso più silenzioso da 19,9 a 48,4. Vedi docs/ROADMAP.md per sapere dove
questo e il resto del modello stanno andando.
Un punteggio statico del corpus non può sapere se un determinato target ha l'auditing degli oggetti 4662 attivo, se include Sysmon, o se esegue un ITDR come MDI — eppure questi elementi spostano enormemente il rumore reale di un edge (DCSync è quasi silenzioso senza auditing 4662 e quasi certamente rilevato con esso). Invece di fingere che un singolo numero si adatti a ogni ambiente, dichiara la postura del target in un piccolo file JSON e NoiseHound regola i punteggi in modo trasparente rispetto alle annotazioni di telemetria del proprio corpus:```json { "name": "CONTOSO.LOCAL-prod", "object_auditing_4662": true, "ds_change_auditing_5136": false, "edr": "MDI", "sysmon": true, "powershell_logging_4104": true, "adjustments": { "HasSession": 65 } }
Adjustments only ever *raise* a score toward a detection floor implied by the
declared posture. `adjustments` are hard per-edge overrides - the place to
record values you have calibrated against your own lab. This is operator-supplied,
not measured; it does not replace Phase 2 live validation, but it turns the
static corpus from "one number for all environments" into "the number for the
environment you are actually in". On the bundled sample, declaring the profile
above flips the quietest route from the LSASS-dump session path to a
directory-write path - which is the correct call once host telemetry is live.```bash
python -m noisehound -i samples/sample_graph.json -s jdoe -o "Domain Admins" \
-e samples/env_profile.example.json
Precedenza del punteggio: static -> environment-adjusted -> live (Phase 2).
I profili ambientali sono validi solo quanto i numeri che ci inserisci.
noisehound-calibrate chiude il ciclo: esegui le tecniche in un lab di rilevamento,
registra cosa ha attivato, e genera un profilo ambientale calibrato.
È già stato fatto. profiles/ include tre profili misurati da
un reale range Hyper-V Vulnerable-AD - livelli audit, EDR (Defender for Endpoint) ed Elastic
SIEM, 30 edge - prodotti dall'harness automatizzato (lab/) e da questo strumento. Usali
direttamente, oppure misura i tuoi:```bash
noisehound -i export.zip -s jdoe -o "Domain Admins" -e profiles/vulnad-hyperv-audit.json
noisehound-calibrate -i lab_detections.json -o env.calibrated.json noisehound -i export.zip -s jdoe -o "Domain Admins" -e env.calibrated.json
Il modello di punteggio è uno stimatore di shrinkage, onesto riguardo alla dimensione del campione:```
p = detections / runs (detection probability)
lab_score = p * severity_loudness + (1 - p) * residual
w = runs / (runs + smoothing) (confidence in the lab)
calibrated = w * lab_score + (1 - w) * corpus_static
lab_score è il costo di rilevamento atteso - la severità SOC quando scatta,
un piccolo residuo quando non lo fa. Il peso w impedisce a una singola esecuzione di
sovrascrivere il corpus, lasciando che un risultato ben campionato domini.
Nell'esempio, HasSession sale da un valore statico di 20 a 52 (il lab ha rilevato il dump LSASS
in 4 esecuzioni su 5), mentre Kerberoast scende da 60 a 34 (non è mai scattato). Usa
--merge existing.json per sovrapporre una nuova calibrazione su un profilo mantenendo
i suoi flag di postura, e --smoothing / --residual per regolare il modello.
I profili di ambiente e la calibrazione sono auto-dichiarati. noisehound-sigma
assegna punteggi rispetto alle rilevazioni che un difensore ha effettivamente scritte: puntalo
verso un set di regole Sigma e determina su quali archi del corpus ogni regola scatterebbe
(abbinando gli ID degli eventi di telemetria dell'arco e la tecnica ATT&CK), quindi emette un
profilo di ambiente che eleva gli archi coperti - un drop-in per --environment.```bash
noisehound-sigma -r ./sigma-rules/ -o env.sigma.json
python -m noisehound -i export.zip -s jdoe -o "Domain Admins" -e env.sigma.json --defensive
Matching è volutamente conservativo, così da non mascherare mai una lacuna: una regola conta solo se fa riferimento a un ID evento che l'edge genera *e*, quando la regola è etichettata ATT&CK, la sua tecnica coincide — quindi una regola DCSync di DS-Access (4662) non viene erroneamente accreditata di coprire letture LAPS che condividono soltanto l'ID evento. Il report elenca sia ciò che le tue regole coprono sia, più utilmente, gli edge di attacco che nessuna regola copre. Combinato con `--defensive`, questo risponde alla domanda: "date le rilevazioni che ho implementato, dov'è ancora invisibile il mio percorso d'attacco più silenzioso?"
---
## AD CS ESC1-8
Al momento del caricamento, NoiseHound esegue una versione mirata della post-elaborazione ADCS di BloodHound, sintetizzando edge di escalation a partire dai fatti su template/CA conservati. Un diritto `Enroll` su un template vulnerabile diventa un edge `ADCSESCn` diretto dal principal al gruppo Domain Admins del dominio (RID 512), così l'escalation tramite certificati è percorribile e valutata come qualsiasi altro edge:
| Edge | Condizione |
|------|-----------|
| `ADCSESC1` | Subject fornito dal richiedente + EKU client-auth, nessuna firma di approvazione/RA |
| `ADCSESC2` | EKU Any-Purpose / SubCA, nessuna approvazione |
| `ADCSESC3` | Template enrollment-agent + un template di autenticazione sulla stessa CA |
| `ADCSESC4` | Controllo in scrittura pericoloso su un template pubblicato |
| `ADCSESC5` | Controllo dell'oggetto CA o del computer che la ospita |
| `ADCSESC6` | CA con `EDITF_ATTRIBUTESUBJECTALTNAME2` impostato |
| `ADCSESC7` | `ManageCA` / `ManageCertificates` sulla CA |
| `ADCSESC8` | Endpoint HTTP di web-enrollment vulnerabile (coerce + relay NTLM) |
Provalo: `python -m noisehound -i samples/sample_adcs_ce.zip -s jdoe -o "Domain Admins"`.
Semplificazioni documentate (falliscono in modo sicuro mostrando più percorsi): le restrizioni di enrollment a livello di CA non sono modellate (l'enrollment tramite template è considerato sufficiente); ESC5 copre l'oggetto CA e il suo host, non ogni contenitore PKI; ESC9/10/13 sono fuori scope. Gli edge ESC sintetici già presenti in un export post-elaborato vengono preservati.
---
## Il corpus (`edge_mappings/`)
Il corpus edge-telemetry è la vera proprietà intellettuale di questo strumento; il codice è una matematica grafica relativamente semplice sopra di esso. Ogni `edge_mappings/<Edge>.json` mappa un tipo di edge di BloodHound alla sua superficie di rilevamento:
- sorgenti di telemetria previste (Windows Security Event ID, Sysmon Event ID, rete, euristiche EDR/ITDR) con affidabilità per sorgente e indicazione se l'audit pertinente è attivo per impostazione predefinita
- uno score di rumore statico (0-100)
- tecnica MITRE, privilegio prerequisito, la consueta primitiva di abuso e note```json
{
"edge_type": "DCSync",
"static_noise_score": 85,
"telemetry": [
{"source": "windows_security", "event_id": 4662,
"detail": "Directory Service Access - requires object auditing (default OFF)",
"reliability": "high_if_auditing_enabled", "default_enabled": false},
{"source": "edr_heuristic", "product_class": "MDI",
"detail": "Non-DC hosts issuing DRSGetNCChanges - high fidelity",
"reliability": "high"}
],
"mitre_technique": "T1003.006",
"notes": "Assumes default audit policy (mostly OFF) but high EDR/MDI coverage."
}
Estendere il corpus è dove dovrebbe andare la maggior parte dello sforzo continuo. Aggiungi un nuovo file JSON, mantieni lo schema (validato al caricamento) e verrà rilevato automaticamente. v0.3 include 43 tipi di edge che coprono gli edge relativi ad abuso ACL, Kerberos, delega, ADCS ESC1-8, LAPS/gMSA, GPO, trust e diritti di accesso rilevanti per il path-finding.
I punteggi sono inizializzati dalla noise matrix del DreadHost Red Team Operator Playbook (mappature degli eventi Windows/Sysmon, valutazioni del rumore delle tecniche) e dai fatti standard di rilevamento AD. Calibrali in base ai dati di rilevamento del tuo laboratorio.
profiles/ (livelli audit / EDR / Elastic) con validazione a ciclo chiuso. Restanti: gli altri ~28 edge (coercion/relay, ADCS ESC2-13, CanRDP), il livello degli alert runtime MDI (la postura funziona; il percorso degli alert richiede un DC bare-metal/Ludus - vedi docs/CALIBRATION.md), e un asse dei profili degli strumenti selezionabile (docs/TOOLING_AXIS.md) per far sì che i punteggi riflettano la tradecraft pronta all'uso rispetto a quella nativa.live_noise_score ricavato dalla configurazione Defender/Sysmon/audit di un target reale, riutilizzando la logica di detection-boundary di OffsetInspect. annotate() accetta già un override live_scores; l'hook CLI arriverà nella Fase 2.Il corpus è estensibile dalla community ed è lì che i contributi contano di più. Aggiungere un edge è un singolo file JSON validato al caricamento e nella CI:```bash noisehound-validate # schema + consistency checks over the corpus python -m pytest tests/ -q
Vedi [CONTRIBUTING.md](https://github.com/warpedatom/noisehound/blob/HEAD/CONTRIBUTING.md) per lo schema, la guida al punteggio e le linee guida per le PR, e [`docs/edge_schema.json`](https://github.com/warpedatom/noisehound/blob/HEAD/docs/edge_schema.json) per lo schema formale degli edge.
## Calibrazione con un lab
30 edge vengono misurati (vedi [`profiles/`](https://github.com/warpedatom/noisehound/blob/HEAD/profiles/)); gli altri sono stime finché non li misuri, e ogni ambiente è diverso. [`docs/CALIBRATION.md`](https://github.com/warpedatom/noisehound/blob/HEAD/docs/CALIBRATION.md) è un playbook completo: topologia del lab, l'esatta policy di audit di Windows e la configurazione di Sysmon per far scattare gli event ID del corpus, un runbook di esercitazione per ogni edge, un livello di realismo APT29-via-Caldera, e come consolidare i risultati in un profilo calibrato. Inizia con `noisehound-calibrate --template -o lab_detections.json`.
Il kit [`lab/`](https://github.com/warpedatom/noisehound/blob/HEAD/lab/) automatizza la strumentazione per le rilevazioni: `Enable-Telemetry.ps1` attiva la policy di audit, il logging dei blocchi di script, la SACL DCSync e Sysmon; `Collect-Detections.ps1` conta ciò che è scattato in una finestra temporale. Si appoggia a [GOAD](https://github.com/Orange-Cyberdefense/GOAD) o [Vulnerable-AD](https://github.com/WazeHell/vulnerable-AD) (o al tuo lab CRTP/CRTO) per il dominio vulnerabile stesso, invece di reimplementarli.
## Uso responsabile
NoiseHound è per test di sicurezza autorizzati, esercitazioni purple-team, ingegneria delle rilevazioni e ricerca. Legge i dati di BloodHound che hai già raccolto e calcola classifiche; non esegue nulla contro un target. Usalo solo dove hai esplicita autorizzazione scritta. I contributi non devono includere dati specifici di un target o dati di engagement reali.
## Test```bash
python -m pytest tests/ # with pytest
python tests/test_noisehound.py # dependency-light smoke run
noisehound/ engine: schema, corpus, ingest, adcs, annotate, environment, solver, report, cli, calibrate edge_mappings/ the telemetry corpus (one JSON per edge type) - the IP samples/ sample_graph.json, sample_bloodhound_ce.zip, sample_adcs_ce.zip, sample_fullspectrum_ce.zip, env_profile.example.json, lab_detections.example.json, sample_report.html docs/ WALKTHROUGH.md (start here), CYPHER.md, VALIDATION.md, CALIBRATION.md, ROADMAP.md, seed_demo_graph.cypher, seed_showcase_graph.cypher, images/ tests/ unit + end-to-end tests
| Opzione | Significato |
|---|
--input, -i | BloodHound .zip, .json o directory di esportazioni |
--source, -s | Principal di partenza (jdoe o un object id) |
--objective, -o | Nodo target (Domain Admins o un object id) |
--paths, -k | Numero di percorsi più silenziosi da restituire (default 5) |
--format, -f | text (default), json o html |
--defensive | Vista blue-team: lacune di rilevamento sui percorsi più silenziosi + correzioni |
--rank-by | noise (default) o probability (P di un alert correlato) |
--correlation | Coefficiente di correlazione SOC per P(detected), 0..1 (default 0,5) |
--pareto | Restituisce la frontiera di Pareto su noise/hops/P(detect) |
--engine | auto (default), python o rust (il motore DeadAir) |
--avoid NODE | Esclude un nodo da tutti i percorsi (ripetibile) |
--avoid-edge TYPE | Esclude un tipo di edge da tutti i percorsi (ripetibile) |
--corpus | Sostituisce la directory del corpus di edge-mapping |
--environment, -e | JSON della postura target dichiarata dall'operatore (regola i punteggi) |
--max-weight / --mean-weight | Pesi di scoring (devono sommare a 1,0) |
--default-noise | Punteggio per i tipi di edge assenti dal corpus (default 60) |