📦 Volatility3 Linux Plugin - Inodes
The filesystem is one of the most basic and important concepts in UNIX/Linux. This concept is working around the idea that “everything is a file”, meaning that the hardware, regular files, directories, sockets, kernel data structures, process communications etc are represented as files with their own types. On a filesystem, a file (whatever its type) is assigned with a number called an "inode". An inode is an interface between the blocks on the filesystem and the file.
When a process is running, it is interacting with the hardware, the kernel, the user’s resources etc, therefore opening the required files. Linux is keeping track of the opened files inodes in memory by using the Virtual File System (VFS) and more precisely the directory entry cache (dentry). In this article, I will present how you can extract inode metadata from a modern Linux memory image using the volatility3 framework.
Linux memory analysis
When performing memory forensics on a Linux memory image, the fact that a lot of distribution exist is making the memory analysis with volatility3 trickier. Volatility3 is basically trying to identify known structures in memory to create python objects that can be exploited. The framework needs symbol tables to be able to know where to find these structures and how they are defined. For example, to identify the structures inside a x64 Intel based Linux Debian machine memory dump, you'll need:
- To find the kernel debugging symbols generated at compilation time matching the kernel version.
- Convert the debugging symbols into symbol tables understandable by volatility3.
- Work with the framework to identify and extract structures from memory and get your artifacts.
You can learn more about theses steps here : https://volatility3.readthedocs.io/en/latest/symbol-tables.html
This process is easier for Windows and Mac because there is "one distribution" per OS. However, the fact that a lot of distributions for Linux exists makes this task more difficult.
Inode forensics value in memory
If you have ever performed digital forensic on a post-mortem Linux investigation, you may know that the inode structure on disk varies depending on the type of filesystem used. For example, Debian is by default using ext4 filesystem whereas Fedora is using XFS and CentOS is using btrfs.
However, the fact that we are performing our analysis in memory, we are talking about extracting inode objects contained in the directory entry cache (dentry) from the Virtual File System (VFS). The VFS is an abstraction of the filesystem within the kernel which allows coexistence between the different type encountered. The fact that dentries are living in RAM and are never saved to the disk is giving us new useful forensics artifacts that may not be found on a classic “dead system”.
When a process is opening files, it is storing a list of file descriptors. Each file descriptor (fd) is a pointer to a structure containing the dentry cache. We can extract the file inode from this structure and get access to its metadata which are very useful forensics artifacts. We can retrieve the following:
- File size in bytes (i_size)
- File permissions (i_mode)
- Last modification time (mtime)
- Last changed time (ctime)
- Last access time (atime)
The Volatility3 inode plugin
To be able to extract inode metadata from memory we can identify those major steps:
- Go through each process using the pslist plugin.
- For each process, extract the list of file descriptors using code from the lsof plugin.
- For each file descriptor, extract the cached dentries, parse the inode metadata and return the result.
As a result, the plugin is extracting all of the inode metadata needed to help us during our investigation (we like timestamps !).
~/work/DFIR/Memory Analysis/MemoryImages/debian 5.10.0-18-amd64 » vol -f Debian\ XFS.vmem -s symbols linux.inodes
Volatility 3 Framework 2.0.1
Progress: 100.00 Stacking attempts finished
PID Process Inode Mode File LastChange LastModify LastAccessed Size
...
2555 firefox-esr 52709413 -rw-r--r-- /home/volatility/.mozilla/firefox/k2jz4psu.default-esr/places.sqlite-wal 2022-09-11 22:05:11.000000 2022-09-11 22:05:11.000000 2022-09-11 22:05:12.000000 2164304
2555 firefox-esr 34057200 -rw-r--r-- /home/volatility/.mozilla/firefox/k2jz4psu.default-esr/storage/permanent/chrome/idb/1451318868ntouromlalnodry--epcr.sqlite-wal 2022-09-11 22:05:04.000000 2022-09-11 22:05:04.000000 2022-09-11 22:05:04.000000 0
2555 firefox-esr 52709410 -rw-r--r-- /home/volatility/.mozilla/firefox/k2jz4psu.default-esr/places.sqlite 2022-09-11 22:05:04.000000 2022-09-11 22:05:04.000000 2022-09-11 22:05:04.000000 5242880
2555 firefox-esr 52709413 -rw-r--r-- /home/volatility/.mozilla/firefox/k2jz4psu.default-esr/places.sqlite-wal 2022-09-11 22:05:11.000000 2022-09-11 22:05:11.000000 2022-09-11 22:05:12.000000 2164304
2555 firefox-esr 52709411 -rw-r--r-- /home/volatility/.mozilla/firefox/k2jz4psu.default-esr/favicons.sqlite 2022-09-11 22:05:01.000000 2022-09-11 22:05:01.000000 2022-09-11 22:05:01.000000 5242880
2555 firefox-esr 52709412 -rw-r--r-- /home/volatility/.mozilla/firefox/k2jz4psu.default-esr/favicons.sqlite-wal 2022-09-11 22:05:11.000000 2022-09-11 22:05:11.000000 2022-09-11 22:05:01.000000 1147752
2555 firefox-esr 52709414 -rw-r--r-- /home/volatility/.mozilla/firefox/k2jz4psu.default-esr/content-prefs.sqlite 2022-09-11 22:05:02.000000 2022-09-11 22:05:02.000000 2022-09-11 22:05:03.000000 229376
2555 firefox-esr 35077 srwxrwxrwx socket:[35077] 1970-01-01 01:00:00.000000 1970-01-01 01:00:00.000000 1970-01-01 01:00:00.000000 0
2555 firefox-esr 32451 srwxrwxrwx socket:[32451] 1970-01-01 01:00:00.000000 1970-01-01 01:00:00.000000 1970-01-01 01:00:00.000000 0
2555 firefox-esr 32393 srwxrwxrwx socket:[32393] 1970-01-01 01:00:00.000000 1970-01-01 01:00:00.000000 1970-01-01 01:00:00.000000 0
2555 firefox-esr 32457 srwxrwxrwx socket:[32457] 1970-01-01 01:00:00.000000 1970-01-01 01:00:00.000000 1970-01-01 01:00:00.000000 0
2555 firefox-esr 32455 srwxrwxrwx socket:[32455] 1970-01-01 01:00:00.000000 1970-01-01 01:00:00.000000 1970-01-01 01:00:00.000000 0
2555 firefox-esr 32470 srwxrwxrwx socket:[32470] 1970-01-01 01:00:00.000000 1970-01-01 01:00:00.000000 1970-01-01 01:00:00.000000 0
2555 firefox-esr 31746 srwxrwxrwx socket:[31746] 1970-01-01 01:00:00.000000 1970-01-01 01:00:00.000000 1970-01-01 01:00:00.000000 0
2555 firefox-esr 31748 prw------- pipe:[31748] 2022-09-11 22:05:02.000000 2022-09-11 22:05:02.000000 2022-09-11 22:05:02.000000 0
2555 firefox-esr 34057193 -rw-r--r-- /home/volatility/.mozilla/firefox/k2jz4psu.default-esr/storage/permanent/chrome/idb/3870112724rsegmnoittet-es.sqlite 2022-09-11 22:05:07.000000 2022-09-11 22:05:07.000000 2022-09-11 22:05:11.000000 507904
2555 firefox-esr 34057204 -rw-r--r-- /home/volatility/.mozilla/firefox/k2jz4psu.default-esr/storage/permanent/chrome/idb/3870112724rsegmnoittet-es.sqlite-wal 2022-09-11 22:05:07.000000 2022-09-11 22:05:07.000000 2022-09-11 22:05:07.000000 0
...
The fact that we have extracted timestamps makes it possible to build the timeline of the events via the integration to the Timeliner plugin.
~/work/DFIR/Memory Analysis/MemoryImages/debian 5.10.0-18-amd64 » vol -f Debian\ XFS.vmem -s symbols timeline | more 130 ↵ k1nd0ne@MacBook-Pro-de-Felix
Volatility 3 Framework 2.0.1 Running plugin Bash...
Plugin Description Created Date Modified Date Accessed Date Changed Date
Bash 2490 (bash): "echo "hello bash history"" 2022-09-11 20:04:52.000000 N/A N/A N/A
...
Inodes Process firefox-esr (2555) Open "/usr/lib/firefox-esr/browser/extensions/langpack-fr@firefox-esr.mozilla.org.xpi" N/A 2022-08-23 23:09:13.000000 2022-09-11 22:04:59.000000 2022-09-11 21:51:29.000000
Inodes Process firefox-esr (2555) Open "/usr/lib/firefox-esr/browser/features/doh-rollout@mozilla.org.xpi" N/A 2022-08-23 23:09:13.000000 2022-09-11 22:04:59.000000 2022-09-11 21:51:29.000000
Inodes Process firefox-esr (2555) Open "/usr/lib/firefox-esr/browser/features/formautofill@mozilla.org.xpi" N/A 2022-08-23 23:09:13.000000 2022-09-11 22:04:59.000000 2022-09-11 21:51:29.000000
Inodes Process firefox-esr (2555) Open "/usr/lib/firefox-esr/browser/features/pictureinpicture@mozilla.org.xpi" N/A 2022-08-23 23:09:13.000000 2022-09-11 22:04:59.000000 2022-09-11 21:51:29.000000
Inodes Process firefox-esr (2555) Open "/usr/lib/firefox-esr/browser/features/proxy-failover@mozilla.com.xpi" N/A 2022-08-23 23:09:13.000000 2022-09-11 22:04:59.000000 2022-09-11 21:51:29.000000
Inodes Process firefox-esr (2555) Open "/usr/lib/firefox-esr/browser/features/screenshots@mozilla.org.xpi" N/A 2022-08-23 23:09:13.000000 2022-09-11 22:04:59.000000 2022-09-11 21:51:29.000000
Inodes Process firefox-esr (2555) Open "/usr/lib/firefox-esr/browser/features/webcompat@mozilla.org.xpi" N/A 2022-08-23 23:09:13.000000 2022-09-11 22:04:59.000000 2022-09-11 21:51:29.000000
Inodes Process Privileged Cont (2626) Open "/usr/lib/firefox-esr/browser/extensions/langpack-fr@firefox-esr.mozilla.org.xpi" N/A 2022-08-23 23:09:13.000000 2022-09-11 22:04:59.000000 2022-09-11 21:51:29.000000
Conclusion
To conclude, this plugin is a good way to an in depth understanding of how a Linux kernel is storing files in memory and what are the information you can extract from a Linux memory acquisitions. This plugin was tested on a Debian with kernel version 5.10.0.18-amd64. The plugin is available on the forensicxlab github repository: https://github.com/forensicxlab/volatility3_plugins. You should identify each steps described before in the source code comments. Do not hesitate to reach me at felix.guyard@forensicxlab.com to make this article better, or to make a pull-request on the repository to enhance this plugin.
Happy Hunting!
https://www.kernel.org/doc/html/latest/filesystems/vfs.html
http://books.gigatux.nl/mirror/kerneldevelopment/0672327201/ch12lev1sec7.html
http://books.gigatux.nl/mirror/kerneldevelopment/0672327201/ch12lev1sec6.html