Goodkit is the name of the framework that we are building. That framework is used in order to build observers as side VMs that colocates in the same VMM as the target it introspects.
-
firecracker-main: Modified Firecracker source code. Firecracker is a lightweight VMM (Virtual Machine Monitor) developed by AWS. This version has been modified to support observer VMs that can introspect a target VM's memory.
-
images_builder: Contains Dockerfiles and scripts to build ext4 rootfs images for the guest and observer VMs. Each subfolder (guest, observer, etc.) contains a Dockerfile that defines the filesystem contents.
-
ioctl_injector: A userspace application that runs inside the observer VM. It uses ioctl calls to communicate with the custom kernel module and perform memory introspection operations on the target VM.
-
usecase: Contains the source code for various security use cases and detection modules. These are automatically integrated into the target VM during image building. Examples include:
- Rootkit detection modules (diamorphine, adore-ng, sutekh, spy, cred-load)
- Ransomware detection and replay tools
- Each use case demonstrates a specific introspection capability
-
linux-5.10.198: Modified Linux kernel source code containing the GoodKit kernel module.
If you just cloned the repository, the fastest path is the setup.sh script at the
root. It reproduces the full build environment end to end:
./setup.shIt will:
- install the kernel build dependencies (Ubuntu/Debian, via
apt), - download a
linux-5.10.198and extract it intolinux-5.10.198, - copy the provided
goodkit-kernel-5.10.198.configinto it, - apply the Goodkit kernel patch
goodkit-kernel-5.10.198.patch, - build
vmlinux, - install Rust (if missing) and build the modified Firecracker VMM,
- build the guest/observer rootfs images with
make images(requires Docker).
Useful toggles (opt out of individual stages):
| Variable | Effect |
|---|---|
FRESH=1 |
wipe linux-5.10.198-test and redo from scratch |
NO_APT=1 |
do not install system build dependencies |
NO_RUST=1 |
do not install the Rust toolchain |
NO_IMAGES=1 |
skip the rootfs image build (make images) |
SKIP_KERNEL=1 |
do not build the kernel |
SKIP_FC=1 |
do not build Firecracker |
Example — everything except the Docker images:
NO_IMAGES=1 ./setup.shThe sections below describe the same steps performed manually, if you prefer to run them one by one.
This project requires compiling a custom Linux kernel. The setup works on Ubuntu/Debian systems.
Install the necessary packages for kernel compilation:
sudo apt-get update
sudo apt-get install -y build-essential libncurses-dev bison flex libssl-dev libelf-dev bc dwarvesFor more details on kernel compilation prerequisites, see: https://phoenixnap.com/kb/build-linux-kernel
Note: If you are using a different distribution, please refer to your distribution's package manager to install equivalent packages. Do not follow the tutorial for .config setup as we provide a ready-to-use configuration file.
The .config file is already provided in the linux-5.10.198 folder, so you do not need to configure it manually. Simply navigate to the kernel folder and build:
cd linux-5.10.198
make -j$(nproc) vmlinuxThis will produce the vmlinux kernel image that will be used by both the target and observer VMs. It is located at linux-5.10.198/vmlinux.
Firecracker requires Rust and Docker to build.
Follow the official Rust installation guide:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/envFollow the official Docker installation guide for your distribution, or on Ubuntu/Debian.
For more details, refer to the official Docker documentation: https://docs.docker.com/engine/install/
To build Firecracker, run:
cd firecracker-main
cargo build --releaseThe binary will be located at firecracker-main/target/release/firecracker.
A Makefile in the root folder orchestrates the build of all components. Running make will build:
- Firecracker VMM
- The Linux kernel (vmlinux)
- The ioctl injector application
- The rootfs images for guest and observer VMs
makeIndividual targets are also available:
make firecracker # Build only Firecracker
make kernel # Build only the kernel
make images # Build only the rootfs images
make ioctl # Build only the ioctl injectorThe following introspection use cases are available:
| Use Case | Description |
|---|---|
USE_CASE_PROCESS_LIST |
List all running processes in the target VM |
USE_CASE_OPEN_FILE_LIST |
List open files in the target VM |
USE_CASE_CREDENTIAL_LIST |
Inspect credential structures |
USE_CASE_ROOTKIT_MODULES |
Detect hidden kernel modules |
USE_CASE_TTY_CHECK |
Check TTY/keyboard input monitoring |
USE_CASE_KEYLOGGER_CHECK |
Detect keylogger presence |
USE_CASE_NETFILTER_FUNC_CHECK |
Check netfilter function hooks |
USE_CASE_VM_AREA_CHECK |
Inspect virtual memory areas |
USE_CASE_PROC_FILE_OPS |
Check /proc file operations for tampering |
USE_CASE_MICROBENCH |
Performance microbenchmark |
USE_CASE_ALLOC_PAGES |
Memory allocation introspection |
You can add your own use cases by integrating them into the observer application in ioctl_injector/ and specifying them in the boot arguments.
The cfg.yml file is the main configuration file for the system. Key sections:
boot-source: Defines the kernel and boot arguments for the target VM
boot-source:
kernel_image_path: ../linux-5.10.198/vmlinux
boot_args: console=ttyS0 reboot=k panic=1 pci=off init=/init.shdrives: Defines the root filesystem for the target VM
drives:
- drive_id: rootfs
path_on_host: ../images_builder/rootfs/guest.ext4
is_root_device: true
is_read_only: falsemachine-config: Target VM resources (vCPUs and memory)
machine-config:
vcpu_count: 1
mem_size_mib: 1024observers: List of observer VMs. Each observer has its own configuration:
dom0-role: Role of the observer (Default, Server, Client)drives: Observer's root filesystemboot-source: Observer kernel and boot args (specify use case here, e.g.,init=/init.sh USE_CASE_PROCESS_LIST)machine-config: Observer resources includingaccess_target_memory: trueto enable introspectionmemory-region: (Optional) Restrict which memory regions the observer can accessallowed-functions: (Optional) List of allowed functions in the observer.probes-configuration: (Optional) Configuration for probes if needed.allowed-symbol: (Optional) List of allowed symbols in the observer.
The default configuration applies if the optional attributes are not specified.
You can add multiple observers by adding more entries to the observers list.
To change the use case, modify the boot_args in the observer's boot-source section.
Navigate to the firecracker-main folder and run:
cd firecracker-main
./target/release/firecracker --no-api --config-file ../cfg.yml --no-seccompWhere cfg.yml is your configuration file.
Output:
- The target VM output will be printed to the terminal
- Observer outputs will be written to files named
Observer_n°Xwhere X is the observer ID (0, 1, 2, ...)
- https://archive.fosdem.org/2020/schedule/event/rust_vm_introspection/ : Rustifying VMI
- https://wenzel.github.io/libmicrovmi/index.html : LibVMI documentation.
This is a tool that can be leveraged not a framework
- Diamorphine (rootkit) : https://github.com/m0nad/Diamorphine
- Commix (rootkit) : https://github.com/commixproject/commix?tab=readme-ov-file
- Chkrootkit (rootkit) : https://www.chkrootkit.org/
- https://archive.fosdem.org/2020/schedule/event/rust_vm_introspection/ : Rustifying VMI
- https://wenzel.github.io/libmicrovmi/index.html : LibVMI documentation.