Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
SPiCa — Detector de rootkit Linux baseado em eBPF usando análise multi-canal de visão cruzada (sched_switch, NMI, /proc) para detectar DKOM, adulteração de tracepoint e ocultação de processos com verificação de integridade em nível de hardware. | Kitploit
Ferramentas/GitHubGitHub/0xkirisame/spica
Ferramentas DefensivasGerenciamento de Indicadores de Comprometimento (IOC)Análise ForenseAnálise de MalwareAnálise de BináriosDetecção de IntrusãoPapers e PesquisaAprendizado e EducaçãoResposta a IncidentesDetecção de Anomalias
GitHub0xkirisame/spica
1046há 1 mêsRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

SPiCa

Detector de rootkit Linux baseado em eBPF usando análise multi-canal de visão cruzada (sched_switch, NMI, /proc) para detectar DKOM, adulteração de tracepoint e ocultação de processos com verificação de integridade em nível de hardware.

Ver Repositório

SPiCa

Integridade de Processos do Sistema e Análise de Visão Cruzada

SPiCa

"Vou cantar, então brilhe intensamente, SPiCa..."

SPiCa é um detector de rootkit Linux baseado em eBPF escrito em Rust. O nome vem da música de Hatsune Miku SPiCa e da estrela que ela referencia — Spica (Alpha Virginis), o ponto mais brilhante em Virgem. O que parece uma única estrela a olho nu é na verdade uma binária espectroscópica: duas estrelas em órbita mútua, indistinguíveis como objetos separados sem medir seus espectros. SPiCa aplica o mesmo princípio à observação do kernel: múltiplos canais independentes medem o mesmo estado do kernel a partir de mecanismos fisicamente distintos, e um rootkit que suprime um é exposto pelos outros.

Aviso: Partes significativas deste código foram geradas ou refatoradas com auxílio de GLM. Testes rigorosos e design iterativo foram aplicados, mas revise o código quanto à segurança e desempenho antes do uso em produção.


Índice

  1. Modelo de Ameaça
  2. Visão Geral da Arquitetura
  3. O Canal de Observação sched_switch
  4. O Canal de Integridade NMI
  5. Lógica de Detecção
  6. Sigilo de Endereço Limitado pelo Verificador
  7. Portão de Acesso ao Mapa LSM
  8. Gerenciamento e Ofuscação de Chaves
  9. Selagem TPM Vinculada a PCR (Design)
  10. Defesa em Profundidade
  11. O Incidente do Bug BTF
  12. Limitações Conhecidas e Superfície de Ataque
  13. Compilar e Executar
  14. Roadmap
  15. Glossário

1. Modelo de Ameaça

O adversário restrito: o rootkit eBPF

SPiCa foi projetado para derrotar o adversário restrito por eBPF — um atacante com privilégios elevados (CAP_BPF ou CAP_SYS_ADMIN) que carrega um programa eBPF privilegiado no kernel. Esse adversário é fundamentalmente mais fraco que um rootkit LKM porque o verificador BPF impõe restrições rígidas:

Com LKMs bloqueados pela porta LSM após a inicialização, esse adversário restrito é a ameaça realista restante. A maquinaria anti-evasão do SPiCa é calibrada para essa ameaça — toda defesa é honesta sobre o que cobre e o que não cobre.

Não objetivos

  • Exploits de kernel de nível nacional — corrupção de memória que resulta em escrita arbitrária no kernel sem init_module. SPiCa eleva o nível ao bloquear o vetor mais fácil de LKM, mas não limita o adversário superior.
  • LKMs hostis carregados antes da inicialização do SPiCa — defesa em profundidade (Secure Boot, assinatura de módulos, IMA) é necessária para a janela de inicialização.
  • Exploits do verificador — se o verificador BPF for inseguro (CVEs históricas: CVE-2020-27194, CVE-2022-23222, CVE-2023-2163), o adversário escapa do modelo restrito para execução arbitrária de código no kernel. Esta é uma classe de ameaça separada. As defesas do SPiCa se mantêm sob um verificador correto.

SPiCa é a camada de último recurso em uma pilha de defesa em profundidade, não um substituto para as camadas acima.


2. Visão Geral da Arquitetura

SPiCa executa quatro programas eBPF anexados a hooks do kernel, além de um motor de detecção em userspace que correlaciona suas saídas com a visão que o sistema tem de si mesmo (/proc).

Três canais de observação, cada um suprimível apenas por um mecanismo de custo crescente

A principal propriedade arquitetural: um rootkit não pode suprimir todos os três canais simultaneamente sem que a supressão em si se torne detectável ou desestabilizadora. Suprimir NMI requer patchear o IDT (Tabela de Descritores de Interrupção), o que causa pânico na maioria dos kernels. Esta é a "bomba viva" — o único caminho do atacante para a cegueira total é aquele que provavelmente trava o sistema.

