Metadata-Version: 2.5
Name: pakunoda
Version: 0.9.6
Summary: Extract Volatility 3 ISF profiles from raw Linux memory dumps via BTF and kallsyms
Project-URL: Homepage, https://github.com/monkeywave/pakunoda
Project-URL: Repository, https://github.com/monkeywave/pakunoda
Author-email: Anonymous <anonymous@example.com>
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: btf,isf,kallsyms,linux,memory-forensics,volatility
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Information Technology
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Topic :: System :: Operating System Kernels :: Linux
Requires-Python: >=3.10
Requires-Dist: click>=8.1
Requires-Dist: fastjsonschema>=2.18
Requires-Dist: jsonschema>=4.0
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == 'dev'
Requires-Dist: hypothesis>=6.0; extra == 'dev'
Requires-Dist: mypy>=1.0; extra == 'dev'
Requires-Dist: pytest-benchmark>=4.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
Requires-Dist: pytest-timeout>=2.1; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: ruff>=0.1; extra == 'dev'
Provides-Extra: reproduce
Requires-Dist: volatility3==2.27.0; extra == 'reproduce'
Provides-Extra: volatility3
Requires-Dist: volatility3==2.27.0; extra == 'volatility3'
Description-Content-Type: text/markdown

<p align="center">
  <picture>
    <source media="(prefers-color-scheme: dark)" srcset="./misc/pakunoda-dark.png">
    <source media="(prefers-color-scheme: light)" srcset="./misc/pakunoda-light.png">
    <img alt="Pakunoda" src="./misc/pakunoda-light.png" width="500">
  </picture>
</p>

# pakunoda

Extract Volatility 3 ISF profiles from raw Linux memory dumps via BTF and kallsyms.

Volatility 3 needs a symbol profile (ISF JSON) that matches the exact kernel of the
machine you captured. Normally you build one with `dwarf2json` from a `vmlinux` with
debug symbols, which means tracking down the matching kernel debug package — often
impossible for an unknown or long-decommissioned host. pakunoda skips that step
entirely: it reads the metadata the kernel embeds about itself in its own `.rodata`
(BTF type information, the kallsyms symbol table, and the `linux_banner` string) out
of the raw dump and reconstructs the ISF profile directly. No `vmlinux`, no debug
packages, no matching kernel, and on that path no network access either.

## Installation

Requires Python 3.10 or later.

```bash
git clone https://github.com/monkeywave/pakunoda.git
cd pakunoda
pip install -e .
```

To run the test suite, install the development extras instead:

```bash
pip install -e ".[dev]"
pytest
```

## Usage

Generate a profile from a dump. With no `-o`, the profile is written next to the
dump as `<dumpname>_profile.isf.json`:

```bash
pakunoda extract my-webserver-new.lime
```

Point `-o` at a directory (existing, or with a trailing slash to have it created)
to write the default filename inside it:

```bash
pakunoda extract my-webserver-new.lime -o ~/cases/webserver/
```

Or name the output file exactly:

```bash
pakunoda extract my-webserver-new.lime -o webserver.isf.json
```

Other commands:

- `pakunoda probe <dump>` — report which artifacts (banner, DTB, BTF, kallsyms) were
  found and where, without generating a profile.
- `pakunoda info <isf.json | dump>` — summarise either kind of file. Given a profile
  it reports type and symbol counts, the kernel banner, and whether key structs are
  present; given a memory dump it reports the container format, size, physical
  segments and the kernel found inside. Which one it is comes from the file's
  contents, not its extension. The dump summary costs one pass over the image for
  the banner (about 0.4 s per GB warm); `--no-banner` skips it.
- `pakunoda validate <isf.json>` — check an ISF file against the Volatility 3 schema.
  `--strict` also fails on warnings. Handed a memory dump it exits 5 and points at
  `pakunoda extract`.
