Memory dump
For the 2019 Volatility Plugin Contest, dumpmem was developed to acquire live memory on FreeBSD. The code still works in 2024. The code uses devinfo(3), the device and resource information utility library to retrieve the start and size of resources of the ram0 device. It reads those regions from the special file /dev/mem(4) and writes them in LiME format.
Differences between volatility2 and volatility3
The profile argument to determine which symbols to use was removed, now it is automatically guessed.
It is no longer needed to build a crafted kernel module to create a profile, dwarf2json can create a profile from the kernel that is running (see following paragraph).
Volatility3 seems faster than volatility2: 3 to 5seconds per simple plugin execution with volatility3 versus 10 to 15 seconds per simple plugin execution with volatility2.
Volatility3ISF generation
dwarf2json needs slight modifications to generate volatility3 Intermediate Symbol File (ISF) suitable for FreeBSD analysis. In the FreeBSD kernel, the version is stored in the "version" string.This "version" string is stored in the ".data" section of the kernel.
To generate the volatility3 Intermediate Symbol File, the kernel and the kernel debug data are needed. Symbol data is taken from the kernel. Types and symbol types are taken from the kernel debug data.Note: a minimum of 8GB of ram is needed to process this data.
The volatility3 Intermediate Symbol File contains almost all data needed for memory analysis. In the excerpt below, we can see the "char" base type, the "proc" and "proclist" user types, the "obj_type" enumeration, the "allproc" and "version" symbols:
The generated volatility3 Intermediate Symbol Files can be validated using the isfinfo plugin:
Extraction of FreeBSD identifiers from Volatility3 intermediate Symbol File
The identifier of the FreeBSD operating system is stored in the "version" string. MacOS also uses this string, so the existence of the "kfreebsd_brand_info" symbol is used to distinguish between the two:
FreeBSD Intel Stacker
On FreeBSD amd64, "KPML4phys" stores the physical address of the kernel level 4 page map table.
On FreeBSD i386 with PAE (Physical Address Extension, a feature allowing a 32bit processor to access more than 4GB of physical memory), "IdlePDPT" stores the physical address of the kernel page directory pointer table.
On FreeBSD i386 without PAE, "IdlePTD" stores the physical address of the kernel page table directory.
Volatility knows how to do the address translation from this physical address.
Features implemented in FreeBSD
Banners
The banners plugin was modified to detect FreeBSD banner.
This helps us to find the version a memory image is running in case it is not known:
PsList
PsList displays running processes.
FreeBSD uses a "proc" structure to store information about processes, on version 14.0 it is like this:
"allproc" is a list of all processes:
The PsList plugin walks the"allproc" list. "p_pid" stores the process identifier, "p_comm" the process name, and "p_pptr" points to the parent process.
Creds
Creds displays security credentials for the processes.
FreeBSD uses "ucred" structure to store credentials of a process, on version 14.0 it is like this:
The Creds plugin displays the user and group identifications (effective, real and saved), the file creation mode mask, the credential flags, and the groups.
Envars
Envars displays environment variables for the processes.
FreeBSD holds pointers to argument strings and environment strings in "ps_strings" structure.
"ps_envstr" points to the process environment vector and "ps_nenvstr" is the number of elements in "ps_envstr".
LsKld
LsKld displays files dynamically linked into the kernel.
FreeBSD uses "linker_file" structures to store information about files loaded by the kernel linker:
"linker_files" is the list of all those "linker_file" structures:
The LsKld plugin walks the"linker_files" list, and displays unique ids, reference counts, file sizes, load addresses and file names.
LsMod
LsMod displays kernel modules loaded into the kernel.
FreeBSD uses "module"structures to store information about modules.
"modules" is the list of all modules.
The LsMod plugin walks the"modules" list and displays unique ids, names and file name.
Lsof
Lsof displays file descriptor information for the processes.
FreeBSD stores information about file descriptors in a "filedesc" structure, containing an open file table of "filedescent" structures.
The Lsof plugin enumerates the open.
file descriptors and attempts to display a nice description (file name, socket type…).
Mount
Mount displays currently mounted filesystems.
FreeBSD stores information about mounted filesystems in "mount" structures.
"mountlist" is a list of all mounted filesystems.
The Mount plugin walks the "mountlist" list and displays the mounted filesystem, the directory on which it is mounted and the filesystem type name.
Maps
Maps displays virtual memory mappings for the processes.
Each process has a "vmspace" structure describing the process address space. It contains a"vm_map" structure which contains a binary-search tree of "vm_map_entry"structures.
The Maps plugin walks those structures and is able to dump them if requested.
PsAux
PsAux displays binary information and command line arguments for the processes.
It works similarly as the Envars plugin.
"ps_argvstr" points to the argv vector and "ps_nargvstr" is the same as the program's argc.
PsTree
PsTree displays processes in a tree.
Volshell
A freebsd flag was added to volshell to specify that the operating system is FreeBSD.
In the example below, the list of processes is retrieved and the first process in the list is displayed.
Availability
dumpmem is available at https://github.com/ant1/dumpmem.
The pull request to add FreeBSD support to dwarf2json is available at https://github.com/volatilityfoundation/dwarf2json/pull/64.
The pull request to add FreeBSD support to volatility3 is available at https://github.com/volatilityfoundation/volatility3/pull/1182.
Bugs
Enumerations do not seem to be handled correctly.
For instance "v_type" instruct vnode:
Conclusion
This work allows to perform memory analysis on FreeBSD or FreeBSD based memory images. FreeBSD is usually less covered by forensic tools.
Extending volatility3 to support FreeBSD turned out to be easier than extending volatility2 to support FreeBSD for two reasons:
- dwarf2json allows to easily create an ISF from an existing kernel, while we had to build a custom module which was not exhaustive previously
- with volatility2 the overlay was painful to develop (547 lines) while with volatility3 the automagic is quite easy (143 lines)
It should be straight forward to improve plugins or contribute new plugins. We encourage you to test, provide feedback and extend these new features.