Modelo de detecção — três frases```

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

root@kitploit:~
Cada classe de detecção é um veredito diferencial: uma discrepância entre dois ou mais canais. O motor de detecção é uma função pura sobre o registro + snapshot do /proc + timestamps dos canais — sem E/S, sem efeitos colaterais, totalmente testável unitariamente.

### A reformulação do NMI: da observação à integridade

No design original, o NMI era um segundo canal de observação de processos que amostrava a CPU e reportava qual tarefa estava em execução. Isso era redundante: o sched\_switch já observa o escalonamento, e o NMI amostrava os mesmos dados por meio de um mecanismo diferente. A redundância custava ~1000+ eventos/s/CPU no ring-buffer de dados de processos que 99,999% das vezes confirmavam "sim, o escalonador está fazendo o que o escalonador faz."

Na arquitetura reformulada, **o NMI é redirecionado da observação de processos para a verificação de integridade de tracepoints.** Ele não reporta mais qual processo está na CPU. Em vez disso, ele verifica se `sched_switch` está realmente em execução lendo um heartbeat compartilhado `.bss`. Isso:

1. Elimina ~99% do tráfego do ring-buffer do NMI (eventos de estado estacionário próximos de zero)
2. Detecta diretamente desanexação de tracepoint, supressão e falhas de BTF/attach (o bug original do BTF — veja [§11](#11-the-btf-bug-incident))
3. Executa a partir de uma interrupção de hardware, fora do caminho de despacho do tracepoint — imune a `bpf_override_return`, interceptação de kprobe e manipulação do array de funções
4. Lê globais `.bss` via acesso direto à memória, não helpers do BPF — imune a `fmod_ret` em funções helper

---

## 3. O Canal de Observação sched\_switch

Um programa eBPF anexado ao tracepoint `sched_switch` é disparado toda vez que o kernel escala um processo para uma CPU. Ele lê o PID e o comm da tarefa de entrada diretamente dos argumentos do tracepoint usando leituras tradicionais de deslocamento fixo (não-BTF):```
ctx.read_at::<u32>(56)    → next_pid
ctx.read_at::<[u8;16]>(40) → next_comm

Deliberadamente não BTF/CO-RE. A disposição dos argumentos do tracepoint é estável entre versões do kernel (faz parte da ABI do tracepoint). Usar offsets fixos evita a fragilidade de versão do kernel da navegação de structs resolvida por BTF. Esta é uma escolha de design deliberada documentada em §11.

Em cada invocação, o programa:

  1. Lê next_pid e next_comm do contexto do tracepoint
  2. Filtra a tarefa ociosa (PID 0)
  3. Ofusca com XOR a struct ProcessInfo com BASE_KEY
  4. Submete ao buffer circular sc_sched
  5. Escreve bpf_ktime_get_ns() no .bss global SCHED_HEARTBEAT — o heartbeat que o verificador de integridade NMI monitora

O programa evita deliberadamente bpf_get_current_pid_tgid() neste contexto. No momento da sched_switch, "current" é a tarefa que está saindo, não a que está entrando. Os argumentos do tracepoint fornecem a identidade correta (entrada) do processo.

Disciplina da base de tempo

O motor de detecção usa uma única base de tempo monotônica: nanossegundos desde a inicialização do processo SPiCa (Instant::now() desde a entrada de run_detection()). Quando um evento sched chega, o manipulador de eventos armazena o now fornecido pelo chamador (nanos locais do processo), não o valor eBPF bpf_ktime_get_ns() embutido no evento. Isso evita a incompatibilidade de base de tempo que ocorreria se o tempo de boot do kernel fosse misturado com o tempo local do processo — um bug que estava presente em versões anteriores e fazia com que todos os predicados de atividade falhassem silenciosamente.


4. O Canal de Integridade NMI

Design: .bss heartbeat, sem BTF, sem navegação de struct do kernel

O programa NMI está anexado a um contador de perf de hardware (HW_CPU_CYCLES) que dispara no nível de interrupção de hardware. NMIs não podem ser desabilitados com cli — suprimi-los requer reprogramar a PMU ou hookar a IDT, ambos os quais são barulhentos e desestabilizadores.

O mecanismo de verificação de integridade é extremamente simples:``` .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:~
### Por que isso detecta todos os ataques no escopo

| Ataque | O que acontece | O que o NMI vê |
|---|---|---|
| Tracepoint removido do array de funcs | sched\_switch para de executar | `SCHED_HEARTBEAT` congela → TAMPER |
| Erro de BTF / falha de attach (silenciosa) | sched\_switch nunca executa | `SCHED_HEARTBEAT` permanece 0 → TAMPER (após carência) |
| `bpf_override_return` em uma função do escalonador | Se impedir o tracepoint de disparar | `SCHED_HEARTBEAT` congela → TAMPER |
| Bytecode corrigido in-place | Requer escrita arbitrária no kernel (nível LKM) | Fora do modelo de ameaça do eBPF |
| Ponteiro do consumidor do ring buffer manipulado | Eventos de sched não chegam ao espaço do usuário | `SCHED_HEARTBEAT` ainda avança (o programa executa) → sem TAMPER falso; espaço do usuário detecta via `max(sched_last)` obsoleto → SILENT |

### Por que `.bss` especificamente

Variáveis globais `.bss` são armazenadas na seção de dados interna do programa BPF, apoiadas por um mapa de array interno que o carregador gerencia. Elas são:

- **Não podem ser fixadas separadamente** — não aparecem como mapas nomeados em `/sys/fs/bpf/`
- **Não interceptáveis via hooks `bpf_map_update_elem`** — escritas em `.bss` são armazenamentos diretos na memória, não chamadas de sistema de atualização de mapa. O antigo mecanismo `sc_canary` (comparar uma cópia `.bss` com uma cópia de mapa nomeado para detectar interceptação de `bpf_map_update_elem`) não é mais necessário.
- **Compartilhadas entre programas no mesmo objeto ELF** — sched\_switch e NMI se comunicam através de `.bss` sem nenhuma interface externa

### Imunidade à interceptação baseada em BPF

O verificador de integridade do NMI é estruturalmente imune a ataques de substituição do BPF devido a uma propriedade fundamental: `bpf_override_return` intercepta **chamadas** de função, mas o verificador do NMI não *chama* as coisas que verifica — ele *lê a memória `.bss` diretamente*. Você não pode substituir o valor de retorno de uma leitura de memória porque uma leitura de memória não é uma chamada de função.

Além disso:
- `bpf_probe_read_kernel` (usado para leituras de structs do kernel em designs alternativos) é um helper seguro contra falhas que aceita qualquer endereço — mas o design de heartbeat `.bss` do SPiCa nem precisa dele. O verificador lê globais `.bss` via instruções de carga direta.
- O programa NMI é executado em contexto NMI, onde kprobes são estruturalmente não confiáveis (o kernel os adia ou suprime). Um ataque baseado em kprobe contra a execução do verificador luta contra o hardware.

### Semântica de eventos do NMI

O ring buffer do NMI (`sc_nmi`) carrega eventos leves:

| `event_type` | Significado | Ação do espaço do usuário |
|---|---|---|
| 0 | Heartbeat — NMI ativo, sched\_switch ativo | Atualizar timestamp `last_nmi_heartbeat` |
| 1 | TAMPER — NMI ativo, heartbeat de sched\_switch congelado | Imprimir `[TAMPER]` imediatamente |

Eventos são emitidos no máximo uma vez por segundo (limitados por `NMI_LAST_EMIT`). Se o ring buffer do NMI ficar silencioso por mais de 5 segundos, o espaço do usuário dispara `[SILENT]` — o próprio canal NMI está morto.

---

## 5. Lógica de Detecção```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;

