Skip to main content

Command Palette

Search for a command to run...

Holmes CTF 2025 - The Tunnel Without Walls [4/4]

Updated
8 min readView as Markdown

Quatrième épreuves du CTF “Holmes CTF 2025”

The Tunnel Without Walls

A memory dump from a connected Linux machine reveals covert network connections, fake services, and unusual redirects. Holmes investigates further to uncover how the attacker is manipulating the entire network!

Dans ce challenge, nous disposons d'un dump mémoire Linux**.**

  • memdump.mem

L’analyse est réalisée principalement avec Volatility 3, complétée par différentes commandes Linux (strings, grep, john, etc.) lorsque cela est nécessaire.

Difficulté : 🟩🟧🟥 - Hard

Questions

1 - What is the Linux kernel version of the provided image? (string)

La commande windows.info n’étant pas compatible avec une image Linux, nous pouvons utiliser le plugin suivant :

  • banners.Banners

✅ Réponse : 5.10.0-35

2 - The attacker connected over SSH and executed initial reconnaissance commands. What is the PID of the shell they used? (number)

⚠️ La première étape consiste à télécharger les symboles permettant de débloquer les fonctionnalités de Volatility pour cette version précise du kernel Linux.

Les symboles sont disponibles ici :

Une fois les symboles installés, nous pouvons commencer à analyser le dump mémoire.

Ce que nous cherchons ici est le shell utilisé par l’attaquant. De plus, ce shell doit être lié à un processus SSH.

Nous pouvons commencer par lister les processus avec :

python3 vol.py -f memdump.mem linux.psaux.PsAux

En filtrant les résultats, nous pouvons identifier les différents processus SSH :

Nous pouvons également retrouver les différents processus bash :

L’un des processus bash provient d’une session SSH, comme nous pouvons le voir grâce à son processus parent (13607). Nous pouvons donc en conclure qu’il s’agit du shell utilisé par l’attaquant.

✅ Réponse : 13608

3 - After the initial information gathering, the attacker authenticated as a different user to escalate privileges. Identify and submit that user's credentials. (user:password)

Ici, deux informations sont nécessaires pour valider le flag :

  • le nom d’utilisateur ;

  • le mot de passe.

Cherchons ces informations étape par étape.

En regardant les commandes exécutées par le processus bash identifié dans la question précédente, nous pouvons facilement retrouver le nom de l’utilisateur :

Première réponse, nom d’utilisateur : jm

Pour retrouver le mot de passe, nous devons maintenant récupérer deux fichiers présents dans le dump mémoire :

  • /etc/passwd

  • /etc/shadow

Nous allons utiliser le plugin linux.pagecache.InodePages.

Sous Linux, le page cache conserve en mémoire les données des fichiers récemment lus ou écrits. Ce plugin permet notamment de :

  • parcourir les inodes présents en mémoire ;

  • retrouver les pages de cache associées à chaque inode ;

  • afficher les informations relatives à ces pages (adresses mémoire, index des pages, etc.) ;

  • reconstruire ou analyser le contenu des fichiers encore présents dans le page cache.

Cela va nous permettre de retrouver nos fichiers et, si possible, d’en extraire leur contenu.

Nous utilisons la commande suivante :

python3 vol.py -f memdump.mem -o /htb/htb_sherlock/tunnels/ linux.pagecache.InodePages --dump --find /etc/passwd

Nous faisons ensuite la même chose pour /etc/shadow.

Le résultat est plutôt positif :

Nous avons donc accès aux deux fichiers, en cherchant dedans :

Nous obtenons la première information nécessaire pour retrouver le mot de passe : son hash.

Il faut maintenant tenter de retrouver le mot de passe correspondant à ce hash.

  • jm → nom de l’utilisateur ;

  • $1$ → indique un hash MD5 crypt (ancien format md5crypt) ;

  • jm$poAH2RyJp8ZllyUvIkxxd0 → correspond au hash du mot de passe.

J’utilise John the Ripper afin de retrouver le mot de passe correspondant à ce hash :

john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt

John the Ripper parvient à retrouver le mot de passe.

✅ Réponse : jm:WATSON0

4 - The attacker downloaded and executed code from Pastebin to install a rootkit. What is the full path of the malicious file? (/path/filename.ext)

Un rootkit est un type de malware conçu pour dissimuler sa présence ou celle d’autres logiciels malveillants. Il peut modifier le fonctionnement du système en agissant à différents niveaux : espace utilisateur, kernel, firmware, etc.

Il peut notamment permettre de cacher des processus, des fichiers ou encore des connexions réseau.

D’après cette définition, un plugin Volatility est particulièrement intéressant pour détecter ce type de malware :

Ce plugin permet de détecter des modules kernel Linux qui sont chargés en mémoire mais qui ont été retirés des listes officielles du kernel.

Un rootkit peut charger un module kernel puis le retirer de la liste des modules chargés. Cela permet notamment d’éviter sa détection avec des commandes telles que :

  • lsmod

  • cat /proc/modules

En cherchant via strings dans le dump via strings memdump.mem | egrep -i 'Nullincrevenge.ko' | head -n 50 :

En recherchant ensuite le fichier dans le cache avec :

