EVENT_03 - Writeups

Date : 26/03/2019 - 18h (slides)

Menu

crypto_0030_bienvenue


Titre : Bienvenue

Points : 30


Description


Vous êtes les bienvenus avec un petit chiffrement antique. Amusez-vous bien ! :p

CI3u_7yRSn3c4sY{v_rnePbe3y@}T1nnpl


Réalisation


CRYPTIS{b13nvenu3_3n_cryp74n@lyse} Le but de ce challenge est d’échauffer votre capacité d’analyse, une simple analyse de la structure du chiffré à partir d’un mot connu, suffit à déceler ce chiffrement.

  • Script de la scytale avec un clair et une clé donné : ```python #!/usr/bin/python3 import os, sys

clair = sys.argv[1] decalage = int(sys.argv[2]) taille = len(clair) chiffre = []

cpt1 = 0 cpt2 = 1

for i in range(taille): chiffre.append(clair[cpt1]) cpt1 += decalage if cpt1 > taille-1 : cpt1 = cpt2 cpt2 += 1

print(““.join(chiffre))


```bash
$ python scytale.py CRYPTIS{b13nvenu3_3n_cryp74n@lyse} 5
CI3u_7yRSn3c4sY{v_rnePbe3y@}T1nnpl

Résolution


Après 2 événements, on commence à connaître le début du flag CRYPTIS, on va donc procéder à une attaque par clair connu.

Une attaque à texte clair connu est un modèle d’attaque en cryptanalyse où l’attaquant possède des textes clairs ainsi que leurs versions chiffrées et est libre de les utiliser pour révéler d’autres informations secrètes comme la clé de chiffrement.

En observant le chiffré, on peut s’apercevoir que le tag CRYPTIS apparaît en effet, ainsi que les {}. Les caractères ne sont juste pas à leur place. Le flag aurait donc eu ses lettres décalées dans l’espace à l’aide d’un chiffrement antique comme la consigne le précise.

En observant d’encore plus près, l’espacement entre les lettres CRYPTIS est un interval régulier, de là, on peut penser qu’il s’agit peut-être d’un chiffrement par une Scytale.

  • Connaitre taille de clé :
    • Diviser taille du chiffré par l’écart entre 2 lettres censées être juxtaposées (C et R)
    • 34/7 = 5,…
    • Prendre la partie entière du calcul : 5

Script résolvant la scytale à partir d’une clé donnée:

#!/usr/bin/python3
import os, sys

chiffre = sys.argv[1]
cle = int(sys.argv[2])
taille = len(chiffre)
clair = []

if taille % cle == 0 :
	decalage = taille/cle
else :
	decalage = (taille/cle)+1

cpt1 = 0
cpt2 = 1

for i in range(taille):
	clair.append(chiffre[cpt1])
	cpt1 += decalage
	if cpt1 > taille-1 :
		cpt1 = cpt2
		cpt2 += 1

print("".join(clair))
$ python scytale_resolv.py CI3u_7yRSn3c4sY{v_rnePbe3y@}T1nnpl 5
CRYPTIS{b13nvenu3_3n_cryp74n@lyse}

ATTENTION : Si vous choisissez d’utiliser un site tel que www.dcode.fr, n’oubliez pas de préserver la ponctuation !

CRYPTIS{b13nvenu3_3n_cryp74n@lyse}

crypto_0100_asr


Titre : ASR

Points : 100


Description


Nous avons tous les éléments nécessaires au déchiffrement du fichier flag.txt.enc, mais nos meilleurs agents n’y parviennent pas. Pouvez-vous y jeter un coup d’oeil ?


Réalisation


Le but de ce challenge est de familiariser les participants à l’utilisation de la commande openssl sur le chiffrement asymétrique RSA. Nous fournirons alors pour ce challenge 2 clés. La clé privée (priv_key.pem) ainsi que la clé publique ( pub_key.pem). Nous mettrons le flag dans un fichier texte ( flag.txt.enc), chiffré avec la clé publique.

Cependant, pour ajouter un petit peu de difficulté à ce challenge, nous allons inverser le nom des fichiers priv_key.pem et pub_key.pem. C’est-à-dire que le fichier pub_key.pem va maintenant contenir la clé privée et priv_key.pem va contenir la clé publique.

Il nous faut maintenant créer nos 3 fichiers et réaliser l’inversion.

# générer notre priv_key.pem
$ openssl genrsa -out priv_key.pem 2048

# générer notre pub_key.pem, dérivée de priv_key.pem
$ openssl rsa -in priv_key.pem -pubout -out pub_key.pem

# créer notre fichier flag.txt
$ echo 'CRYPTIS{keys_manager_expert_<3}' > flag.txt

# chiffrer notre flag.txt en flag.txt.enc avec pub_key.pem
$ openssl rsautl -encrypt -pubin -inkey pub_key.pem -in flag.txt -out flag.txt.enc

# inverser priv_key.pem et pub_key.pem
$ mv priv_key.pem temp.pem
$ mv pub_key.pem priv_key.pem
$ mv temp.pem pub_key.pem

Pour ce challenge, nous fournirons les fichiers: priv_key.pem, public_key.pem et flag.txt.enc.


Résolution


Ce challenger nous fournit 3 fichiers: priv_key.pem, pub_key.pem et flag.txt.pem. On comprend donc rapidement que le but sera de déchiffrer flag.txt.enc afin d’obtenir le flag. Vu les noms des fichiers de ce challenge, il est question d’un chiffrement asymétrique, c’est-à-dire que, l’on utilise la clé publique afin de chiffrer et la clé privée afin de déchiffrer. Le chiffrement asymétrique le plus utilisé est RSA.

Regardons rapidement le type des fichiers que l’on nous donne, ainsi que leur contenu.

$ file priv_key.pem
priv_key.pem: ASCII text
$ cat priv_key.pem
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1QlMus9ncgT25KTZI4NW
ipUkGkR3CdrqFBSRobikF5fYLbFK9ox/07bfJBLTvlrvkC2ceERbYgnOkPYAvua2
1MwBRFTBH1yhUPnBq9jFomO9aXuuOKqAaKmXPUCps96lsXwN6W2sBwd2TwUzg7k3
e2rpC3p2M1oYmzNkp0FE6++kwFBXricbVdVsjJ/TFqAN/J/3REKHS/QACqZkFuCJ
HeEGM2CsasY1HGPKeXXk4TUYJnJ39+b/jtpu/xnhY30pFLpmaPJTifkLWLVGFUzf
zrK5JA0VS9i5yjIvi4WAUssC6grhQz0zaDZGfpwx4OivlueKxZnH4TBuQkLZThJW
GQIDAQAB
-----END PUBLIC KEY-----

################################################################

$ file pub_key.pem
pub_key.pem: PEM RSA private key
$ cat pub_key.pem
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA1QlMus9ncgT25KTZI4NWipUkGkR3CdrqFBSRobikF5fYLbFK
9ox/07bfJBLTvlrvkC2ceERbYgnOkPYAvua21MwBRFTBH1yhUPnBq9jFomO9aXuu
OKqAaKmXPUCps96lsXwN6W2sBwd2TwUzg7k3e2rpC3p2M1oYmzNkp0FE6++kwFBX
ricbVdVsjJ/TFqAN/J/3REKHS/QACqZkFuCJHeEGM2CsasY1HGPKeXXk4TUYJnJ3
9+b/jtpu/xnhY30pFLpmaPJTifkLWLVGFUzfzrK5JA0VS9i5yjIvi4WAUssC6grh
Qz0zaDZGfpwx4OivlueKxZnH4TBuQkLZThJWGQIDAQABAoIBAQC97XiW4+nZ4Uss
NTvRSXqSOrzhHkDybFVcaaocgDzrO9jjg7jNbh1YZyUxSAe3IeOKqt9g6bB/Czc6
TdgEWjSOKwLGJLm4eCDpzIE58Bzi1gE8VaPRqVCp/uhzF380eT9HqM3OWpSP/7se
YAi5Wxt30KzMKvXOeniNhZgq9Sm5HV/IIfXACC0oPucH9TCgS8Z1+d53CwlGYFEf
3yHsQnUB4JQqnN73UYJsf4MzIqnDHvL6vsyC6OVTcx7fnzA904MXutPOi9P5WQjw
KAKAikV28p2uZ6947TQlmXSCwbkznj+pWChYVLtP70uNR+4Ywl+lu33CSvdDEC89
ON0WXAQxAoGBAP7iQCUUYjySAfRRKh9lqlaOOYWMAwowV4G/tKHO35GWN0vJ/5nW
Vue2SZ6yynfh9wpR6oJrX+HRv5aM8YDxO0+MyGwNB/emwZjv0eGPHu8+k+R7eSVC
Wp5TVqZXrq5pks1EGjd1rmQ5i0+e4vWXgfZifUUdz2f4913Ms1BcQd+/AoGBANX4
IlQi6vdVlpaKGOZnj1GHQBiCWXXqg7JKhcq2v3ef9uKwh5HnfNeZTeQeadKWJ4Gv
ph/ZTWcMO2p1kPQ8wHzJn6k+UN/DruSe1CIvuJhrj6jJbs9HUiFXN2WtOxpf3zdr
i3Yv7PorluHJradU4O3sCYOedq6SXcDZxePWRsAnAoGBAPKVFwOzYMPRGrcSwIpd
Uj9K4Ygu932tALvmXt5ZbAK9+ybQu8oIa3Hg1jSKaZSrpVlXGWDDHOBppnR89CUK
cq6FiQL9bAXR2hPau+B3PLPq1QryURybCHADVUa/0OsCY8uk82axRCbzdZlz2QJx
DioXFq6/bnTASX4mosrq4281AoGAQtQWPLsPMiLsPqZxMn1D2Q3qKf2EXXzalzQJ
Z4/+ayluHc1O+nYXmusJ1ebd3GUDf9DRjP782uOKJy0DEhVrdU4v7NdGwSzIEiW9
UdQfzpNBslD/qAO5lio8Zihd3lX1TMTtMQO0+0nj/S9Van7rJcRkEFTM8qdKWvJp
iUiinl8CgYEAhbtJYGkcxCf4W7eQC2cXsRol9aL0DDwZeboPh/KqsMx4/+Qt7+5u
5cQpMzNNwalbJ3uQCKlW41A8sW+kj9Cu8ZvX6qnnbmL/x+6flACs0qTGAOTR3dAd
FVnLzIrIMwwn3poLwtf0EM3zX1dhYU/IMNnmRqoQ3mPhPBAZEth+c7M=
-----END RSA PRIVATE KEY-----

