Writeup DGA - CTF - ShadowMallet

This article describes my solution for the 150-point challenge called “ShadowMallet”.


Un administrateur sécurité de DGA MI détecte une activité anormale sur l’un de ses serveurs. Aidez le  !


We have a file that once decompressed doesn’t give us much information about what type of file it is.

file shadowmallet
shadowmallet: data

Having searched for a long time what kind of file it could be (and therefore using the right tool) I found this article StackExchange which allows to easily identify a memory image.

hexdump -C shadowmallet | head -10
00000000  53 ff 00 f0 53 ff 00 f0  53 ff 00 f0 53 ff 00 f0  |S...S...S...S...|
00000010  53 ff 00 f0 53 ff 00 f0  cc e9 00 f0 53 ff 00 f0  |S...S.......S...|
00000020  a5 fe 00 f0 87 e9 00 f0  53 ff 00 f0 46 e7 00 f0  |........S...F...|
00000030  46 e7 00 f0 46 e7 00 f0  57 ef 00 f0 53 ff 00 f0  |F...F...W...S...|
00000040  22 00 00 c0 4d f8 00 f0  41 f8 00 f0 fe e3 00 f0  |"...M...A.......|
00000050  39 e7 00 f0 59 f8 00 f0  2e e8 00 f0 d4 ef 00 f0  |9...Y...........|
00000060  a4 f0 00 f0 f2 e6 00 f0  6e fe 00 f0 53 ff 00 f0  |........n...S...|
00000070  ed ef 00 f0 53 ff 00 f0  c7 ef 00 f0 6d 59 00 c0  |....S.......mY..|
00000080  53 ff 00 f0 53 ff 00 f0  53 ff 00 f0 53 ff 00 f0  |S...S...S...S...|

We now know that it is a memory image. The tool of choice to use is Volatility. Before we can use this tool on our memory image we need to generate a profile. I won’t go into the details of what a profile is because this is not the purpose of this article.

To generate a profile you need to know the GNU/Linux distribution and the kernel version to have the right memory mapping (among others).

Profile’s generation

As said before, we need to identify the GNU/Linux distribution as well as the kernel version.

strings shadowmallet | grep -i "kernel" | head -n 10
4.19.0-9-amd64 (debian-kernel@lists.debian.org) (gcc version 8.3.0 (Debian 8.3.0-6)) #1 SMP Debian 4.19.118-2 (2020-04-29)

The kernel version is 4.19.0-9. Now comes the choice of distribution. I saw several times the appearance of Debian, so there was a good chance it was a Debian. Because I didn’t find any strings that gave the right version that was being used, I tried several until I found the right one: Debian 10.4.0.

Once the installation of Debian is done in a virtual machine, the only thing left to do is to generate the profile.

Install required utilities

sudo apt install build-essential dwarfdump git zip

Clone the Volatility repositories

git clone https://github.com/volatilityfoundation/volatility.git

Generate the profile

cd volatility/tools/linux/

Zip all the things

sudo zip $(lsb_release -i -s)_$(uname -r)_profile.zip module.dwarf /boot/System.map-$(uname -r)

Once this is done, you end up with the following file.

file Debian_4.19.0-9-amd64_profile.zip
Debian_4.19.0-9-amd64_profile.zip: Zip archive data, at least v2.0 to extract

I then retrieved this file on my computer, created a virtual environment, cloned the volatility repository and placed this file in zip format in volatility/volatility/plugins/overlays/linux/.

virtualenv2 shadow
cd shadow
source bin/activate.fish
(shadow) git clone https://github.com/volatilityfoundation/volatility.git
(shadow) mv ~/Debian_4.19.0-9-amd64_profile.zip volatility/volatility/plugins/overlays/linux/
(shadow) mv ~/shadowmallet .
(shadow) cd volatility/

Some Python modules are required to execute Volatility correctly.

(shadow) pip install distorm3 Crypto pycrypto

Now, we can see if everything is ready to work by executing the following command.

(shadow) python vol.py --info | grep Debian
Volatility Foundation Volatility Framework 2.6.1
LinuxDebian_4_19_0-9-amd64_profilex64 - A Profile for Linux Debian_4.19.0-9-amd64_profile x64

Our profile is detected!

Forensic analysis

Now we have everything we need to conduct our forensic analysis. We need to proceed in this way in order, for example, to display the processes running while the memory capture was in progress.

(shadow) python vol.py -f ../shadowmallet --profile=LinuxDebian_4_19_0-9-amd64_profilex64 linux_pslist
Volatility Foundation Volatility Framework 2.6.1
Offset             Name                 Pid             PPid            Uid             Gid    DTB                Start Time
------------------ -------------------- --------------- --------------- --------------- ------ ------------------ ----------
0xffff94495d612c40 systemd              1               0               0               0      0x000000001ce1e000 2020-11-09 17:30:29 UTC+0000
0xffff94495d6149c0 kthreadd             2               0               0               0      ------------------ 2020-11-09 17:30:29 UTC+0000
0xffff94495d613b00 rcu_gp               3               2               0               0      ------------------ 2020-11-09 17:30:29 UTC+0000
0xffff94495d610000 rcu_par_gp           4               2               0               0      ------------------ 2020-11-09 17:30:29 UTC+0000

I pass you all the different plugins tried to find something abnormal … Until the moment when the display of the hidden modules gives something interesting.

(shadow) python vol.py -f ../shadowmallet --profile=LinuxDebian_4_19_0-9-amd64_profilex64 linux_hidden_modules
Volatility Foundation Volatility Framework 2.6.1
Offset (V)         Name
------------------ ----
0xffffffffc04a6000 netfilter
0xffffffffc0578300 qni

In its normal workings, the netfilter module (firewall within the GNU/Linux kernel) is not supposed to be hidden.

So I decided to extract it for further analysis. I use the linux_moddump plugin with the -D flag to specify the directory where the Loadable Kernel Module (LKM) file should be stored and the -b flag to specify the offset of the module to dump.

(shadow) mkdir modules
(shadow) python vol.py -f ../shadowmallet --profile=LinuxDebian_4_19_0-9-amd64_profilex64 linux_moddump -D modules/ -b 0xffffffffc04a6000
Volatility Foundation Volatility Framework 2.6.1
Wrote 668514 bytes to netfilter.0xffffffffc04a6000.lkm

We can verify that it has extracted what we asked it to do.

(shadow) file modules/netfilter.0xffffffffc04a6000.lkm
modules/netfilter.0xffffffffc04a6000.lkm: ELF 64-bit LSB relocatable, Intel 80386, version 1 (SYSV), BuildID[sha1]=43d8d77459d809b0337cbd723733ac10f8b582e8, not stripped

I started with a rather simple search with the command strings. Magic operates.

(shadow) strings modules/netfilter.0xffffffffc04a6000.lkm

We can see that this string has nothing to do here. This is the flag to validate this challenge.