Linux Kernel Security Scanner
A single-binary, one-shot incident response scanner written in C++23. Deploy into restricted environments with zero dependencies and detect hidden kernel modules, rootkits, compromised syscall tables, and more.
Built for real-world incident response
8 self-registering scanners covering kernel modules, processes, network, syscalls, entrypoints, and BPF. Add new scanners with zero framework changes.
Machine-readable JSON and human-friendly colored text output. Structured findings with severity levels, details, and key-value evidence.
Each scanner runs in a forked child process with a configurable timeout. One hung scanner never blocks the rest of the assessment.
Build a fully static binary with no runtime dependencies beyond libc. Deploy via SCP into compromised environments with no package manager needed.
Requires root privileges for deep kernel inspection. Accesses /proc/kcore, kernel symbol tables, cgroups, and raw network socket state.
Exit 0 when clean, 1 when findings detected, 2 on errors. Designed for automation, CI pipelines, and scripted incident response workflows.
8 specialized detectors for kernel-level threats
Detects hidden Loadable Kernel Modules by comparing module visibility across /proc/modules, /sys/module, and /proc/kallsyms. Identifies modules present in kallsyms but missing from procfs/sysfs.
Discovers hidden processes using multi-view cross-checks: /proc enumeration, kill(0) probing, cgroup task files, and /proc/loadavg analysis. Revalidation snapshots eliminate transient race conditions.
Detects hidden or redirected network sockets by comparing /proc/net tables, netlink diagnostics via ss, and process file descriptor scanning. Two-snapshot validation reduces false positives.
Validates syscall entrypoints by reading MSRs (IA32_LSTAR, IA32_CSTAR, IA32_SYSENTER_EIP) and IDT vectors via /proc/kcore. Detects entrypoint redirection to module code or trampolines. x86_64-specific.
Analyzes ftrace function hooks for suspicious kernel path redirection. Checks tracer configuration, filter functions against critical patterns covering syscalls, VFS, credentials, and LSM hooks.
Discovers kprobe and kretprobe events targeting sensitive kernel functions. Matches against critical patterns including syscalls, credentials, module loading, VFS, network, LSM, and BPF functions.
Examines syscall table entries by parsing /proc/kcore ELF core image. Verifies each entry resolves to core kernel text or legitimate modules. Detects entries pointing outside kernel memory.
Comprehensive eBPF/BPF security scanner analyzing programs, maps, and links via bpftool. Detects ownerless high-risk hooks, suspicious naming patterns, bpffs mount anomalies, and checks hardening sysctls.
Simple CLI for rapid deployment and scripting
# sudo ./klint
[hidden_lkm] (kernel)
OK
[hidden_processes] (process)
WARNING cgroup task anomaly detected
pid: 31337
source: cgroup tasks vs /proc
[syscall_table_integrity] (kernel)
CRITICAL sys_call_table entry points outside kernel text
syscall: __x64_sys_getdents64
address: 0xffffffffc0a01234
# sudo ./klint --json
{
"scanners": [...],
"summary": {
"total": 8,
"clean": 6,
"findings": 2,
"errors": 0,
"skipped": 0,
"timed_out": 0
}
}
# Run only specific scanners
# sudo ./klint --scanner hidden_lkm --scanner hidden_processes
# Exclude a scanner
# sudo ./klint --exclude bpf_rootkit_detection
# List available scanners
# ./klint --list
SCANNER CATEGORIES REQUIRES
-----------------------------------------------------------------------
bpf_rootkit_detection kernel, network, persistence, tool:bpftool
process
ftrace_redirection kernel -
hidden_lkm kernel -
hidden_network_sockets network tool:ss
hidden_processes process -
kernel_entrypoint_integrity kernel -
syscall_table_integrity kernel -
unknown_kprobes kernel -
# Set per-scanner timeout (default: 30s)
# sudo ./klint --timeout 60
# Disable colored output
# sudo ./klint --no-color
# Combine for CI pipelines
# sudo ./klint --json --timeout 45 \
--exclude bpf_rootkit_detection
# Check exit code
# sudo ./klint --json; echo "Exit: $?"
Designed for reliability in hostile environments
Each scanner is a standalone .cpp file that auto-registers at static initialization time via a Registrar object. Adding a new scanner requires zero changes to the framework—just drop in a new file and rebuild.
// Each scanner self-registers:
static Registrar reg_{Scanner{
.name = "hidden_lkm",
.func = run,
.categories = kCategories,
.requirements = kRequirements,
}};
Every scanner executes in a forked child process with results serialized as JSON over a pipe. This provides crash isolation, timeout enforcement, and prevents one scanner's failure from affecting the rest of the assessment.
Scanners cross-reference multiple kernel data sources to detect inconsistencies. Hidden LKM compares /proc/modules vs /sys/module vs /proc/kallsyms. Hidden processes checks /proc vs kill() vs cgroups. This multi-view approach is resilient to single-source tampering.
Every finding carries a Severity (Info, Warning, Critical), a one-line summary, optional detail text, and structured key-value evidence. Results aggregate into a typed ScanResult with clean separation of findings and errors.
Build from source in under a minute
$ git clone https://github.com/h2337/klint.git klint
$ cd klint
$ mkdir build && cd build
$ cmake ..
$ cmake --build .
# Fully static, no runtime deps
$ cmake -DSTATIC_BUILD=ON ..
$ cmake --build .
# Deploy to target
$ scp klint root@target:/tmp/
$ ssh root@target /tmp/klint --json
# Enable sanitizers (dev)
$ cmake -DENABLE_SANITIZERS=ON ..
# Treat warnings as errors
$ cmake -DWERROR=ON ..