On peut en conclure que c’est bien RSA qui est utilisé dans ce challenge. Nous allons donc maintenant utiliser openssl afin de déchiffrer notre flag.txt.enc.

$ openssl rsautl -decrypt -inkey priv_key.pem -in flag.txt.enc -out flag.txt.dec
unable to load Private Key
4357084780:error:09FFF06C:PEM routines:CRYPTO_internal:no start line:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.240.1/libressl-2.6/crypto/pem/pem_lib.c:683:Expecting: ANY PRIVATE KE
#:(

Ca ne fonctionne pas, openssl n’arrive pas à charger notre priv_key.pem(unable to load Private Key). Il y a donc un problème.

En relisant un peu les fichiers priv_key.pem et pub_key.pem on s’aperçois d’un petit problème. En effet, dans pub_key.pem on peut lire BEGIN RSA PRIVATE KEY et END RSA PRIVATE KEY. C’est très étrange, car ces 2 chaînes se trouvent normalement dans le contenu d’une clé privée.

Peut-être que les contenus des 2 fichiers ont été inversés ? Essayons donc de déchiffrer avec pub_key.pem qui est peut-être notre vraie clé privée.

$ openssl rsautl -decrypt -inkey pub_key.pem -in flag.txt.enc -out flag.txt.dec
$ cat flag.txt.dec
CRYPTIS{keys_manager_expert_<3}

C’était donc bien ça, pub_key.pem est en réalité priv_key.pem. Les 2 clés ont donc été inversées.

CRYPTIS{keys_manager_expert_<3}

crypto_0100_brutus


Titre : Brutus

Points : 100


Description


Nous avons intercepté un message étrange d’un certain brutus. Aidez-nous à le décrypter !

Mb rtgokgtg fohi hi hj ingrrktmk lza xmbqb,

Uj noehsowo nwpq pq pr qvozzsbus thi suiqh,

Cr ljgakawew vexy xy xz ydwhhajca bpq mnrgkgqc,

Anmmd bgzmbd.

Réponse sous la forme : CRYPTIS{clef1_clef2_clef3}


Réalisation


Clair:

La premiere clef de ce challenge est petit,
La deuxieme clef de ce challenge est cesar,
La troisieme clef de ce challenge est optimise,
Bonne chance.

On va chercher à complexifier le chiffrement de césar. Pour se faire, il existe le chiffrement de césar progressif. Il suffit d’incrémenter la clé à chaque mot chiffré ou tous les n caractères.

Pour ce challenge, ce sera à chaque mot excepté Bonne chance qui possèdera la même clé.

Le site www.dcode.fr propose ce fameux chiffrement ainsi que son déchiffrement.

Ce qui nous donne:

Mb rtgokgtg fohi hi hj ingrrktmk lza xmbqb,
Uj noehsowo nwpq pq pr qvozzsbus thi suiqh,
Cr ljgakawew vexy xy xz ydwhhajca bpq mnrgkgqc,
Anmmd bgzmbd.

Résolution


Par culture générale ou à partir d’une simple recherche sur Internet, on devine que Brutus est le fils de César. On va donc tenter de force-brute le message chiffré.

La plateforme gchq.github.io/CyberChef/ propose un déchiffrement assez fluide étant donné qu’il est possible de passer d’une clé à l’autre très rapidement.

  • Prendre le Rot13 du site
  • Variation de la clé de déchiffrement en observant le résultat obtenu

Dès la première clé choisi, excepté 0 et un multiple de 26, on peut voir un mot en clair. Si on incrémente la clé, le mot précédant apparait en clair et ainsi de suite.

Nous devinons donc un cesar progressif à chaque mot.

Utilisation du site www.dcode.fr afin d’utiliser le déchiffrement du César progressif.

  • Texte obtenu :

Clair obtenu:

La premiere clef de ce challenge est petit,
La deuxieme clef de ce challenge est cesar,
La troisieme clef de ce challenge est optimise,
Bonne chance.

Il suffit de concaténer les clés trouvées afin d’obtenir le flag !

CRYPTIS{petit_cesar_optimise}

crypto_0100_gilbert


Titre : gilbert

Points : 100


Description


Vous allez m’aimer.. on va s’aimer !!

⠃⠇⠼⠁⠝⠙⠎⠼⠉⠉⠗⠼⠉⠞

PS : Le flag est à entrer sous la forme CRYPTIS{message}


Réalisation


Le but de ce challlenge est d’encoder un flag dans le langage braille.

Utilisons www.dcode.fr/alphabet-braille afin d’encoder le flag bl1nd_s3cr3t en braille, nous obtenons alors:

⠃⠇⠼⠁⠝⠙⠎⠼⠉⠉⠗⠼⠉⠞

Résolution


Le titre du challenge et la description nous laisseraient penser à Gilbert Montagné - On va s’aimer. La particularité de cette célébrité est qu’elle est non voyante. On pense alors au fait que les non voyants peuvent lire en utilisant ce que l’on appelle le braille.

Après une recherche pour savoir à quoi cela ressemble, on trouve une grande similitude avec notre contenu.

On utilise alors www.dcode.fr/alphabet-brailleafin afin de décoder, on obtient alors:

bl1nd_s3cr3t

CRYPTIS{bl1nd_s3cr3t}

crypto_0150_aqzwe


Titre : aqzwe

Points : 150


Description


On a trouver un message dans un vieille clé usb qui trainait :

VTUY¨OD{V°i^4tçF4v5m4t}

Réalisation


Petit challenge ou chaque lettre est remplacé par celle qui se trouve juste à droite sur un clavier azerty. Exemple : A=>Z , B=>N ….

Go to => Dcode mettre le flag et chiffrer


Résolution


petite recherche google avec crypto & azerty Go to => Dcode mettre le message et déchiffrer

CRYTPIS{C0up3r_D3c4l3r}

crypto_0150_blaise


Titre : Blaise

Points : 150


Description


Nous avons intercepté un fichier chiffré de la part de Blaise, on vous laisse vous en occuper.


Réalisation


Bonjour,
Petit chiffrement de blaise pour s'échauffer dans ce ctf de crypto.
Dêpechez vous de rentrer le flag, et je continue d'écrire pour que l'analyse statistique soit relativement simple. Vous allez bien ?
Allé, bonne chance à vous !
CRYPTIS{blaise_forever_coeur_coeur}

Utilisation du site www.dcode.fr afin de chiffrer le texte avec la clé salute et en préservant la ponctuation :

Toydhyj,
Ppnbx uhtzyvwmphm hw bwubww pzok w'wcsunjxec xtrk cp wmj ve nlrtlo.
Oyiiuhpt osms oy kiftcyk pw fwuz, il jp whrliyox h'wcccki hofl jyw l'lhtpqsp mmelidnbume dibx jewummnexygx kixjei. Nofm tpdek vbif ?
Awfx, fgnyy vlsnny t zgud !
WKCHTTM{upsidy_ysjegyk_ggefl_vswuc}

Résolution


Après avoir fait une brève recherche du titre du challenge sur Internet, nous constatons que Blaise est le prénom de Mr. Vigenère.

Nous avons le choix entre une attaque par clair connu avec le tag CRYPTIS qu’on peut remarque WKCHTTM{upsidy_ysjegyk_ggefl_vswuc}, une attaque par analyse statistique ou en calculant la taille de la clé par analyse de chaîne de caractères égales.

Les deux premières attaques peuvent être faites via le site www.dcode.fr.

  • Attaque par clair connu : le texte clair connu n’est pas assez suffisant afin d’obtenir le résultat escompté
  • Attaque par analyse statistique : Bingo ! Le site décrypte un texte totalement plausible en utilisant la clé salute :

On obtient alors le clair suivant:

BONJOURPETITCHIFFREMENTDEBLAISEPOURSECHAUFFERDANSCECTFDECRYPTODEPECHEZVOUSDERENTRERLEFLAGETJECONTINUEDECRIREPOURQUELANALYSESTATISTIQUESOITRELATIVEMENTSIMPLEVOUSALLEZBIENALLEBONNECHANCEAVOUSCRYPTISBLAISEFOREVERCOEURCOEUR

Il ne reste plus qu’à remettre la ponctuation et les minuscules à CRYPTISBLAISEFOREVERCOEURCOEUR:

CRYPTIS{blaise_forever_coeur_coeur}

crypto_0150_square


Titre : Square

Points : 150


Description


On commence à en voir partout des comme ça


Réalisation


Créer un simple QRCode qui va contenir une chaine de caractères qui correspondera au flag CRYPTIS{QRC0D3_15_4_TH1NG}. Nous allons utiliser le site: http://generator.code-qr.net/


Résolution


Il y a plusieurs manières de lire un QRCode:

  • utiliser un smartphone ou un décodeur de QRCode en ligne

  • utiliser la librairie zbar-tools avec la commande zbarimg en ligne de commande

$ zbarimg square.png
QR-Code:CRYPTIS{QRC0D3_15_4_TH1NG}

CRYPTIS{QRC0D3_15_4_TH1NG}

