Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
SPiCa — Rilevatore di rootkit Linux basato su eBPF che utilizza analisi multi-canale a vista incrociata (sched_switch, NMI, /proc) per rilevare DKOM, manomissioni dei tracepoint e occultamento di processi con verifica dell'integrità a livello hardware. | Kitploit
Strumenti/GitHubGitHub/0xkirisame/spica
Strumenti DifensiviGestione degli Indicatori di Compromissione (IOC)Informatica ForenseAnalisi MalwareAnalisi di BinariRilevamento IntrusioniPaper e RicercaApprendimento e FormazioneRisposta agli IncidentiRilevamento di Anomalie
GitHub0xkirisame/spica
10461 mese faRevisionato da Kitploit

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

SPiCa

Rilevatore di rootkit Linux basato su eBPF che utilizza analisi multi-canale a vista incrociata (sched_switch, NMI, /proc) per rilevare DKOM, manomissioni dei tracepoint e occultamento di processi con verifica dell'integrità a livello hardware.

Vedi Repository

SPiCa

Integrità dei Processi di Sistema e Analisi Cross-view

SPiCa

"Canterò, quindi risplendi, SPiCa..."

SPiCa è un rilevatore di rootkit Linux basato su eBPF scritto in Rust. Il nome deriva dalla canzone di Hatsune Miku SPiCa e dalla stella a cui fa riferimento — Spica (Alpha Virginis), il punto più luminoso della Vergine. Ciò che a occhio nudo appare come una singola stella è in realtà una binaria spettroscopica: due stelle in orbita reciproca, indistinguibili come oggetti separati senza misurarne lo spettro. SPiCa applica lo stesso principio all'osservazione del kernel: canali indipendenti multipli misurano lo stesso stato del kernel da meccanismi fisicamente distinti, e un rootkit che ne sopprime uno viene esposto dagli altri.

Avvertenza: Parti significative di questo codice sono state generate o rifattorizzate con assistenza GLM. Sono stati applicati test rigorosi e progettazione iterativa, ma rivedere il codice per sicurezza e prestazioni prima dell'uso in produzione.


Tabella dei Contenuti

  1. Modello di Minaccia
  2. Panoramica dell'Architettura
  3. Il Canale di Osservazione sched_switch
  4. Il Canale di Integrità NMI
  5. Logica di Rilevamento
  6. Segretezza degli Indirizzi Vincolata dal Verificatore
  7. Gate di Accesso alle Mappe LSM
  8. Gestione delle Chiavi e Offuscamento
  9. Sigillatura TPM Vincolata a PCR (Progettazione)
  10. Difesa in Profondità
  11. L'Incidente del Bug BTF
  12. Limitazioni Note e Superficie di Attacco
  13. Compilazione ed Esecuzione
  14. Roadmap
  15. Glossario

1. Modello di Minaccia

L'avversario vincolato: il rootkit eBPF

SPiCa è progettato per sconfiggere l'avversario vincolato da eBPF — un attaccante con privilegi elevati (CAP_BPF o CAP_SYS_ADMIN) che carica un programma eBPF privilegiato nel kernel. Questo avversario è fondamentalmente più debole di un rootkit LKM perché il verificatore BPF impone vincoli severi:

Con i moduli LKM bloccati dal gate LSM dopo l'avvio, questo avversario vincolato è la minaccia realistica rimanente. La macchina anti-evasione di SPiCa è calibrata per questa minaccia — ogni difesa è trasparente su cosa copre e cosa no.

Non obiettivi

  • Exploit del kernel di livello statale — corruzione della memoria che produce scrittura arbitraria nel kernel senza init_module. SPiCa alza il livello bloccando il vettore LKM più facile, ma non pone un tetto all'avversario.
  • Moduli LKM ostili caricati prima dell'avvio di SPiCa — è necessaria una difesa in profondità (Secure Boot, firma dei moduli, IMA) per la finestra di avvio.
  • Exploit del verificatore — se il verificatore BPF non è corretto (CVE storici: CVE-2020-27194, CVE-2022-23222, CVE-2023-2163), l'avversario sfugge al modello vincolato e arriva all'esecuzione di codice arbitrario nel kernel. Questa è una classe di minaccia separata. Le difese di SPiCa valgono sotto un verificatore corretto.

SPiCa è il livello di ultima istanza in una pila di difesa in profondità, non un sostituto dei livelli superiori.


2. Panoramica dell'Architettura

SPiCa esegue quattro programmi eBPF collegati a hook del kernel, più un motore di rilevamento in spazio utente che correla incrociata il loro output con la visione che il sistema ha di sé stesso (/proc).

Tre canali di osservazione, ciascuno sopprimibile solo da un meccanismo di costo crescente

La proprietà architetturale chiave: un rootkit non può sopprimere tutti e tre i canali simultaneamente senza che la soppressione stessa diventi rilevabile o destabilizzante. Sopprimere l'NMI richiede di patchare l'IDT (Interrupt Descriptor Table), che causa il panico sulla maggior parte dei kernel. Questa è la "bomba attiva" — l'unico percorso dell'attaccante verso la cecità totale è uno che probabilmente crasha il sistema.

Modello di rilevamento — tre frasi```

sched sees it, /proc doesn't → DKOM NMI finds sched's heartbeat stopped → TAMPER sched goes globally silent, /proc != empty → SILENT

root@kitploit:~
Ogni classe di rilevamento è un verdetto differenziale: una discrepanza tra due o più canali. Il motore di rilevamento è una funzione pura sul registro + snapshot /proc + timestamp dei canali — nessuna I/O, nessun effetto collaterale, completamente testabile tramite unit test.

### La riprogettazione dell'NMI: dall'osservazione all'integrità

Nel progetto originale, l'NMI era un secondo canale di osservazione dei processi che campionava la CPU e segnalava quale task era in esecuzione. Ciò era ridondante: sched\_switch osserva già lo scheduling, e l'NMI campionava gli stessi dati tramite un meccanismo diverso. La ridondanza costava circa 1000+ eventi ring-buffer/sec/CPU di dati di processo che per il 99.999% del tempo confermavano "sì, lo scheduler sta facendo ciò che fa lo scheduler."

Nell'architettura riprogettata, **l'NMI viene riutilizzato dall'osservazione dei processi alla verifica dell'integrità dei tracepoint.** Non segnala più quale processo è sulla CPU. Invece, verifica che `sched_switch` sia effettivamente in esecuzione leggendo un heartbeat condiviso `.bss`. Questo:

1. Elimina circa il 99% del traffico ring-buffer dell'NMI (eventi quasi zero in stato stazionario)
2. Rileva direttamente il distacco, la soppressione dei tracepoint e i fallimenti BTF/iniezione (il bug BTF originale — vedere [§11](#11-the-btf-bug-incident))
3. Viene eseguito da un interrupt hardware, al di fuori del percorso di dispatch dei tracepoint — immune a `bpf_override_return`, intercettazione kprobe e manipolazione di array di funzioni
4. Legge i globali `.bss` tramite accesso diretto alla memoria, non helper BPF — immune a `fmod_ret` sulle funzioni helper

---

## 3. Il canale di osservazione sched\_switch

Un programma eBPF collegato al tracepoint `sched_switch` si attiva ogni volta che il kernel pianifica un processo su una CPU. Legge il PID e il comm del task in arrivo direttamente dagli argomenti del tracepoint utilizzando letture tradizionali a offset fisso (non BTF):```
ctx.read_at::<u32>(56)    → next_pid
ctx.read_at::<[u8;16]>(40) → next_comm

