From bb7e63ac60b59479f738d5093036edb1e31f8665 Mon Sep 17 00:00:00 2001 From: Jakub WERLINSKI Date: Sat, 25 Jul 2026 00:51:37 +0200 Subject: [PATCH] =?UTF-8?q?refactor(blue-memory):=20bo=C3=AEte=20d'analyse?= =?UTF-8?q?=20SSH=20(environnement=20fourni,=20stand-alone)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le challenge devient un conteneur accessible en SSH où le dump + les outils sont déjà en place : le joueur se connecte et analyse dedans, sans rien installer (cohérent avec les autres challenges SSH de la plateforme). - Dockerfile : openssh-server, user analyst/forensics, dump+outils dans le home, EXPOSE 22, CMD sshd -D (règle aussi le "Could not get port") - mission.txt : message d'accueil (MOTD) avec les commandes - suppression de docker-entrypoint.sh (modèle HTTP abandonné) - docker-compose : test local via ssh -p 2222 - docs joueur/admin : accès SSH + série de 6 flags --- .../Dockerfile | 87 ++++------- .../docker-compose.yml | 14 +- .../docker-entrypoint.sh | 64 -------- .../docs/ADMIN_DEPLOYMENT.md | 144 ++++++++---------- .../docs/USER_GUIDE.md | 42 ++--- .../mission.txt | 30 ++++ 6 files changed, 150 insertions(+), 231 deletions(-) delete mode 100644 challenges/2-Blue-Team-Memory-Forensics-Jakub/docker-entrypoint.sh create mode 100644 challenges/2-Blue-Team-Memory-Forensics-Jakub/mission.txt diff --git a/challenges/2-Blue-Team-Memory-Forensics-Jakub/Dockerfile b/challenges/2-Blue-Team-Memory-Forensics-Jakub/Dockerfile index c103834..caf7dbb 100644 --- a/challenges/2-Blue-Team-Memory-Forensics-Jakub/Dockerfile +++ b/challenges/2-Blue-Team-Memory-Forensics-Jakub/Dockerfile @@ -1,74 +1,47 @@ # ============================================================================= -# Blue Team CTF – Memory Forensics Challenge (Container) +# Blue Team CTF – Mémoire & Analyse de Malware (environnement d'analyse SSH) # ============================================================================= -# Stage 1 : Génère le dump mémoire et le PCAP -# Stage 2 : Image légère avec uniquement les outils d'analyse + les fichiers +# Stage 1 : génère le dump mémoire + le PCAP (flag lu depuis challenge.env) +# Stage 2 : boîte d'analyse accessible en SSH — dump + outils déjà en place, +# le joueur se connecte et analyse dedans (rien à installer chez lui) # ============================================================================= # ── Stage 1 : Builder (génération des artefacts) ───────────────────────────── FROM python:3.11-slim AS builder - WORKDIR /build - -# Copier les scripts de génération COPY setup/ ./setup/ - -# Installer les dépendances de génération RUN pip install --no-cache-dir -r setup/requirements.txt - -# Générer le dump mémoire et le PCAP -RUN python setup/generate_challenge.py && \ - python setup/generate_pcap.py +RUN python setup/generate_challenge.py && python setup/generate_pcap.py -# ── Stage 2 : Image finale (challenge) ─────────────────────────────────────── +# ── Stage 2 : Boîte d'analyse SSH ──────────────────────────────────────────── FROM python:3.11-slim LABEL maintainer="Jakub – ESGI Projet Annuel 2026" -LABEL description="Blue Team CTF – Mémoire et Analyse de Malware" - -# Empêcher Python de bufferiser stdout/stderr +LABEL description="Blue Team CTF – Mémoire et Analyse de Malware (SSH)" ENV PYTHONUNBUFFERED=1 -ENV TERM=xterm-256color - -WORKDIR /challenge - -# Copier les artefacts générés depuis le builder -COPY --from=builder /build/challenge/ ./challenge/ - -# Copier les outils d'analyse (accessibles au joueur) -COPY tools/ ./tools/ -# Copier le template de rapport -COPY report/ ./report/ - -# Copier le script de validation (le joueur peut valider ses réponses) -COPY solution/validate_flag.py ./solution/validate_flag.py - -# Hash SHA256 du flag (généré au build depuis challenge.env) — jamais le flag en clair -COPY --from=builder /build/valout/flag.sha256 ./solution/flag.sha256 - -# Copier le README -COPY README.md ./README.md - -# Copier le script d'accueil -COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh -RUN chmod +x /usr/local/bin/docker-entrypoint.sh - -# Créer un utilisateur non-root pour le joueur -RUN useradd -m -s /bin/bash analyst && \ - chown -R analyst:analyst /challenge - -# Installer les outils utiles pour l'analyse +# Serveur SSH + petits utilitaires d'analyse (les outils Python n'ont besoin +# que de la stdlib, déjà présente). RUN apt-get update && apt-get install -y --no-install-recommends \ - less \ - nano \ - vim-tiny \ - xxd \ - file \ - && rm -rf /var/lib/apt/lists/* - -USER analyst - -ENTRYPOINT ["docker-entrypoint.sh"] -CMD ["/bin/bash"] + openssh-server less nano vim-tiny xxd file && \ + rm -rf /var/lib/apt/lists/* && \ + mkdir -p /run/sshd && ssh-keygen -A + +# Utilisateur joueur (identifiants communiqués dans l'énoncé CTFd). +# Pas de root en SSH ; authentification par mot de passe autorisée. +RUN useradd -m -s /bin/bash analyst && echo 'analyst:forensics' | chpasswd && \ + sed -i 's/#\?PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config && \ + sed -i 's/#\?PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config + +# Environnement d'analyse dans le home du joueur +WORKDIR /home/analyst +COPY --from=builder /build/challenge/ ./ +COPY tools/vol_analyzer.py tools/extract_strings.py ./ +COPY solution/validate_flag.py ./check_flag.py +COPY --from=builder /build/valout/flag.sha256 ./flag.sha256 +COPY mission.txt /etc/motd +RUN chown -R analyst:analyst /home/analyst + +EXPOSE 22 +CMD ["/usr/sbin/sshd", "-D", "-e"] diff --git a/challenges/2-Blue-Team-Memory-Forensics-Jakub/docker-compose.yml b/challenges/2-Blue-Team-Memory-Forensics-Jakub/docker-compose.yml index 80f31ea..99bc53b 100644 --- a/challenges/2-Blue-Team-Memory-Forensics-Jakub/docker-compose.yml +++ b/challenges/2-Blue-Team-Memory-Forensics-Jakub/docker-compose.yml @@ -1,5 +1,8 @@ # ============================================================================= -# Blue Team CTF – Docker Compose +# Blue Team CTF – Docker Compose (test local) +# Boîte d'analyse SSH : le joueur se connecte via ssh. +# En prod, le plugin CTFdDockerContainersPlugin alloue le port dynamiquement +# (port interne du challenge dans CTFd = 22). # ============================================================================= services: @@ -8,9 +11,6 @@ services: context: . dockerfile: Dockerfile container_name: blueteam-memory-forensics - stdin_open: true # -i : garder stdin ouvert - tty: true # -t : allouer un pseudo-TTY - volumes: - # Le rapport est partagé avec l'hôte pour pouvoir le récupérer - - ./report:/challenge/report - # Pas de ports exposés : le challenge est 100% en CLI dans le conteneur + ports: + - "2222:22" # test local : ssh analyst@127.0.0.1 -p 2222 (mot de passe : forensics) + restart: unless-stopped diff --git a/challenges/2-Blue-Team-Memory-Forensics-Jakub/docker-entrypoint.sh b/challenges/2-Blue-Team-Memory-Forensics-Jakub/docker-entrypoint.sh deleted file mode 100644 index fa17999..0000000 --- a/challenges/2-Blue-Team-Memory-Forensics-Jakub/docker-entrypoint.sh +++ /dev/null @@ -1,64 +0,0 @@ -#!/bin/bash -# ============================================================================= -# Blue Team CTF – Script d'accueil du conteneur -# Mode dual : HTTP (port 8000) pour le download des artefacts -# + terminal interactif pour l'analyse locale -# ============================================================================= - -# ── Démarrer le serveur HTTP en arrière-plan ────────────────────────────────── -python3 -m http.server 8000 --directory /challenge/challenge & -HTTP_PID=$! -echo "[+] Serveur HTTP démarré sur le port 8000 (PID: $HTTP_PID)" - -cat << 'BANNER' - - ╔══════════════════════════════════════════════════════════════╗ - ║ ║ - ║ 🔵 BLUE TEAM CTF – Mémoire et Analyse de Malware ║ - ║ ║ - ║ Jakub – ESGI Projet Annuel 2026 ║ - ║ ║ - ╠══════════════════════════════════════════════════════════════╣ - ║ ║ - ║ 📖 Contexte : ║ - ║ L'attaquant a déployé un implant en mémoire qui ║ - ║ communique avec un serveur C2. ║ - ║ Trouvez le C2 et le flag ! ║ - ║ ║ - ║ 🌐 Téléchargement des artefacts (via CTFd) : ║ - ║ http://:8000/memory.dmp ║ - ║ http://:8000/network_capture.pcap ║ - ║ http://:8000/hints.txt ║ - ║ ║ - ║ 📁 Fichiers disponibles localement : ║ - ║ challenge/memory.dmp → Dump mémoire ║ - ║ challenge/network_capture.pcap → Capture réseau (bonus) ║ - ║ challenge/hints.txt → Indices ║ - ║ report/report_template.md → Rapport à remplir ║ - ║ ║ - ║ 🔧 Outils d'analyse (dans ce terminal) : ║ - ║ python3 tools/vol_analyzer.py -f challenge/memory.dmp \ ║ - ║ windows.info | pslist | pstree | netscan | ║ - ║ malfind | dlllist | handles | dumpfiles | ║ - ║ strings | registry ║ - ║ ║ - ║ ✅ Validation : ║ - ║ python3 solution/validate_flag.py ║ - ║ ║ - ║ 💡 Commencez par : ║ - ║ python3 tools/vol_analyzer.py -f challenge/memory.dmp \ ║ - ║ windows.pslist ║ - ║ ║ - ╚══════════════════════════════════════════════════════════════╝ - -BANNER - -# ── Mode dual : interactif (local) vs détaché (CTFd) ───────────────────────── -if [ -t 0 ]; then - # TTY présent → mode interactif (docker run -it) : lancer bash - exec "$@" -else - # Pas de TTY → mode CTFd détaché : le conteneur vit via le serveur HTTP - echo "[+] Mode non-interactif détecté (CTFd). En attente sur le serveur HTTP..." - wait $HTTP_PID -fi diff --git a/challenges/2-Blue-Team-Memory-Forensics-Jakub/docs/ADMIN_DEPLOYMENT.md b/challenges/2-Blue-Team-Memory-Forensics-Jakub/docs/ADMIN_DEPLOYMENT.md index d7a407c..68e486a 100644 --- a/challenges/2-Blue-Team-Memory-Forensics-Jakub/docs/ADMIN_DEPLOYMENT.md +++ b/challenges/2-Blue-Team-Memory-Forensics-Jakub/docs/ADMIN_DEPLOYMENT.md @@ -1,107 +1,83 @@ -# Blue Team Memory Forensics - Guide Admin/Deploiement +# Blue Team Memory Forensics — Guide Admin / Déploiement -## 1) Build de l'image -Depuis `challenges/2-Blue-Team-Memory-Forensics`: +Challenge de type **container** : une **boîte d'analyse accessible en SSH**. Le joueur +fait *Start Instance*, se connecte en SSH, et analyse le dump avec les outils déjà en +place (rien à installer côté joueur). -```bash -docker build -t blue-team-memory-forensics:latest . -``` - -## 2) Test local (mode dual : HTTP + terminal) +## 1) Fournir le flag (ne PAS le committer) -Lancer le conteneur localement pour vérifier que tout fonctionne : +Le flag n'est pas codé en dur : il vient d'un fichier gitignoré, puis est cuit dans le +dump/PCAP au build, et son hash SHA256 est généré pour l'auto-vérification. ```bash -docker run -it --rm -p 8000:8000 blue-team-memory-forensics:latest -``` - -- **HTTP (port 8000)** : artefacts disponibles à `http://localhost:8000/` -- **Terminal interactif** : outils d'analyse (`vol_analyzer.py`) utilisables directement - -## 3) Export et transfert vers le serveur -```bash -docker save -o blue-team-memory-forensics.tar blue-team-memory-forensics:latest -scp -i "" ".\blue-team-memory-forensics.tar" jakub@:/tmp/ -``` - -## 4) Import sur le serveur -```bash -docker load -i /tmp/blue-team-memory-forensics.tar -docker images | grep blue-team-memory-forensics -``` - -## 5) Configuration CTFd (soutenance) -Challenge type: `container` - -- **Name**: `Blue Team - Jakub - Memoire et analyse de malware (Volatility)` -- **Category**: `Blue Team` -- **Image**: `blue-team-memory-forensics:latest` -- **Port**: `8000` -- **Command**: laisser vide (l'entrypoint gère tout : HTTP + terminal) -- **Initial Value**: `100` -- **Decay Limit**: `0` -- **Minimum Value**: `100` -- **Volumes**: vide - -> **Note** : Le conteneur démarre automatiquement : -> 1. Un serveur HTTP sur le port 8000 → les joueurs téléchargent les artefacts via l'URL CTFd -> 2. Un terminal bash → accessible via `docker exec` pour les tests admin - -## 6) Creation du flag (obligatoire) -Dans l'onglet `Flags`: -- **Type**: `Static` -- **Valeur**: la valeur définie dans `setup/challenge.env` (`FLAG=...`) — **pas** de flag en clair dans le dépôt. Voir « Fournir le flag » ci-dessous. -- **Case Sensitive**: activé - -## 7) Sequence de validation -1. Laisser le challenge en `Hidden`. -2. Tester `Start Instance` avec un compte joueur. -3. Vérifier l'accès HTTP aux fichiers : `http://:8000/memory.dmp` -4. Vérifier que `hints.txt` et `network_capture.pcap` sont bien accessibles. -5. Soumettre le flag (celui de `challenge.env`) pour valider. -6. Passer en `Visible`. - -## Fournir le flag (ne PAS le committer) - -Le flag n'est plus codé en dur : il est fourni au build via un fichier gitignoré, -puis cuit dans le dump + le PCAP, et son hash SHA256 est généré pour le validateur. - -```bash -cd setup +cd challenges/2-Blue-Team-Memory-Forensics-Jakub/setup cp challenge.env.example challenge.env $EDITOR challenge.env # FLAG=blue{...} (choisir une valeur rotée) ``` -Puis (re)builder l'image ; `gen`/`generate_challenge.py` lit `challenge.env` automatiquement. -Si aucun `challenge.env` n'est fourni, le build réussit mais avec un flag **placeholder** -(`blue{PLACEHOLDER_...}`). Le même flag doit être saisi côté CTFd (étape 6). +Si aucun `challenge.env` n'est fourni, le build réussit mais avec un flag **placeholder**. -> ⚠️ Rotation : l'ancien flag `blue{m3m_f0r3ns1cs_v0l4t1l1ty_m4st3r}` est resté public -> dans l'historique git — choisir une **nouvelle** valeur dans `challenge.env`. +> ⚠️ Rotation : l'ancien flag est resté public dans l'historique git — choisir une +> **nouvelle** valeur dans `challenge.env`. -## 8) Troubleshooting -Si l'instance ne démarre pas : +## 2) Build de l'image ```bash -docker ps -a -docker logs +sudo docker build -t rootmeup/bt2-memory-forensics:1.0 \ + /srv/ctf-challenges/RootMeUp/challenges/2-Blue-Team-Memory-Forensics-Jakub ``` -Si l'image n'existe pas : +## 3) Test local ```bash -docker load -i /tmp/blue-team-memory-forensics.tar +docker compose up --build -d # expose 2222->22 +ssh analyst@127.0.0.1 -p 2222 # mot de passe : forensics +# dans la boîte : +python3 vol_analyzer.py -f memory.dmp windows.pslist ``` -Si le port 8000 ne répond pas : - +Vérifier que le flag roté est bien cuit dans le dump : ```bash -# Vérifier que le serveur HTTP tourne dans le conteneur -docker exec ps aux | grep http.server +sudo docker run --rm --entrypoint python3 rootmeup/bt2-memory-forensics:1.0 \ + vol_analyzer.py -f memory.dmp windows.strings --pid 6847 | grep -i FLAG= ``` -## 9) Accès terminal admin (debug) +## 4) Configuration CTFd + +Identifiants SSH de la boîte : **`analyst` / `forensics`** (dans l'énoncé joueur). + +**Challenge « point d'entrée » (type `container`)** — porte le bouton *Start Instance* : +- **Type** : `container` +- **Image** : `rootmeup/bt2-memory-forensics:1.0` +- **Port** : `22` +- **Connection Info** *(obligatoire, sinon pas de bouton)* : + `Connectez-vous : ssh analyst@100.118.132.76 -p [port instance] (mot de passe : forensics)` +- **Flag** : le PID → `6847` (Static, case sensitive) + +**Série de flags** (catégorie `Blue Team — Memory Forensics`), les suivants en type `standard` : + +| Flag | Question | Réponse | +|---|---|---| +| 1 (container) | PID du processus malveillant | `6847` | +| 2 (standard) | Nom de l'exécutable | `svchost_update.exe` | +| 3 (standard) | IP du serveur C2 | `185.141.27.83` | +| 4 (standard) | Domaine du C2 | `c2.darkops-syndicate.net` | +| 5 (standard) | Port du C2 | `4444` | +| 6 (standard) | Flag final | valeur de `challenge.env` (`blue{...}`) | + +## 5) Séquence de validation + +1. Laisser en `Hidden`. +2. *Start Instance* avec un compte de test → récupérer l'adresse/port. +3. `ssh analyst@ -p ` (mdp `forensics`) → le shell doit s'ouvrir sur le home + avec `memory.dmp` et les outils. +4. Lancer `python3 vol_analyzer.py -f memory.dmp windows.pslist` → doit fonctionner. +5. Soumettre les 6 réponses dans CTFd → toutes acceptées. +6. Passer en `Visible`. + +## 6) Troubleshooting + ```bash -docker exec -it bash -# Puis utiliser les outils d'analyse : -python3 tools/vol_analyzer.py -f challenge/memory.dmp windows.pslist +sudo docker ps -a # l'instance tourne ? (mapping ...->22/tcp) +sudo docker logs # erreurs sshd ? +# « Could not get port » côté plugin → vérifier que l'image a bien EXPOSE 22 (c'est le cas). ``` diff --git a/challenges/2-Blue-Team-Memory-Forensics-Jakub/docs/USER_GUIDE.md b/challenges/2-Blue-Team-Memory-Forensics-Jakub/docs/USER_GUIDE.md index 4c0e31f..1756397 100644 --- a/challenges/2-Blue-Team-Memory-Forensics-Jakub/docs/USER_GUIDE.md +++ b/challenges/2-Blue-Team-Memory-Forensics-Jakub/docs/USER_GUIDE.md @@ -5,29 +5,32 @@ Analyser un dump mémoire Windows compromis pour identifier le processus malveil ## Accès au challenge (via CTFd) -1. Connectez-vous avec votre compte joueur. -2. Ouvrez le challenge `Blue Team - Jakub - Memoire et analyse de malware (Volatility)`. -3. Cliquez sur `Start Instance` et notez l'URL d'instance fournie par CTFd. -4. Téléchargez les artefacts depuis l'URL d'instance : - ``` - http://:8000/memory.dmp - http://:8000/network_capture.pcap - http://:8000/hints.txt +Ce challenge est un **environnement d'analyse fourni** : tout est déjà installé, +tu n'as **rien à mettre en place** sur ta machine. + +1. Connecte-toi avec ton compte joueur et ouvre le challenge. +2. Clique sur **Start Instance** : CTFd t'affiche une **adresse** et un **port**. +3. Connecte-toi en **SSH** à la boîte d'analyse : + ```bash + ssh analyst@ -p + # mot de passe : forensics ``` +4. Tu arrives dans un shell où le dump et les outils sont **déjà en place** + (le message d'accueil rappelle les commandes). -## Outils d'analyse +## Outils d'analyse (déjà dans la boîte) > ⚠️ **Important** : le dump `memory.dmp` est dans un **format pédagogique dédié à ce > challenge**, pas une image mémoire brute standard. Le vrai Volatility 3 (`vol.py`) ne > sait pas le lire, et un `strings` classique ne révèle pas le flag (il est encodé). -> Utilisez l'**outil fourni dans le conteneur** : `tools/vol_analyzer.py` (un -> « mini‑Volatility » qui reproduit les commandes `windows.*` sur ce format). +> Utilise l'outil fourni : **`vol_analyzer.py`** (un « mini‑Volatility » qui reproduit +> les commandes `windows.*` sur ce format). -Depuis le terminal du challenge (ou après avoir récupéré les fichiers du dépôt) : +Dans ton home (`~`) : ```bash # Syntaxe générale -python3 tools/vol_analyzer.py -f challenge/memory.dmp +python3 vol_analyzer.py -f memory.dmp # Commandes disponibles : # windows.info windows.pslist windows.pstree windows.netscan @@ -35,13 +38,14 @@ python3 tools/vol_analyzer.py -f challenge/memory.dmp # windows.strings windows.registry ``` -Outils complémentaires : -- **`tools/extract_strings.py`** — extraction/décodage des chaînes du binaire extrait. -- **Wireshark / `tshark`** — analyse du PCAP réseau (`network_capture.pcap`) pour l'étape bonus. +Fichiers et outils complémentaires : +- **`memory.dmp`** — le dump à analyser · **`network_capture.pcap`** — capture réseau (bonus) · **`hints.txt`** — indices. +- **`extract_strings.py`** — extraction/décodage des chaînes. +- **`check_flag.py`** — auto-vérification hors ligne de tes réponses (optionnel). ## Piste de résolution -Toutes les commandes ci-dessous se lancent via `python3 tools/vol_analyzer.py -f challenge/memory.dmp `. +Toutes les commandes ci-dessous se lancent via `python3 vol_analyzer.py -f memory.dmp `, **dans la boîte SSH**. 1. `windows.pslist` / `windows.pstree` — cherchez un nom ou une hiérarchie suspecte. 2. Identifiez le processus suspect en regardant son PPID et sa session. @@ -54,7 +58,7 @@ Toutes les commandes ci-dessous se lancent via `python3 tools/vol_analyzer.py -f `blue{...}` ## Soumission -Soumettez le flag final dans CTFd depuis la page du challenge. +Soumets tes réponses dans CTFd (série de flags : PID, exécutable, IP/domaine/port du C2, flag final). ## Indices -Si vous êtes bloqué, consultez `hints.txt` téléchargé depuis l'instance. +Si tu es bloqué, consulte `hints.txt` (dans ton home sur la boîte SSH). diff --git a/challenges/2-Blue-Team-Memory-Forensics-Jakub/mission.txt b/challenges/2-Blue-Team-Memory-Forensics-Jakub/mission.txt new file mode 100644 index 0000000..e7cb8ae --- /dev/null +++ b/challenges/2-Blue-Team-Memory-Forensics-Jakub/mission.txt @@ -0,0 +1,30 @@ +======================================================================== + BLUE TEAM CTF — Mémoire & Analyse de Malware +======================================================================== + +Contexte : la machine Windows DESKTOP-F4K3LAB a été compromise. Un dump +mémoire a été capturé avant son isolation. Un implant en mémoire communique +avec un serveur C2. À toi d'analyser le dump et de répondre aux questions. + +Fichiers (dans ton dossier ~) : + memory.dmp le dump mémoire à analyser + network_capture.pcap capture réseau (bonus) + hints.txt indices si tu es bloqué + +Outils (déjà installés ici) : + python3 vol_analyzer.py -f memory.dmp + commandes : windows.info | pslist | pstree | netscan | malfind | + dlllist | handles | dumpfiles | strings | registry + python3 extract_strings.py + +Commence par : + python3 vol_analyzer.py -f memory.dmp windows.pslist + +Auto-vérification (optionnel, hors ligne) : + python3 check_flag.py + +/!\ Le dump est dans un format dédié à ce challenge : utilise vol_analyzer.py, + et non un Volatility standard. + +Soumets tes réponses dans CTFd. Bon courage. +========================================================================