Detecção SILENT no nível de canal

SILENT é um veredito no nível de canal, não por processo. Ele dispara quando:

  1. canal sched morto: max(sched_last) em todos os registros está obsoleto além de CHANNEL_DEAD_NANOS enquanto /proc não está vazio. A guarda de /proc não vazio é a garantia de atividade: em qualquer sistema Linux em execução, /proc não está vazio (init, threads do kernel, kworkers), e o escalonador nunca está verdadeiramente ocioso (ticks de timer, espera de I/O, callbacks RCU). Um max(sched_last) obsoleto em um sistema não vazio significa que o canal morreu — não que o sistema está ocioso.

  2. canal NMI morto: Nenhum evento de heartbeat (event_type=0) chegou do buffer circular NMI por >5 segundos. Isso significa que o evento perf NMI parou de disparar — ou o evento perf foi desconectado ou o PMU foi reprogramado.

Ambas as verificações possuem um período de espera de 30 segundos para evitar inundação de alertas.

Detecção de rootkit LD_PRELOAD ([HOOK])

SPiCa lê /proc via dois mecanismos independentes a cada tick:

  1. Chamada de sistema getdents64 bruta (read_tgids()) — O std::fs::read_dir do Rust chama isso diretamente via libc::syscall(SYS_getdents64, ...), ignorando todos os hooks de funções libc. Rootkits LD_PRELOAD não podem interceptar este caminho.

  2. libc readdir (read_tgids_libc()) — chama libc::opendir / libc::readdir via FFI, que passa pelo linker dinâmico e é totalmente interceptável por hooks de /etc/ld.so.preload.