Intenzionalmente non BTF/CO-RE. Il layout degli argomenti del tracepoint è stabile tra le versioni del kernel (fa parte dell'ABI del tracepoint). L'uso di offset hardcoded evita la fragilità legata alla versione del kernel della navigazione delle struct risolta con BTF. Questa è una scelta progettuale deliberata documentata in §11.

Ad ogni invocazione, il programma:

  1. Legge next_pid e next_comm dal contesto del tracepoint
  2. Filtra l'idle task (PID 0)
  3. Offusca con XOR la struct ProcessInfo con BASE_KEY
  4. Invia al ring buffer sc_sched
  5. Scrive bpf_ktime_get_ns() nel globale .bss SCHED_HEARTBEAT — l'heartbeat che il controllore di integrità NMI monitora

Il programma evita deliberatamente bpf_get_current_pid_tgid() in questo contesto. Al momento di sched_switch, "current" è il task uscente, non quello entrante. Gli argomenti del tracepoint forniscono l'identità corretta del processo (entrante).

Disciplina della base temporale

Il motore di rilevamento utilizza una singola base temporale monotica: nanosecondi dall'avvio del processo di SPiCa (Instant::now() dall'ingresso di run_detection()). Quando arriva un evento di sched, il gestore dell'evento memorizza il now fornito dal chiamante (nanosecondi locali del processo), non il valore bpf_ktime_get_ns() dell'eBPF incorporato nell'evento. Questo evita la discrepanza di base temporale che si verificherebbe se il tempo di avvio del kernel venisse mescolato con il tempo locale del processo — un bug presente nelle versioni precedenti e che causava il silenzioso fallimento di tutti i predicati di liveness.


4. Il Canale di Integrità NMI

Design: heartbeat .bss, nessun BTF, nessun attraversamento di struct del kernel

Il programma NMI è collegato a un contatore hardware perf (HW_CPU_CYCLES) che si attiva a livello di interrupt hardware. Gli NMI non possono essere disabilitati con cli — sopprimerli richiede la riprogrammazione del PMU o l'hooking dell'IDT, entrambi interventi rumorosi e destabilizzanti.

Il meccanismo di controllo dell'integrità è estremamente semplice:``` .bss (shared within SPiCa's ELF object — all programs see the same memory): SCHED_HEARTBEAT ← written by sched_switch on every invocation NMI_LAST_HB ← NMI's record of the last heartbeat it observed NMI_FIRST_TICK ← first NMI invocation timestamp (grace period reference) NMI_LAST_EMIT ← throttle: last event emission timestamp

sched_switch runs → SCHED_HEARTBEAT = bpf_ktime_get_ns()

NMI fires (once per second, throttled): if SCHED_HEARTBEAT == NMI_LAST_HB: if past grace period (5 seconds since first NMI tick): → sched_switch stopped running → emit event_type=1 (TAMPER) else: → sched_switch is alive → emit event_type=0 (heartbeat OK) NMI_LAST_HB = SCHED_HEARTBEAT

root@kitploit:~
### Perché rileva ogni attacco nello scope

| Attacco | Cosa succede | Cosa vede NMI |
|---|---|---|
| Tracepoint scollegato dall'array funcs | sched\_switch smette di eseguire | `SCHED_HEARTBEAT` si blocca → TAMPER |
| Bug BTF / fallimento di attach (silente) | sched\_switch non esegue mai | `SCHED_HEARTBEAT` rimane a 0 → TAMPER (dopo la grazia) |
| `bpf_override_return` su una funzione dello scheduler | Se impedisce al tracepoint di attivarsi | `SCHED_HEARTBEAT` si blocca → TAMPER |
| Bytecode modificato in-place | Richiede scrittura kernel arbitraria (a livello LKM) | Fuori dal modello di minaccia eBPF |
| Puntatore del consumatore del ring buffer manipolato | gli eventi di sched non raggiungono lo spazio utente | `SCHED_HEARTBEAT` continua ad avanzare (il programma è in esecuzione) → nessun falso TAMPER; lo spazio utente rileva tramite `max(sched_last)` obsoleto → SILENT |

### Perché specificamente `.bss`

Le variabili globali `.bss` sono memorizzate nella sezione dati interna del programma BPF, supportate da una mappa array interna gestita dal loader. Sono:

