Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ L'investigation préliminaire suggère que **l'attaquant a déployé un implant
## 📁 Structure du Challenge

```
Blue-Team-Memory-Forensics/
2-Blue-Team-Memory-Forensics/
├── README.md ← Vous êtes ici
├── Dockerfile ← Image du challenge
├── docker-compose.yml ← Orchestration Docker
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Blue Team Memory Forensics - Guide Admin/Deploiement

## 1) Build de l'image
Depuis `Challenge/Blue-Team-Memory-Forensics`:
Depuis `challenges/2-Blue-Team-Memory-Forensics`:

```bash
docker build -t blue-team-memory-forensics:latest .
Expand Down
60 changes: 60 additions & 0 deletions challenges/2-Blue-Team-Memory-Forensics/docs/USER_GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Blue Team Memory Forensics - Guide Joueur

## Objectif
Analyser un dump mémoire Windows compromis pour identifier le processus malveillant, le serveur C2 et récupérer le flag final.

## 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://<instance>:8000/memory.dmp
http://<instance>:8000/network_capture.pcap
http://<instance>:8000/hints.txt
```

## Outils d'analyse

> ⚠️ **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).

Depuis le terminal du challenge (ou après avoir récupéré les fichiers du dépôt) :

```bash
# Syntaxe générale
python3 tools/vol_analyzer.py -f challenge/memory.dmp <commande>

# Commandes disponibles :
# windows.info windows.pslist windows.pstree windows.netscan
# windows.malfind windows.dlllist windows.handles windows.dumpfiles
# 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.

## Piste de résolution

Toutes les commandes ci-dessous se lancent via `python3 tools/vol_analyzer.py -f challenge/memory.dmp <commande>`.

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.
3. `windows.netscan` — vérifiez les connexions réseau associées à ce PID.
4. `windows.malfind` — recherchez de l'injection mémoire.
5. `windows.strings --pid <PID>` (ou `tools/extract_strings.py`) — extrayez et analysez les chaînes du binaire malveillant.
6. Récupérez le flag caché dans la configuration du malware.

## Format du flag
`blue{...}`

## Soumission
Soumettez le flag final dans CTFd depuis la page du challenge.

## Indices
Si vous êtes bloqué, consultez `hints.txt` téléchargé depuis l'instance.
6 changes: 6 additions & 0 deletions challenges/3-Red-Team-Binary-Vault/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
solution/
docs/
report/
README.md
docker-compose.yml
*.md
7 changes: 7 additions & 0 deletions challenges/3-Red-Team-Binary-Vault/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Artefacts generes au build -- ne pas committer.
secret.h
flag1.txt
flag2.txt
vault
*.o
__pycache__/
33 changes: 33 additions & 0 deletions challenges/3-Red-Team-Binary-Vault/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# VAULT-9 -- Red Team 3 (reverse + exploitation binaire)
# Build : le binaire est compile sans protections modernes (no PIE,
# no stack canary) pour rendre le ret2win faisable en intermediaire.
FROM debian:12-slim

