KASLD recovers the Linux kernel's virtual and physical memory layout —
primarily the kernel text base — from a local process, using as much as
the process's vantage allows: its privileges and capabilities, the
system's configuration, and any container confinement. It recovers the
kernel text base outright where a leak or side channel allows, and
otherwise narrows it to the smallest set of placements the available
evidence supports. The inference engine fuses evidence from dozens of
independent techniques with the architecture's known invariants,
narrowing the kernel's placement to a residual window — reported as the
surviving slot count and bits of entropy: an upper bound on the protection
KASLR retains from this vantage, not a guarantee the base is beyond an
attacker's reach (see [docs/limitations.md](docs/limitations.md)). On a
fully-patched modern kernel — where x86-64 side channels are mitigated
and no direct kernel-text leak survives — full recovery is often impossible,
but the constraint set is rarely empty. On architectures without KASLR, the
engine locates the bootloader-chosen load address.
Supports:
* x86 (i386+, amd64)
* ARM (armv6, armv7, armv8, aarch64)
* MIPS (mipsbe, mipsel, mips64el)
* PowerPC (ppc, ppc64)
* RISC-V (riscv32, riscv64)
* LoongArch (loongarch64)
* s390
## Quick start
```sh
sudo apt install libc-dev make gcc binutils git
git clone https://github.com/bcoles/kasld
cd kasld
make
./build//kasld
```
The `build//` directory is self-contained and can be deployed to a
target system:
```
build//
kasld <- run this
components/ <- leak components
```
A hardened configuration (`kernel.dmesg_restrict=1`,
`kernel.kptr_restrict=1`, `kernel.perf_event_paranoid=2` or higher,
`kernel.unprivileged_bpf_disabled=1`) narrows the filesystem-oracle
path, but is only one axis of the vantage:
side-channel, weak-entropy, and capability-granted techniques are
independent of these sysctls. For testing, the
[extra/weaken-kernel-hardening](extra/weaken-kernel-hardening) script
can temporarily relax these settings (requires root).
## Example output
The default text mode prints an answer-first overview:
```
KASLD 0.3.1-dev -- Kernel ASLR derandomization
Target: x86_64 / 6.15.6
Running 94 of 97 components (3 experimental skipped; use -x to enable)...
[####################] 100% 94/94 13.9s
Layout
Virtual image base (pinned)
guaranteed 0xffffffff8fe00000 slide +0xee00000
Physical image base (pinned)
guaranteed 0x34600000 slide +0x33600000
Direct map base
guaranteed >= 0xffff800000000000
Note: physical and virtual text randomize independently
Evidence (6 findings, 5 components)
virt kernel text [interior] 0xffffffff8ff04104
from perf_event_open, proc_kallsyms
virt kernel image [base] 0xffffffff8fe00000
from perf_event_open, prefetch, proc_kallsyms
virt directmap [base] 0xffff9eeb80000000
from prefetch_directmap
phys kernel image [base] 0x34600000
from proc_iomem_kernel
phys kernel data [base] 0x36000000
from proc_iomem_kernel
phys kernel BSS [base] 0x36b34000
from proc_iomem_kernel
[-v: detailed results, memory map, system info] [-H: hardening assessment]
```
`-v` adds the full verbose readout (banner, system-config block,
per-component logs, KASLR analysis, memory-layout maps). `-j` emits
machine-readable JSON — the complete structured view, always including
the per-component records and the hardening assessment. `-1` emits a
single shell-pipeable line. `-m` formats for issue trackers. `-H`
appends the hardening assessment to the text/markdown reports.
See [docs/usage.md](docs/usage.md) for the full CLI, output-mode
details, explain mode, and hardening assessment.
## Vantage
What KASLD can recover depends on the running process's *vantage* — not a
single privilege level, but the combination of three independent things:
* **Privileges, groups, and capabilities** — an unprivileged uid, membership
in a group such as `adm` (which grants the kernel logs under `/var/log/`),
a container task holding an extra capability, or root. These do not form a
single ladder, because filesystem permissions gate each source
independently: a container granted `CAP_SYS_RAWIO` is init-namespace root
for that check and can read `/proc/kcore` — a leak an ordinary user cannot
reach — while distributions differ over whether a file such as
`/boot/System.map` is world-readable at all.
* **System configuration** — `kptr_restrict`, `dmesg_restrict`,
`perf_event_paranoid`, unprivileged BPF, kernel lockdown. Configuration is
independent of privilege: root cannot read `/proc/kallsyms` under
`kptr_restrict=2`, while a relaxed sysctl or unprivileged BPF can hand a
plain user a leak that a hardened system would deny.
* **Confinement** — a namespace or seccomp sandbox that masks `/proc`
oracles or blocks syscalls, narrowing what any privilege level observes.
The three axes gate each leak source independently — so more privilege is not a
superset of less: configuration can deny a source to root, and side channels
bypass the sysctls entirely. [docs/usage.md](docs/usage.md#vantage) has a
leak-source-by-gate matrix showing which axis controls each source.
KASLD assumes few privileges by default and opportunistically uses whatever
the vantage grants. The reported *guaranteed* window never depends on
privilege: elevated access or a weak configuration can widen what is
attempted, never the sound layout the evidence proves. The verbose (`-v`),
JSON (`-j`), and Markdown (`-m`) outputs report the detected vantage —
container, confinement, readable oracles, and the capability-gated leaks
reachable from the current capabilities.
## Documentation
New to KASLD? Read in order: [docs/kaslr.md](docs/kaslr.md) (what KASLR is and
what it randomizes) → [docs/architecture.md → A leak from end to
end](docs/architecture.md#a-leak-from-end-to-end) (how KASLD turns one leak into
an answer) → [docs/limitations.md](docs/limitations.md) (what a result does and
does not prove) → [CONTRIBUTING.md](CONTRIBUTING.md) (add a leak component or
inference rule). The table below indexes the docs by topic.
| Topic | Document |
|---|---|
| KASLR primer | [docs/kaslr.md](docs/kaslr.md) — per-arch KASLR history, default text base, vmsplit, FG-KASLR |
| Usage & CLI | [docs/usage.md](docs/usage.md) — CLI, output modes, explain mode, hardening assessment |
| Interpreting results | [docs/limitations.md](docs/limitations.md) — what a negative or partial result means: sound-but-not-complete, and why a failure is not a security guarantee |
| Bypass techniques | [docs/bypass-techniques.md](docs/bypass-techniques.md) — filesystem leaks, side-channels, syscall / ioctl leaks, weak entropy, patched CVEs, arbitrary read |
| Exploitation | [docs/exploitation.md](docs/exploitation.md) — where KASLR-defeat fits in an exploit, control-flow vs data-only, pwntools template, `ksymoff` |
| Footprint & detection | [docs/footprint.md](docs/footprint.md) — what a run looks like on a monitored host: the behavioural signature to detect it, and the operator's OPSEC cost; loud by design |
| Utilities | [extra/README.md](extra/README.md) — the `extra/` helper scripts (capture/replay, soundness validation, posture-diff, `ksymoff`) and how they combine |
| Architecture & internals | [docs/architecture.md](docs/architecture.md) — the inference engine, data-flow seams, tagged-line protocol, cross-region derivation |
| Contributing | [CONTRIBUTING.md](CONTRIBUTING.md) — writing a component or rule, emitter API, exit codes, metadata |
| Testing & CI | [docs/testing.md](docs/testing.md) — host tests, replay fixtures, cross-arch under qemu-user, coverage |
| Reproducibility | [docs/reproducibility.md](docs/reproducibility.md) — independent verification: on the local kernel, live across architectures, or over the captured corpus |
## Building
A compiler which supports the `_GNU_SOURCE` macro is required due to
use of non-portable code (`MAP_ANONYMOUS`, `getline()`, `popen()`, …).
```
make # build kasld + components
make run # build and run
make test # build and run unit tests
make cross # cross-compile for all supported architectures
make install # install to /usr/local (PREFIX=/usr/local)
make installcheck # smoke-test the installed bin/kasld + libexec/kasld/
make uninstall # remove installed files
make clean # remove build directory
make print-deps # list build dependencies (libs + per-component flags)
make help # show all targets and options
```
`make print-deps` reports the required toolchain, the two optional libraries
(`pthread`, `zlib`) with their auto-detection result for the current compiler,
and the per-component compile/link flag exceptions — enough to populate a
distribution package's control file without reading the Makefile's probe logic.
`make installcheck` runs the installed `bin/kasld` and confirms it discovers its
components via the FHS `../libexec/kasld` path — a post-install smoke test for
the split-install layout, using the same `PREFIX`/`DESTDIR` as `make install`
(so it also works against a `DESTDIR` staging root in package CI).
`make install` also installs `man1` manual pages for `kasld` and `ksymoff` to
`/share/man/man1/`, so `man kasld` and `man ksymoff` work after install.
KASLD can be cross-compiled with `make` by specifying the appropriate
compiler (`CC`). Static linking is applied automatically when cross-compiling:
```
make CC=aarch64-linux-musl-gcc
```
Build all supported cross-compilation targets (toolchains must be in `PATH`):
```
make cross
```
## License
KASLD is MIT licensed (see [LICENSE](LICENSE)). Some leak components adapt
third-party proof-of-concept code or implement a technique first published by
others; each such file credits its original author and source in its header,
and [THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md) lists each with its license
or reuse basis (upstream license, author permission, or technique/reproducer
material reimplemented here).
## Citing KASLD
KASLD is MIT licensed — attribution is not required for use, but if you
reference it in research, tooling, exploits, or writing, a citation or link is
appreciated:
> **KASLD: Kernel Address Space Layout Derandomization**, Brendan Coles,
> https://github.com/bcoles/kasld
BibTeX:
```bibtex
@software{kasld,
title = {KASLD: Kernel Address Space Layout Derandomization},
author = {Coles, Brendan},
url = {https://github.com/bcoles/kasld},
version = {0.3.0},
year = {2026}
}
```
GitHub also shows a *"Cite this repository"* button from
[CITATION.cff](CITATION.cff). For an unreleased build from `master`, cite the
specific commit and the date accessed — e.g. `bcoles/kasld@`
(accessed YYYY-MM-DD) — since `-dev` version strings are not unique to a single
commit.