- **Non pinnabili separatamente** — non appaiono come mappe nominate in `/sys/fs/bpf/`
- **Non intercettabili tramite hook `bpf_map_update_elem`** — le scritture `.bss` sono store diretti in memoria, non syscall di aggiornamento mappa. Il vecchio meccanismo `sc_canary` (confrontare una copia `.bss` con una copia di mappa nominata per rilevare l'intercettazione di `bpf_map_update_elem`) non è più necessario.
- **Condivise tra programmi nello stesso oggetto ELF** — sched\_switch e NMI comunicano attraverso `.bss` senza alcuna interfaccia esterna

### Immunità all'intercettazione basata su BPF

Il controllore di integrità NMI è strutturalmente immune agli attacchi di override BPF a causa di una proprietà fondamentale: `bpf_override_return` intercetta **chiamate** di funzione, ma il controllore NMI non *chiama* le cose che verifica — *legge direttamente la memoria `.bss`*. Non è possibile sovrascrivere il valore di ritorno di una lettura di memoria perché una lettura di memoria non è una chiamata di funzione.

Inoltre:
- `bpf_probe_read_kernel` (usato per letture di struct kernel in progetti alternativi) è un helper fault-safe che accetta qualsiasi indirizzo — ma il design heartbeat `.bss` di SPiCa non ne ha nemmeno bisogno. Il controllore legge le globali `.bss` tramite istruzioni di caricamento diretto.
- Il programma NMI viene eseguito in contesto NMI, dove i kprobe sono strutturalmente inaffidabili (il kernel li differisce o sopprime). Un attacco basato su kprobe contro l'esecuzione del controllore combatte contro l'hardware.

### Semantica degli eventi NMI

Il ring buffer NMI (`sc_nmi`) trasporta eventi leggeri:

| `event_type` | Significato | Azione dello spazio utente |
|---|---|---|
| 0 | Heartbeat — NMI vivo, sched\_switch vivo | Aggiorna timestamp `last_nmi_heartbeat` |
| 1 | TAMPER — NMI vivo, heartbeat sched\_switch congelato | Stampa `[TAMPER]` immediatamente |

Gli eventi vengono emessi al massimo una volta al secondo (limitati da `NMI_LAST_EMIT`). Se il ring buffer NMI diventa silenzioso per più di 5 secondi, lo spazio utente attiva `[SILENT]` — il canale NMI stesso è morto.

---

## 5. Logica di Rilevamento```mermaid
graph TD
    subgraph RING0["Kernel Space: Four eBPF Programs"]
        direction TB
        SCHED_P["TracePoint, sched_switch<br/>read next_pid, next_comm<br/>write SCHED_HEARTBEAT (.bss)<br/>XOR obfuscate → sc_sched"]
        NMI_P["PerfEvent hardware NMI<br/>read SCHED_HEARTBEAT (.bss)<br/>compare to NMI_LAST_HB<br/>frozen → event_type=1 (TAMPER)<br/>alive → event_type=0 (heartbeat)<br/>→ sc_nmi"]
        LSM_P["BPF LSM, kernel_read_file<br/>READING_MODULE<br/>gate=0: allow + log<br/>gate=1: EPERM + log → sc_lsm"]
        WATCH_P["TracePoint, sched_process_exit<br/>current == SPICA_PID (.bss)? → sc_wd flag"]
    end

    subgraph RING3["User Space: Differential Engine"]
        ENGINE["SPiCa (Tokio async)"] -->|XOR deobfuscate| RB_S[(sc_sched RingBuf)]
        ENGINE -->|event_type=0: heartbeat<br/>event_type=1: TAMPER| RB_N[(sc_nmi RingBuf)]
        ENGINE -->|raw read| RB_L[(sc_lsm RingBuf)]
        ENGINE -->|read_dir| PROC[" /proc"]
        RB_S --> FSM{Detection FSM}
        PROC --> FSM
        FSM -->|scheduled, absent /proc, >2s| D1["[DKOM]"]
        FSM -->|in /proc, never seen by sched, >5s| D2["[GHOST]"]
        RB_N -->|event_type = 1| D3["[TAMPER]"]
        FSM -->|sched channel silent, /proc ≠∅| D4["[SILENT]"]
        FSM -->|raw getdents64 ≠ libc readdir| D9["[HOOK]"]
        RB_S -->|same TGID, different start_time_ns| D5["[DUPE]"]
        RB_L -->|allowed = 1| D7["[LKM-ALLOW]"]
        RB_L -->|allowed = 0| D8["[LKM-DENY]"]
        WATCH_P -.->|pin exists at startup| D6["[WATCHDOG]"]
    end

    classDef kernbox  fill:#fdf2f8,stroke:#9333ea,stroke-width:2px,color:#581c87;
    classDef userbox  fill:#eff6ff,stroke:#2563eb,stroke-width:2px,color:#1e3a8a;
    classDef alertbox fill:#fff7ed,stroke:#ea580c,stroke-width:1px,color:#7c2d12;
    classDef storage  fill:#f8fafc,stroke:#64748b,stroke-width:1px;
    class RING0 kernbox;
    class RING3 userbox;
    class D1,D2,D3,D4,D5,D6,D7,D8,D9 alertbox;
    class RB_S,RB_N,RB_L,PROC storage;

Rilevamento SILENT a livello di canale

SILENT è un verdetto a livello di canale, non per processo. Si attiva quando:

  1. Canale sched morto: max(sched_last) su tutti i record del registro è obsoleto oltre CHANNEL_DEAD_NANOS mentre /proc non è vuoto. La guardia di /proc non vuoto è la garanzia di attività: su qualsiasi sistema Linux in esecuzione, /proc non è vuoto (init, thread del kernel, kworker), e lo scheduler non è mai veramente inattivo (timer tick, I/O in attesa, callback RCU). Un max(sched_last) obsoleto su un sistema non vuoto significa che il canale è morto — non che il sistema sia inattivo.

  2. Canale NMI morto: Nessun evento heartbeat (event_type=0) è arrivato dal ring buffer NMI per più di 5 secondi. Ciò significa che l'evento perf NMI ha smesso di scattare — o l'evento perf è stato staccato o il PMU è stato riprogrammato.

Entrambi i controlli hanno un periodo di raffreddamento di 30 secondi per evitare un'inondazione di avvisi.

Rilevamento rootkit LD_PRELOAD ([HOOK])

SPiCa legge /proc tramite due meccanismi indipendenti ad ogni tick:

  1. Syscall getdents64 raw (read_tgids()) — std::fs::read_dir di Rust chiama direttamente libc::syscall(SYS_getdents64, ...), bypassando tutti gli hook delle funzioni libc. Le rootkit LD_PRELOAD non possono intercettare questo percorso.

  2. readdir di libc (read_tgids_libc()) — chiama libc::opendir / libc::readdir tramite FFI, passando attraverso il linker dinamico ed è completamente intercettabile dagli hook di /etc/ld.so.preload.

Se getdents64 vede PID che readdir di libc non vede, una rootkit userspace sta agganciando readdir per nascondere processi. SPiCa attiva [HOOK]:``` [HOOK] 3 PID(s) hidden from libc readdir — LD_PRELOAD rootkit suspected

root@kitploit:~
This técnica trasforma il privilegio a livello kernel di SPiCa in un rilevamento attivo dei rootkit in spazio utente. Il percorso grezzo delle syscall è la verità di base — nessun hook in spazio utente può renderlo cieco. Il percorso libc è la visione "percepita" che uno strumento normale (ps, ls) vedrebbe. La discrepanza è una prova inequivocabile di intercettazione delle librerie.

**Rootkit rilevati da `[HOOK]`:**

| Rootkit | Meccanismo di occultamento | Rilevato |
|---------|----------------------------|----------|
| Symbiote | LD_PRELOAD parassita, hook `readdir` | Sì (quando si nasconde attivamente) |
| JynxKit | LD_PRELOAD, occultamento `MAGIC_GID` tramite `readdir` | Sì |
| Azazel | LD_PRELOAD, hook `readdir` + `stat` | Sì |
| Medusa/OrBit | LD_PRELOAD, `readdir` + furto di credenziali | Sì |

**Testato contro Symbiote reale:** Un campione Symbiote vivo (SHA256 `f55af21f...`, MalwareBazaar) è stato distribuito tramite `/etc/ld.so.preload` su una VM Ubuntu 24.04. Il campione hooka `readdir`, `readdir64`, `stat`, `fstatat`, `pam_authenticate`, `pcap_loop`, `recvmsg`, `fopen`, `read`, `execve`. Quando l'hook LD_PRELOAD nasconde attivamente un PID da `readdir`, SPiCa attiva `[HOOK]` entro un ciclo di tick (<1 s). Quando Symbiote è caricato ma passivo (non si nasconde attivamente), SPiCa produce zero falsi positivi.

### Finestra di grazia

Una finestra di grazia di 50 ms previene falsi positivi sui processi appena forkati. I controlli SILENT a livello di canale hanno un periodo di grazia di 5 secondi (il riferimento `NMI_FIRST_TICK` del programma NMI) in modo che la latenza di avvio non produca falsi allarmi TAMPER.

---

## 6. Segretezza dell'indirizzo limitata dal Verifier

### Definizione

**La segretezza dell'indirizzo limitata dal Verifier** è una proprietà di sicurezza computazionale che vale sotto il modello di avversario vincolato da eBPF. Afferma:

> Dato un avversario che può caricare programmi eBPF (CAP\_BPF) ma è vincolato dal verifier BPF (loop limitati, helper ristretti, nessuna scrittura arbitraria nel kernel), l'indirizzo del kernel della sezione dati `.bss` di un programma BPF è computazionalmente impossibile da scoprire.

### I quattro meccanismi

La proprietà è una composizione di quattro barriere indipendenti:

1. **kASLR** — Il Kernel Address Space Layout Randomization randomizza la regione dell'heap del kernel dove la memoria delle mappe BPF (incluse le mappe di supporto `.bss`) è allocata. L'indirizzo esatto cambia ad ogni avvio.

2. **Limite di istruzioni del Verifier** — Il verifier BPF limita le istruzioni totali per programma a circa 1 milione e richiede loop con terminazione dimostrabile. Il programma di scansione di un avversario può sondare al massimo N ≈ 10^6 indirizzi per caricamento tramite `bpf_probe_read_kernel`. Dato uno spazio di ricerca randomizzato da kASLR, la probabilità di successo per programma è trascurabile.

3. **Gate di accesso alle mappe LSM** (vedere [§7](#7-lsm-map-access-gate)) — Senza il gate, un avversario potrebbe enumerare le mappe BPF per ID (`BPF_MAP_GET_NEXT_ID` → `BPF_MAP_GET_FD_BY_ID` → `BPF_MAP_LOOKUP_ELEM`) e leggere direttamente i contenuti di `.bss`. Il gate rimuove questo percorso facile, costringendo l'avversario nel percorso di scansione della memoria limitato dal verifier.

4. **Posizionamento di `.bss`** — Le variabili globali di `.bss` non appaiono nelle interfacce di enumerazione delle mappe con nomi leggibili dall'uomo. La mappa di supporto interna `.bss` è denominata `.bss` da libbpf/aya, ma i suoi contenuti (le variabili globali effettive) sono accessibili solo se si ha il file descriptor della mappa. Il file descriptor della mappa richiede o la tabella dei fd del processo di caricamento o l'ID della mappa (bloccato dal gate).

### Struttura dell'argomento formale```
Adversary's goal:    locate SPiCa's .bss in kernel virtual memory
Search space:        kernel heap region, kASLR-randomized (~2^30 entropy)

Path A — map enumeration (blocked):
  BPF_MAP_GET_NEXT_ID → BPF_MAP_GET_FD_BY_ID → BPF_MAP_LOOKUP_ELEM
  → blocked by LSM gate (§7) for non-SPiCa processes

Path B — memory scan (bounded):
  bpf_probe_read_kernel(addr, buf, len) — fault-safe, accepts any addr
  Per-program capacity: N ≈ 10^6 probes (instruction limit)
  Success probability per load: N / |search space| ≈ 10^6 / 2^30 ≈ 10^-24
  Can reload programs, but: each load is a syscall (observable), and
  the target address doesn't change between loads (same boot session)

Path C — timing side channel (theoretical):
  bpf_probe_read_kernel timing varies on fault vs success
  Binary search over the heap could reduce scan complexity to O(log |A|)
  → O(30) probes, well within instruction budget
  LIMITATION: must be acknowledged. Mitigated by rate-limiting BPF_PROG_LOAD
  via the LSM gate (future work).

Cosa rende questo innovativo

La maggior parte della ricerca sulla sicurezza di BPF tratta il verificatore come una superficie d'attacco (bug del verificatore, insuondità, JIT spray). Questo lavoro inverte la prospettiva: i vincoli del verificatore sono una primitiva difensiva che delimita lo spazio di ricerca dell'avversario. La segretezza non è crittografica (non è AES); è computazionale — limitata da ciò che il verificatore consente all'avversario di calcolare.

Limitazioni (da dichiarare onestamente)

  • Exploit del verificatore — Se il verificatore non è solido, il limite di istruzioni viene meno e l'avversario può eseguire calcoli arbitrari. Questo è al di fuori del modello di minaccia eBPF.
  • Canali laterali temporali — bpf_probe_read_kernel è osservabile temporalmente (errore vs successo impiega cicli diversi). Una ricerca binaria basata sul timing sull'heap è teoricamente più efficiente della scansione lineare. Il limite di istruzioni limita i probe per programma, ma la ricerca binaria potrebbe ridurre il numero di probe a O(log |A|) ≈ 30. Questa è una limitazione reale. Mitigazione: limitare la frequenza di BPF_PROG_LOAD tramite il gate LSM.
  • Root in userspace — Un processo root in userspace (non vincolato dal verificatore) può enumerare le mappe per ID. Il gate LSM blocca questo, ma solo per i processi non SPiCa. Un processo che compromette il PID di SPiCa stesso ha accesso completo.

7. Gate di accesso alle mappe LSM

Il problema

Le variabili globali .bss sono supportate da una mappa BPF interna. Qualsiasi processo con CAP_BPF può enumerare tutte le mappe sul sistema:``` bpf(BPF_MAP_GET_NEXT_ID, …) → iterate all map IDs bpf(BPF_MAP_GET_FD_BY_ID, id) → get fd to any map bpf(BPF_MAP_LOOKUP_ELEM, fd, key, value) → read map contents

root@kitploit:~
Contro l'avversario eBPF (che non può effettuare chiamate di sistema), `.bss` è nascosto. Contro root in userspace, è una mappa standard — completamente leggibile. Il gate LSM colma questa lacuna.

### La difesa

Un hook BPF LSM sulla chiamata di sistema `bpf` controlla i comandi di accesso alle mappe:```
hook = "bpf"
  read cmd (arg 0)
  if cmd == BPF_MAP_GET_FD_BY_ID:
    read map_id from userspace bpf_attr (bpf_probe_read_user)
    if map_id matches any of SPiCa's stored IDs (.bss):
      if caller_tgid != SPICA_PID:
        return -EPERM

Gli ID delle mappe vengono scritti in .bss dal caricatore in spazio utente subito dopo il caricamento del programma, prima che l'hook LSM sia armato (stesso schema temporale del già esistente sc_gate per il blocco dei moduli del kernel). Non è necessario BTF: cmd e map_id provengono dagli argomenti della syscall, non dalle strutture del kernel.

Chirurgico: blocca solo l'accesso agli specifici ID delle mappe di SPiCa. Altri strumenti BPF (tcpdump, bpftrace, bcc) di altri processi accedono alle proprie mappe e non vengono influenzati.

Cosa non copre

  • ptrace / /proc/pid/mem — Un altro processo root potrebbe leggere direttamente la memoria del processo SPiCa tramite ptrace, bypassando completamente la syscall BPF. Si tratta di una limitazione fondamentale: non è possibile proteggersi da un processo con lo stesso livello di privilegio che legge la tua memoria tramite /proc/pid/mem. Difesa: invio dei log fuori dall'host (se l'attaccante può leggere la memoria locale, può anche sopprimere gli avvisi locali — solo la registrazione remota è utile).
  • PID di SPiCa compromesso — Se l'attaccante ottiene il controllo del processo di SPiCa, ha accesso legittimo alle mappe.