RUN apt-get update && \
apt-get install -y --no-install-recommends \
gcc libc6-dev socat python3 && \
rm -rf /var/lib/apt/lists/*

RUN useradd -m -s /usr/sbin/nologin ctf

WORKDIR /build
COPY challenge/vault.c ./vault.c
COPY setup/gen_secret.py ./gen_secret.py

# Genere secret.h + flags, compile, installe dans /challenge.
RUN python3 gen_secret.py && \
gcc -fno-stack-protector -no-pie -fno-pie -O0 -w -o vault vault.c && \
mkdir -p /challenge && \
cp vault /challenge/vault && \
cp flag1.txt flag2.txt /challenge/ && \
chmod 0555 /challenge/vault && \
chmod 0444 /challenge/flag1.txt /challenge/flag2.txt && \
rm -rf /build

COPY docker-entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh

WORKDIR /challenge
EXPOSE 9003
USER ctf
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
60 changes: 60 additions & 0 deletions challenges/3-Red-Team-Binary-Vault/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# 🔴 Red Team 3 — VAULT-9 (Reverse & Exploitation binaire)

### Challenge Jakub — niveau intermédiaire

Premier challenge de **pwn** de la plateforme RootMeUp : un binaire Linux à
rétro-ingénier puis à exploiter. Conçu pour combler l'écart entre les Blue Team
(accessibles) et les Red Team 1 & 2 (Linux/web).

## 📌 Documentation

- Guide joueur : [`docs/USER_GUIDE.md`](docs/USER_GUIDE.md)
- Guide admin / déploiement : [`docs/ADMIN_DEPLOYMENT.md`](docs/ADMIN_DEPLOYMENT.md)
- Solution (⚠️ spoilers) : [`solution/SOLUTION.md`](solution/SOLUTION.md)

## 🎯 Résumé

| | |
|---|---|
| Catégorie | Red Team — Reverse + Exploitation binaire |
| Difficulté | Intermédiaire |
| Flags | 2 (progressifs) |
| Accès | `nc <ip> <port>` (instance Docker par équipe) |
| Compétences | reverse (XOR), débordement de tampon, ret2win, pwntools |

## 🧩 Déroulé

1. **Reverse** — la console vérifie une licence obfusquée en XOR (`check_license`). Le joueur récupère la clé → **flag 1**.
2. **Exploitation** — le terminal de maintenance déborde `buf[64]` (lecture de 200 octets). Le joueur détourne l'exécution (`ret2win`) vers la fonction cachée `vault()` → **flag 2**.

## 📁 Structure

```
3-Red-Team-Binary-Vault/
├── README.md
├── Dockerfile ← build + service socat (port 9003)
├── docker-compose.yml ← test local
├── docker-entrypoint.sh
├── challenge/
│ └── vault.c ← source du binaire (sans secret en clair)
├── setup/
│ └── gen_secret.py ← génère secret.h + flags au build (⚠️ spoiler)
├── docs/
│ ├── USER_GUIDE.md
│ └── ADMIN_DEPLOYMENT.md
├── solution/
│ ├── SOLUTION.md ← ⚠️ spoilers
│ └── exploit.py ← exploit pwntools (testé)
└── report/
└── report_template.md
```

## ⚙️ Build rapide

```bash
docker compose up --build -d # écoute sur 9003
nc 127.0.0.1 9003
docker compose down
```

> Artefacts générés (`secret.h`, `flag*.txt`, `vault`) : ignorés par git, jamais committés.
98 changes: 98 additions & 0 deletions challenges/3-Red-Team-Binary-Vault/challenge/vault.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* VAULT-9 :: Console d'administration
* Challenge Red Team 3 (intermediaire) - RootMeUp
*
* Deux etapes :
* 1. Reverse : contourner la verification de licence (obfusquee en XOR).
* 2. Exploitation : debordement de tampon (ret2win) vers vault().
*
* secret.h est genere au build par setup/gen_secret.py : il contient
* la licence encodee en XOR (jamais le texte en clair) afin que `strings`
* sur le binaire distribue ne revele pas la solution.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "secret.h" /* LICENSE_ENC[], LICENSE_LEN, XOR_KEY */

char flag1[128];
char flag2[128];

static void load_flag(const char *path, char *dst, size_t n)
{
int fd = open(path, O_RDONLY);
if (fd < 0) { strncpy(dst, "FLAG_MANQUANT", n); dst[n - 1] = 0; return; }
ssize_t r = read(fd, dst, n - 1);
if (r < 0) r = 0;
dst[r] = 0;
char *nl = strchr(dst, '\n');
if (nl) *nl = 0;
close(fd);
}

static void setup(void)
{
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
load_flag("/challenge/flag1.txt", flag1, sizeof(flag1));
load_flag("/challenge/flag2.txt", flag2, sizeof(flag2));
}

/* Etape 2 : fonction "gagnante" jamais atteinte par le flux normal. */
void vault(void)
{
puts("");
puts("[+] Coffre deverrouille -- acces au module memoire protege accorde.");
printf("[+] flag 2: %s\n", flag2);
fflush(stdout);
_exit(0);
}

/* Etape 1 : la licence attendue est stockee XORee avec XOR_KEY. */
static int check_license(const char *input)
{
if (strlen(input) != LICENSE_LEN)
return 0;
for (size_t i = 0; i < LICENSE_LEN; i++) {
if ((unsigned char)(input[i] ^ XOR_KEY) != LICENSE_ENC[i])
return 0;
}
return 1;
}

/* Debordement volontaire : read() ecrit jusqu'a 200 octets dans buf[64]. */
static void access_terminal(void)
{
char buf[64];
puts("");
puts("=== Terminal de maintenance ===");
printf("Commande > ");
read(0, buf, 200);
printf("Commande '%s' non reconnue.\n", buf);
Comment on lines +69 to +74
}