- `pakunoda donor` — manage the donor profiles a no-BTF run selects from. `list`
  shows what this machine has and what the shipped index knows of, `fetch`
  downloads the donor a given dump would select, `add` registers an ISF you already
  have, and `sync` refreshes the index. See
  [docs/PROFILE_CACHE.md](docs/PROFILE_CACHE.md).

`info` and `validate` both accept lzma-compressed `.json.xz` profiles as well as
plain `.json`.

Common flags: `--arch` selects the target architecture (default `auto`), `-v` enables
verbose logging, `-q` suppresses everything but errors, and `--json` switches to
machine-readable output for scripting.

## Example

```
$ pakunoda extract my-webserver-new.lime
pakunoda v0.5.0 — Volatility 3 ISF extractor
Dump: my-webserver-new.lime
Arch: auto

Detected arch: x86_64
ISF generated: /home/analyst/cases/my-webserver-new_profile.isf.json
  Types: 12043  Symbols: 8587  Enums: 743  Base types: 12
  Kernel: 6.12.48+deb13-amd64
  Time: 23.71s

Ready to use with Volatility 3:
  vol -f my-webserver-new.lime -s /home/analyst/cases linux.pslist
  vol -f my-webserver-new.lime -s /home/analyst/cases linux.lsmod

If Vol3 shows errors or empty results, clear its symbol cache:
  rm -f ~/.cache/volatility3/identifier.cache
Also ensure no other ISF files with the same kernel exist under the -s directory.
```

## Using the result with Volatility 3

Pass the directory holding the generated ISF file to Volatility 3 as its symbol
directory:

```bash
vol -f my-webserver-new.lime -s /home/analyst/cases linux.pslist
```

Volatility 3 caches which ISF file matches which kernel banner. If it reports errors
or returns empty results after you generate a new profile, clear that cache:

```bash
rm -f ~/.cache/volatility3/identifier.cache
```

Also make sure no other ISF file for the same kernel sits under the `-s` directory,
or Volatility 3 may pick the wrong one.

## What it needs from the dump

BTF and kallsyms both live in the kernel's `.rodata` section, so a dump that captured
kernel memory normally contains everything pakunoda needs. BTF is present on kernels
built with `CONFIG_DEBUG_INFO_BTF`, which covers mainstream distribution kernels from
roughly 5.2 onwards. When BTF is absent — older kernels, or a custom build without it
— pakunoda falls back to identifying the kernel by structure detection and selecting a
donor profile whose layout matches what the dump actually contains.

That path works out of the box and needs no setup. The wheel ships an 11,123-row
index of every donor ISF that exists in
[Abyss-W4tcher/volatility3-symbols](https://github.com/Abyss-W4tcher/volatility3-symbols),
covering x86-64 and x86-32, so a run that needs a donor downloads exactly the one
profile that matches — mean 1.9 MB — checks it against the size and hash the index
pinned, confirms it parses as an ISF, and only then keeps it. `--offline` keeps
selection but never reaches the network, naming the profile it would have fetched;
`--no-donor` skips the donor leg altogether and falls through to structural
recovery. [docs/PROFILE_CACHE.md](docs/PROFILE_CACHE.md) covers all of it: how
donor selection is graded and recorded in the output, how to refresh or pre-populate
the cache for an air-gapped machine, and how to register donors of your own. For
modern 64-bit kernels you can ignore it entirely.

Supported architectures are x86-64, ARM64, and x86-32 (i386/i686). On a PAE i386
kernel the page-table walk is declined rather than approximated, and is reported as a
capability gap. Dumps in raw, LiME, and ELF core formats are read directly.

## Note on `--research`

`--research` enables prototype research algorithms (structural analysis, profile HMMs,
constellation-based reconstruction) that are part of the ongoing research behind the
tool. They are off by default and are **not** needed for normal extraction — the
default path is the one you want. Use `pakunoda extract <dump> --research-list` to see
what is available.

## Further reading

For reproducing the results in the accompanying paper, see
[README_ARTIFACT.md](README_ARTIFACT.md).

## Licence

Apache-2.0.