8. Gestione delle chiavi e offuscamento

Chiave proveniente dal TPM

Sugli host dotati di TPM, la chiave di offuscamento XOR a 64 bit proviene da TPM2_GetRandom tramite la crate tss-esapi (chiamata diretta alla libreria libtss2-esys). La chiave non passa attraverso pipe, nessuna riga di comando di un sotto-processo, nessun disco. Esiste solo nell'hardware TPM e nella memoria volatile del kernel (mappa di supporto .bss) per la durata del processo SPiCa.

Sugli host senza TPM (VM senza vTPM, container, macchine senza chip TPM), SPiCa ricade su una chiave a tempo di compilazione per build generata da /dev/urandom dallo script di build. Il fallback è visibilmente rumoroso all'avvio con un banner di avviso.

Posizionamento in .bss

I seguenti valori risiedono nella sezione .bss del programma eBPF, scritti dallo spazio utente tramite set_global() prima che qualsiasi programma venga caricato:

Le mappe BPF nominate sono enumerabili tramite l'interfaccia di iterazione delle mappe della syscall bpf() (bloccata dal gate LSM — vedi §7); le variabili globali in .bss sono accessibili attraverso la stessa mappa interna ma non sono né nominate né pinnabili separatamente.

Offuscamento XOR — difesa dalla fuga di lettura, non crittografia

