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 cat
, head
or similar normally doesn't give anything useful. But looking at the start of the file with hexdump
reveals the ASCII characters of EMiL
.
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 System.map
-file:
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. curl
.
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:
nc3{ahh_ja_nu_kan_jeg_huske_det}
I was waaaayy off!
But, thank you, that was very helpful