Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ Install volatility on your system easily with Docker and get provided with comma
Volatility profiles and symbols automatic generation for :

![](https://img.shields.io/badge/Fedora/[amd64,i386]-All%20versions-blue)
![](https://img.shields.io/badge/AlmaLinux/[amd64]-All%20versions-blue) : The script may support other architectures but not for all versions
![](https://img.shields.io/badge/RockyLinux/[amd64]-All%20versions-blue) : The script may support other architectures but not for all versions

---

Expand Down
19 changes: 19 additions & 0 deletions profiles_and_symbols_builders/AlmaLinux/Dockerfile-almalinux
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM golang:alpine AS dwarf2json_builder

RUN apk add git && git clone https://github.com/volatilityfoundation/dwarf2json.git
WORKDIR /go/
RUN cd dwarf2json/ && go build

FROM almalinux:9.2
COPY --from=dwarf2json_builder /go/dwarf2json/dwarf2json /usr/bin/dwarf2json
RUN dnf update -y
RUN dnf install -y dracut linux-firmware perl wget gcc git autoconf automake libtool make zip elfutils-libelf-devel nano
WORKDIR /tmp
RUN git clone https://github.com/davea42/libdwarf-code.git && \
cd libdwarf-code/ && \
ACLOCAL_PATH=/usr/share/aclocal sh autogen.sh && \
mkdir build && \
cd build && \
../configure --disable-dependency-tracking && \
make install
RUN git clone https://github.com/volatilityfoundation/volatility
212 changes: 212 additions & 0 deletions profiles_and_symbols_builders/AlmaLinux/automate_almalinux.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
import sys

sys.path.insert(0, "..")

import logging
from dataclasses import dataclass
import os, signal
from pathlib import Path
import click
import re
import requests
from profiles_and_symbols_builders.base import (
Container,
VolBuild,
get_project_base_path,
)

# CTRL-C instant killer
def handler(signum, frame):
os.kill(os.getpid(), signal.SIGKILL)


signal.signal(signal.SIGINT, handler)

logging.basicConfig(
level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s"
)


@dataclass
class Generator:
kernel: str
destination_path: Path

def __post_init__(self):
self.version = self.kernel.split(".el")[0]
self.release = self.kernel.split("el")[1].split(".")[0].replace("_",".")
self.arch = self.kernel.split(".")[-1]
self.profile_name = f"AlmaLinux_{self.kernel}.zip"
self.isf_name = f"AlmaLinux_{self.kernel}.json.xz"
self.image_name = "almalinux-volatility"
self.volatility_builder_path = "/tmp/volatility/tools/linux"
self.container_name = f"almalinux-volatility-{self.kernel}"
self.container_obj = Container(
self.image_name,
self.container_name,
get_project_base_path() / "AlmaLinux/Dockerfile-almalinux",
)
self.vol_obj = VolBuild(
self.destination_path,
self.kernel,
self.kernel,
self.profile_name,
self.isf_name,
self.volatility_builder_path,
self.container_obj,
)

self.base_repo_url_vol = [
f"https://repo.almalinux.org/almalinux/{self.release}/BaseOS/{self.arch}/os/Packages/",
f"https://repo.almalinux.org/almalinux/{self.release}/AppStream/{self.arch}/os/Packages/",
f"https://repo.almalinux.org/almalinux/{self.release}/devel/{self.arch}/os/Packages/",
f"https://repo.almalinux.org/vault/{self.release}/BaseOS/debug/{self.arch}/Packages/",
]

# (package_name, exit_on_error)
self.vol2_packages = [
("kernel-core", True),
("kernel-devel", True),
("kernel-modules", True),
("kernel-modules-core", False),
]

self.vol3_packages = [
("kernel-debuginfo", True),
]

def check_profile_existence(self):
return (self.destination_path / self.profile_name).exists()

def check_isf_existence(self):
return (self.destination_path / self.isf_name).exists()

def container_init(self):
self.container_obj.build_image()
self.container_obj.kill_container()
self.container_obj.remove_container()
self.container_obj.create_container()

def check_rpms(self, target):
if target == "vol2":
packages = self.vol2_packages
elif target == "vol3":
packages = self.vol3_packages
else:
raise Exception("Invalid target")

full_packages = []
for package in packages:
package_name, exit_on_error = package
print(package_name)
package_url = None

for base_repo_url in self.base_repo_url_vol:
try:
r = requests.get(base_repo_url).text
package_url = re.findall(f'"({package_name}-{self.kernel}.rpm)"', r)[0]
full_packages.append(
(package_url.split("/")[-1], f"{base_repo_url}{package_url}")
)
break # Exit the loop if the package is found
except Exception as e:
continue # Try the next base_repo_url if the package is not found

if package_url is None and exit_on_error:
raise Exception(
f'Error while fetching package url for "{package_name}" : Package not found in any repositories.'
)

if target == "vol2":
self.vol2_packages = full_packages
elif target == "vol3":
self.vol3_packages = full_packages

def download_rpms(self, target):
if target == "vol2":
packages = self.vol2_packages

elif target == "vol3":
packages = self.vol3_packages

else:
raise Exception("Invalid target")

logging.info(f"[{self.kernel}][{target}] Downloading rpms...")

for package in packages:
package_name, package_url = package
print(package_name)
package_dl = self.container_obj.docker_exec(f"wget {package_url}")
if package_dl.returncode != 0:
raise Exception(
f"Error while fetching {package_name} : {package_dl.stderr.decode()}"
)

def install_rpms(self, target: str):
if target == "vol2":
packages = self.vol2_packages

elif target == "vol3":
packages = self.vol3_packages
else:
raise Exception("Invalid target")

logging.info(f"[{self.kernel}][{target}] Installing rpms...")
for package in packages:
package_name, package_url = package
print(package_name)
rpm_cmd = f"rpm -i --nodeps {package_name}"
package_install = self.container_obj.docker_exec(rpm_cmd)
if package_install.returncode != 0:
raise Exception(
f"Error while installing {package_name} : {package_install.stderr.decode()}"
)

def __del__(self):
self.container_obj.kill_container()
self.container_obj.remove_container()


@click.command()
@click.option(
"-k",
"--kernel",
type=str,
help="AlmaLinux kernel to generate profile against (ex: 4.18.0-477.10.1.el8_8.x86_64)",
required=True,
)
@click.option(
"-o",
"--output-dir",
type=click.Path(writable=True, readable=True, exists=True),
help="Output directory for profiles and symbols",
required=True,
)
def main(kernel, output_dir: Path):
gen_obj = Generator(kernel.strip(), Path(output_dir))

if not gen_obj.check_isf_existence() or not gen_obj.check_profile_existence():
logging.info(f"[{gen_obj.kernel}] Initializing variables...")
gen_obj.container_init()

if not gen_obj.check_isf_existence():
try:
gen_obj.check_rpms("vol3")
gen_obj.download_rpms("vol3")
gen_obj.install_rpms("vol3")
gen_obj.vol_obj.vol3_build_isf("/usr/lib/")
except Exception as e:
logging.error(f"[{gen_obj.kernel}] Vol3 build failed : {e}")

if not gen_obj.check_profile_existence():
try:
gen_obj.check_rpms("vol2")
gen_obj.download_rpms("vol2")
gen_obj.install_rpms("vol2")
gen_obj.vol_obj.vol2_build_profile()
except Exception as e:
logging.error(f"[{gen_obj.kernel}] Vol2 build failed : {e}")

if __name__ == "__main__":
main()
20 changes: 20 additions & 0 deletions profiles_and_symbols_builders/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,24 @@ python3 Fedora/automate_fedora.py --kernel '4.2.6-200.fc22.x86_64' --output-dir
python3 Fedora/automate_fedora.py --kernel '6.2.9-200.fc37.x86_64' --output-dir generated_files
```

## AlmaLinux generation

Generation example :

```sh
mkdir generated_files
python3 AlmaLinux/automate_almalinux.py --kernel '4.18.0-477.10.1.el8_8.x86_64' --output-dir generated_files
python3 AlmaLinux/automate_almalinux.py --kernel '5.14.0-284.18.1.el9_2.x86_64' --output-dir generated_files
```

## RockyLinux generation

Generation example :

```sh
mkdir generated_files
python3 RockyLinux/automate_rockylinux.py --kernel '4.18.0-477.10.1.el8_8.x86_64' --output-dir generated_files
python3 RockyLinux/automate_rockylinux.py --kernel '5.14.0-284.25.1.el9_2.x86_64' --output-dir generated_files
```

It will output one Volatility2 profile and one Volatility3 symbols file (ISF).
19 changes: 19 additions & 0 deletions profiles_and_symbols_builders/RockyLinux/Dockerfile-rockylinux
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM golang:alpine AS dwarf2json_builder

RUN apk add git && git clone https://github.com/volatilityfoundation/dwarf2json.git
WORKDIR /go/
RUN cd dwarf2json/ && go build

FROM rockylinux:9.2
COPY --from=dwarf2json_builder /go/dwarf2json/dwarf2json /usr/bin/dwarf2json
RUN dnf update -y
RUN dnf install -y dracut linux-firmware perl wget gcc git autoconf automake libtool make zip elfutils-libelf-devel nano
WORKDIR /tmp
RUN git clone https://github.com/davea42/libdwarf-code.git && \
cd libdwarf-code/ && \
ACLOCAL_PATH=/usr/share/aclocal sh autogen.sh && \
mkdir build && \
cd build && \
../configure --disable-dependency-tracking && \
make install
RUN git clone https://github.com/volatilityfoundation/volatility
Loading