Tutti i campi di ProcessInfo vengono piegati con XOR utilizzando la BASE_KEY a 64 bit prima di essere scritti nei buffer ad anello. Il campo event_type è intenzionalmente lasciato non offuscato in modo che lo spazio utente possa leggerlo come sentinella prima di deoffuscare il resto.

Si tratta di offuscamento contro la fuga di lettura, non di crittografia contro un avversario capace. XOR con una chiave ripetuta di 8 byte è strutturalmente vulnerabile al testo noto: i valori prevedibili di comm ("bash", "systemd", "kthreadd") XORati contro il testo cifrato recuperano direttamente i byte della chiave. La difesa è appropriata per l'avversario eBPF (che non può facilmente leggere il buffer ad anello — richiede lo stesso divario di capacità che protegge .bss), non per un avversario con accesso binario + intercettazione del buffer ad anello.


9. Sigillatura TPM vincolata a PCR (Progettazione)

Stato: Fase di progettazione. Non ancora implementata. Questa sezione documenta l'architettura target per il documento di ricerca.

Panoramica

La sigillatura TPM vincolata a PCR sposta il confine della distribuzione delle chiavi dal livello software al silicio. La chiave viene sigillata al momento dell'installazione rispetto ai valori attesi dei Platform Configuration Register (PCR) e può essere dissigillata solo se lo stato di avvio del sistema corrisponde alle misurazioni attese.

Catena di misurazione all'avvio

Durante l'avvio, il firmware, il bootloader e il kernel misurano componenti critici nei PCR:

Nota: L'allocazione dei PCR dipende dalla catena di avvio. GRUB misura il kernel nel PCR 4; systemd-stub misura nel PCR 4 e la riga di comando nel PCR 8. La politica di sigillatura deve corrispondere alla catena di avvio target.

