Skip to content

Commit a5ebdbf

Browse files
committed
Update README
1 parent 96f317e commit a5ebdbf

1 file changed

Lines changed: 100 additions & 84 deletions

File tree

README.md

Lines changed: 100 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,11 @@ Supports:
2626
## Table of Contents
2727

2828
* [Usage](#usage)
29+
* [Command-line options](#command-line-options)
2930
* [Example Output](#example-output)
30-
* [pwntools Template](#pwntools-template)
3131
* [Explain mode](#explain-mode)
3232
* [Hardening assessment](#hardening-assessment)
33+
* [pwntools Template](#pwntools-template)
3334
* [Building](#building)
3435
* [Configuration](#configuration)
3536
* [Architecture and Design](#architecture-and-design)
@@ -76,21 +77,29 @@ Supports:
7677

7778
## Usage
7879

80+
Each component in the `src/` directory is a standalone leak component using
81+
a different technique to retrieve or infer kernel addresses. The `kasld`
82+
orchestrator discovers and executes all components, displays results in
83+
real-time, and produces a section-aware summary with validated addresses
84+
grouped by kernel section (text, modules, direct map, etc).
85+
86+
Fetch and build:
87+
7988
```
8089
sudo apt install libc-dev make gcc binutils git
8190
git clone https://github.com/bcoles/kasld
8291
cd kasld
83-
make run
92+
make
8493
```
8594

86-
Each component in the `src/` directory is a standalone leak component using
87-
a different technique to retrieve or infer kernel addresses. The `kasld`
88-
orchestrator discovers and executes all components, displays results in
89-
real-time, and produces a section-aware summary with validated addresses
90-
grouped by kernel section (text, modules, direct map, etc).
95+
Run:
96+
97+
```
98+
./build/<arch>/kasld
99+
```
91100

92-
After building, the `build/<arch>/` directory is self-contained and can be
93-
deployed to a target system:
101+
The `build/<arch>/` directory is self-contained and can be deployed to a
102+
target system:
94103

95104
```
96105
build/<arch>/
@@ -105,6 +114,27 @@ are expected to return limited results. For testing purposes, the
105114
can temporarily relax these settings (requires root).
106115

107116

117+
### Command-line options
118+
119+
```
120+
-j, --json Machine-readable JSON output
121+
-1, --oneline Single-line summary output
122+
-m, --markdown Markdown table output
123+
-c, --color Colorize text output (auto-detected for TTYs)
124+
-q, --quiet Suppress banner, progress, and warnings
125+
-v, --verbose Show component output
126+
-e, --explain Show technique explanations before each component
127+
-f, --fast Use 2s per-component timeout (fast scan mode)
128+
-w, --workers N Parallel inference workers (default: nproc; 0 = sequential)
129+
-x, --experimental Enable experimental components
130+
-s, --skip PATTERN Skip matching components (glob, comma-separated; multiple --skip flags accumulate)
131+
-H, --hardening Show post-run hardening assessment
132+
-t, --timeout N Per-component timeout in seconds (default: 30)
133+
-V, --version Print version and exit
134+
-h, --help Show this help
135+
```
136+
137+
108138
### Example Output
109139

110140
The following is example output from a default Debian 13 (x86-64) system:
@@ -201,57 +231,6 @@ Physical memory layout:
201231

202232
</details>
203233

204-
### pwntools Template
205-
206-
The `--json` (`-j`) flag emits machine-readable output. The
207-
`kaslr.virtual.text_base` field contains the leaked kernel text base as
208-
a hex string, and `kaslr.virtual.slide_bytes` contains the KASLR slide
209-
as an integer. Both can be consumed directly by pwntools to resolve
210-
runtime symbol addresses and build a ROP chain.
211-
212-
```python
213-
#!/usr/bin/env python3
214-
import json, subprocess, sys
215-
from pwn import *
216-
217-
# Leak kernel base with KASLD
218-
result = subprocess.run(
219-
[
220-
"./build/x86_64-linux-gnu/kasld",
221-
"--json",
222-
"--fast",
223-
"--quiet"
224-
],
225-
capture_output=True,
226-
text=True
227-
)
228-
data = json.loads(result.stdout)
229-
context.arch = {"x86_64": "amd64"}.get(data["arch"], data["arch"])
230-
kaslr = data["kaslr"].get("virtual")
231-
if not kaslr:
232-
log.failure("kasld did not find the kernel text base")
233-
sys.exit(1)
234-
text_base = int(kaslr["text_base"], 16)
235-
slide = int(kaslr["slide_bytes"])
236-
log.success(f"kernel text base: {hex(text_base)} (slide +{hex(slide)})")
237-
238-
# Resolve runtime addresses via vmlinux symbol table
239-
vmlinux = ELF("vmlinux", checksec=False)
240-
vmlinux.address = text_base
241-
commit_creds = vmlinux.symbols["commit_creds"]
242-
prepare_kernel_cred = vmlinux.symbols["prepare_kernel_cred"]
243-
log.info(f"commit_creds: {hex(commit_creds)}")
244-
log.info(f"prepare_kernel_cred: {hex(prepare_kernel_cred)}")
245-
246-
# Build ROP chain
247-
rop = ROP(vmlinux)
248-
rop.call(prepare_kernel_cred, [0])
249-
# move rax -> rdi here with a target-specific gadget
250-
# rop.raw(rop.find_gadget(["mov rdi, rax", "ret"]).address)
251-
rop.call(commit_creds)
252-
payload = flat(rop.chain())
253-
```
254-
255234
### Explain mode
256235

257236
The `--explain` (`-e`) flag prints a brief technique explanation before
@@ -308,6 +287,56 @@ where it appears in a top-level `"hardening"` object with fields
308287
`active_defenses`, `suggestions`, `patched_vulns`, `unpatched_vulns`,
309288
`config_surface`, and `no_mitigation`.
310289

290+
### pwntools Template
291+
292+
The `--json` (`-j`) flag emits machine-readable output. The
293+
`kaslr.virtual.text_base` field contains the leaked kernel text base as
294+
a hex string, and `kaslr.virtual.slide_bytes` contains the KASLR slide
295+
as an integer. Both can be consumed directly by pwntools to resolve
296+
runtime symbol addresses and build a ROP chain.
297+
298+
```python
299+
#!/usr/bin/env python3
300+
import json, subprocess, sys
301+
from pwn import *
302+
303+
# Leak kernel base with KASLD
304+
result = subprocess.run(
305+
[
306+
"./build/x86_64-linux-gnu/kasld",
307+
"--json",
308+
"--fast",
309+
"--quiet"
310+
],
311+
capture_output=True,
312+
text=True
313+
)
314+
data = json.loads(result.stdout)
315+
context.arch = {"x86_64": "amd64"}.get(data["arch"], data["arch"])
316+
kaslr = data["kaslr"].get("virtual")
317+
if not kaslr:
318+
log.failure("kasld did not find the kernel text base")
319+
sys.exit(1)
320+
text_base = int(kaslr["text_base"], 16)
321+
slide = int(kaslr["slide_bytes"])
322+
log.success(f"kernel text base: {hex(text_base)} (slide +{hex(slide)})")
323+
324+
# Resolve runtime addresses via vmlinux symbol table
325+
vmlinux = ELF("vmlinux", checksec=False)
326+
vmlinux.address = text_base
327+
commit_creds = vmlinux.symbols["commit_creds"]
328+
prepare_kernel_cred = vmlinux.symbols["prepare_kernel_cred"]
329+
log.info(f"commit_creds: {hex(commit_creds)}")
330+
log.info(f"prepare_kernel_cred: {hex(prepare_kernel_cred)}")
331+
332+
# Build ROP chain
333+
rop = ROP(vmlinux)
334+
rop.call(prepare_kernel_cred, [0])
335+
# move rax -> rdi here with a target-specific gadget
336+
# rop.raw(rop.find_gadget(["mov rdi, rax", "ret"]).address)
337+
rop.call(commit_creds)
338+
payload = flat(rop.chain())
339+
```
311340

312341
## Building
313342

@@ -325,26 +354,6 @@ make clean # remove build directory
325354
make help # show all targets and options
326355
```
327356

328-
Command-line options:
329-
330-
```
331-
-j, --json Machine-readable JSON output
332-
-1, --oneline Single-line summary output
333-
-m, --markdown Markdown table output
334-
-c, --color Colorize text output (auto-detected for TTYs)
335-
-q, --quiet Suppress banner, progress, and warnings
336-
-v, --verbose Show component output
337-
-e, --explain Show technique explanations before each component
338-
-f, --fast Use 2s per-component timeout (fast scan mode)
339-
-w, --workers N Parallel inference workers (default: nproc; 0 = sequential)
340-
-x, --experimental Enable experimental components
341-
-s, --skip PATTERN Skip matching components (glob, comma-separated; multiple --skip flags accumulate)
342-
-H, --hardening Show post-run hardening assessment
343-
-t, --timeout N Per-component timeout in seconds (default: 30)
344-
-V, --version Print version and exit
345-
-h, --help Show this help
346-
```
347-
348357
KASLD can be cross-compiled with `make` by specifying the appropriate
349358
compiler (`CC`). Static linking is applied automatically when cross-compiling:
350359

@@ -453,9 +462,9 @@ are equivalent. The number of skipped components is noted in the
453462

454463
At phase boundaries the orchestrator runs a set of inference plugins compiled
455464
directly into the orchestrator binary. Plugins read collected results and
456-
tighten the constraint bounds used during validation — they may only raise
457-
`text_base_min`, lower `text_base_max`, or narrow `page_offset_min/max`.
458-
This commutativity invariant means plugin order within a phase is irrelevant.
465+
tighten the memory section constraint bounds used during validation. The
466+
commutativity invariant — plugins may only tighten bounds, never widen them —
467+
means plugin order within a phase is irrelevant.
459468

460469
Inference plugins run in four phases:
461470

@@ -496,14 +505,16 @@ Currently implemented:
496505
| `min_offset_from_image_size` | POST_COLLECTION | Forbidden lower slots from kernel image size (MIPS/LoongArch) |
497506
| `module_text_bound` | POST_COLLECTION | Module region → text bounds |
498507
| `phys_virt_synth` | POST_COLLECTION | Narrows `page_offset_min/max` by synthesising `PAGE_OFFSET = virt − phys + PHYS_OFFSET` from per-component (PHYS/DRAM, VIRT/DIRECTMAP) pairs |
499-
| `randomize_memory_page_offset` | POST_COLLECTION | Cross-origin min-DIRECTMAP / min-PHYS`page_offset_base` (x86-64) |
508+
| `randomize_memory_page_offset` | POST_COLLECTION | Pins `page_offset_base` on x86-64 with CONFIG_RANDOMIZE_MEMORY. Path 1: same-(origin, region, name) PHYS + VIRT/DIRECTMAP pairing. Path 2: cross-origin min-DIRECTMAP / min-PHYS-RAM_BASE fallback. Both paths enforce 1-GiB PUD alignment |
500509
| `riscv64_fdt_kaslr_seed` | POST_COLLECTION | riscv64 FDT `kaslr-seed` → exact `text_base` |
501510
| `riscv64_non_efi_phys_base` | POST_COLLECTION | Exact physical base on non-EFI riscv64 |
502511
| `text_cluster_filter` | POST_COLLECTION | TEXT-result cluster outlier rejection |
503512
| `va_bits_from_results` | POST_COLLECTION | VA_BITS detection from directmap addresses (arm64) |
504513
| `x86_32_vmsplit_ceiling` | POST_COLLECTION | x86-32 vmsplit ceiling |
505514
| `x86_64_coupling_validate` | POST_COLLECTION | x86-64 directmap/text region coupling validation |
506515
| `x86_64_la57_from_directmap` | POST_COLLECTION | x86-64 L4/L5 paging detection from directmap addresses |
516+
| `x86_64_vmalloc_base_bound` | POST_COLLECTION | x86-64 CONFIG_RANDOMIZE_MEMORY: `page_offset_base + directmap_size_tb * 1 TiB + PUD_SIZE``vmalloc_base` lower bound (chained from `/proc/zoneinfo` `max_pfn`) |
517+
| `x86_64_vmemmap_base_bound` | POST_COLLECTION | x86-64 CONFIG_RANDOMIZE_MEMORY: `vmalloc_base + VMALLOC_SIZE_TB * 1 TiB + PUD_SIZE``vmemmap_base` lower bound; `CPU_ENTRY_AREA_BASE − vmemmap_size` → upper bound |
507518
| `x86_firmware_memmap_holes` | POST_COLLECTION | x86 `/sys/firmware/memmap` System RAM hole validation |
508519

509520
Inference plugins live in `src/inference/` and register via a linker section
@@ -1287,17 +1298,22 @@ The following KASLD components read from `/proc`:
12871298
The following KASLD components read from `/sys`:
12881299

12891300
* [acpi_mrrm.c](src/components/acpi_mrrm.c) — physical memory range base addresses from the Intel ACPI MRRM table via `/sys/firmware/acpi/memory_ranges/`
1301+
* [boot_params_e820.c](src/components/boot_params_e820.c) — x86 E820 physical memory map and initrd physical address from `/sys/kernel/boot_params/data`
12901302
* [sysfs_cbmem_address.c](src/components/sysfs_cbmem_address.c) — coreboot CBMEM physical memory addresses from `/sys/bus/coreboot/devices/`
12911303
* [sysfs_cxl_region.c](src/components/sysfs_cxl_region.c) — CXL memory region host physical addresses from `/sys/bus/cxl/devices/`
1304+
* [sysfs_devicetree_elfcorehdr.c](src/components/sysfs_devicetree_elfcorehdr.c) — kdump crash kernel ELF core header physical address from `/sys/firmware/devicetree/base/chosen/`
12921305
* [sysfs_devicetree_initrd.c](src/components/sysfs_devicetree_initrd.c) — initrd address from `/sys/firmware/devicetree/`
12931306
* [sysfs_devicetree_memory.c](src/components/sysfs_devicetree_memory.c) — memory regions from `/sys/firmware/devicetree/`
12941307
* [sysfs_devicetree_reserved_memory.c](src/components/sysfs_devicetree_reserved_memory.c) — reserved DRAM region addresses from `/sys/firmware/devicetree/base/reserved-memory/`
1308+
* [sysfs_devicetree_uefi_mmap.c](src/components/sysfs_devicetree_uefi_mmap.c) — EFI memory map buffer physical address from `/sys/firmware/devicetree/base/chosen/linux,uefi-mmap-*` (UEFI-booted device tree platforms)
12951309
* [sysfs_efi_runtime_map.c](src/components/sysfs_efi_runtime_map.c) — EFI runtime map virtual and physical addresses from `/sys/firmware/efi/runtime-map/`
12961310
* [sysfs_firmware_memmap.c](src/components/sysfs_firmware_memmap.c) — firmware memory map from `/sys/firmware/memmap/`
1311+
* [sysfs_iommu_reserved_regions.c](src/components/sysfs_iommu_reserved_regions.c) — physical DRAM addresses of IOMMU reserved regions from `/sys/kernel/iommu_groups/*/reserved_regions`
12971312
* [sysfs_iscsi_transport_handle.c](src/components/sysfs_iscsi_transport_handle.c) — iSCSI transport handle from `/sys/class/iscsi_transport/`
12981313
* [sysfs-kernel-notes-xen.c](src/components/sysfs-kernel-notes-xen.c) — Xen notes from `/sys/kernel/notes`
12991314
* [sysfs_memory_blocks.c](src/components/sysfs_memory_blocks.c) — memory block addresses from `/sys/devices/system/memory/`
13001315
* [sysfs-module-sections.c](src/components/sysfs-module-sections.c) — module section addresses from `/sys/module/*/sections/`
1316+
* [sysfs_nd_region.c](src/components/sysfs_nd_region.c) — NVDIMM/PMem region physical start addresses from `/sys/bus/nd/devices/region*/`
13011317
* [sysfs_nf_conntrack.c](src/components/sysfs_nf_conntrack.c) — netfilter conntrack hash from `/sys/module/nf_conntrack/`
13021318
* [sysfs_pci_resource.c](src/components/sysfs_pci_resource.c) — PCI BAR addresses from `/sys/bus/pci/devices/`
13031319
* [sysfs_qcom_rmtfs_mem.c](src/components/sysfs_qcom_rmtfs_mem.c) — Qualcomm RMTFS reserved physical memory addresses from `/sys/class/rmtfs/`

0 commit comments

Comments
 (0)