python3 vol.py -f memdump.mem linux.pagecache.Files | grep "Nullincrevenge"

Nous retrouvons le chemin complet du fichier malveillant.

✅ Réponse : /usr/lib/modules/5.10.0-35-amd64/kernel/lib/Nullincrevenge.ko

5 - What is the email account of the alleged author of the malicious file? (user@example.com)

Nous allons commencer par extraire le fichier :

python3 vol.py -f memdump.mem linux.pagecache.InodePages -o /dumpfile/ --find /usr/lib/modules/5.10.0-35-amd64/kernel/lib/Nullincrevenge.ko --dump

Puis, avec strings sur le fichier extrait :

strings inode_0x9b3386454a80.dmp

Nous pouvons retrouver l’adresse e-mail associée au fichier malveillant :

✅ Réponse : i-am-the@network.now

6 - The next step in the attack involved issuing commands to modify the network settings and installing a new package. What is the name and PID of the package? (package name,PID)

Lorsqu’il s’agit d’identifier les commandes exécutées par l’attaquant, nous pouvons directement utiliser le plugin :

python3 vol.py -f memdump.mem linux.bash.Bash

Nous pouvons notamment observer l’installation et l’exécution de dnsmasq.

dnsmasq est un logiciel pouvant notamment servir de serveur DNS, de cache DNS et de serveur DHCP, notamment pour les petits réseaux.

Nous devons maintenant retrouver son PID.

Pour cela :

python3 vol.py -f memdump.mem linux.psaux | grep "dnsmasq"

Et le processus correspondant apparaît dans les résultats :

✅ Réponse : dnsmasq,38687

7 - Clearly, the attacker's goal is to impersonate the entire network. One workstation was already tricked and got its new malicious network configuration. What is the workstation's hostname?

Si nous reprenons les commandes observées avec :

python3 vol.py -f memdump.mem linux.bash.Bash

Nous pouvons comprendre que l’attaquant met en place une attaque MITM (Man-In-The-Middle) afin de pouvoir contrôler le trafic du réseau depuis une machine compromise.

Nous pouvons également voir qu’un fichier de configuration dnsmasq est utilisé.

Nous allons donc l’extraire :

python3 vol.py -f memdump.mem -o dump_file/dnsmasq.conf linux.pagecache.InodePages --find /etc/dnsmasq.conf --dump

Puis, en utilisant strings sur le fichier récupéré :

Nous disposons désormais de suffisamment d’informations concernant la configuration utilisée pour le MITM.

En recherchant dans le dump les adresses IP correspondant au réseau 192.168.211.XXX :

strings memdump.mem | grep -E '192.168.211.[0-9]{1,3}'

Nous retrouvons notamment l’adresse IP ainsi que le nom de la workstation compromise.

✅ Réponse : Parallax-5-WS-3

8 - After receiving the new malicious network configuration, the user accessed the City of CogWork-1 internal portal from this workstation. What is their username? (string)

En recherchant la chaîne username= dans le dump :

strings memdump.mem | grep -i 'username='

Nous pouvons retrouver plusieurs éléments intéressants :

Avec ces nouveaux éléments, nous pouvons effectuer une recherche plus précise :

strings memdump.mem | grep -i -C 10 "mike.sullivan"

Nous pouvons voir que l’identifiant retrouvé est utilisé pour se connecter à une adresse IP privée correspondant au portail interne.

✅ Réponse : mike.sullivan

9 - Finally, the user updated a software to the latest version, as suggested on the internal portal, and fell victim to a supply chain attack. From which Web endpoint was the update downloaded?

En cherchant strings memdump.mem | grep -E '192.168.211.[0-9]{1,3}' on tombe sur quelque chose d'intéressant qui correspond parfaitement à ce que l'on cherche dans la question :

✅ Réponse : /win10/update/CogSoftware/AetherDesk-v74-77.exe

10 - To perform this attack, the attacker redirected the original update domain to a malicious one. Identify the original domain and the final redirect IP address and port. (domain,IP:port)

En analysant à nouveau les résultats de :

python3 vol.py -f memdump.mem linux.bash.Bash

Nous pouvons comprendre que le conteneur Docker sert notamment de serveur Web.

Le but est donc de récupérer le fichier de configuration default.conf.

Nous pouvons le retrouver avec :

python3 vol.py -f memdump.mem linux.pagecache.Files | grep "/tmp/default.conf"

Nous retrouvons bien le fichier et pouvons l’extraire avec :

python3 vol.py -f memdump.mem -o dump_file linux.pagecache.InodePages --find /tmp/default.conf --dump

Nous pouvons désormais consulter son contenu :

Nous observons notamment une adresse IP externe associée à un port peu commun. C’est un bon point de départ.

Il faut maintenant retrouver l’adresse de redirection.

En reprenant la configuration de dnsmasq :

Nous pouvons alors assembler les deux informations afin d’obtenir la réponse finale.

✅ Réponse : updates.cogwork-1.net:13.62.49.86:7477

More from this blog

M

menta.re

6 posts

Cybersecurity Engineer 🛰️ Currently diving into defensive security operations & incident response

Root-Me profile : https://www.root-me.org/MenTa