Se getdents64 vê PIDs que a libc readdir não vê, um rootkit de espaço do usuário está fazendo hook do readdir para ocultar processos. SPiCa dispara [HOOK]:``` [HOOK] 3 PID(s) hidden from libc readdir — LD_PRELOAD rootkit suspected

root@kitploit:~
Esta técnica transforma o privilégio de nível de kernel do SPiCa em uma detecção ativa de rootkits do espaço do usuário. O caminho da chamada de sistema bruta é a verdade fundamental — nenhum hook do espaço do usuário pode cegá-la. O caminho da libc é a visão "percebida" que uma ferramenta normal (ps, ls) veria. A discrepância é uma prova inequívoca de interceptação de biblioteca.

**Rootkits detectados por `[HOOK]`:**

| Rootkit | Mecanismo de ocultação | Detectado |
|---------|-----------------|----------|
| Symbiote | LD_PRELOAD parasítico, hook `readdir` | Sim (quando ocultando ativamente) |
| JynxKit | LD_PRELOAD, ocultação via `MAGIC_GID` via `readdir` | Sim |
| Azazel | LD_PRELOAD, hooks `readdir` + `stat` | Sim |
| Medusa/OrBit | LD_PRELOAD, hook `readdir` + roubo de credenciais | Sim |

**Testado contra o Symbiote real:** Uma amostra ao vivo do Symbiote (SHA256 `f55af21f...`, MalwareBazaar) foi implantada via `/etc/ld.so.preload` em uma VM Ubuntu 24.04. A amostra intercepta `readdir`, `readdir64`, `stat`, `fstatat`, `pam_authenticate`, `pcap_loop`, `recvmsg`, `fopen`, `read`, `execve`. Quando o hook LD_PRELOAD oculta ativamente um PID do `readdir`, o SPiCa dispara `[HOOK]` dentro de um ciclo de tick (<1 s). Quando o Symbiote está carregado, mas passivo (não ocultando ativamente), o SPiCa produz zero falsos positivos.

### Grace window

Uma janela de graça de 50 ms evita falsos positivos em processos recém-forkados. As verificações SILENT em nível de canal têm um período de graça de 5 segundos (a referência `NMI_FIRST_TICK` do programa NMI) para que a latência de inicialização não produza alertas TAMPER falsos.

---

## 6. Verifier-Bounded Address Secrecy

### Definição

**Verifier-bounded address secrecy** é uma propriedade de segurança computacional que é válida sob o modelo de adversário restrito a eBPF. Ela afirma:

> Dado um adversário que pode carregar programas eBPF (CAP\_BPF) mas é limitado pelo verificador BPF (loops limitados, helpers restritos, sem escrita arbitrária no kernel), o endereço do kernel da seção de dados `.bss` de um programa BPF é computacionalmente inviável de descobrir.

### Os quatro mecanismos

A propriedade é uma composição de quatro barreiras independentes:

1. **kASLR** — Kernel Address Space Layout Randomization randomiza a região do heap do kernel onde a memória dos mapas BPF (incluindo os mapas de apoio `.bss`) é alocada. O endereço exato muda a cada inicialização.

2. **Limite de instruções do Verificador** — O verificador BPF limita o total de instruções por programa a ~1 milhão e exige loops que terminam comprovadamente. Um programa de varredura de um adversário pode sondar no máximo N ≈ 10^6 endereços por carga via `bpf_probe_read_kernel`. Dado um espaço de busca randomizado por kASLR, a probabilidade de sucesso por programa é desprezível.

3. **Portão de acesso a mapas LSM** (veja [§7](#7-lsm-map-access-gate)) — Sem o portão, um adversário poderia enumerar mapas BPF por ID (`BPF_MAP_GET_NEXT_ID` → `BPF_MAP_GET_FD_BY_ID` → `BPF_MAP_LOOKUP_ELEM`) e ler o conteúdo de `.bss` diretamente. O portão remove esse caminho fácil, forçando o adversário ao caminho de varredura de memória limitada pelo verificador.

4. **Posicionamento de `.bss`** — As globais `.bss` não aparecem em interfaces de enumeração de mapas nomeados com nomes legíveis por humanos. O mapa de apoio `.bss` interno é nomeado `.bss` por libbpf/aya, mas seu conteúdo (as variáveis globais reais) é acessível apenas se você tiver o fd do mapa. O fd do mapa requer a tabela de fd do processo de carregamento ou o ID do mapa (bloqueado pelo portão).

### Estrutura do argumento formal```
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).

O que torna isso inovador

A maior parte da pesquisa de segurança em BPF trata o verificador como uma superfície de ataque (bugs do verificador, inconsistência, JIT spray). Este trabalho inverte o enquadramento: as restrições do verificador são uma primitiva defensiva que limita o espaço de busca do adversário. O sigilo não é criptográfico (não é AES); é computacional — limitado pelo que o verificador permite que o adversário compute.

Limitações (devem ser declaradas honestamente)

  • Explorações do verificador — Se o verificador for inconsistente, o limite de instruções quebra e o adversário pode realizar computação arbitrária. Isso está fora do modelo de ameaças do eBPF.
  • Canais laterais de temporização — bpf_probe_read_kernel é observável em termos de temporização (falha vs. sucesso leva ciclos diferentes). Uma busca binária baseada em temporização sobre o heap é teoricamente mais eficiente que uma varredura linear. O limite de instruções restringe as sondagens por programa, mas a busca binária poderia reduzir o número de sondagens para O(log |A|) ≈ 30. Esta é uma limitação real. Mitigação: limitar a taxa de BPF_PROG_LOAD através do gate LSM.
  • Root do espaço de usuário — Um processo root no espaço de usuário (não restringido pelo verificador) pode enumerar mapas por ID. O gate LSM bloqueia isso, mas apenas para processos não-SPiCa. Um processo que comprometa o próprio PID do SPiCa tem acesso total.

7. Gate de Acesso a Mapas do LSM

O problema

Globais .bss são suportados por um mapa BPF interno. Qualquer processo com CAP_BPF pode enumerar todos os mapas no 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:~
Contra o adversário eBPF (que não pode chamar syscalls), `.bss` está oculto. Contra o root do userspace, é um mapa padrão — totalmente legível. O portão LSM fecha essa lacuna.

### A defesa```
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

Os IDs dos mapas são escritos no .bss pelo carregador do espaço do usuário imediatamente após o carregamento do programa, antes que o hook do LSM seja armado (mesmo padrão de temporização do sc_gate existente para bloqueio de LKM). Nenhum BTF é necessário — cmd e map_id vêm dos argumentos da chamada de sistema, não de estruturas do kernel.

Cirúrgico: bloqueia apenas o acesso aos IDs de mapa específicos do SPiCa. Outras ferramentas BPF de outros processos (tcpdump, bpftrace, bcc) acessam seus próprios mapas e não são afetadas.

O que não cobre

  • ptrace / /proc/pid/mem — Outro processo root poderia ler a memória do processo do SPiCa diretamente via ptrace, contornando completamente a chamada de sistema BPF. Esta é uma limitação fundamental: você não pode se proteger contra um processo com o mesmo nível de privilégio lendo sua memória via /proc/pid/mem. Defesa: envio de logs para fora do host (se o atacante consegue ler a memória local, ele também pode suprimir alertas locais — apenas o registro remoto ajuda).
  • PID próprio do SPiCa comprometido — Se o atacante obtiver controle do processo do SPiCa, ele terá acesso legítimo aos mapas.

8. Gerenciamento de Chaves & Ofuscação

Chave originada do TPM

