In this blog post I’ll be demonstrating a process of obtaining or acquiring a memory image from a running Linux system. The tool of choice LiME (Linux Memory Extractor) and is available on Github.
After a forensic image has been acquired we will use Volatility with a custom Linux profile for the analysis, to keep things simple I’ve used the latest Debian Stretch kernel version
4.9.0-8-amd64 as the target system so it’s easily repeatable.
Building LiME Kernel Module
LiME (formerly DMD) is a Loadable Kernel Module (LKM), which allows the acquisition of volatile memory from Linux and Linux-based devices, such as those powered by Android. read more
To use the Kernel module it must be built for that specific Kernel version, otherwise insmod will not be able to load it. There are also times when targets may use non-standard Kernels i.e. Grsecurity or completely custom ones.
Ideally the following should be done on a forensics workstation. But there are times when it may be necessary to compile and load the module directly on a target system, an example would be when a custom Linux Kernel is present.
sudo apt install linux-headers-4.9.0-8-amd64
sudo apt install build-essential
git clone https://github.com/504ensicsLabs/LiME
You’ll notice a file being created named
lime-4.9.0-8-amd64.ko this is our LKM.
With LiME you have the option to either write to disk or transfer over the network. The latter may pose issues with firewalls or high network usage environments. Nevertheless, the option is there, for our purposes we will be writing to a disk. In a real world scenario you’d be writing to some form of external media.
Write to disk
The following uses insmod to load our compiled Loadable Kernel Module. The options
timeout=0 are important for Volatility. Testing revealed there are a few issues with type
sudo insmod lime-4.9.0-8-amd64.ko "path=/media/external/dump.mem format=lime timeout=0"
Write over the network
Similar to the above we start a listening session on a port 4444 using
sudo insmod lime-4.9.0-8-amd64.ko "path=tcp:4444 format=lime timeout=0"
On a remote host workstation we can use netcat to establish a connection and download the image:
nc 10.10.1.10 4444 > dump.mem
When complete to unload the Kernel Module simply type:
sudo rmmod lime
Building Linux Volatility Profile
Building a Linux profile for Volatility requires a bit more effort. There are times when it may not work correctly. Many people have experienced issues with Linux Kernel versions 4.8+ due to the way Kernel address space layout randomization (KASLR) works.
As mentioned above in this blog post we’ll be building a Linux profile for Debian Stretch system with the Kernel Version:
4.9.0-8-amd64 (2018-08-21) which is confirmed working with Volatility.
git clone https://github.com/volatilityfoundation/volatility
sudo apt install dwarfdump pcregrep libpcre++-dev python-dev python-pip
Install Python Modules
pip install pycrypto Distorm3 OpenPyxl ujson
Building a Profile
volatility/tools/linux and type the following:
sudo make -C /lib/modules/$(uname -r)/build CONFIG_DEBUG_INFO=y M=$PWD modules
dwarfdump -di ./module.o > module.dwarf
sudo zip Debian4908.zip module.dwarf /boot/System.map-$(uname -r)
Move or copy the created zip file to the following directory within Volatility:
cp Debian4908.zip ../../plugins/overlays/linux/
Now when running
--info we should see our newly created Linux Profile(s) LinuxDebian4908x64 as available. The archive we created will be prepended with Linux and appended with x64 dependent on the architecture type.
Memory Analysis with Volatility
Now comes the fun part. Once everything is set up correctly and we’ve acquired a forensic image using LiME. We can start our analysis with Volatility.
An example command using options
-f memory file,
--profile profile name and
linux_banner plugin would look something like this:
python vol.py -f debian-latest.lime --profile=LinuxDebian4908x64 linux_banner
The following is a list of working plugins under our profile.
linux_arp - Print the ARP table
linux_aslr_shift - Automatically detect the Linux ASLR shift
linux_banner - Prints the Linux banner information
linux_bash - Recover bash history from bash process memory
linux_bash_env - Recover a process' dynamic environment variables
linux_bash_hash - Recover bash hash table from bash process memory
linux_check_fop - Check file operation structures for rootkit modifications
linux_check_idt - Checks if the IDT has been altered
linux_check_modules - Compares module list to sysfs info, if available
linux_check_tty - Checks tty devices for hooks
linux_cpuinfo - Prints info about each active processor
linux_dmesg - Gather dmesg buffer
linux_dump_map - Writes selected memory mappings to disk
linux_dynamic_env - Recover a process' dynamic environment variables
linux_elfs - Find ELF binaries in process mappings
linux_enumerate_files - Lists files referenced by the filesystem cache
linux_find_file - Lists and recovers files from memory
linux_getcwd - Lists current working directory of each process
linux_hidden_modules - Carves memory to find hidden kernel modules
linux_ifconfig - Gathers active interfaces
linux_info_regs - It's like 'info registers' in GDB. It prints out all the
linux_iomem - Provides output similar to /proc/iomem
linux_kaslr_shift - Automatically detect KASLR physical/virtual shifts and alternate DTBs
linux_kernel_opened_files - Lists files that are opened from within the kernel
linux_keyboard_notifiers - Parses the keyboard notifier call chain
linux_ldrmodules - Compares the output of proc maps with the list of libraries from libdl
linux_library_list - Lists libraries loaded into a process
linux_librarydump - Dumps shared libraries in process memory to disk
linux_list_raw - List applications with promiscuous sockets
linux_lsmod - Gather loaded kernel modules
linux_lsof - Lists file descriptors and their path
linux_malfind - Looks for suspicious process mappings
linux_memmap - Dumps the memory map for linux tasks
linux_moddump - Extract loaded kernel modules
linux_mount - Gather mounted fs/devices
linux_netfilter - Lists Netfilter hooks
linux_netscan - Carves for network connection structures
linux_netstat - Lists open sockets
linux_pidhashtable - Enumerates processes through the PID hash table
linux_pkt_queues - Writes per-process packet queues out to disk
linux_plthook - Scan ELF binaries' PLT for hooks to non-NEEDED images
linux_proc_maps - Gathers process memory maps
linux_proc_maps_rb - Gathers process maps for linux through the mappings red-black tree
linux_procdump - Dumps a process's executable image to disk
linux_process_hollow - Checks for signs of process hollowing
linux_psaux - Gathers processes along with full command line and start time
linux_psenv - Gathers processes along with their static environment variables
linux_pslist - Gather active tasks by walking the task_struct->task list
linux_psscan - Scan physical memory for processes
linux_pstree - Shows the parent/child relationship between processes
linux_strings - Match physical offsets to virtual addresses (may take a while, VERY verbose)
linux_threads - Prints threads of processes
linux_tmpfs - Recovers tmpfs filesystems from memory
linux_volshell - Shell in the memory image
There may be issues with targets with unique kernel versions or those that utilize additional SDK. Not to mention further issues with KASLR on newer Linux Kernels.