crypto_0200_in_the_title


Titre : in_the_title}

Points : 200


Description


Lors de nos récentes recherches, nous avons retrouvé ce fichier texte chiffré. Pouvez-vous nous aider à le déchiffrer ?


Réalisation


Le but de ce challenge est de réaliser un chiffrement par substitution. Ce dernier consiste à remplacer une lettre par une autre. Par exemple, remplacer tous les a d’un texte par des r. Ce challenge permettra aussi de présenter lors de la résolution l’outil quipqiup.com qui est souvent utilisé pour attaquer des textes chiffrés par substitution.

Voici notre texte de départ, dans lequel nous avons ajouté la première partie du flag:

# contenu à chiffrer
$ cat flag.txt
Sputnik is a spacecraft launched under the Soviet space program. Sputnik 1,2 and 3 were the official Soviet names of those objects, while the remaining designations in the series were not official names, but were names applied in the West, to objects whose original Soviet names may not have been known at the time. Now you know my story. The flag is: CRYPTIS{mayde_mayde_the_flag_is_

Présentation des fonctions importantes pour réaliser notre script de chiffrement:

>>> import string
>>> string.ascii_lowercase # alphabet miniscule
'abcdefghijklmnopqrstuvwxyz'
>>> string.ascii_uppercase # alphabet majuscule
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
# mélanger un chaine de caractères de maniére random
>>> import random
>>> chaine = 'spoutnik
>>> ''.join(random.sample(chaine, len(chaine)))
'tsnokiup'
# subsitution sur une chaine
>>> chaine = 'bonjour tout le monde'
>>> alphabet_1 = 'bonjurtlermd'
>>> alphabet_2 = 'abcdefghijkl'
>>> transposition_tab = str.maketrans(alphabet_1, alphabet_2) # notre table de substitution
>>> chaine.translate(transposition_tab)
'abcdbej gbeg hi kbcli'
# les 'b' sont devenus des 'a'
# les 'o' sont devenus des 'b'
# les 'n' sont devenus des 'c'
# ...

Après ces quelques explications, voici notre script final de chiffrement:

#!/usr/bin/env python3

import string
import random

# on récupére le contenu du fichier
f = open('flag.txt', 'r')
data = f.read()
f.close()

charset_classic = string.ascii_lowercase + string.ascii_uppercase
#charset_random = ''.join(random.sample(charset_classic, len(charset_classic)))
charset_random = 'tuchgyabqzjvwiedxsnmorkplf' + 'tuchgyabqzjvwiedxsnmorkplf'.upper()

transposition_tab = str.maketrans(charset_classic, charset_random)

substitution_cipher = data.translate(transposition_tab)

print(substitution_cipher)

La ligne charset_random = 'tuchgyabqzjvwiedxsnmorkplf' + 'tuchgyabqzjvwiedxsnmorkplf'.upper() permet d’avoir la même substitution pour une même lettre, qu’elle soit en minuscule, ou en majuscule. On utilise un charset_random statique, car sinon, ce dernier changerait à chaque exécution du script.

$ python3 ./substitution.py > flag.txt.enc
$ cat flag.txt.enc
Ndomiqj qn t ndtcgcstym vtoicbgh oihgs mbg Nerqgm ndtcg dseastw. Ndomiqj 1,2 tih 3 kgsg mbg eyyqcqtv Nerqgm itwgn ey mbeng euzgcmn, kbqvg mbg sgwtqiqia hgnqaitmqein qi mbg ngsqgn kgsg iem eyyqcqtv itwgn, uom kgsg itwgn tddvqgh qi mbg Kgnm, me euzgcmn kbeng esqaqitv Nerqgm itwgn wtl iem btrg uggi jieki tm mbg mqwg. Iek leo jiek wl nmesl. Mbg yvta qn: CSLDMQN{wtlhg_wtlhg_mbg_yvta_qn_

On peut maintenant ajouter le flag.txt.enc au challenge. La seconde partie du flag sera le titre du challenge, c’est-à-dire in_the_title}


Résolution


Pour ce challenge, on se retrouve avec un fichier texte chiffré qui contient sûrement le flag. En effet, à la fin de celui-ci, on peut voir : SLDMQN{wtlhg_wtlhg_mbg_yvta_qn_. Cette chaîne ressemble très fortement au début du format du flag que nous recherchons : CRYPTIS{???_???_. Aussi le titre du challenge nous mène à penser que ce dernier correspond à la fin du flag.

$ cat flag.txt.enc
Ndomiqj qn t ndtcgcstym vtoicbgh oihgs mbg Nerqgm ndtcg dseastw. Ndomiqj 1,2 tih 3 kgsg mbg eyyqcqtv Nerqgm itwgn ey mbeng euzgcmn, kbqvg mbg sgwtqiqia hgnqaitmqein qi mbg ngsqgn kgsg iem eyyqcqtv itwgn, uom kgsg itwgn tddvqgh qi mbg Kgnm, me euzgcmn kbeng esqaqitv Nerqgm itwgn wtl iem btrg uggi jieki tm mbg mqwg. Iek leo jiek wl nmesl. Mbg yvta qn: CSLDMQN{wtlhg_wtlhg_mbg_yvta_qn_

On peut s’apercevoir que le chiffrement s’applique sur des lettres. Il s’agit peut-être d’un chiffrement par décalage ? Testons avec CSLDMQN qui doivent normalement correspondre à notre début de flag : CRYPTIS.

>>> ord('C') - ord('C')
0
>>> ord('S') - ord('R')
1
>>> ord('L') - ord('Y')
-13
>>> ord('D') - ord('P')
-12
>>> ord('M') - ord('T')
-7
>>> ord('Q') - ord('I')
8
>>> ord('N') - ord('S')
-5

Cette voie n’a pas l’air d’être la bonne, il n’y a pas vraiment de lien entre tous ces décalages. Il s’agit peut-être d’un chiffrement par substitution ? Utilisons l’outil quipqiup.com pour nous faire une petite idée.

Comme premier résultat, on obtient alors:

Sp?tni? is a spacecraft la?nched ?nder the So?iet space program. Sp?tni? 1,2 and 3 were the official So?iet names of those ob?ects, while the remaining designations in the series were not official names, b?t were names applied in the West, to ob?ects whose original So?iet names may not ha?e been ?nown at the time. Now yo? ?now my story. The flag is: CRYPTIS{mayde_mayde_the_flag_is_

Nous avons donc le début du flag : CRYPTIS{mayde_mayde_the_flag_is_ il ne reste plus qu’à lui concaténer le nom du challenge.

CRYPTIS{mayde_mayde_the_flag_is_in_the_title}

crypto_0200_metamorphe


Titre : Métamorphe

Points : 200


Description


Nous avons intercepté un étrange fichier, veuillez trouver son secret !


Réalisation


Voici notre texte clair de départ:

Welcome in the biggest hacker contest in France.OOooooops, you want to know the flag, don't you?Here you are. CRYPTIS{I_h0p3_y0u_did_n0t_try_t0_d3crypt_on3_by_on3_4g41n_;-)} Have fun!

Le but va être de changer la base de chaque caractère ASCII de manière aléatoire. De plus, nous allons ajouter la base8, auquel peu de personne pourrait penser aux premiers abords..

On obtient alors le contenu suivant:

0x57 0x65 0x6c 0x63 0x6f 0x6d 1100101 040 1101001 110 0x20 0164 104 101 040 98 105 0147 0147 0145 0x73 1110100 0x20 104 0141 99 0153 101 114 040 99 0157 0156 0164 0145 0163 0164 0x20 0x69 1101110 040 70 0x72 0x61 110 0x63 0145 46 1001111 1001111 1101111 111 0x6f 0157 0157 112 115 0x2c 32 0171 1101111 0165 32 119 1100001 0156 0164 0x20 116 111 040 107 0156 1101111 0167 32 116 104 0145 32 1100110 108 97 103 0x2c 100000 100 1101111 110 047 116 32 121 0x6f 0165 0x3f 72 0x65 1110010 0145 100000 0171 1101111 0165 32 0x61 1110010 101 101110 67 0x52 0x59 0120 0x54 0x49 0x53 0x7b 1001001 95 104 060 0160 51 0x5f 121 48 117 0137 1100100 105 0144 0x5f 0156 0x30 1110100 0137 0x74 1110010 0171 1011111 0164 110000 95 1100100 110011 0x63 114 1111001 0160 116 95 1101111 110 51 95 1100010 0x79 1011111 1101111 0156 110011 0x5f 52 0147 064 49 110 0x5f 073 45 051 125 0x48 1100001 0x76 0145 100000 0x66 0165 0x6e 100001

Les nombres octals seront différenciés des nombres décimaux par un 0 qui précéderont leur nombre.


Résolution


En analysant le fichier on peut reconnaître une suite de nombre en base16, en base10 ainsi qu’en binaire.

On va donc procéder à l’écriture d’un script afin de les mettre en ASCII:

#!/usr/bin/python3

f = open("ciphertext.txt","r")
rep=""
for ligne in f:
	tab=ligne.split(" ")
	for nb in tab:
		if '0x' in nb:
			rep+=chr(int(nb.lstrip("0x"),16))
			pass
		elif len(nb)==2:
			rep+=chr(int(nb))
		elif len(nb)==3 or len(nb)==4:
			rep+=chr(int(nb))
		else:
			rep+=chr(int(nb,2))
print(rep)
$ python resolv.py ciphertext.txt 
Welcome(in �he(bi���st h�c�er(c������ in(Franc�.OOooo��ps, �o� wa�� to(k�o� th� flag, don/t yo�?Her� �o� are.CRYxTIS{I_h<�3_y0u�di�_�0t�tr�_�0_d3cry�t_on3_by_o�3_4�@1n_I-3}Hav� f�n!

Le résultat obtenu n’est pas celui escompté mais nous pouvons voir que nous sommes sur la bonne voie. Essayons alors de deviner le flag à partir du résultat précédent.

Regardons les caractères non imprimables : ils étaient, chacun d’eux, précédés d’un 0. Nous les avons pris pour des nombres décimaux. Après une rapide recherche des tables ASCII, nous constatons que la base octale est aussi utilisée.

Modifions le code afin de tester l’hypothèse que les nombres précédés d’un 0 soient en base8.

#!/usr/bin/python3

f = open("ciphertext.txt","r")
rep=""
for ligne in f:
	tab=ligne.split(" ")
	for nb in tab:
		if '0x' in nb:
			rep+=chr(int(nb.lstrip("0x"),16))
			pass
		elif len(nb)==2:
			rep+=chr(int(nb))
		elif len(nb)==3 and nb[0]!="0":
			rep+=chr(int(nb))
		elif len(nb)==3 and nb[0]=="0" or len(nb)==4:
			rep+=chr(int(nb,8))
		else:
			rep+=chr(int(nb,2))
print(rep)
$ python resolv.py ciphertext.txt 
Welcome in the biggest hacker contest in France.OOooooops, you want to know the flag, don't you?Here you are. CRYPTIS{I_h0p3_y0u_did_n0t_try_t0_d3crypt_on3_by_on3_4g41n_;-)} Have fun!

En effet, c’était bien de la base octal ! Il ne reste plus qu’à rentrer le flag.

CRYPTIS{I_h0p3_y0u_did_n0t_try_t0_d3crypt_on3_by_on3_4g@1n_;-)}

crypto_0200_my_brain


Titre : myBrain

Points : 200


Description


What the FUCK..

++++[++++>—<]>.>-[—>+<]>—.+++++++.———.++++.———–.++++++++++.-[–>+++<]>.—-.+[++>—<]>-.–.-[—–>+<]>++.————–.—–.+++++++.-[—>+<]>–.+[->+++<]>+.++++++++.-[–>+<]>—-.-[—–>+<]>–.——-.——–.+++++++++++++.[–>+<]>–.+++[->++<]>.——-.+[–>+<]>.[->++<]>-.-[–>+<]>.>–[–>+++<]>.


Réalisation


Le but de ce challenge est de vous faire découvrir le langage de programmation exotique brainfuck. Pour encoder notre flag dans ce langage nous utiliserons https://www.dcode.fr/langage-brainfuck afin d’encoder CRYPTIS{w31rd_fuck1ng_l4ng4g3}.

++++[++++>---<]>.>-[--->+<]>---.+++++++.---------.++++.-----------.++++++++++.-[-->+++<]>.----.+[++>---<]>-.--.-[----->+<]>++.--------------.-----.+++++++.-[--->+<]>--.+[->+++<]>+.++++++++.-[-->+<]>----.-[----->+<]>--.-------.--------.+++++++++++++.[-->+<]>--.+++[->++<]>.-------.+[-->+<]>.[->++<]>-.-[-->+<]>.>--[-->+++<]>.

Résolution


Utilisation de https://www.dcode.fr/langage-brainfuck afin de décoder:

++++[++++>---<]>.>-[--->+<]>---.+++++++.---------.++++.-----------.++++++++++.-[-->+++<]>.----.+[++>---<]>-.--.-[----->+<]>++.--------------.-----.+++++++.-[--->+<]>--.+[->+++<]>+.++++++++.-[-->+<]>----.-[----->+<]>--.-------.--------.+++++++++++++.[-->+<]>--.+++[->++<]>.-------.+[-->+<]>.[->++<]>-.-[-->+<]>.>--[-->+++<]>.

On obtient alors le flag.

CRYPTIS{w31rd_fuck1ng_l4ng4g3}

crypto_0300_divina_commedia


Titre : Divina Commedia

Points : 300

Description


Que quoi ?

D'`%q"]!<}k3VDUTA@,ba<(:KlHGYh3%|B/@~=O^)Lrqpun4rqSRh.lNd*bg`&d]E[!_^@\UTx;:PtT6RKoONMFKDhHA@?>bBA:"8\};43876/Sts1*Non,+*#"!E%|dz@a}vuzs9qYun4Uk1onmlNMib(fH^]b[Z~^@\[ZSw:POTSLpPOH0FjW

Réalisation


Objectif : découvrir qu’il existe des langages exotiques. Go to => Malbolge Tools Mettre le flag et le tour est joué


Résolution

Une recherche google avec :

Divina Commedia language programmation

Et on trouve le language Malbolge

CRYPTIS{Wtf_M4lb0lg3_?}

crypto_0300_h


Titre : H

Points : 300


Description


H H H H H H H H


Réalisation


L’objectif de se challenge est d’utiliser des algorithmes de hachage. Un serveur va être dans l’attente de clients qui devront réussir un challenge afin d’obtenir le flag.

Le challenge consiste à hacher 3 chaines de caractères envoyées par le serveur en moins de 2 secondes. Les 3 chaines devront être hachées en md5 puis en sha-256 et sha1.

Voici le code du serveur qui proposera le challenge:

def serv(port):

    ma_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
    ma_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
    ma_socket.bind(('', port))
    ma_socket.listen(socket.SOMAXCONN)

    surveillance = [ma_socket]
    dic={}
    while 1:
        (evnt_entree,evnt_sortie,evnt_exception) = select.select(surveillance,[],[])
        
        for un_evenement in evnt_entree:
            if (un_evenement == ma_socket):
                try:
                    # il y a une demande de connexion
                    nouvelle_connexion, depuis = ma_socket.accept()
                    print ("Nouvelle connexion depuis ", depuis)
                
                    nouvelle_connexion.sendall(b'Bienvenue, Il faut renvoyer les deux mots de passes hasher : 1er =>md5, 2e =>sha256, 3e =>sha1\n')
                    time.sleep(1)
                    nouvelle_connexion.sendall(b'format attendu : [hash1,hash2,hash3]\n')
                    
                    def m2p():
                        return ''.join(random.choices(string.ascii_uppercase + string.digits, k=10))

                    
                    password=[m2p(),m2p(),m2p()]

                    dic[depuis[0]]=[password,time.time()]
                    nouvelle_connexion.sendall(bytes(str(password),"utf-8"))

                    surveillance.append(nouvelle_connexion)
                    continue
                except :
                    pass
                
            try:
                ligne = un_evenement.recv(1024)
                if not ligne :
                    un_evenement.close()
                    surveillance.remove(un_evenement) # le client s'est déconnecté
                else :
                    
                    hash1=hashlib.md5(dic[un_evenement.getpeername()[0]][0][0].encode()).hexdigest()
                    hash2=hashlib.sha256(dic[un_evenement.getpeername()[0]][0][1].encode()).hexdigest()
                    hash3=hashlib.sha1(dic[un_evenement.getpeername()[0]][0][2].encode()).hexdigest()
                    print(ligne.decode("utf-8","ignore"))
                    if "["+hash1+","+hash2+","+hash3+"]" == ligne.decode("utf-8","ignore") and time.time()-dic[un_evenement.getpeername()[0]][1]<2:
                        un_evenement.sendall(bytes("CRYPTIS{tr1pl3_h4sh}","utf-8"))
                        print ("A réussi => ",un_evenement.getpeername())
                    else:
                        un_evenement.sendall(bytes("Trop lent ;-) ( Faut surement scripter ...)","utf-8"))
            except Exception as e:
                print(e)
                pass

    ma_socket.close()

Résolution


Pour obtenir le flag, il faut se connecter sur le serveur et répondre au challenge en moins de 2 secondes. Pour réaliser nos hachages, nou utiliserons la librairie hashlib de python.

Voici un code permettant de réaliser la connexion, puis le hachage des 3 chaines et enfin l’envoi:

def client():
    sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
    sock.connect(("localhost",3000))
    rep=sock.recv(1024)
    print(rep)
    rep=sock.recv(1024)
    print(rep)
    rep=sock.recv(1024)
    print(rep)

    valeurs=re.findall("'(\S+)', '(\S+)', '(\S+)'",str(rep))

    hash1=hashlib.md5(valeurs[0][0].encode()).hexdigest()
    hash2=hashlib.sha256(valeurs[0][1].encode()).hexdigest()
    hash3=hashlib.sha1(valeurs[0][2].encode()).hexdigest()
    
    print(valeurs[0])
    sock.sendall(bytes(str("["+hash1+","+hash2+","+hash3+"]"),"utf-8"))
    
    rep=sock.recv(1024) # obtenir la réponse (flag)
    print(rep)
    sock.close()
    print("End client")

CRYPTIS{tr1pl3_h4sh}

crypto_0300_over26


Titre : over26

Points : 300


Description


It’s over 26 !!!!!

^mtkodn8N51N+!N!z/K1:


Réalisation


L’objectif de ce challenge est de vous faire découvrir que ROT peut dépasser 25 lorsque l’on utilise l’ensemble des caractères ASCII. On utilisera CyberChef pour encoder le flag CRYPTIS{3xt3nd3d_r0t}.

On utilisera ROT_27(CRYPTIS{3xt3nd3d_r0t}), ce qui nous donne:

^mtkodn8N51N+!N!z/K1:

Résolution


  • Cette suite de caractère nous fait penser à un chiffrement par décalage.
  • Le titre du challenge signifie “au-delà de 26” . Peut être un décalage de 27 ?

On utilisera CyberChef pour décoder ^mtkodn8N51N+!N!z/K1:

On retrouve dans les “recettes” ROT 47. On l’utilisera avec comme décalage -27.

On obtient alors le flag.

CRYPTIS{3xt3nd3d_r0t}

crypto_0300_png


Titre : PNG

Points : 300


Description


Nos meilleurs cryptographes ont réussi à déchiffrer le message et nous assure que c’est un fichier PNG. Arriverez-vous à le déchiffrer aussi ?


Réalisation


Le XOR est une méthode de chiffrement souvent utilisée en CTF, nous allons initier les participants à une des proptiétés importante de ce dernier:

 # chiffrement XOR 
 10111 # message
+10001 # clé 
 -----
 00110 # chiffré

Si nous connaissons le chiffré ainsi que la clair d’un message chiffré par un XOR. Alors il est très facile de retrouver la clé utilisée. C’est le principe de l’attaque par clair connu. Voici la propriété qui permet cela:

 # attaque par clair connu
 10111 # message
 00110 # chiffré
 -----
 10001 # clé

Prennons une image sur laquelle se trouve un flag, et appliquons un XOR sur tout sont contenu avec la clé WINDOWSW. Utilisons CyberChef en lui fournissant en input le contenu de l’image, et en choisissant XOR comme algorithme avec la clé WINDOWSW. Il suffit maintenant de récupérer le fichier qui est en output.


Résolution


Dans l’énoncé on nous affirme que le fichier est un PNG. C’est sûrement un indice. Après une petite recherche sur Google on trouve que tous les PNG ont une entête identique. C’est premier octets correspondent au magic number. Ce dernier défini le type de fichier auquel nous avons à faire.

Pour les fichiers PNG, le magic numbers est 89 50 4E 47 0D 0A 1A 0Ace qui correspond en ascii à la chaine .PNG.

Avec XOR si on connait le chiffrer et le clair alors on peut trouver la clé. Exemple :

 10111 # message
+10001 # clé 
 -----
 00110 # chiffré
----------------
 10111 # message
+00110 # chiffré
 -----
 10001 # clé

Si on XOR l’entête des PNG et l’entête de notre fichier, on retrouve la clé XOR utilisée:

 DE 19 00 03 42 5D 49 5D
+89 50 4E 47 0D 0A 1A 0A
 -----------------------
 57 49 4E 44 4F 57 53 57

Notre clé est donc 57 49 4E 44 4F 57 53 57, convertie en ascii, nous avons le clé: WINDOWSW.

Utilisons maintenant CyberChef avec en input l’image et appliquant un XOR avec la clé WINDOWSW et récupérer l’output. On obtient alors une vraie image, avec le flag à l’intérieur.

CRYPTIS{X0R_1M4G3_34SY}

crypto_0300_raptorisation


Titre : Raptorisation

Points : 300


Description


Mon dieu… Vous avez créé des raptors ?


Réalisation


# Générer notre priv_key.pem
$ openssl genrsa -out priv_key.pem 512
$ cat priv_key.pem 
-----BEGIN RSA PRIVATE KEY-----
MIIBXwIBAAJJAMLLsk/b+SO2Emjj8Ro4lt5FdLO6WHMMvWUpOIZOIiPu63BKF8/Q
jRa0aJGmFHR1mTnG5Jqv5/JZVUjHTB1/uNJM0VyyO0zQowIDAQABAkgyAw5Cxp1O
d95+I5exPbouUvLFeiBfWXP+1vh2MvU8+IhmCf9j+hFOK13x22JJ+Orwv1+iatW4
5It/qwUNMvxXS0RuItCLp7ECJQDM6VRX8SfElUbleEECmsavcGBMZOgoEBisu1OC
M7tX83puaJUCJQDzXLgl8AM5bxHxSaWaD+c9tDFiyzBbjr/tpcqEC+JMU2tqrlcC
JQCjGt8+GQD0o3YJVc05i4W3RBYC+RcqPJXHeFyieRcYjP/ZPnkCJQDVUULBTl8l
KuzJWcrk/metuJNJi925g6lMwHSBxoD4cm7HtkUCJFqWTOzCIODw7eoypcJYjm2O
/ohEsSjEXsg6Bh8mY3LunBaqiA==
-----END RSA PRIVATE KEY-----

# Générer notre pub_key.pem, dérivée de priv_key.pem
$ openssl rsa -in priv_key.pem -pubout -out pub_key.pem
$ cat pub_key.pem 
-----BEGIN PUBLIC KEY-----
MGQwDQYJKoZIhvcNAQEBBQADUwAwUAJJAMLLsk/b+SO2Emjj8Ro4lt5FdLO6WHMM
vWUpOIZOIiPu63BKF8/QjRa0aJGmFHR1mTnG5Jqv5/JZVUjHTB1/uNJM0VyyO0zQ
owIDAQAB
-----END PUBLIC KEY-----

# Créer notre fichier flag.txt
$ echo 'Bien joué ! CRYPTIS{rsa_factorisation_heavy}' > flag.txt

# Chiffrer notre flag.txt en flag.txt.enc avec pub_key.pem
$ openssl rsautl -encrypt -pubin -inkey pub_key.pem -in flag.txt -out ciphertext.txt

Pour ce challenge, nous fournirons les fichiers: public_key.pem et ciphertext.txt.


Résolution


Ce challenge nous fournit 2 fichiers: pub_key.pem et ciphertext.txt. On comprend donc rapidement que le but sera de déchiffrer flag.txt.enc afin d’obtenir le flag.

Regardons rapidement le type des fichiers que l’on nous donne, ainsi que leur contenu:

$ file pub_key.pem
pub_key.pem: ASCII text
$ cat pub_key.pem
-----BEGIN PUBLIC KEY-----
MGQwDQYJKoZIhvcNAQEBBQADUwAwUAJJAMLLsk/b+SO2Emjj8Ro4lt5FdLO6WHMM
vWUpOIZOIiPu63BKF8/QjRa0aJGmFHR1mTnG5Jqv5/JZVUjHTB1/uNJM0VyyO0zQ
owIDAQAB
-----END PUBLIC KEY-----

################################################################

$ file ciphertext.txt
ciphertext.txt: data

On peut en conclure que c’est bien RSA qui est utilisé dans ce challenge.

Nous allons donc maintenant utiliser openssl afin de voir si n est factorisable et ainsi trouver la clé privée.

# Extraction de N et e
$ openssl rsa -in pub_key.pem -pubin -text -modulus 
RSA Public-Key: (576 bit)
Modulus:
    00:c2:cb:b2:4f:db:f9:23:b6:12:68:e3:f1:1a:38:
    96:de:45:74:b3:ba:58:73:0c:bd:65:29:38:86:4e:
    22:23:ee:eb:70:4a:17:cf:d0:8d:16:b4:68:91:a6:
    14:74:75:99:39:c6:e4:9a:af:e7:f2:59:55:48:c7:
    4c:1d:7f:b8:d2:4c:d1:5c:b2:3b:4c:d0:a3
Exponent: 65537 (0x10001)
Modulus=C2CBB24FDBF923B61268E3F11A3896DE4574B3BA58730CBD652938864E2223EEEB704A17CFD08D16B46891A61474759939C6E49AAFE7F2595548C74C1D7FB8D24CD15CB23B4CD0A3
writing RSA key
-----BEGIN PUBLIC KEY-----
MGQwDQYJKoZIhvcNAQEBBQADUwAwUAJJAMLLsk/b+SO2Emjj8Ro4lt5FdLO6WHMM
vWUpOIZOIiPu63BKF8/QjRa0aJGmFHR1mTnG5Jqv5/JZVUjHTB1/uNJM0VyyO0zQ
owIDAQAB
-----END PUBLIC KEY-----

# RSA 576 bits a été factorisé en 2003!
# Nous obtenons e = 65537 et n en base 16

# Décodage en base10 de N
$ python -c "print int('C2CBB24FDBF923B61268E3F11A3896DE4574B3BA58730CBD652938864E2223EEEB704A17CFD08D16B46891A61474759939C6E49AAFE7F2595548C74C1D7FB8D24CD15CB23B4CD0A3', 16)"
188198812920607963838697239461650439807163563379417382700763356422988859715234665485319060606504743045317388011303396716199692321205734031879550656996221305168759307650257059

On peut maintenant utiliser le site factordb afin de factoriser N.

  • Calcul de p et q sur factordb
    • p = 398075086424064937397125500550386491199064362342526708406385189575946388957261768583317
    • q = 472772146107435302536223071973048224632914695302097116459852171130520711256363590397527
  • Rsatool.py : calcul de d à partir des arguments donnés et recrée, ainsi, la clef privée
$ python rsatool.py -p 398075086424064937397125500550386491199064362342526708406385189575946388957261768583317 -q 472772146107435302536223071973048224632914695302097116459852171130520711256363590397527 -n 188198812920607963838697239461650439807163563379417382700763356422988859715234665485319060606504743045317388011303396716199692321205734031879550656996221305168759307650257059 -e 65537 -o private_key.pem

Using (p, q) to initialise RSA instance

n =
c2cbb24fdbf923b61268e3f11a3896de4574b3ba58730cbd652938864e2223eeeb704a17cfd08d16
b46891a61474759939c6e49aafe7f2595548c74c1d7fb8d24cd15cb23b4cd0a3

e = 65537 (0x10001)

d =
32030e42c69d4e77de7e2397b13dba2e52f2c57a205f5973fed6f87632f53cf8886609ff63fa114e
2b5df1db6249f8eaf0bf5fa26ad5b8e48b7fab050d32fc574b446e22d08ba7b1

p =
cce95457f127c49546e57841029ac6af70604c64e8281018acbb538233bb57f37a6e6895

q =
f35cb825f003396f11f149a59a0fe73db43162cb305b8ebfeda5ca840be24c536b6aae57

Saving PEM as private_key.pem

$ cat private_key.pem 
-----BEGIN RSA PRIVATE KEY-----
MIIBXwIBAAJJAMLLsk/b+SO2Emjj8Ro4lt5FdLO6WHMMvWUpOIZOIiPu63BKF8/QjRa0aJGmFHR1
mTnG5Jqv5/JZVUjHTB1/uNJM0VyyO0zQowIDAQABAkgyAw5Cxp1Od95+I5exPbouUvLFeiBfWXP+
1vh2MvU8+IhmCf9j+hFOK13x22JJ+Orwv1+iatW45It/qwUNMvxXS0RuItCLp7ECJQDM6VRX8SfE
lUbleEECmsavcGBMZOgoEBisu1OCM7tX83puaJUCJQDzXLgl8AM5bxHxSaWaD+c9tDFiyzBbjr/t
pcqEC+JMU2tqrlcCJQCjGt8+GQD0o3YJVc05i4W3RBYC+RcqPJXHeFyieRcYjP/ZPnkCJQDVUULB
Tl8lKuzJWcrk/metuJNJi925g6lMwHSBxoD4cm7HtkUCJFqWTOzCIODw7eoypcJYjm2O/ohEsSjE
Xsg6Bh8mY3LunBaqiA==
-----END RSA PRIVATE KEY-----

Il existe une méthode de factorisation plus rapide grâce à l’outil RsaCtfTool.py:

# Le script va calculer la clé privée à partir de la clé publique
$ python RsaCtfTool/RsaCtfTool.py --publickey ./pubkey.pem --private > private_key.pem
$ cat private_key.pem
-----BEGIN RSA PRIVATE KEY-----
MIIBXwIBAAJJAMLLsk/b+SO2Emjj8Ro4lt5FdLO6WHMMvWUpOIZOIiPu63BKF8/Q
jRa0aJGmFHR1mTnG5Jqv5/JZVUjHTB1/uNJM0VyyO0zQowIDAQABAkgyAw5Cxp1O
d95+I5exPbouUvLFeiBfWXP+1vh2MvU8+IhmCf9j+hFOK13x22JJ+Orwv1+iatW4
5It/qwUNMvxXS0RuItCLp7ECJQDM6VRX8SfElUbleEECmsavcGBMZOgoEBisu1OC
M7tX83puaJUCJQDzXLgl8AM5bxHxSaWaD+c9tDFiyzBbjr/tpcqEC+JMU2tqrlcC
JQCjGt8+GQD0o3YJVc05i4W3RBYC+RcqPJXHeFyieRcYjP/ZPnkCJQDVUULBTl8l
KuzJWcrk/metuJNJi925g6lMwHSBxoD4cm7HtkUCJFqWTOzCIODw7eoypcJYjm2O
/ohEsSjEXsg6Bh8mY3LunBaqiA==
-----END RSA PRIVATE KEY-----

# Déchiffrement
$ openssl rsautl -decrypt -in ciphertext.txt -out plaintext.txt -inkey private_key.pem
$ cat plaintext.txt
Bien joué ! CRYPTIS{rsa_factorisation_heavy}

De plus, si obtenir la clé privée ne vous intéresse pas, que vous souhaitez seulement obtenir le texte clair, vous pouvez directement implémenter cette commande.

Bien sûr, elle ne marche que si la factorisation de la clé publique est réussie.

# Le script calcule la clé privée et l'applique sur le texte chiffré
$ python RsaCtfTool.py --publickey ./pub_key.pem --uncipherfile ./ciphertext.txt 
[+] Clear text : ��')�2�A�zdX���|�fH�MBien joué ! CRYPTIS{rsa_factorisation_heavy}

CRYPTIS{rsa_factorisation_heavy}

crypto_0400_boing


Titre : Boing

Points : 400


Description


Bon courage!


Réalisation


L’objectif de ce challenge est de montrer que le changement de base n’est pas un moyen de hachage. Pour cela, nous allons utiliser trois bases : la base32, base64 et la base85.

#!/usr/bin/env python3

def chiffrement():
    flag="CRYPTIS{B4s3_1s_n0t_s3cur3}"
    def encode(msg): # on encode avec une base choisis en random
        msg=msg.encode('utf-8')
        i=random.randint(0,3)
        if i==0:
            msg=base64.b85encode(msg)
        elif i==1:
            msg=base64.b64encode(msg)
        elif i==2:
            msg=base64.b32encode(msg)
        return msg.decode('utf-8')

    msg=flag
    for i in range(0,47): # on va encoder 47 fois 
        msg=encode(msg)

    msg=base64.b32encode(msg.encode('utf-8')).decode('utf-8') # et puis une fois en base 32
    msg=base64.b85encode(msg.encode('utf-8')).decode('utf-8') # une autre fois en base 85
    msg=base64.b64encode(msg.encode('utf-8')).decode('utf-8') # et pour finir par la base 64

    return msg

chiffrement()

Résolution


Lorsque que l’on décode la base64 on a encore un string (énorme) et qui ressemble à de la base64, mais ça n’en n’est pas, car il y a des caractères qui ne font pas partit de la base64:

“OGQ;xK~zFXOGZ;hOBhOOG->tGBiX+OGQjPf$ZdOGQ*jO

Par exemple, le caractère { n’en fait pas parti. Après un peu de recherche on apprend l’existance de la base85 qui parait être intéressante. Mais lorsque l’on décode une seconde fois, on se retrouve avec une nouvelle base : la base32.

Maintenant, il nous reste plus qu’à identifier quel type de base est utilisée dans le message et de décoder tant que nous n’avons pas le flag.

#!/usr/bin/env python3

# Alphabet b85
# 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcedfghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~

# Alphabet b64
# 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcedfghijklmnopqrstuvwxyz+/=

# Alphabet b32
# ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=

def dechiffrement():
    def decode(message):
        b85=False
        for c in "!#$%&()*-;<>?@^_`{|}~":
            if c in str(message):
                b85=True
                break
        if b85:#b85
            print("b85")
            message=base64.b85decode(message)
        else:
            b64=False
            for c in "abcedfghijklmnopqrstuvwxyz+/":
                if c in str(message):
                    b64=True
                    break;
            if b64:#b64
                print("b64")
                message=base64.b64decode(message)
            else:#b32
                print("b32")
                message=base64.b32decode(message)
        return message.decode('utf-8')

    f=open("cipher","r")
    msg=f.read().rstrip("\n").encode('utf-8')
    while "CRYPTIS" not in str(msg):
        msg=decode(msg)
    return msg

CRYPTIS{B4s3_1s_n0t_s3cur3}

crypto_0400_brutor


Titre : Brutor

Points : 400


Description


Deux cent cinquante-six


Réalisation


Le but de ce challenge est d’initier les participants à l’attaque par dictionnaire. On chiffre un fichier contenant le flag. La commande openssl permet de chiffrer un fichier. En l’occurence, on va chercher à chiffrer en utilisant l’algorithme AES-256-CBC:

$ openssl enc -e -aes-256-cbc -in fichier -out advanced_encrypt -pass pass:pineapple
# -enc -e -aes-256-cbc: chiffrement souhaité
# -in fichier: fichier à chiffrer
# -out advanced_encrypt: fichier de sortie (chiffré)
# -pass pass:pineapple:  chiffrer avec le mot de passe "pineapple"

On obtient alors le fichier advanced_encrypt encodé avec AES-256-CBC et le mot de passe pineapple.


Résolution


On obtient un fichier. On veut vérifier son type avec la commande file:

$ file advanced_encrypt
openssl enc'd data with salted password

Avec l’indication advanced_encrypt et le fait qu’il s’agisse d’un encodage avec openssl, on déduit depuis la description qu’il doit probablement s’agir d’un chiffrement AES-256-CBC.

On décide de faire un script python pour brute-force le mot de passe à l’aide de la wordlist rockyou.txt qui contient une grande liste de mot de passe (ceux les plus utilisés comme azerty ou 123456). Cette wordlist nous permettra d’essayer cette multitude de mot de passe.

# coding: utf-8
import subprocess

password = ""
stop = False

f = open("rockyou.txt","rb") 		# On ouvre rockyou.txt
for l in f: 										# Pour chaque mot dans rockyou
	if stop : 										# Si stop == True
		break 											# On arrête la boucle
	try:
    # On crée la commande pour décoder le fichier advanced_encrypt avec le mot de passe sélectionné 
    # On rajoute decode("utf-8") parce que la lecture est en binaire
    # Et on rajotue .rstrip("\n") pour supprimer le retour à la ligne après l
		bashCommand = "openssl enc -d -aes-256-cbc -in advanced_encrypt -out fichier -pass pass:"+l.decode("utf-8").rstrip("\n") 
    # On exécute la commande
		process = subprocess.Popen(bashCommand.split(), stdout=subprocess.PIPE,stderr=subprocess.PIPE)
		output, error = process.communicate()
    # On ouvre le fichier résultant de la commande
		d = open("fichier","r")
    # Pour chaque ligne dans le fichier
		for k in d :
      # Si on trouve le début du flag CRYPTIS
			if "CRYPTIS" in k :
        # On l'affiche et on met stop = True pour arrêter le programme
				print(k)
				stop = True
	except:
    # En cas d'erreur on continue simplement l'exécution du programme
		continue

CRYPTIS{435_15_345Y}

crypto_0400_rsa_server


Titre : RSA server

Points : 400


Description


Connectez-vous sur nc 10.10.10.10 6688, et répondez à toutes les questions afin d’obtenir le graal :)


Réalisation


Le but de ce challenge est d’améliorer la compréhension de l’algorithme RSA. Ce challenge sera composé d’un serveur avec lequel il faudra discuter afin d’obtenir le flag. Cette discussion sera sous la forme de questions/réponses. Le but étant d’avoir toutes les bonnes réponses afin d’arriver sur la dernière question qui va indiquer comment avoir le flag. Les questions porteront sur des principes clés de RSA (sans jeu de mots): nombre premier, calculs de produits, ou d’inverse,….

Voici le code du serveur avec lequel il faudra discuter afin d’obtenir le flag. Il est composé de plusieurs questions, par exemple, on donne p et q, pour commencer il faudra dire si oui ou non les valeurs sont possibles, c’est-à-dire si pet qsont des nombres premiers.

#!/usr/bin/env python3

### Question 1 ###
q1_p = b'p=28423083049\n\n' # prime
q1_q = b'q=28423083050\n\n' # not prime

q1_poss = b'no\n'

### Question 2 ###
q2_p = b'p=94603\n\n' # prime
q2_q = b'q=93187\n\n' # prime

q2_poss = b'yes\n'
q2_n = b'8815769761\n'

### Question 3 ###
q3_p = b'p=81203\n\n' # prime
q3_n = b'n=6315400919\n\n'

q3_poss = b'yes\n'
q3_q = b'77773\n'

### Question 4 ###
q4_p = b'p=97846775312392801037224396977012615848433199640105786119757047098757998273009741128821931277074555731813289423891389911801250326299324018557072727051765547115514791337578758859803890173153277252326496062476389498019821358465433398338364421624871010292162533041884897182597065662521825095949253625730631876637\n\n' # prime
q4_q = b'q=92092076805892533739724722602668675840671093008520241548191914215399824020372076186460768206814914423802230398410980218741906960527104568970225804374404612617736579286959865287226538692911376507934256844456333236362669879347073756238894784951597211105734179388300051579994253565459304743059533646753003894560\n\n' # not prime

q4_poss = b'no\n'

### Question 5 ###
q5_p = b'p=97846775312392801037224396977012615848433199640105786119757047098757998273009741128821931277074555731813289423891389911801250326299324018557072727051765547115514791337578758859803890173153277252326496062476389498019821358465433398338364421624871010292162533041884897182597065662521825095949253625730631876637\n\n' # prime
q5_q = b'q=92092076805892533739724722602668675840671093008520241548191914215399824020372076186460768206814914423802230398410980218741906960527104568970225804374404612617736579286959865287226538692911376507934256844456333236362669879347073756238894784951597211105734179388300051579994253565459304743059533646753003894559\n\n' # prime

q5_poss = b'yes\n'
q5_n = b'9010912747277787249738727439840427055736519196538871349093408340706668231808840540195374015916168031416186859836416053338250477003776576736854137538279810042409758765948034443613881324504120707334213544491046703922409406729564516371394804946909037646047891880347940067132730874804943893719672960932378043325067514786209219718314429979032869544980643978919561908707109629612202311323626173343456843249212057093980583352634168733656443959925428846968193413110401346035535595817965624054783296380268863401241570313602685481219583686719199499297832165308522137209299081956650614940546284136240753995440003473611843518083\n'

### Question 6 ###
q6_p = b'p=97846775312392801037224396977012615848433199640105786119757047098757998273009741128821931277074555731813289423891389911801250326299324018557072727051765547115514791337578758859803890173153277252326496062476389498019821358465433398338364421624871010292162533041884897182597065662521825095949253625730631876637\n\n'
q6_q = b'q=92092076805892533739724722602668675840671093008520241548191914215399824020372076186460768206814914423802230398410980218741906960527104568970225804374404612617736579286959865287226538692911376507934256844456333236362669879347073756238894784951597211105734179388300051579994253565459304743059533646753003894559\n\n'
q6_e = b'e=65537\n\n'

q6_poss = b'yes\n'
q6_d = b'1405046269503207469140791548403639533127416416214210694972085079171787580463776820425965898174272870486015739516125786182821637006600742140682552321645503743280670839819078749092730110549881891271317396450158021688253989767145578723458252769465545504142139663476747479225923933192421405464414574786272963741656223941750084051228611576708609346787101088759062724389874160693008783334605903142528824559223515203978707969795087506678894006628296743079886244349469131831225757926844843554897638786146036869572653204735650843186722732736888918789379054050122205253165705085538743651258400390580971043144644984654914856729\n'

### Question 7 ###
q7_p = b'p=97846775312392801037224396977012615848433199640105786119757047098757998273009741128821931277074555731813289423891389911801250326299324018557072727051765547115514791337578758859803890173153277252326496062476389498019821358465433398338364421624871010292162533041884897182597065662521825095949253625730631876637\n\n'
q7_n = b'n=9010912747277787249738727439840427055736519196538871349093408340706668231808840540195374015916168031416186859836416053338250477003776576736854137538279810042409758765948034443613881324504120707334213544491046703922409406729564516371394804946909037646047891880347940067132730874804943893719672960932378043325067514786209219718314429979032869544980643978919561908707109629612202311323626173343456843249212057093980583352634168733656443959925428846968193413110401346035535595817965624054783296380268863401241570313602685481219583686719199499297832165308522137209299081956650614940546284136240753995440003473611843518083\n\n'
q7_e = b'e=65537\n\n'
q7_cipher = b'cipher=8434260773219247080449092258807570659425382119782765782445135163671240539934208578183717702012873111940818345280035950268637501669888888931702482678416634136676477907871501325631573372152841674165213077625100917976146135244213652745342091597478784514048600307936993232027723622225090781657348745776499453911361208412550372382043915409846147359322099140077294278092862410546772717584674453672517524114847220496777052809936576362799231364786071356281525928955850130890663335120948203155635358201934527397238590124239967992629439400267802801057019391725930869029713104527166774276057070627903454133576283846132724013518\n\n'

q7_poss = b'yes\n'
q7_plaintext = b'561711819220594430501559128455193300454533528677678378623972820270701707964868669587814742047101\n'

bad = b'\nBad answer :( Let\'s retry\n'

import socket, os, sys

access_mask = '' # filtre les clients, ici aucun n'est filtre
server_port = 6688

my_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)

# be able to re-use the port faslty
my_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

my_sock.bind((access_mask, server_port))

# configure the queue
my_sock.listen(socket.SOMAXCONN)

def treate_client(pid, cli_sock, tsap_cli):
    print ("New connection from: ", tsap_cli)
    try:
        # q1
        cli_sock.send(b'\n########## Question 1 ##########\n')
        cli_sock.send(q1_p)
        cli_sock.send(q1_q)
        cli_sock.send(b'Is it possible ? (yes/no) -> ')
        if cli_sock.recv(1024) != q1_poss:
            cli_sock.send(bad)
            exit(1)

        # q2
        cli_sock.send(b'\n########## Question 2 ##########\n')
        cli_sock.send(q2_p)
        cli_sock.send(q2_q)
        cli_sock.send(b'Is it possible ? (yes/no) -> ')
        if cli_sock.recv(1024) != q2_poss:
            cli_sock.send(bad)
            exit(1)
        cli_sock.send(b'Value of \'n\' ? -> ')
        if cli_sock.recv(1024) != q2_n:
            cli_sock.send(bad)
            exit(1)

        # q3
        cli_sock.send(b'\n########## Question 3 ##########\n')
        cli_sock.send(q3_p)
        cli_sock.send(q3_n)
        cli_sock.send(b'Is it possible ? (yes/no) -> ')
        if cli_sock.recv(1024) != q3_poss:
            cli_sock.send(bad)
            exit(1)
        cli_sock.send(b'Value of \'q\' ? -> ')
        if cli_sock.recv(1024) != q3_q:
            cli_sock.send(bad)
            exit(1)

        # q4
        cli_sock.send(b'\n########## Question 4 ##########\n')
        cli_sock.send(q4_p)
        cli_sock.send(q4_q)
        cli_sock.send(b'Is it possible ? (yes/no) -> ')
        if cli_sock.recv(1024) != q4_poss:
            cli_sock.send(bad)
            exit(1)

        # q5
        cli_sock.send(b'\n########## Question 5 ##########\n')
        cli_sock.send(q5_p)
        cli_sock.send(q5_q)
        cli_sock.send(b'Is it possible ? (yes/no) -> ')
        if cli_sock.recv(1024) != q5_poss:
            cli_sock.send(bad)
            exit(1)
        cli_sock.send(b'Value of \'n\' ? -> ')
        if cli_sock.recv(1024) != q5_n:
            cli_sock.send(bad)
            exit(1)

        # q6
        cli_sock.send(b'\n########## Question 6 ##########\n')
        cli_sock.send(q6_p)
        cli_sock.send(q6_q)
        cli_sock.send(q6_e)
        cli_sock.send(b'Is it possible ? (yes/no) -> ')
        if cli_sock.recv(1024) != q6_poss:
            cli_sock.send(bad)
            exit(1)
        cli_sock.send(b'Value of \'d\' ? -> ')
        if cli_sock.recv(1024) != q6_d:
            cli_sock.send(bad)
            exit(1)
        
        # q7
        cli_sock.send(b'\n########## Question 7 ##########\n')
        cli_sock.send(q7_p)
        cli_sock.send(q7_n)
        cli_sock.send(q7_e)
        cli_sock.send(q7_cipher)
        cli_sock.send(b'Is it possible ? (yes/no) -> ')
        if cli_sock.recv(1024) != q7_poss:
            cli_sock.send(bad)
            exit(1)
        cli_sock.send(b'Send the value of \'plaintext\' ? -> ')
        if cli_sock.recv(1024) != q7_plaintext:
            cli_sock.send(bad)
            exit(1)
        
        cli_sock.send(b'\n########## Congratulation ##########\n')
        cli_sock.send(b'Convert the plaintext to hex, then to ascii to get the flag :)')
        
        print ("Flag found by: ", tsap_cli)
    except (ConnectionResetError, BrokenPipeError):
        pass
    finally:
        print('Deconnection from: ', tsap_cli)
        cli_sock.close()


def main():
    while 1:
        (cli_sock, tsap_cli) = my_sock.accept()
        pid = os.fork()
        if not pid:
            treate_client(pid, cli_sock, tsap_cli)
    my_sock.close()

main()


Résolution


En se connectant avec netcatavec sur 10.10.10.10sur le port 6688 on obtient ce message:

$ nc 10.10.10.10 6688

########## Question 1 ##########
p=28423083049

q=28423083050

Is it possible ? (yes/no) -> 

On doit répondre par yes ou no à la question posée. Pour cela, on va utiliser le code python suivant qui fait toutes les étapes de RSA facilement:

#!/usr/bin/env python3
from Crypto.Util.number import inverse

### encrypt with public key (n=3233,e=17)
message = 97
p = 61 # secret
q = 53 # secret

n = p*q
phi = (p-1)*(q-1)
e = 17

ciphertext = pow(message, e, n) # 2790

### decrypt
p = 61
n = 3233
e = 17
ciphertext = 1632

q = n//p
phi = (p-1)*(q-1)
d = inverse(e, phi)
message = pow(ciphertext, d, n)

Pour la premiére question, il faut s’assurer tout d’abord que pet qsont des nombres premiers. Pour cela, on peut utiliser http://factordb.com/. On apprend que ces derniers ne sont donc pas premiers car ils ont des diviseurs en plus de 1 et eux-mêmes. Il faut donc répondre no à cette première question.

Question suivante:

$ nc 127.0.0.1 6688

########## Question 1 ##########
p=28423083049

q=28423083050

It is possible ? (yes/no) -> no

########## Question 2 ##########
p=94603

q=93187

It is possible ? (yes/no) ->

On a de nouvelles valeurs pour pet q, ces derniers sont bien premiers, il faudra donc répondre yes.

########## Question 2 ##########
p=94603

q=93187

It is possible ? (yes/no) -> yes
Value of 'n' ? ->

Cette fois il faudra renvoyer la valeur de n qui est le produit de pet q. On va directement utiliser l’interpréteur python, pour cela:

$ python3
>>> p = 94603
>>> q = 93187
>>> p * q
>>> 8815769761

Il faudra donc renvoyer 8815769761 afin de passer à la question suivante.

Les questions suivantes sont similaires…

Sur la question 7, le plaintext doit être passé en hexpuis en ascci.

$ python3
>>> import binascii
>>> plaintext = 561711819220594430501559128455193300454533528677678378623972820270701707964868669587814742047101
>>> binascii.unhexlify(hex(plaintext)[2:])
b'CRYPTIS{rsa_sp3cialist_since_26/03/2019}'
>>> # [2:] pour retirer le '0x'

CRYPTIS{rsa_sp3cialist_since_26/03/2019}

crypto_0500_inutile_v3


Titre : Inutile V3

Points : 500


Description


Il paraît que le mot de passe est en 3 parties.

Quelque chose de type : partie1_partie2_partie3


Réalisation


Utilisation de CyberChef et Dcode pour la réalisation des étapes suivantes :

  • base32 ( Pensez à boire 1,5 litres d’eau parce que déjà c’est bon pour la santé, et ensuite l’eau on adore ça, dans 20 ou 30 ans y en aura plus )
  • base32 ( base32 ( Les maths c’est nul, 2 fois 32 ça fait pas 64 ) )
  • base 64( Les maths c’est nul, 2 fois 32 ça fait pas 64 )
  • base64 ( Vous avez vu ? Ça a bien fait deux chaînes de caractères différentes. Sinon, la première partie du flag est dessous, comme 10 ou 58 sont en dessous de 64 )
  • base58 ( Maintenant qu’on en a terminé avec les BASES (mdr je suis trop drôle), voilà la première partie : CRYPTIS{ , déçu ? )

  • Binaire ( Nos experts aiment jouer au Takuzu. C’est comme le Sudoku pour les nuls. D’ailleurs nos experts sont huit dans sa tête… )
  • Octale ( Sinon Les Huit Salopards c’était un bon film… Autant que les Top 10 sur YouPub )
  • Décimal ( Félicitations, vous avez terminé la version. La fin du flag est : } . De rien. )
  • Hexadécimal ( Trop facile l’hexadécimal donc si vous avez commencé par ça… Dommage parce que la solution n’est pas ici. )

  • Cesar ( C’est assez facile le César. Si je vous dis chiffrement par substitution simple pour l’alphabet hébreux, vous pensez à quoi ? )
  • Atbash ( La solution du chiffrement en dessous c’est la réponse à la question sur la vie, l’univers, le reste. )
  • ROT 42 ( La vraie première partie du flag est : M4DN355 )

  • Brainfuck ( Du déjà vu, en plus c’était aussi mon challenge. Paraît que les Francs Maçons ont bâti Pig Ben..? Ken..? Pen..? Je ne sais plus. )
  • Pig Pen ( Il ne vous a pas manqué, il est de retour : le phoque ! )
  • Morse ( C’est vraiment un code chinois dessous. )
  • Code chinois ( La deuxième partie du flag est : M4D3 )

  • Langage des Signes ( J’ai jamais regardé Star Trek )
  • Klingon ( Sûrement mon gnomique d’esclave qui a encore dessiné sans mon accord )
  • Gnomique ( La dernière partie du flag est : TH15_CH4LL3NG3 )

Pour le Pig Pen, Code chinois, Langage des Signes, Klingon et Gnomique, le rendu a été fait sous forme d’image, mises chacune dans une archive respective protégée par un mot de passe (exception pour Langage des Signes qui n’a pas été mise dans une archive).


Résolution


Après avoir récupéré tous les fichiers, on se retrouve avec indications.txt. Lorsqu’on l’ouvre, on peut remarquer plusieurs chaînes de caractères. La première, consitutée de lettres majuscules et de lettres peut faire penser à une base32 ou base64.

Après avoir essayé la base32, on se retrouve avec

Pensez à boire 1,5 litres d’eau parce que déjà c’est bon pour la santé, et ensuite l’eau on adore ça, dans 20 ou 30 ans y en aura plus

Rien de bien utile.

La suivante est du même genre. Ce n’est ni une base32 ni une base64.

Cependant, après avoir passé une première fois une base32, on remarque qu’on se retrouve toujours avec une chaîne de caractères avec des lettres majuscules et des chiffres.

Après avoir essayé une seconde base32, on obtient:

Les maths c’est nul, 2 fois 32 ça fait pas 64

Toujours rien d’utilisable pour le flag..

La troisième chaîne est, elle, encodée dans une base64:

Les maths c’est nul, 2 fois 32 ça fait pas 64

De même pour la quatrième:

Vous avez vu ? Ça a bien fait deux chaînes de caractères différentes. Sinon, la première partie du flag est dessous, comme 10 ou 58 sont en dessous de 64

On nous parle de 10 et 58. Après quelques recherches, on découvre que la base 58 existe.

La chaîne en dessous est d’ailleurs encodée dans cette base:

Maintenant qu’on en a terminé avec les BASES ( mdr je suis trop drôle ), voilà la première partie : CRYPTIS{ , déçu ?

On tourne en rond pour le moment.. passons à la suite.

Il s’agit dans l’ordre, comme on peut le remarquer, de chaînes encodées respectivement en binaire, octal, décimal et hexadécimal. Le résultat est celui ci dessous:

- Nos experts aiment jouer au Takuzu. C’est comme le Sudoku pour les nuls. D’ailleurs nos experts sont huit dans sa tête…  )
- Sinon Les Huit Salopards c’était un bon film… Autant que les Top 10 sur YouPub
- Félicitations, vous avez terminé la version. La fin du flag est : } . De rien. 
- Trop facile l’hexadécimal donc si vous avez commencé par ça… Dommage parce que la solution n’est pas ici. 

Toujours rien.

La suite est légèrement différente.

Le début de la chaîne est:

F’hvw

Or on sait que F = E en César, et en plus ' n’est pas chiffré par César.

On tente alors au hasard de le déchiffrer avec cette méthode.

C’est assez facile le César. Si je vous dis chiffrement par substitution simple pour l’alphabet hébreux, vous pensez à quoi ?

Notre ami Google nous apprend que cette méthode de chiffrement pourrait être l’Atbash.

La phrase du dessous donne alors:

La solution du chiffrement en dessous c’est la réponse à la question sur la vie, l’univers, le reste.

Notre culture générale nous rappelle que cette réponse est 42.

Qu’apporterait 42 à un chiffrement.. Mais oui ! Un ROT !

La vraie première partie du flag est : M4DN355

Enfin !

La suite est connue : du brainfuck

Du déjà vu, en plus c’était aussi mon challenge. Paraît que les Francs Maçons ont bâti Pig Ben..? Ken..? Pen..? Je ne sais plus.

Google nous sauve encore une fois : Pig Pen.

C’est aussi le mot de passe pour unzip la première archive : PigPen

Avec Dcode on peut retrouver le message suivant

Il ne vous a pas manqué, il est de retour : le phoque !

Le phoque..? Ah mais oui.

En regardant la phrase en dessous, ça nous rappelle le morse !

C’est vraiment un code chinois dessous

Là encore, le mot de passe de l’archive 2 nous est donné : codechinois

Toujours en utilisant Dcode:

La deuxième partie du flag est : M4D3 

On touche au but !

La troisième archive n’était pas protégée par un mot de passe.

En y regardant de plus près on retrouve le langage des signes français.

J’ai jamais regardé Star Trek

Le mot de passe de l’archive 4 serait Star_Trek ?

Bingo !

On se retrouve avec des signes un peu étranges.

Google, toujours présent, nous rappelle que dans Star Trek, la langue utilisée est le Klingon !

Dcode, avec sa variété de chiffrement différent, en propose le déchiffrement

Sûrement mon gnomique d’esclave qui a encore dessiné sans mon accord

En accord avec les indications.. Le mot de passe serait gnomique ?

Et oui !

La dernière phrase est donc :

La dernière partie du flag est : THIS_CHALLENGE

En replaçant I, S A et E on retrouve le flag : TH15_CH4LL3NG3

CRYPTIS{M4DN355_M4D3_TH1S_CH4LL3NG3}