Em hosts equipados com TPM, a chave de ofuscação XOR de 64 bits é obtida do TPM2_GetRandom através da crate tss-esapi (chamada direta à biblioteca libtss2-esys). A chave não transita por pipe, linha de comando de subprocesso ou disco. Ela existe apenas no hardware do TPM e na memória volátil do kernel (mapa de suporte .bss) durante a duração do processo do SPiCa.

Em hosts sem TPM (VMs sem vTPM, contêineres, máquinas sem chip TPM), o SPiCa recai para uma chave de tempo de compilação por build gerada a partir de /dev/urandom pelo script de build. A queda é visivelmente ruidosa na inicialização com um banner de aviso.

Posicionamento no .bss

Os seguintes valores residem na seção .bss do programa eBPF, escrita pelo espaço do usuário via set_global() antes que qualquer programa seja carregado:

Mapas BPF nomeados são enumeráveis através da interface de iteração de mapas da chamada de sistema bpf() (bloqueada pela porta do LSM — veja §7); globais .bss são acessados através do mesmo mapa interno, mas não são separadamente nomeados ou fixáveis.

Ofuscação XOR — defesa contra vazamento por leitura, não criptografia

Todos os campos de ProcessInfo são dobrados por XOR com a BASE_KEY de 64 bits antes de serem escritos nos buffers de anel. O campo event_type é intencionalmente deixado sem ofuscação para que o espaço do usuário possa lê-lo como um sentinela antes de desofuscar o restante.

Isso é ofuscação contra vazamento por leitura, não criptografia contra um adversário capaz. XOR com uma chave repetitiva de 8 bytes é estruturalmente vulnerável a texto claro conhecido: valores previsíveis de comm ("bash", "systemd", "kthreadd") aplicados XOR ao texto cifrado recuperam bytes da chave diretamente. A defesa é apropriada para o adversário do eBPF (que não pode ler facilmente o buffer de anel — requer a mesma lacuna de capacidade que protege .bss), não para um adversário com acesso binário + interceptação de buffer de anel.


9. Selagem TPM Vinculada a PCR (Design)

Status: Fase de design. Ainda não implementado. Esta seção documenta a arquitetura alvo para o artigo de pesquisa.

Visão Geral

A selagem TPM vinculada a PCR move o limite de distribuição de chaves da camada de software para o silício. A chave é selada no momento da instalação contra valores esperados dos Registradores de Configuração de Plataforma (PCRs), e só pode ser desselada se o estado de inicialização do sistema corresponder às medições esperadas.

Cadeia de medição de inicialização

Durante a inicialização, o firmware, o bootloader e o kernel medem componentes críticos nos PCRs:

Nota: A alocação de PCR é dependente da cadeia de inicialização. O GRUB mede o kernel no PCR 4; o systemd-stub mede no PCR 4 e a linha de comando no PCR 8. A política de selagem deve corresponder à cadeia de inicialização alvo.

O fluxo selar → desselar → injetar → falha segura

  1. Selar (momento da instalação): A chave de 64 bits é selada contra valores esperados de PCR usando TPM2_Create com uma sessão TPM2_PolicyPCR. O blob selado é armazenado em disco. Ele é criptografado com a chave interna do TPM e só pode ser descriptografado quando os PCRs especificados corresponderem.

  2. Desselar (inicialização precoce, estágio initramfs): Antes que qualquer código de espaço do usuário não confiável execute, o hook initramfs do SPiCa solicita TPM2_Unseal. Se os valores atuais de PCR corresponderem à política de selagem, o TPM libera a chave.

  3. Injetar: A chave é escrita no .bss via set_global() antes que os programas sejam carregados.

  4. A armadilha: Se um atacante modificou o kernel (incompatibilidade PCR 4), trocou o initramfs (incompatibilidade PCR 9) ou alterou a política de Secure Boot (incompatibilidade PCR 7), os hashes do PCR divergem. O TPM se recusa a desselar, e o SPiCa falha de forma segura — ele se recusa a iniciar em vez de executar cego com uma chave comprometida.

Opções de política de PCR

Para o artigo de pesquisa, apresente a política forte e discuta a troca do resselamento nas limitações.

Relação com o sigilo de endereço limitado pelo verificador

Os dois mecanismos são complementares:

  • Selagem PCR protege a chave na inicialização — garante que a chave só esteja disponível em um estado de sistema confiável.
  • Sigilo de endereço limitado pelo verificador + porta LSM protegem a chave em tempo de execução — garantem que o adversário do eBPF não possa localizar ou ler o .bss onde a chave reside.

Nenhum é suficiente sozinho. A selagem PCR não ajuda se a chave for comprometida em tempo de execução (enumeração de mapas). O sigilo de endereço não ajuda se o sistema foi comprometido antes do SPiCa iniciar (initramfs hostil).

O que a selagem PCR NÃO detecta

  • Desanexação do programa LSM em tempo de execução — Os programas BPF LSM (spica_lsm_modblock, a porta de acesso ao mapa) são carregados em tempo de execução e NÃO são medidos em nenhum PCR. Um rootkit que os desanexa após a inicialização não é detectado pela selagem PCR. O que detecta isso é o heartbeat NMI (detectando que o próprio sistema de detecção parou de executar).
  • Exploração do kernel pós-inicialização — Se o kernel for explorado após a inicialização (corrupção de memória → escrita arbitrária), os PCRs permanecem inalterados. Esta é a não-meta "estado-nação".

10. Defesa em Profundidade