Il flusso sigilla → dissigilla → inietta → fail-safe

  1. Sigilla (al momento dell'installazione): La chiave a 64 bit viene sigillata rispetto ai valori PCR attesi utilizzando TPM2_Create con una sessione TPM2_PolicyPCR. Il blob sigillato viene memorizzato su disco. È crittografato con la chiave interna del TPM e può essere decrittografato solo quando i PCR specificati corrispondono.

  2. Dissigilla (avvio precoce, fase initramfs): Prima che qualsiasi codice utente non affidabile venga eseguito, l'hook initramfs di SPiCa richiede TPM2_Unseal. Se gli attuali valori PCR corrispondono alla politica di sigillatura, il TPM rilascia la chiave.

  3. Inietta: La chiave viene scritta in .bss tramite set_global() prima del caricamento dei programmi.

  4. La trappola: Se un attaccante ha modificato il kernel (mancata corrispondenza PCR 4), sostituito l'initramfs (mancata corrispondenza PCR 9) o alterato la politica Secure Boot (mancata corrispondenza PCR 7), gli hash PCR divergono. Il TPM rifiuta di dissigillare e SPiCa fallisce in sicurezza: rifiuta di avviarsi anziché funzionare alla cieca con una chiave compromessa.

Opzioni della politica PCR

Per il documento di ricerca, presentare la politica forte e discutere il compromesso della riscrittura nelle limitazioni.

Relazione con la segretezza dell'indirizzo vincolata dal verificatore

I due meccanismi sono complementari:

  • La sigillatura PCR protegge la chiave all'avvio — garantisce che la chiave sia disponibile solo su uno stato di sistema affidabile.
  • La segretezza dell'indirizzo vincolata dal verificatore + il gate LSM proteggono la chiave in esecuzione — garantiscono che l'avversario eBPF non possa localizzare o leggere il .bss in cui risiede la chiave.

Nessuno dei due è sufficiente da solo. La sigillatura PCR non aiuta se la chiave viene compromessa in esecuzione (enumerazione delle mappe). La segretezza dell'indirizzo non aiuta se il sistema è stato compromesso prima dell'avvio di SPiCa (initramfs ostile).

Cosa la sigillatura PCR NON rileva

  • Distacco dei programmi LSM in esecuzione — I programmi BPF LSM (spica_lsm_modblock, il gate di accesso alle mappe) vengono caricati in esecuzione e NON vengono misurati in alcun PCR. Un rootkit che li stacca dopo l'avvio non viene rilevato dalla sigillatura PCR. Ciò che lo rileva è il battito cardiaco NMI (rilevando che il sistema di rilevamento stesso ha smesso di funzionare).
  • Sfruttamento del kernel post-avvio — Se il kernel viene sfruttato dopo l'avvio (corruzione della memoria → scrittura arbitraria), i PCR rimangono invariati. Questo è il "non obiettivo" per attori statali.

10. Difesa in profondità

SPiCa è l'ultimo livello di enforcement. Completa un sistema correttamente configurato, non sostituisce i livelli superiori.```mermaid flowchart TD SB["UEFI Secure Boot
─────────────────────────────
Verifies bootloader signature against
the UEFI db certificate store
Measured to PCR 7"] MS["Kernel Module Signing
─────────────────────────────
CONFIG_MODULE_SIG_FORCE=y
Kernel rejects unsigned .ko at load time"] IMA["IMA, Integrity Measurement Architecture
─────────────────────────────
Measures file hashes to TPM PCR10
Appraise policy blocks non-matching signatures"] SPICA["SPiCa
─────────────────────────────
LSM gate: blocks LKM loads + map enumeration
sched_switch + NMI integrity channels
Differential detection: DKOM · GHOST · TAMPER · SILENT · DUPE
PCR-bound key sealing (design phase)"]

root@kitploit:~
SB  -->|"boot chain verified"| MS
MS  -->|"signed modules only"| IMA
IMA -->|"measured + appraised"| SPICA

classDef firmware fill:#fef3c7,stroke:#d97706,stroke-width:2px,color:#78350f
classDef kernel   fill:#fdf2f8,stroke:#9333ea,stroke-width:2px,color:#581c87
classDef spica    fill:#eff6ff,stroke:#2563eb,stroke-width:2px,color:#1e3a8a
class SB firmware
class MS,IMA kernel
class SPICA spica
root@kitploit:~
SPiCa controlla tutti e quattro i livelli all'avvio e ne stampa lo stato.

---

## 11. L'incidente del bug BTF

### Cosa è successo

Durante i test su Ubuntu (ultimo kernel), un'incompatibilità BTF ha causato l'attacco con successo del programma tracepoint `sched_switch` ma **non ha mai generato un singolo evento.** La syscall `attach()` ha restituito `Ok(())`, quindi SPiCa è proceduto normalmente — ma il ring buffer di sched è rimasto vuoto. Nessun allarme di rilevamento è scattato perché il motore di rilevamento non aveva dati di scheduling. **SPiCa ha funzionato alla cieca senza alcuna indicazione di fallimento.**

Questa è la modalità di errore peggiore per uno strumento di sicurezza: cecità silenziosa.

### Perché non è stato rilevato

Il motore di rilevamento originale ragionava **per processo**: ogni record di processo aveva timestamp `sched_last` e `nmi_last`, e la vivacità era calcolata per record. Quando sched\_switch è morto globalmente:

1. `sched_live` è diventato falso per ogni record (nessun nuovo evento sched → tutti i valori `sched_last` invecchiano)
2. Il predicato `TAMPER` per processo (`in_proc && nmi_live && !sched_live`) poteva scattare, ma richiedeva che `nmi_live` fosse mantenuto *continuamente* per 2 secondi. I campioni NMI sono radi (periodo di 10M cicli), quindi `suspect_since` continuava a resettarsi a causa della variazione di campionamento e non raggiungeva mai la maturità.
3. Il predicato `SILENT` per processo richiedeva `sched_live`, che ora era falso per tutto — il predicato si invertiva proprio nella condizione che doveva rilevare.
4. Non c'era **nessun controllo di vivacità a livello di canale** — nessun meccanismo del tipo "sched ha MAI generato un evento?" o "max(sched_last) è obsoleto?".

Inoltre, è stata scoperta una discrepanza di base temporale: `sched_last` memorizzava `bpf_ktime_get_ns()` (nanosecondi di avvio del kernel) mentre `evaluate()` confrontava con `nanos_since_startup()` (nanosecondi locali al processo). Il `wrapping_sub` di queste diverse basi temporali produceva valori enormi, rendendo tutti i predicati di vivacità banalmente falsi. La logica di rilevamento non aveva mai funzionato correttamente in produzione — il bug BTF lo aveva solo mascherato impedendo l'arrivo degli eventi.

### Come la riprogettazione lo risolve

| Problema | Risoluzione |
|---|---|
| Nessun controllo di vivacità a livello di canale | Ora `evaluate()` calcola `max(sched_last)` e attiva `[SILENT]` se obsoleto mentre `/proc` non è vuoto |
| TAMPER per processo non raggiungeva mai la maturità (reset da jitter) | TAMPER ora è un segnale diretto dal programma NMI (confronto heartbeat `.bss`), non un FSM per processo con soglie |
| SILENT per processo si invertiva quando sched moriva | SILENT ora è a livello di canale, calcolato da aggregati, non predicati per record |
| Discrepanza di base temporale | Ora `sched_last` memorizza il tempo locale del processo (parametro `now`), non `bpf_ktime_get_ns()` |
| NMI era un'osservazione ridondante | NMI ora è un controllore di integrità — rileva la morte di sched direttamente tramite heartbeat `.bss` |

---

## 12. Limitazioni note e superficie d'attacco

### All'interno del modello di minaccia eBPF

| Attacco | Stato | Note |
|---|---|---|
| **Manipolazione del puntatore consumer del ring buffer** | **Rilevato** (SILENT) | `max(sched_last)` diventa obsoleto → SILENT. `SCHED_HEARTBEAT` continua ad avanzare (il programma è in esecuzione) → nessun falso TAMPER. |
| **DKOM della struttura dell'evento Perf** (campo `state` azzerato) | **Rilevato** (SILENT) | NMI smette di scattare → nessun evento heartbeat → SILENT sul canale NMI |
| **Spoofing del campo `task_struct`** (sovrascrittura di pid/tgid) | **Parziale** (DUPE) | Se il TGID contraffatto corrisponde a un record esistente con un `start_time_ns` diverso, DUPE scatta. Se anche `start_time_ns` viene contraffatto, questo passa inosservato. |
| **Distacco del programma eBPF** (rimozione dall'array funcs) | **Rilevato** (TAMPER) | L'heartbeat NMI si blocca → TAMPER |
| **Bytecode modificato in-place** | **Non rilevato** | Richiede scrittura arbitraria del kernel (livello LKM) — al di fuori del modello di minaccia eBPF |
| **Canale laterale temporale su `bpf_probe_read_kernel`** | **Rischio teorico** | La ricerca binaria sull'heap potrebbe trovare `.bss` in circa 30 sonde. Vedi le limitazioni in [§6](#6-verifier-bounded-address-secrecy). |

### Al di fuori del modello di minaccia eBPF (riconosciuto, non risolto)

| Attacco | Stato | Note |
|---|---|---|
| **Hook del gestore IDT/NMI** | **La bomba attiva** | Bypass architetturale completo. Panico del kernel quasi certo. |
| **Soppressione dual-channel** | **La bomba attiva** | Sopprime simultaneamente sia sched che NMI. Eredita l'instabilità dell'hooking NMI. |
| **Exploit del verifier** | **Non obiettivo** | Esecuzione arbitraria di codice kernel. Classe di minaccia separata. |
| **ptrace / `/proc/pid/mem`** | **Limitazione fondamentale** | Lettura della memoria con gli stessi privilegi. Solo l'invio dei log fuori dall'host aiuta. |
| **Patch del puntatore consumer + heartbeat** | **Livello LKM** | Se l'attaccante ha scrittura arbitraria del kernel, può sia avanzare il puntatore consumer che scrivere heartbeat falsi. Ma scrittura arbitraria del kernel = livello LKM = al di fuori del modello di minaccia. |

---

## 13. Costruzione ed esecuzione

### Prerequisiti

- Kernel Linux >= 5.15 con `CONFIG_DEBUG_INFO_BTF=y` (solo per l'hook LSM)
- Per il blocco dei moduli: `CONFIG_BPF_LSM=y` e `lsm=bpf` nella riga di comando del kernel
- Chip TPM 2.0 + libreria `tpm2-tss` (opzionale; ricade con un avviso visibile)
- Toolchain Rust nightly

> **Nota:** Il passaggio `generate-vmlinux` **non è più richiesto**. I programmi eBPF utilizzano offset di tracepoint tradizionali e globali `.bss` — non è necessaria la navigazione delle strutture CO-RE/BTF. Il comando xtask `generate-vmlinux` è mantenuto per uso futuro ma non fa parte del pipeline di build.

Verifica che BPF LSM sia attivo: `cat /sys/kernel/security/lsm` dovrebbe contenere `bpf`.

### Impostazione```shell
make install-deps     # system packages + nightly Rust (pacman/apt/dnf auto-detected)
make install-tools    # bpf-linker
make build            # compiles eBPF + userspace (no vmlinux generation needed)

Esecuzione```shell

make run # sudo ./target/release/spica

root@kitploit:~
### Installa in initramfs (protezione all'avvio anticipato)```shell
sudo make install     # spica install — auto-detects Debian (initramfs-tools) or Fedora (dracut)

Verificare che funzioni```shell

sudo insmod some_module.ko # should fail with EPERM (gate locked) cat /sys/kernel/security/lsm # should contain 'bpf' ls /sys/fs/bpf/spica_watchdog # exists if previous run was killed ungracefully

root@kitploit:~
### Sviluppo (macOS o Linux)

I programmi eBPF non possono essere eseguiti su macOS. `cargo check` e i test unitari per la logica di rilevamento funzionano; la verifica completa a runtime richiede Linux.```shell
make check      # cargo check for workspace
make check-ebpf # cargo check for the eBPF crate (bpfel-unknown-none)
make test       # unit tests for detection FSM, key derivation, obfuscation

14. Roadmap

  • Sigillatura delle chiavi legata ai PCR — vera attestazione hardware. Al momento dell'installazione, sigillare la chiave con i valori PCR attesi (PCR 4/7/9/10). A runtime, l'apertura fallisce se i PCR sono cambiati. Sostituisce l'attuale uso TPM solo GetRandom con una piena radice di fiducia hardware. Vedi §9.
  • Gate di accesso LSM alle mappe — hook LSM BPF sulla chiamata di sistema bpf che blocca l'enumerazione delle mappe dello stato interno di SPiCa da processi non SPiCa. Vedi §7.
  • Limitazione della frequenza di BPF_PROG_LOAD — Estendere il gate LSM per limitare la frequenza dei caricamenti di programmi BPF da processi non SPiCa, mitigando il rischio di canale laterale temporale sulla scoperta di .bss. Vedi §6 limitazioni.
  • Aggiornamento dell'offuscamento PRF con SipHash — Se il modello di minaccia si estende a includere avversari con accesso in lettura al ring buffer, sostituire XOR con un flusso di chiave SipHash-1-3 (la dipendenza siphasher è già nell'albero per il token di integrità).
  • Backend di logging enterprise — Opzionale invio a Elasticsearch/Elastic SIEM per ambienti SOC. Tutti gli avvisi, eventi di terminazione e anomalie del contatore di riavvii inviati fuori dall'host in tempo reale.
  • Supporto per distribuzioni aggiuntive — Arch (mkinitcpio), openSUSE.
  • Pipeline CI — Test di fumo Linux che esercitano il vero flusso eBPF di caricamento + attach + ring buffer.

15. Glossario


Licenza

Licenza del motore SPiCa: MIT O Apache-2.0 (workspace). Il programma eBPF esporta una licenza GPL tramite lo statico _license — questo è un requisito del kernel per i programmi eBPF che utilizzano helper con licenza GPL, e si applica solo al bytecode eBPF caricato, non al binario userspace.

Attribuzione del personaggio: "Hatsune Miku" e le relative opere grafiche del personaggio sono proprietà protette da copyright di Crypton Future Media, INC. (www.piapro.net). Questo progetto è uno strumento di ricerca indipendente e non commerciale, non affiliato a Crypton Future Media. Personaggio utilizzato ai sensi della Piapro Character License (PCL).

Il nome del progetto SPiCa è ispirato alla canzone originale di Toku-P.

Scarica lo strumento
VincoloEffetto sull'avversario
Cicli limitati (~1 milione di istruzioni per programma)Non può scansionare tutta la memoria del kernel
Sicurezza dei puntatori (il dereferenziamento diretto richiede un target provabilmente valido e limitato)Non può seguire puntatori arbitrari
Helper limitati (allowlist per tipo di programma)Non può chiamare kmalloc, vmalloc o qualsiasi funzione di allocazione del kernel
Nessuna scrittura arbitraria nel kernel (bpf_probe_write_kernel fortemente limitato)Non può modificare task_struct, array di funzioni tracepoint o bytecode del programma BPF
Accesso alle mappe limitato ai riferimenti caricatiNon può accedere a mappe appartenenti ad altri programmi (a meno che non siano enumerate per ID — vedi §7)
CanaleMeccanismoCosa lo sopprimeCosto della soppressione
/procEnumerazione della directory procfsDKOM (scollegare il processo dalla lista dei task)Basso — tecnica di rootkit ben nota
sched_switchTracepoint eBPF sullo schedulerScollegare il programma dall'array funcs; filtrare il contestoMedio — richiede scrittura nel kernel nell'array funcs
NMIInterrupt hardware del contatore di performance → Evento perf eBPFAgganciare il gestore IDT/NMIPanico del kernel quasi certo — interrupt hardware, non mascherabile
AvvisoCondizioneCosa rileva
[DKOM]TGID programmato dal kernel assente da /proc per >2 sManipolazione diretta degli oggetti del kernel: processo nascosto dall'enumerazione userspace
[GHOST]TGID presente in /proc ma mai visto da sched_switch per >5 sSpoofing di /proc: voce fittizia inserita per superare i controlli DKOM
[TAMPER]NMI rileva heartbeat di sched_switch congelato (event_type=1)Tracepoint staccato, soppresso o fallimento BTF/attach
[SILENT]max(sched_last) obsoleto nell'intero registro mentre /proc non è vuoto; oppure heartbeat NMI assente per >5 sPerdita di osservazione a livello di canale: canale sched o NMI morto
[DUPE]Stesso TGID, diverso start_time_ns tra eventiSpoofing del campo task_struct: la rootkit modifica tgid per impersonare un processo legittimo
[HOOK]PID visibili tramite getdents64 raw ma assenti da readdir di libcLD_PRELOAD rootkit — intercettazione di librerie userspace che nasconde processi a ps, ls e altri strumenti (Symbiote, JynxKit, Azazel, Medusa/OrBit)
[WATCHDOG]Il pin /sys/fs/bpf/spica_watchdog esiste all'avvioL'istanza precedente è stata terminata in modo non pulito (SIGKILL, OOM, crash)
[LKM-ALLOW]READING_MODULE intercettato mentre il gate è aperto (finestra di avvio)Record di audit: modulo caricato prima del blocco del gate
[LKM-DENY]READING_MODULE intercettato mentre il gate è bloccatoinsmod/modprobe bloccati dopo l'inizializzazione
GlobaleScopoScritto da
BASE_KEYChiave di offuscamento XORspazio utente al momento del caricamento
SPICA_PIDTGID di SPiCa (watchdog)spazio utente al momento del caricamento
SCHED_HEARTBEATTimestamp di attività di sched_switchprogramma sched_switch ad ogni invocazione
NMI_LAST_HBRecord dell'ultimo heartbeat dello scheduler da parte di NMIprogramma NMI ad ogni controllo
NMI_FIRST_TICKktime della prima invocazione di NMI (periodo di grazia)programma NMI alla prima invocazione
NMI_LAST_EMITThrottle: ktime dell'ultima emissione di eventiprogramma NMI ad ogni emissione
PCRCosa misuraStabilità
PCR 4Codice del bootloader + immagine del kernel (GRUB misura entrambi)Cambia con l'aggiornamento del kernel
PCR 5Tabella delle partizioni GPT/MBR, configurazione di avvioStabile tra gli aggiornamenti
PCR 7Politica Secure Boot (politica SI, MOK, db/dbx)Stabile tra aggiornamenti del kernel
PCR 8Riga di comando del kernel (misurazioni di systemd-stub)Stabile a meno che la riga di comando non cambi
PCR 9Initramfs (GRUB misura initrd qui)Cambia con l'aggiornamento di initramfs
PCR 10Elenco di misurazioni IMACambia man mano che gli eseguibili vengono misurati
PoliticaSigillata controRobustezzaCosto operativo
FortePCR 4 + 7 + 9 + 10Rileva modifiche al kernel, initramfs, Secure Boot e IMARiscrittura dopo ogni aggiornamento del kernel/initramfs
BilanciataPCR 7 + 10Rileva modifiche Secure Boot e valutazione IMA; stabile tra aggiornamenti del kernelRiscrittura solo in caso di modifica della politica Secure Boot o IMA
MinimaPCR 7 soloRileva solo modifiche allo stato Secure BootMolto stabile; associazione più debole
TermineDefinizione
BPFBerkeley Packet Filter — motore di esecuzione nel kernel per programmi in sandbox. Il BPF moderno (eBPF) si estende oltre i pacchetti a tracing, sicurezza e networking.
BTFBPF Type Format — informazioni di debug del kernel che consentono ai programmi CO-RE (Compile Once, Run Everywhere) di navigare in modo portabile le strutture del kernel.
CO-RECompile Once, Run Everywhere — tecnica BPF che utilizza BTF per scrivere programmi portabili che si adattano a diverse versioni del kernel.
DKOMDirect Kernel Object Manipulation — tecnica rootkit che rimuove un processo dalla lista collegata del kernel per nasconderlo da /proc.
fmod_retTipo di programma BPF che modifica il valore di ritorno di una funzione del kernel tramite il trampolino BPF.
freplaceEstensione di programma BPF — si attacca a una specifica (sotto)funzione di un altro programma BPF, intercettandone l'esecuzione.
funcs arrayL'array di puntatori a funzione in una struttura tracepoint del kernel che contiene le funzioni di callback (inclusi i programmi BPF) da invocare quando il tracepoint si attiva.
IDTInterrupt Descriptor Table — struttura della CPU che mappa i vettori di interrupt alle funzioni handler. Agganciare l'entry NMI richiede la modifica dell'IDT.
kASLRKernel Address Space Layout Randomization — randomizza gli indirizzi di codice/dati del kernel a ogni avvio per ostacolare lo sfruttamento.
NMINon-Maskable Interrupt — interrupt hardware che non può essere disabilitato dal software (cli). Utilizzato dai contatori perf per l'osservazione a livello hardware.
PCRPlatform Configuration Register — registro TPM che accumula misurazioni (hash) dei componenti di avvio. Non può essere resettato (tranne riavvio), solo esteso.
PMUPerformance Monitoring Unit — contatori hardware nella CPU che contano eventi (cicli, cache miss, ecc.) e possono attivare interrupt (NMI) a soglie.
TPMTrusted Platform Module — coprocessore crittografico che fornisce archiviazione di chiavi con radice hardware, generazione di numeri casuali e attestazione delle misurazioni.
VerifierIl verificatore BPF — componente del kernel che analizza staticamente i programmi BPF prima del caricamento per garantire che terminino e non accedano a memoria non sicura.