int main(void)
{
setup();

char license[128];
puts("========================================");
puts(" VAULT-9 :: Console d'administration ");
puts("========================================");
printf("Cle de licence > ");
if (!fgets(license, sizeof(license), stdin))
return 0;
license[strcspn(license, "\r\n")] = 0;

if (check_license(license)) {
puts("[+] Licence valide. Bienvenue, administrateur.");
printf("[+] Preuve d'acces (flag 1): %s\n", flag1);
access_terminal();
} else {
puts("[-] Licence invalide. Acces refuse.");
}
return 0;
}
9 changes: 9 additions & 0 deletions challenges/3-Red-Team-Binary-Vault/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Deploiement local pour tests. En production, le plugin
# CTFdDockerContainersPlugin gere l'allocation dynamique du port.
services:
vault:
build: .
container_name: rt3-vault
ports:
- "9003:9003"
restart: unless-stopped
6 changes: 6 additions & 0 deletions challenges/3-Red-Team-Binary-Vault/docker-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/sh
# Sert le binaire vulnerable : une instance par connexion TCP.
set -e
PORT="${CHALLENGE_PORT:-9003}"
echo "[*] VAULT-9 en ecoute sur le port ${PORT}"
exec socat -T120 TCP-LISTEN:"${PORT}",reuseaddr,fork EXEC:"/challenge/vault",stderr
85 changes: 85 additions & 0 deletions challenges/3-Red-Team-Binary-Vault/docs/ADMIN_DEPLOYMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Guide admin / déploiement — VAULT-9 (Red Team 3)

## Résumé technique

| Élément | Valeur |
|---|---|
| Type CTFd | Container (plugin CTFdDockerContainersPlugin) |
| Port interne | `9003` (TCP, servi par `socat`, une instance/connexion) |
| Fichier à joindre au challenge | le binaire **`vault`** (voir extraction ci-dessous) |
| Flags | 2 — voir `solution/SOLUTION.md` |
| Compilation | `-fno-stack-protector -no-pie -fno-pie -O0` |

Les secrets (licence, flags) sont générés au build par `setup/gen_secret.py` et **ne sont pas embarqués** dans le binaire (lus depuis `/challenge/flag*.txt` au runtime). `strings vault` ne révèle donc rien.

> ✅ **Validé bout-en-bout en conteneur Docker le 20/07/2026** : build OK,
> service accessible sur 9003, exploit `solution/exploit.py` récupère les 2 flags.

## Prérequis / pièges courants

- **Compose v1 vs v2** : `docker compose` (avec espace) n'existe qu'avec le plugin v2.
Sur Kali/Debian, le paquet `docker-compose` (2.40.x) fournit la commande
**`docker-compose`** (avec tiret). Si `docker compose up --build` renvoie
`unknown flag: --build`, utilisez `docker-compose` ou la méthode build/run manuelle ci-dessous.
- **Droits Docker** : si le user n'est pas dans le groupe `docker`, préfixer chaque
commande par `sudo` (sinon `permission denied ... /var/run/docker.sock`).

## Build & test local

```bash
cd challenges/3-Red-Team-Binary-Vault
docker-compose up --build -d # ou : docker compose up --build -d (plugin v2)
# le service écoute sur le port 9003
nc 127.0.0.1 9003
```

Sans Compose (marche partout) :

```bash
docker build -t rt3-vault .
docker run -d -p 9003:9003 --name rt3-vault rt3-vault
```

Test automatique de la solution :

```bash
# extraire le binaire de l'image dans solution/, puis lancer l'exploit :
docker cp rt3-vault:/challenge/vault solution/vault
cd solution && python3 exploit.py 127.0.0.1 9003
```

Arrêt :

```bash
docker compose down
```

## Extraire le binaire à distribuer

Le joueur doit télécharger le **même** binaire que celui déployé :

```bash
docker compose up --build -d
docker cp rt3-vault:/challenge/vault ./vault
docker compose down
```

Joindre `./vault` comme fichier du challenge dans CTFd. **Ne jamais** joindre `flag1.txt`, `flag2.txt` ni `secret.h`.

## Intégration CTFd (plugin conteneurs)

1. Builder l'image sur l'hôte Docker de la VM (`docker build -t rt3-vault .`).
2. Dans CTFd → challenge de type **Container** : image `rt3-vault`, port interne **9003**.
3. Renseigner les 2 flags (sensibles à la casse), en points progressifs.
4. Joindre le binaire `vault` (fichier téléchargeable).
5. Tester le **Start Instance** avec un compte non-admin (IP + port dynamique alloués par le plugin).

## Sécurité de déploiement

- Le conteneur tourne en utilisateur non privilégié `ctf`, `nologin`.
- Le binaire est volontairement vulnérable **mais confiné au conteneur** : aucun accès hôte, pas de shell exposé (le ret2win n'offre qu'un `puts` du flag, pas de RCE arbitraire).
- `socat` limite chaque session (`-T120`, timeout 120 s) pour éviter les connexions pendantes.

## Modifier les flags / la licence

Éditer `setup/gen_secret.py` (constantes `LICENSE`, `XOR_KEY`, `FLAG1`, `FLAG2`) puis rebuilder. Penser à régénérer/rejoindre le binaire et à mettre à jour les flags dans CTFd.
Loading