O SPiCa é a última camada de aplicação. Ele complementa um sistema configurado adequadamente, não substitui as camadas acima.```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 verifica todas as quatro camadas na inicialização e exibe seu status.

---

## 11. O Incidente do Bug BTF

### O que aconteceu

Durante os testes no Ubuntu (kernel mais recente), uma incompatibilidade BTF fez com que o programa de tracepoint `sched_switch` anexasse com sucesso, mas **nunca disparasse um único evento.** A chamada de sistema `attach()` retornou `Ok(())`, então o SPiCa prosseguiu normalmente — mas o ring buffer de sched permaneceu vazio. Nenhum alerta de detecção foi acionado porque o motor de detecção não tinha dados de escalonamento. **SPiCa funcionou às cegas sem qualquer indicação de falha.**

Este é o pior modo de falha para uma ferramenta de segurança: cegueira silenciosa.

### Por que não foi detectado

O motor de detecção original raciocinava **por processo**: cada registro de processo tinha timestamps `sched_last` e `nmi_last`, e a vivacidade era calculada por registro. Quando sched\_switch morreu globalmente:

1. `sched_live` tornou-se falso para cada registro (sem novos eventos sched → todos os valores `sched_last` envelhecem)
2. O predicado `TAMPER` por processo (`in_proc && nmi_live && !sched_live`) poderia disparar, mas exigia que `nmi_live` fosse mantido *continuamente* por 2 segundos. As amostras NMI são esparsas (período de 10M ciclos), então `suspect_since` era continuamente redefinido devido à variação da amostragem e nunca amadurecia.
3. O predicado `SILENT` por processo exigia `sched_live`, que agora era falso para tudo — o predicado invertia exatamente na condição que deveria detectar.
4. **Não havia verificação de vivacidade em nível de canal** — nenhum mecanismo do tipo "sched JÁ disparou?" ou "max(sched_last) está obsoleto?".

Além disso, foi descoberta uma incompatibilidade de base temporal: `sched_last` armazenava `bpf_ktime_get_ns()` (nanossegundos de inicialização do kernel) enquanto `evaluate()` comparava com `nanos_since_startup()` (nanossegundos locais do processo). O `wrapping_sub` dessas bases temporais diferentes produzia valores enormes, tornando todos os predicados de vivacidade trivialmente falsos. A lógica de detecção nunca havia funcionado corretamente em produção — o bug BTF apenas a mascarou ao impedir a chegada de eventos.

### Como o redesign corrige

| Problema | Correção |
|---|---|
| Nenhuma verificação de vivacidade em nível de canal | `evaluate()` agora calcula `max(sched_last)` e dispara `[SILENT]` se estiver obsoleto enquanto `/proc` não está vazio |
| TAMPER por processo nunca amadurecia (reset por jitter) | TAMPER agora é um sinal direto do programa NMI (comparação de heartbeat `.bss`), não uma FSM por processo com limites |
| SILENT por processo invertia quando sched morria | SILENT agora é em nível de canal, calculado a partir de agregados, não de predicados por registro |
| Incompatibilidade de base temporal | `sched_last` agora armazena tempo local do processo (parâmetro `now`), não `bpf_ktime_get_ns()` |
| NMI era observação redundante | NMI agora é um verificador de integridade — detecta morte de sched diretamente via heartbeat `.bss` |

---

## 12. Limitações Conhecidas e Superfície de Ataque

### Dentro do modelo de ameaça eBPF

| Ataque | Status | Notas |
|---|---|---|
| **Manipulação do ponteiro consumidor do ring buffer** | **Detectado** (SILENT) | `max(sched_last)` fica obsoleto → SILENT. `SCHED_HEARTBEAT` ainda avança (programa executa) → sem falso TAMPER. |
| **DKOM da struct perf event** (zerar campo `state`) | **Detectado** (SILENT) | NMI para de disparar → sem eventos de heartbeat → SILENT no canal NMI |
| **Spoofing de campo `task_struct`** (sobrescrever pid/tgid) | **Parcial** (DUPE) | Se o TGID spoofado corresponder a um registro existente com `start_time_ns` diferente, DUPE dispara. Se `start_time_ns` também for spoofado, isso passa despercebido. |
| **Desanexação do programa eBPF** (remover do array funcs) | **Detectado** (TAMPER) | Heartbeat NMI congela → TAMPER |
| **Bytecode patchado in-place** | **Não detectado** | Requer escrita arbitrária no kernel (nível LKM) — fora do modelo de ameaça eBPF |
| **Canal lateral de temporização no `bpf_probe_read_kernel`** | **Risco teórico** | Busca binária na heap poderia encontrar `.bss` em ~30 sondas. Veja limitações em [§6](#6-verifier-bounded-address-secrecy). |

### Fora do modelo de ameaça eBPF (reconhecido, não resolvido)

| Ataque | Status | Notas |
|---|---|---|
| **Hook de IDT/manipulador NMI** | **A bomba viva** | Burlamento arquiteturalmente completo. Quase certeza de pânico no kernel. |
| **Supressão de canal duplo** | **A bomba viva** | Suprimir simultaneamente sched + NMI. Herda instabilidade do hooking NMI. |
| **Exploração do Verificador** | **Não é objetivo** | Escapada para execução arbitrária de código do kernel. Classe de ameaça separada. |
| **ptrace / `/proc/pid/mem`** | **Limitação fundamental** | Leitura de memória com mesmo privilégio. Apenas envio de logs fora do host ajuda. |
| **Patch de ponteiro consumidor + heartbeat** | **Nível LKM** | Se o atacante tiver escrita arbitrária no kernel, pode avançar o ponteiro consumidor E escrever heartbeats falsos. Mas escrita arbitrária no kernel = nível LKM = fora do modelo de ameaça. |

---

## 13. Compilar & Executar

### Pré-requisitos

- Kernel Linux >= 5.15 com `CONFIG_DEBUG_INFO_BTF=y` (apenas para o hook LSM)
- Para bloqueio de módulos: `CONFIG_BPF_LSM=y` e `lsm=bpf` na linha de comando do kernel
- Chip TPM 2.0 + biblioteca `tpm2-tss` (opcional; recai com aviso visível)
- Cadeia de ferramentas Rust nightly

> **Nota:** A etapa `generate-vmlinux` **não é mais necessária**. Os programas eBPF usam offsets de tracepoint tradicionais e globais `.bss` — nenhuma navegação de struct CO-RE/BTF é necessária. O comando xtask `generate-vmlinux` é mantido para uso futuro, mas não faz parte do pipeline de compilação.

Verifique se BPF LSM está ativo: `cat /sys/kernel/security/lsm` deve conter `bpf`.

### Setup```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)

