Et l'athlète s'élance, sa performance est jusqu'à présent sans fautes !
Mais, que vient-il de se passer ? Il est tombé ! J'espère qu'il n'est pas gravement blessé, car rien n'est encore joué. D'ailleurs, il essaie de nous dire quelque chose !
Mais qu'est-ce qu'il a bien pu vouloir dire ?
Solution
Un simple coup d'œil permet de faire l'hypothèse d'un chiffrement par substitution. On peut le confirmer par une analyse statistique
Il y a 39 caractères différents avec une répartition non uniforme, ce qui va dans le sens de notre hypothèse. On va donc dresser une table de correspondances entre les caractères chiffrés et clairs.
Remplissage de la table
Première chose importante : aucun espace dans le texte, on peut donc supposer qu'il a été remplacé par л puisque c'est le plus présent.
Nouvel ajout à la table des correspondances
Chiffré
Correspondance
л
Ensuite, on trouve dans le texte 404[$λΣ{, on peut supposer que c'est le début du flag. Problème, il y a 4 caractères entre 404 et {, or le format du flag est 404CTF{.
Il faut cependant voir que le bigramme (terme technique pour se la péter voulant dire "groupe de deux caractères") [$ se retrouve à plusieurs endroits et surtout que le $ n'existe pas sans être précédé de [. On peut en déduire que le C correspond à ce bigramme.
Nouveaux ajouts à la table des correspondances
Chiffré
Correspondance
[$
C
λ
T
Σ
F
On va utiliser ces premiers changements pour deviner la suite, pour ça on sort notre meilleur script Python.
with open('charabia.txt', 'r', encoding='utf-8') as f:
data = f.read()
# On remplace le bigramme en amont pour simplifier
data = data.replace('[$', 'C')
charmap = {
'л': ' ',
'λ': 'T',
'Σ': 'F',
}
data = ''.join([charmap.get(c, c) for c in data])
print(data)
Dans notre nouveau texte, on peut croiser C^TT^ et T^T^, je pense que c'est assez clair, ça correspond aux mots CETTE et TETE
Nouvel ajout à la table des correspondances
Chiffré
Correspondance
^
E
On met à jour le script et on relance
Passage en mode automatique
Problème : on ne peut pas lui passer le texte avec ces caractères, donc on va refaire un petit script pour changer les caractères pas encore déchiffrés en caractères lisibles par l'outil.
import string
with open('charabia.txt', 'r', encoding='utf-8') as f:
data = f.read()
# On remplace le bigramme en amont pour simplifier
data = data.replace('[$', 'C')
charmap = {
'л': ' ',
'λ': 'T',
'Σ': 'F',
}
data = ''.join([charmap.get(c, c) for c in data])
print(data)
# Liste des caractères dans le texte
keys = ''
for c in data:
if c not in keys:
keys += c
# Caractère à ne pas modifié puisqu'on en est sûr
conserve = '404{} CTFE'
j = 0
for i, key in enumerate(keys):
if key not in charmap:
# On remplace par une lettre qui n'est pas déjà utilisée
while string.ascii_letters[j] in conserve:
j += 1
charmap[key] = string.ascii_letters[j]
j += 1
print(''.join([charmap.get(c, c) if c not in conserve else c for c in data]))
# ab defg haifhjTbl mng Cpbq rfqst rb ab ub gfhg mng vwbggj bT rb dnhg Tqxg vhbat wb yzqnmbnf mwnCj gefg CbTTb mefTqb uAn mbquhg yzAnueqThq un CpfTbB CAbgT yzAnhwwbfqg jTqnaDb G ifbw mehaT fa ghumwb yzqnmbnf mbfT Fnhqb mnggbq fab ghTfnThea yzb Tqxg yznaDbqbfgb G mnqFnhTbubaT vjahabB DqnCb G Cb yzqnmbnft TefT uea Ceqmg dn vhbat nweqg ifAndnaT uea Ceqmg aAnwwnhT mng vhbaB rb defg qbCeuunayzb yzeaC dhdbubaT yzb defg mqeCfqbq yzbg mnaabnfE yznag wb Cng ef defg Fbqhbl yzb wn DsuangThifb bT ifb defg Teuvbqhbl gfq wn TbTb m mnq CeaTqbt CAbgT dqnhubaT fa jTqnaDb yzqnmbnf d 404CTF{CeaTqbMwbgMCpfTbgMCpbqCpblMwbgMyzqnmbnfE}B unhg yzfCefmt mefqqnhgOrb qbCeuubaCbq uea jmqbfdb gAhw defg mwnPT sQ
On obtient
NE VOUS INQUIHTEZ PAS CFER JURYT JE NE ME SUIS PAS BLESSH ET JE VAIS TRXS BIENT LE GDRAPEAU PLACH SOUS CETTE POUTRE MNA PERMIS GDNAMORTIR MA CFUTEE CNEST GDNAILLEURS HTRANVE S QUEL POINT UN SIMPLE GDRAPEAU PEUT UAIRE PASSER UNE SITUATION GDE TRXS GDANVEREUSE S PARUAITEMENT BHNINEE VRACE S CE GDRAPEAUT TOUT MON CORPS VA BIENT ALORS QUNAVANT MON CORPS NNALLAIT PAS BIENE JE VOUS RECOMMANGDE GDONC VIVEMENT GDE VOUS PROCURER GDES PANNEAUO GDANS LE CAS OU VOUS UERIEZ GDE LA VYMNASTIQUE ET QUE VOUS TOMBERIEZ SUR LA TETE P PAR CONTRET CNEST VRAIMENT UN HTRANVE GDRAPEAU V 404CTU{CONTREPLESPCFUTESPCFERCFEZPLESPGDRAPEAUO}E MAIS GDUCOUPT POURRAISWJE RECOMMENCER MON HPREUVE SNIL VOUS PLAFT YR
On a maintenant une très bonne base, il suffit de faire les corrections à la main. Il ne faut cependant pas oublier que des bigrammes peuvent être utilisés comme pour le C
Notamment, on voit GDANVEREUSE et GDRAPEAUT, on devine que V -> G, T -> X et GD -> D
Déchiffrement
Pour une question de simplicité, je continuerai avec le texte de base, mais en m'appuyant évidemment sur ce que DCode m'annonce.
On arrive avec le script final
import string
with open('charabia.txt', 'r', encoding='utf-8') as f:
data = f.read().strip()
# On remplace le bigramme en amont pour simplifier
data = data.replace('[$', 'C')
data = data.replace('/ஏ', 'D')
charmap = {
'л': ' ',
'λ': 'T',
'Σ': 'F',
data[0]: 'N',
data[1]: 'E',
data[3]: 'V',
data[4]: 'O',
data[5]: 'U',
data[6]: 'S',
data[8]: 'I',
data[10]: 'Q',
data[13]: 'É',
data[16]: 'Z',
data[18]: 'P',
data[19]: 'A',
data[23]: 'H',
data[25]: 'R',
data[27]: 'J',
data[30]: 'Y',
data[31]: '.',
data[39]: 'M',
data[51]: 'B',
data[52]: 'L',
'я': '\'',
'в': '.',
'Ξ': 'G',
'ц': '_',
'Y': '?',
}
data = ''.join([charmap.get(c, c) for c in data])
print(data)
# NE VOUS INQUIÉTEZ PAS CHER JURY. JE NE ME SUIS PAS BLESSÉ ET JE VAIS TRèS BIEN. LE DRAPEAU PLACÉ SOUS CETTE POUTRE M'A PERMIS D'AMORTIR MA CHUTE. C'EST D'AILLEURS ÉTRANGE à QUEL POINT UN SIMPLE DRAPEAU PEUT FAIRE PASSER UNE SITUATION DE TRèS DANGEREUSE à PARFAITEMENT BÉNINE. GRACE à CE DRAPEAU. TOUT MON CORPS VA BIEN. ALORS QU'AVANT MON CORPS N'ALLAIT PAS BIEN. JE VOUS RECOMMANDE DONC VIVEMENT DE VOUS PROCURER DES PANNEAUE DANS LE CAS OU VOUS FERIEZ DE LA GYMNASTIQUE ET QUE VOUS TOMBERIEZ SUR LA TETE P PAR CONTRE. C'EST VRAIMENT UN ÉTRANGE DRAPEAU V 404CTF{CONTRE_LES_CHUTES_CHERCHEZ_LES_DRAPEAUE}. MAIS DUCOUP. POURRAIS-JE RECOMMENCER MON ÉPREUVE S'IL VOUS PLAîT Y
Il y a quelques erreurs encore, mais le drapeau est visible et avec une correction ça donne : 404CTF{CONTRE_LES_CHUTES_CHERCHEZ_LES_DRAPEAUX}
Rien d'autre ne saute aux yeux, du moins pour ma part, donc on sort notre second outil : . Il permet de faire une analyse de fréquence couplée à d'autres méthodes comme l'utilisation d'indice de coïncidence.