Strong Daddy - 128pts
Ton pote se vante car son père est militaire dans l'armée de terre et il lui aurait soit-disant appris toutes les techniques pour pouvoir échanger des messages sans que l'ennemi ne puisse comprendre.
Il est temps de montrer à cette tête de noeud qu'il n'est pas aussi fort qu'il le prétend
Papa Alpha Papa Alpha
Hotel Oscar Tango Echo Lima
Alpha Lima Papa Hotel Alpha
Charlie Hotel Alpha Romeo Lima India Echo
Kilo India Lima Oscar
Alpha Charlie Charlie Oscar Lima Alpha Delta Echo Golf Alpha Uniform Charlie Hotel Echo
Whisky Hotel India Sierra Kilo Yankee
Tango Hotel Romeo Echo Echo
India November Delta India Alpha
Romeo Oscar Mike Echo Oscar
Delta Echo Lima Tango Alpha
Tango Hotel Romeo Echo Echo
Sierra India Echo Romeo Romeo Alpha
Tango Alpha November Golf Oscar
Uniform November Delta Echo Romeo Sierra Charlie Oscar Romeo Echo
Foxtrot India Victor Echo
Tango Alpha November Golf Oscar
Tango Hotel Romeo Echo Echo
Golf Oscar Lima Foxtrot
Alpha Lima Papa Hotel Alpha
November Oscar Victor Echo Mike Bravo Echo Romeo
Zulu Echo Romeo Oscar
Uniform November Delta Echo Romeo Sierra Charlie Oscar Romeo Echo
Tango Hotel Romeo Echo Echo
Victor India Charlie Tango Oscar Romeo
Tango Hotel Romeo Echo Echo
Romeo Oscar Mike Echo Oscar
Alpha Charlie Charlie Oscar Lima Alpha Delta Echo Delta Romeo Oscar India Tango Echo
Tout ça ressemble beaucoup à un message radio où on utilise un mot au lieu d'épeler chaque lettre pour être sur de la bonne récéption. Un petit tour sur Wikipédia nous en apprend un peu plus.
On se rend compte ici que récupérer uniquement les lettres majuscules à l'air d'être suffisant pour récupérer un message un peu plus lisible. On voit notamment que les premières lettres des 5 lignes forment le mot PHACK, ça semble être une bonne piste. On met tout ça dans un fichier input.txt
et un petit coup de la commande sed va nous permettre de se débarasser des minuscules et des espaces.
$ cat input.txt | sed 's/[a-z ]//g'
PAPA
HOTEL
ALPHA
CHARLIE
KILO
ACCOLADEGAUCHE
WHISKY
THREE
INDIA
ROMEO
DELTA
THREE
SIERRA
TANGO
UNDERSCORE
FIVE
TANGO
THREE
GOLF
ALPHA
NOVEMBER
ZERO
UNDERSCORE
THREE
VICTOR
THREE
ROMEO
ACCOLADEDROITE
On voit un pattern émerger ici, pour la plupart des mots qu'il nous reste, il suffit de récupérer leur première lettre. À l'exception des chiffres et des deux mentions ACCOLADEGAUCHE et ACCOLADEDROITE. On réécrit tout ça avec un seul caractère pour chaque ligne et on récupère un flag où je ne m'y connais pas !
PHACK{W3IRD3ST_5T3GAN0_3V3R}
Caumunikassion - 128pts
Le nouveau stagiaire en communication du P'Hack CTF nous semble étrange. Nous avons peur qu'il utilise ses compétences pour exfiltrer des informations sensibles. Il a principalement travaillé sur le site https://ctf.phack.fr.
On récupère ici le logo de l'évènement et on le passe dans https://aperisolve.fr/ pour découvrir une URL cachée dans l'image dans les données EXIF : https://pastebin.com/raw/xjyzhxYZ. Une fois le pastebin ouvert, on récupère le flag.
PHACK{e4sy_st3g4n0_rigH7?}
L'image est disponible ici : https://blog.julienmialon.com/uploads/ctf/phack/phack_white.png
Chasse aux oeufs - 128pts
Nous n'avons pas pu vous organiser une chasse aux oeufs IRL. Pour compenser nous vous laissons trouver le flag dans cette chasse aux oeufs virtuelle.
Fichier disponible ici https://blog.julienmialon.com/uploads/ctf/phack/easter-eggs.png
On se retrouve ici avec une illustration et d'après le challenge, il faut trouver les oeufs. Un petit tour dans aperi'solve ne donne rien, on se met donc à la recherche manuelle des oeufs dans l'image. Au bout de quelques minutes on a nos 14 oeufs
Après avoir vainement essayé de relier les oeufs entre eux pour voir ce que ça pouvait donner et n'avoir obtenu aucun résultat, on extrait les oeufs dans un fichier à part pour que ce soit plus clair
Et là, il y a deux choses qui saute aux yeux :
- Premièrement, chaque oeuf est d'une couleur unie
- Deuxièmement on en a tout de même plusieurs dans des tons très proche (violet, vert moche)
Souvenir d'un ancien CTF, est-ce que les codes RGB de chaque couleur pourrait être un indice ? On est parti pour extraire chaque code couleur
01 #504841
02 #434B7B
03 #5F4567
04 #676333
05 #6C6C33
06 #6E745F
07 #636834
08 #6C6C33
09 #6E6733
10 #5F3173
11 #6E2774
12 #5F6974
13 #5F3F21
14 #3F5F7D
Vu les plages de valeur en hexa, j'ai bien envie d'en faire de l'ascii pour voir ce qu'il en ressort. On met tout ça en une ligne avec un espace entre chaque doublet hexa :
50 48 41 43 4B 7B 5F 45 67 67 63 33 6C 6C 33 6E 74 5F 63 68 34 6C 6C 33 6E 67 33 5F 31 73 6E 27 74 5F 69 74 5F 3F 21 3F 5F 7D
On utilise ensuite un convertisseur en ligne https://www.rapidtables.com/convert/number/hex-to-ascii.html et on obtient le flag.
PHACK{_Eggc3ll3nt_ch4ll3ng3_1sn't_it_?!?_}
Alter Egg-o - 256pts
L'agent Smith de la HSA (Hack Secret Agency) a retiré trop rapidement la clé USB de son PC (ce n00b !!). La preuve qu'il voulait vous montrer semble corrompue.
Montrer lui que vous pouvez lui sauver la mise et récupérer ce fichier.
Fichier disponible ici https://blog.julienmialon.com/uploads/ctf/phack/altered.png
Franchement cet agent Smith il aurait pu faire attention non ? Bon, est-ce qu'on peut quand même faire quelque chose pour lui ? On tente d'ouvrir le fichier et on reçoit une belle erreur "format de fichier non pris en charge".
On tente la commande file qui pourrait nous indiquer si contrairement à son extension, ce n'était pas un fichier PNG mais autre chose :
$ file altered.png
altered.png: data
Si file ne reçonnait pas ce que c'est non plus, on sort l'artillerie lourde et on lance binwalk pour savoir ce qu'il nous trouve dans le fichier
$ binwalk altered.png
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
64 0x40 Zlib compressed data, best compression
8596 0x2194 Zlib compressed data, best compression
Des données compréssées avec Zlib, bon ça ressemble bien à un PNG cette histoire. Il est temps d'aller faire un tour avec un éditeur hexa dans ce fichier.
Et là, on voit un header de fichier qui commence par DEADBEEF
on va faire un tour du côté de la spécification des fichiers PNG http://www.libpng.org/pub/png/spec/1.2/PNG-Structure.html et on s'aperçoit que le header d'un fichier PNG est composé de 8 octets constants. Ici les 4 premiers ont été altéré. Rectifions ça.
Parfait, on ouvre maintenant notre image et tout s'affiche correctement !
On récupère le flag et on est bon !
PHACK{ju5t_ch4ng3d_a_m4gic_nUmb3R_i5_i7_b4d?}
Petite astuce ici si comme moi vous avez la flemme de recopier le flag depuis l'image : https://azure.microsoft.com/en-us/services/cognitive-services/computer-vision/#features on upload l'image sur ce lien en spécifiant l'action "Read Text" et on récupère le texte en quelques secondes.
Aliens - 256pts
Enfiiiiin!! Nous avons finalement reçu une réponse à nos signaux intergalactiques. Un son a été capté et enregistré venant de l'espace. C'est sûr ça doit vouloir dire quelque chose.
Fichier disponible ici https://blog.julienmialon.com/uploads/ctf/phack/weird.wav
On tente dans un premier temps de lire le fichier son, on entends quelque chose qui pourrait correspondre à du morse dans un premier temps puis un passage qui ne ressemble à rien avant de finir sur quelque chose qui pourrait être du morse.
On ouvre le fichier dans Audacity et on obtient la visualisation suivante
Rien ne semblait concluant à partir de là, je suis donc parti sur complétement autre chose en cherchant des informations dans les bits de poids faible où en tentant de passer le fichier en stéréo alors qu'il est en mono à la base. La solution était bien plus simple ! Il suffisait d'afficher le fichier en mode spectrogramme dans Audacity.
Et on peut lire relativement clairement le flag
PHACK{i7_s0uNds_l1k3_w3jd3n3}
Une Douce Petite Musique - 256pts
Avec vos talents de hacker vous interceptez un échange plutôt louche.
https://blog.julienmialon.com/uploads/ctf/phack/message1.eml
https://blog.julienmialon.com/uploads/ctf/phack/message2.eml
On a donc deux emails ici, commençons par les lire, le premier :
Coucou Patoche,
Ci-joint le secret qu'il te manquait pour m'envoyer un message sécurisé.
Bisous
Avec un fichier joint sous format .ods
Et le second message :
Coucou David,
Ci-joint un message super secret, personne ne va jamais trouver avec notre technique futuriste !
XOXO
--
Patricia
Avec en pièce jointe un fichier son midi. On tente de lire le fichier, un joli son de piano en sort, aucun morceau connu en tout cas. On passe notre fichier son dans https://solmire.com/miditosheetmusic/ pour récupérer la partition.
La dernière notre est la plus haute de toute la partition, c'est un La, autrement noté A dans la notation américaine, si jamais cette partition correspond à notre flag, ça matcherait avec le tableau qu'on avait au début. Bon par contre soyons clair, il est hors de question, vu le nombre de note, de décoder ça à la main. On vérifie tout de même les premières pour être sur de notre théorie, on obtient PHACK si on suppose que le sol de la clé de sol correspond au sol deuxième ligne de notre tableau.
On va charger notre fichier midi avec python et voir ce qu'il y a dedans
from mido import MidiFile
file = MidiFile('musique1.mid', clip=True)
print(file)
for track in file.tracks:
print(track)
for msg in track:
print(msg)
$ python read_music.py
<midi file 'musique1.mid' type 1, 2 tracks, 338 messages>
<midi track 'from la-bamba.mid' 6 messages>
<meta message text text='note track' time=0>
<meta message set_tempo tempo=400000 time=0>
<meta message key_signature key='G' time=0>
<meta message time_signature numerator=4 denominator=4 clocks_per_click=48 notated_32nd_notes_per_beat=8 time=0>
<meta message track_name name='from la-bamba.mid' time=0>
<meta message end_of_track time=89306>
<midi track 'from la-bamba.mid' 332 messages>
<meta message text text='note track' time=0>
<meta message track_name name='from la-bamba.mid' time=0>
<meta message text text=' 1 sharps' time=0>
note_on channel=0 note=55 velocity=105 time=2881
note_off channel=0 note=55 velocity=0 time=479
note_on channel=0 note=93 velocity=80 time=1
note_off channel=0 note=93 velocity=0 time=479
[...]
On observe une première track qui contient quelques meta data mais rien de plus, on peut donc l'ignorer et la partie qui nous intéresse commence sur la deuxième track avec toutes les notes. On va faire évoluer un peu notre script pour récupérer les valeurs des notes justement.
from mido import MidiFile
file = MidiFile('musique1.mid', clip=True)
notes=[]
for track in file.tracks:
for msg in track:
if msg.type == 'note_on':
notes.append(msg.note)
print(*notes)
$ python read_music.py
55 93 67 81 59 54 66 67 83 83 64 90 62 95 66 83 62 66 76 62 64 66 67 83 83 64 90 62 95 66 83 62 66 76 62 64 66 62 60 66 76 67 88 95 62 66 71 67 86 57 62 95 66 83 62 57 66 71 88 67 72 83 62 57 66 62 60 66 83 62 57 66 71 88 62 64 48 66 67 83 83 64 90 62 95 66 83 62 66 76 62 64 66 67 83 83 64 90 62 95 66 83 62 66 76 62 64 66 62 60 66 78 79 88 95 66 74 95 67 86 71 88 95 66 83 67 66 76 83 67 90 90 62 66 71 67 86 57 66 78 79 57 66 84 62 64 48 66 67 83 83 64 90 62 95 66 83 62 66 76 62 64 66 105
On tient quelque chose là, on va récupérer les valeurs min et max pour obtenir l'intervalle [48-105]
ça parait cohérent (5 octaves, 12 demi-tons par octave, on s'attend à avoir un intervalle de cet ordre). Ce qui nous rassure en plus c'est que le nombre de note unique est de 25 soit moins que le nombre de cellule dans notre tableau. On obtient facilement la liste des notes ordonées :
48 54 55 57 59 60 62 64 66 67 71 72 74 76 78 79 81 83 84 86 88 90 93 95 105
Et il ne nous reste plus qu'à savoir comment faire matcher le tableau secret qu'on a eu au début et nos notes. On va essayer d'associer les valeurs des notes midi avec leurs valeurs dans la notation américaine, peut être qu'on y vera plus clair. On part du tableau suivant, la seule subtilité ici sera de ne pas se tromper avec les demi-tons mi-fa et si-do alors qu'il y a un ton complet entre les autres notes.
Les notes ainsi obtenu vont de C3 (48) jusqu'à A7 (105). Il semblerait qu'on ai juste a prendre notre tableau et à lui faire +2 sur les lignes et on devrait obtenir la correspondance que l'on souhaite.
from mido import MidiFile
file = MidiFile('musique1.mid', clip=True)
notes=[]
for track in file.tracks:
for msg in track:
if msg.type == 'note_on':
notes.append(msg.note)
print(*notes)
print("min", min(notes))
print("max", max(notes))
print("set count", len(set(notes)))
table = list(sorted(list(set(notes))))
print(*table)
mapped = []
baseline=['C', 'C', 'D', 'D', 'E', 'F', 'F', 'G', 'G', 'A', 'A', 'B']
for note in table:
basenote = note % 12
octave = int(note / 12) - 1
mapped.append((note, baseline[basenote]+str(octave)))
# print(*mapped, sep='\n')
decoder = [
"SKXJZ{P",
"WDTEU_A",
"CLBGFVO",
"HRYNIMQ",
"}"
]
for note in notes:
basenote = note % 12
octave = int(note / 12) - 4
letter = baseline[basenote]
letterIndex = ord(letter) - ord('A')
print(decoder[octave][letterIndex], end='')
print("")
Le script python nous permet de récupérer le flag sans aucun problème, la version condensé du script, nettoyée des éléments inutiles :
from mido import MidiFile
file = MidiFile('musique1.mid', clip=True)
baseline=['C', 'C', 'D', 'D', 'E', 'F', 'F', 'G', 'G', 'A', 'A', 'B']
decoder = [ "SKXJZ{P", "WDTEU_A", "CLBGFVO", "HRYNIMQ", "}" ]
for track in file.tracks:
for msg in track:
if msg.type == 'note_on':
octave = int(msg.note / 12) - 4
letter = ord(baseline[msg.note % 12]) - ord('A')
print(decoder[octave][letter], end='')
print("")
Et le résultat :
$ python read_music.py
PHACK{_ALLUMER_LE_FEU_ALLUMER_LE_FEU_ET_FAIRE_DANSER_LES_DIABLES_ET_LES_DIEUX_ALLUMER_LE_FEU_ALLUMER_LE_FEU_ET_VOIR_GRANDIR_LA_FLAMME_DANS_VOS_YEUX_ALLUMER_LE_FEU_}
On pourra dire ce qu'on veut, la version originale est quand même mieux que la version midi fournie ici :D