Executar```shell

make run # sudo ./target/release/spica

root@kitploit:~
### Instalar no initramfs (proteção de inicialização antecipada)```shell
sudo make install     # spica install — auto-detects Debian (initramfs-tools) or Fedora (dracut)

Verifique se está funcionando```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:~
### Desenvolvimento (macOS ou Linux)

Os programas eBPF não podem ser executados no macOS. `cargo check` e testes unitários para a lógica de detecção funcionam; a verificação completa em tempo de execução requer 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

  • Selamento de chaves vinculadas a PCR — atestação real de hardware. No momento da instalação, selar a chave aos valores esperados de PCR (PCR 4/7/9/10). Em tempo de execução, a abertura falha se os PCRs forem alterados. Substitui o uso atual de GetRandom apenas no TPM por uma raiz de confiança completa em hardware. Consulte §9.
  • Portão de acesso a mapas do LSM — Hook LSM BPF na chamada de sistema bpf bloqueando a enumeração de mapas do estado interno do SPiCa por processos não SPiCa. Consulte §7.
  • Limitação de taxa de BPF_PROG_LOAD — Estender o portão LSM para limitar a taxa de carregamento de programas BPF a partir de processos não SPiCa, mitigando o risco de canal lateral de temporização na descoberta de .bss. Consulte §6 limitações.
  • Atualização de ofuscação da PRF SipHash — Se o modelo de ameaça crescer para incluir adversários com acesso de leitura ao ring buffer, trocar XOR por um fluxo de chaves SipHash-1-3 (a dependência siphasher já está na árvore para o token de integridade).
  • Backend de registro empresarial — Envio opcional para Elasticsearch/Elastic SIEM para ambientes SOC. Todos os alertas, eventos de término e anomalias de contador de reinicialização enviados para fora do host em tempo real.
  • Suporte adicional a distribuições — Arch (mkinitcpio), openSUSE.
  • Pipeline de CI — Testes de fumaça Linux exercitando fluxo real de carregamento + anexação + ring buffer de eBPF.

15. Glossário


Licença

Licença do SPiCa Engine: MIT OU Apache-2.0 (workspace). O programa eBPF exporta uma licença GPL através do static _license — este é um requisito do kernel para programas eBPF que usam helpers licenciados sob GPL, e se aplica apenas ao bytecode eBPF carregado, não ao binário do espaço do usuário.

Atribuição de Personagem: "Hatsune Miku" e obras de arte de personagem associadas são propriedades protegidas por direitos autorais da Crypton Future Media, INC. (www.piapro.net). Este projeto é uma ferramenta de pesquisa independente, não comercial, não afiliada à Crypton Future Media. Personagem usado sob a Piapro Character License (PCL).

O nome do projeto SPiCa é inspirado pela música original de Toku-P.

Baixar ferramenta
RestriçãoEfeito no adversário
Laços limitados (~1M instruções por programa)Não pode escanear toda a memória do kernel
Segurança de ponteiros (desreferência direta requer alvo comprovadamente válido e limitado)Não pode seguir ponteiros arbitrários
Helpers restritos (lista de permissão por tipo de programa)Não pode chamar kmalloc, vmalloc ou qualquer função de alocação do kernel
Nenhuma escrita arbitrária no kernel (bpf_probe_write_kernel fortemente restrita)Não pode modificar task_struct, arrays de funções de tracepoint ou bytecode de programas BPF
Acesso ao mapa limitado às referências carregadasNão pode acessar mapas pertencentes a outros programas (a menos enumerados por ID — veja §7)
CanalMecanismoO que o suprimeCusto da supressão
/procEnumeração de diretórios procfsDKOM (desvincular processo da lista de tarefas)Baixo — técnica de rootkit bem compreendida
sched_switchTracepoint eBPF no escalonadorDesanexar programa do array de funções; filtrar contextoMédio — requer escrita no kernel no array de funções
NMIInterrupção de contador de performance por hardware → evento de perf eBPFHook no IDT/manipulador NMIQuase certeza de pânico no kernel — interrupção de hardware, não mascarável
AlertaCondiçãoO que detecta
[DKOM]TGID agendado pelo kernel ausente de /proc por >2 sManipulação Direta de Objetos do Kernel — processo ocultado da enumeração do espaço do usuário
[GHOST]TGID presente em /proc mas nunca visto por sched_switch por >5 sFalsificação de /proc — entrada falsa inserida para passar nas verificações DKOM
[TAMPER]NMI detecta heartbeat do sched_switch congelado (event_type=1)Tracepoint desconectado, suprimido ou falha de BTF/attach
[SILENT]max(sched_last) obsoleto em todo o registro enquanto /proc não está vazio; ou heartbeat NMI ausente por >5 sPerda de observação no nível de canal — canal sched ou NMI está morto
[DUPE]Mesmo TGID, diferentes start_time_ns entre eventosFalsificação de campo task_struct — rootkit modifica tgid para se passar por um processo legítimo
[HOOK]PIDs visíveis via getdents64 bruto, mas ausentes de libc readdirRootkit LD_PRELOAD — interceptação de biblioteca no espaço do usuário ocultando processos de ps, ls e outras ferramentas (Symbiote, JynxKit, Azazel, Medusa/OrBit)
[WATCHDOG]O pino /sys/fs/bpf/spica_watchdog existe na inicializaçãoInstância anterior foi encerrada abruptamente (SIGKILL, OOM, crash)
[LKM-ALLOW]READING_MODULE interceptado enquanto a porta está aberta (janela de inicialização)Registro de auditoria: módulo carregado antes da porta ser bloqueada
[LKM-DENY]READING_MODULE interceptado enquanto a porta está bloqueadainsmod/modprobe bloqueados pós-inicialização
GlobalPropósitoEscrito por
BASE_KEYChave de ofuscação XORespaço do usuário no momento do carregamento
SPICA_PIDTGID próprio do SPiCa (watchdog)espaço do usuário no momento do carregamento
SCHED_HEARTBEATTimestamp de atividade do sched_switchprograma sched_switch em cada invocação
NMI_LAST_HBRegistro do NMI do último heartbeat do schedprograma NMI em cada verificação
NMI_FIRST_TICKPrimeiro ktime de invocação do NMI (período de graça)programa NMI na primeira invocação
NMI_LAST_EMITThrottle: último ktime de emissão de eventoprograma NMI em cada emissão
PCRO que medeEstabilidade
PCR 4Código do bootloader + imagem do kernel (GRUB mede ambos)Muda na atualização do kernel
PCR 5Tabela de partição GPT/MBR, configuração de inicializaçãoEstável entre atualizações
PCR 7Política de Secure Boot (política SI, MOK, db/dbx)Estável entre atualizações de kernel
PCR 8Linha de comando do kernel (medições do systemd-stub)Estável a menos que cmdline mude
PCR 9Initramfs (GRUB mede initrd aqui)Muda na atualização do initramfs
PCR 10Lista de medição IMAMuda conforme executáveis são medidos
PolíticaSelado contraForçaCusto operacional
FortePCR 4 + 7 + 9 + 10Detecta alterações no kernel, initramfs, Secure Boot e IMAResselar após cada atualização de kernel/initramfs
EquilibradaPCR 7 + 10Detecta alterações no Secure Boot e avaliação IMA; estável entre atualizações de kernelResselar apenas em mudanças na política de Secure Boot ou IMA
MínimaPCR 7 apenasDetecta apenas alterações no estado do Secure BootMuito estável; vínculo mais fraco
TermoDefinição
BPFBerkeley Packet Filter — motor de execução no kernel para programas em sandbox. O BPF moderno (eBPF) estende-se além de pacotes para rastreamento, segurança e rede.
BTFBPF Type Format — informação de depuração do kernel que permite que programas CO-RE (Compile Once, Run Everywhere) naveguem por estruturas do kernel de forma portátil.
CO-RECompile Once, Run Everywhere — técnica BPF que usa BTF para escrever programas portáteis que se adaptam a diferentes versões do kernel.
DKOMDirect Kernel Object Manipulation — técnica de rootkit que remove um processo da lista encadeada do kernel para ocultá-lo de /proc.
fmod_retTipo de programa BPF que modifica o valor de retorno de uma função do kernel através do trampolim BPF.
freplaceExtensão de programa BPF — anexa a uma (sub)função específica de outro programa BPF, interceptando sua execução.
funcs arrayO array de ponteiros de função em uma estrutura de tracepoint do kernel que mantém funções de retorno de chamada (incluindo programas BPF) a serem invocadas quando o tracepoint dispara.
IDTInterrupt Descriptor Table — estrutura da CPU que mapeia vetores de interrupção para funções manipuladoras. Enganchar a entrada NMI requer correção da IDT.
kASLRKernel Address Space Layout Randomization — randomiza endereços de código/dados do kernel a cada inicialização para dificultar a exploração.
NMINon-Maskable Interrupt — interrupção de hardware que não pode ser desabilitada por software (cli). Usada por contadores de desempenho para observação em nível de hardware.
PCRPlatform Configuration Register — registro do TPM que acumula medições (hashes) de componentes de inicialização. Não pode ser redefinido (exceto reinicialização), apenas estendido.
PMUPerformance Monitoring Unit — contadores de hardware na CPU que contam eventos (ciclos, cache misses, etc.) e podem disparar interrupções (NMIs) em limites.
TPMTrusted Platform Module — coprocessador criptográfico que fornece armazenamento de chaves com raiz em hardware, geração de números aleatórios e atestação de medições.
VerifierO verificador BPF — componente do kernel que analisa estaticamente programas BPF antes do carregamento para garantir que terminem e não acessem memória insegura.