Okay - now to some fun memory forensics! This challenge in the intermediary category is called "Nisseminder" or in english "Elfs Memory". For the challenge, we are provided with a
.tar.xz compressed archive-file.
Extracting the archive reveals one single file named
nisseminder2021 and a quick
file command just shows the file as "data". Not very useful. The file is rather large, and with the "data" type, using
head or similar normally doesn't give anything useful. But looking at the start of the file with
hexdump reveals the ASCII characters of
This means that we most likely are dealing with a memory-dump from a Linux-machine. Furthermore, doing a good-old
strings nisseminder2021 | less on the file, gives us further believes that this is indeed a "LiME" Linux Memory Dump-file.
... PCI Parity Error on Bus/Device/Function PCI System Error on Bus/Device/Function Operating System not found Operating System not found, retrying boot now... Operating System not found, retrying boot in Windows XP Mode active RAM slot #13 RAM slot #14 RAM slot #15 RAM slot #16 RAM slot #17 RAM slot #18 RAM slot #19 RAM slot #20 ... /lib/systemd/systemd ... /bin/systemctl /bin/ip BOOT_IMAGE=/boot/vmlinuz-4.15.0-161-generic root=UUID=2f56d210-f23c-4b78-8d76-86d65bee6631 ro maybe-ubiquity
Okay, so lets treat the file as such and start deep diving info DFIR (Digital Forensics) and try figuring out what has happened in the volatile memory that could give us the flag for this challenge.
This is my first time going into memory forensics - in my day-to-day work I have worked with disk imaging, doing investigations with Autopsy and so on. But memory forensics are something rather high on the learning-dreams for me. So what an opportunity to head-dive right into it? Right?
Firstly we need some tools - I've already heard a lot about a Python-developed tool called
volatility. So why not just start with that? Again, we are going to use Google where I found the guide https://seanthegeek.net/1172/how-to-install-volatility-2-and-volatility-3-on-debian-ubuntu-or-kali-linux/ for installing the tool with the dependencies and what not.
I tried to install and use
volatility3 for Python 3, but was unable to get it working as there was issues with the requirement
libyara. Looking at the Internet, and this seems to be an issue many others encounter. Even though I tried many suggestions, at one point I decided I had to move on as my time to allocate to the CTF was running out. So I tried installing
volatility2 for Python 2.7, and that worked! At some point, when time is not as short-lived, I'm definitely going to produce a working guide - at least one that could help my self in the future..
So, the next task is to figure out what "profile" to use. For every kernel, the structure etc. for the memory - and therefore the memory dumps has changes and more. So to view the correct data from a memory dump, we need this "profile". For Linux memory dumps, we can run a
strings command searching for the information used to decide what profile to use:
user@hostname:~/CTF/NC3/2021-12/Øvet/Nisseminder$ strings nisseminder2021 | grep GNU/Linux ext2fs_get_pathnameWelcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-161-generic x86_64)
This tells us that the memory dump is from a Ubuntu machine version 18.04.3 LTS with the kernel version 4.15.0-161-generic and with a 64-bit instruction-set. Okay. With that information we now need to find the correct profile we can use to interact with the memory dump. Again, looking at a guide from https://heisenberk.github.io/Profile-Memory-Dump/ we are guided to the GitHub https://github.com/volatilityfoundation/profiles where the Volatility Foundation has collected profiles for Linux and Mac.
In here we find a profile named
Ubuntu18043.zip, so I grabbed that and copied it into the correct folder as instructed by the guide. But using that profile seems unsuccessful:
user@hostname:~/CTF/NC3/2021-12/Øvet/Nisseminder$ vol.py -f nisseminder2021 --profile=Ubuntu18043x64 linux_banner Volatility Foundation Volatility Framework 2.6.1 ERROR : volatility.debug : Invalid profile Ubuntu18043x64 selected
This most likely means, that the kernel-version is wrong. Sight. So we might be required to create our own profile, as a short search online didn't reveal any profile that we could verify the kernel for. To do this, we need the original version of Ubuntu - a version "so old" that it is not featured on their main download-site anymore. As a vived Linux-used my self, I looked into my ISO-store but unfortunately only found version 18.04.2 or 18.04.4 - not 18.04.3. Luckily enough, Ubuntu's site still have the old version up - just hidden a bit on the site https://old-releases.ubuntu.com/releases/18.04.3/. From here I created a virtual machine with standard defaults and saw that the kernel version was a bit too old - 4.15.0-55. But nothing a quick upgrade could fix with the command:
apt install linux-image-4.15.0-161-generic linux-headers-4.15.0-161-generic
A quick reboot, and the virtual machine was now on the same Ubuntu- and kernel version as the memory dump. So I then cloned the volatility-tool with git and produced the profile by running
make from the
volatility/tools/linux-directory. After the generation the profile needs to be packed with the
sudo zip Ubuntu18043-4-15-0-161-generic.zip module.dwarf /boot/System.map-4.15.0-161-generic
Now we just have to extract the profile and use it. To perform this step, I used https://transfer.sh/ which is a really nice and easy utility to use for command-line uploading via e.g.
user@hostname:~/CTF/NC3/2021-12/Øvet/Nisseminder$ vol.py -f nisseminder2021 --profile=LinuxUbuntu18043x64 linux_banner Volatility Foundation Volatility Framework 2.6.1 Linux version 4.15.0-161-generic (buildd@lcy01-amd64-012) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)) #169-Ubuntu SMP Fri Oct 15 13:41:54 UTC 2021 (Ubuntu 4.15.0-161.169-generic 4.15.18)
Alright! It worked! We now have access to the memory. Running the command
vol.py --info | grep linux_ will give us a full list of the plugins etc. we can use for our linux-forensics.
A quick look at
linux_pslist to see if anything interesting processes was running, but nothing here. Only a
./avml nisseminder2021 - but that's a process for creating this very memory dump we are looking at. So the next thing very interesting to look into, is the command-history. For this we have the plugin
linux_bash, where we really see some suspicious commands and files.
user@hostname:~/CTF/NC3/2021-12/Øvet/Nisseminder$ vol.py -f nisseminder2021 --profile=LinuxUbuntu18043x64 linux_bash Volatility Foundation Volatility Framework 2.6.1 Pid Name Command Time Command -------- -------------------- ------------------------------ ------- 1516 bash 2021-11-03 13:12:45 UTC+0000 cmd 1516 bash 2021-11-03 13:12:45 UTC+0000 powershell 1516 bash 2021-11-03 13:12:45 UTC+0000 xxd jul.txt.enc 1516 bash 2021-11-03 13:12:45 UTC+0000 HA! 1516 bash 2021-11-03 13:12:45 UTC+0000 exit 1516 bash 2021-11-03 13:12:45 UTC+0000 exit 1516 bash 2021-11-03 13:12:45 UTC+0000 openssl enc -aes-256-cbc -nosalt -e -in jul.txt -out jul.txt.enc -K '4b404e5f4a65475f4875736b335f645f6865725f6b4f64656f72643f3f3f3f3f' -iv '2d4e4333435446326f32314a554c212d' 1516 bash 2021-11-03 13:12:45 UTC+0000 cd c:\windows 1516 bash 2021-11-03 13:12:45 UTC+0000 ls 1516 bash 2021-11-03 13:12:45 UTC+0000 exit 1516 bash 2021-11-03 13:12:45 UTC+0000 ??HH NEJ, det er jo LINUX 1516 bash 2021-11-03 13:12:45 UTC+0000 rm jul.txt 1516 bash 2021-11-03 13:12:52 UTC+0000 sudo cat /etc/shadow 1516 bash 2021-11-03 13:13:06 UTC+0000 cat jul.txt.enc 1516 bash 2021-11-03 13:13:11 UTC+0000 xxd jul.txt.enc 1516 bash 2021-11-03 13:13:23 UTC+0000 sudo ./avml nisseminder2021
So, as far as we can see, they are encrypting a file called
jul.txt ("christmas.txt") and then deleting the original file. The only "problem" here, is the fact that all the information used to encrypt the file is available to us for decryption. Nice!
To decrypt the file, we need to extract it from the memory dump. Using the plugin
linux_find_file -F "jul.txt.enc" could not find the file for us. So lets use
linux_enumerate_files and use
grep to filter the output.
user@hostname:~/CTF/NC3/2021-12/Øvet/Nisseminder$ vol.py -f nisseminder2021 --profile=LinuxUbuntu18043x64 linux_enumerate_files | grep jul.txt.enc Volatility Foundation Volatility Framework 2.6.1 0xffff898674f5dad0 923322 /home/storenisse/jul.txt.enc
And like that, we now have the location of the file. With
linux_find_file we can now retrieve the Inode-information for the file using the
-F for finding the file and then
-i with a
-O to extract the file from the memory dump:
user@hostname:~/CTF/NC3/2021-12/Øvet/Nisseminder$ vol.py -f nisseminder2021 --profile=LinuxUbuntu18043x64 linux_find_file -F "/home/storenisse/jul.txt.enc" Volatility Foundation Volatility Framework 2.6.1 Inode Number Inode File Path ---------------- ------------------ --------- 923322 0xffff898674f5dad0 /home/storenisse/jul.txt.enc user@hostname:~/CTF/NC3/2021-12/Øvet/Nisseminder$ vol.py -f nisseminder2021 --profile=LinuxUbuntu18043x64 linux_find_file -i 0xffff898674f5dad0 -O jul.txt.enc Volatility Foundation Volatility Framework 2.6.1
We know from the bash-command line history, that the file was encrypted with
openssl enc, so let us use that to decrypt the file again:
openssl enc -aes-256-cbc -d -in jul.txt.enc -out jul.txt -K 4b404e5f4a65475f4875736b335f645f6865725f6b4f64656f72643f3f3f3f3f -iv 2d4e4333435446326f32314a554c212d
And with that - we have a flag: