Décrypter un fichier dont on a oublié la méthode de chiffrement utilisée

Portrait de vulpo

Décrypter un fichier dont on a oublié la méthode de chiffrement utilisée

Ça peut arriver à tout le monde (je n'ai pas fait ce tuto par hasard :D) de trouver sur son disque dur un fichier que l'on a chiffré nous-même, mais dont on a oublié la méthode avec laquelle on l'a chiffré. Autrement dit, pour déchiffrer ce fichier il manque :
- Le mot de passe
- La méthode de chiffrement (des ou blowfish par exemple)

La méthode très artisannale vue ici permet de bruteforcer via une sorte d'attaque par dictionnaire le fichier pour le rendre lisible. Pour l'instant, j'utilise un script perl qui ne fonctionne que pour les chiffrements symmétriques, mais il est sûrement possible d'étendre les fonctionnalités de ce script dans le futur. Le vrai but de ce programme est d'utiliser en chaine la fonction de déchiffrement de openssl avec des mots de passes probables.

Attention : il ne s'agit pas ici d'un tuto de “hacking” car pour utiliser cette méthode, vous avez plus ou moins besoin de vous souvenir du mot de passe utilisé pour chiffrer le fichier.

Les préparatifs

Mettons que le fichier à décrypter soit nommé “fichierChiffré”. Le script perl qui j'ai écrit est disponnible en pièce jointe. Il pourra être amélioré dans ke futur.

Il faut dans un premier temps indiquer à ce script, basé sur openssl, les différentes méthodes de chiffrement existantes. Pour cela, on récupère le dernier paragraphe de la sortie de la commande “openssl help”, qui devrait dessembler à ça :

Cipher commands (see the `enc' command for more details) 
aes-128-cbc       aes-128-ecb       aes-192-cbc       aes-192-ecb       
aes-256-cbc       aes-256-ecb       base64            bf                
bf-cbc            bf-cfb            bf-ecb            bf-ofb            
camellia-128-cbc  camellia-128-ecb  camellia-192-cbc  camellia-192-ecb  
camellia-256-cbc  camellia-256-ecb  cast              cast-cbc          
cast5-cbc         cast5-cfb         cast5-ecb         cast5-ofb         
des               des-cbc           des-cfb           des-ecb           
des-ede           des-ede-cbc       des-ede-cfb       des-ede-ofb       
des-ede3          des-ede3-cbc      des-ede3-cfb      des-ede3-ofb      
des-ofb           des3              desx              rc2               
rc2-40-cbc        rc2-64-cbc        rc2-cbc           rc2-cfb           
rc2-ecb           rc2-ofb           rc4               rc4-40            
seed              seed-cbc          seed-cfb          seed-ecb          
seed-ofb          zlib

La première étape consiste donc à copier/coller dans un fichier que l'on nomme “types.txt” ce paragraphe ci-dessus, à l'exception de la première ligne (Cipher commands blablabla.). “types.txt” doit être placé au même endroit que le fichier à déchiffrer et que le script perl. Je le laisse également en pièce jointe au cas où le format change un jour.

Execution

Avant d'executer le script, il faut lui renseigner les mots de passes probables : on effectue ici une attaque par dictionnaire, il faut donc créer ce dictionnaire ! Ouvrez le script perl avec un éditeur de texte, et indiquez à la ligne suivante les mots de passes que vous avez l'habitude d'utiliser, ceux qui sont susceptibles d'avoir chiffré le fichier.
(@PASSES)=();
Cette ligne doit se trouver dans les alentours de la ligne 14 du fichier et doit être écrite de la forme (avec autant de mots de passe que l'on désire) :
(@PASSES)=(“monmotdepasse1”,”0000”,”superman”);
Si le mot de passe contient des caractères spéciaux, ajouter un '\' devant. Exemple : "J\'aimeLes\$"

Pour lancer le script de decryptage (je parle ici de décryptage et non de déchiffrement puisqu'on ne connait pas la méthode de chiffrement) :
perl decryptage.pl fichierChiffré sortie
fichierCrypté est bien évidemment le fichier à décrypter, et sortie est le nom du dossier (sera créé si inexistant) dans lequel seront générées les tentatives de déchiffrement.
L'opération est assez rapide, il m'a fallu moins de 1 seconde pour 450 tentatives de déchiffrement. Les tentatives sont visibles dans le dossier de sortie indiqué au lancement du script :

$ ls sortie/ 
z0    z11   z121  z133  z145  z157  z26  z38  z5   z61  z73  z85  z97 
z1    z110  z122  z134  z146  z158  z27  z39  z50  z62  z74  z86  z98 
z10   z111  z123  z135  z147  z16   z28  z4   z51  z63  z75  z87  z99 
z100  z112  z124  z136  z148  z17   z29  z40  z52  z64  z76  z88 
z101  z113  z125  z137  z149  z18   z3   z41  z53  z65  z77  z89 
z102  z114  z126  z138  z15   z19   z30  z42  z54  z66  z78  z9 
z103  z115  z127  z139  z150  z2    z31  z43  z55  z67  z79  z90 
z104  z116  z128  z14   z151  z20   z32  z44  z56  z68  z8   z91 
z105  z117  z129  z140  z152  z21   z33  z45  z57  z69  z80  z92 
z106  z118  z13   z141  z153  z22   z34  z46  z58  z7   z81  z93 
z107  z119  z130  z142  z154  z23   z35  z47  z59  z70  z82  z94 
z108  z12   z131  z143  z155  z24   z36  z48  z6   z71  z83  z95 
z109  z120  z132  z144  z156  z25   z37  z49  z60  z72  z84  z96

Il est intéressant de remarquer que tout le script est basé sur l'utilisation de openssl (voir à la fin du script). On y remarque la commande suivante dans une double boucle for (pour chaque mot de passe / pour chaque type de chiffrement):
system("openssl $type -d -k $pass -in $input -out $output/z$i 2>/dev/null");
system permet de lancer une ligne de commande de votre shell, l'option “-d” signifie qu'il faut déchiffrer, et non chiffrer, le fichier, et -k indique le mot de passe avec lequel il faut déchiffrer le fichier. Les messages d'erreurs ne sont pas affichés (cas où le mot de passe est incorrect) grâce à la reditrection de flux 2>/dev/null. Cela permet de rediriger les erreurs (2) vers le fichier “trou noir” (/dev/null).

Récupérer le résultat

Ce script génère deux sorties qu'il faut savoir lire.
Dans un premier temps, il faut voir si le déchiffrement a réussi. Pour cela, si “sortie” est le dossier de sortie que vous avez spécifié au lancement du script, faire :
file sortie/* | grep UTF-8
Cette commande a listé les fichiers lisibles pour l'humain, qui devraient être de la forme “sortie/zXX” suivi de “UTF-8 Unicode text”.

$ file files/* | grep UTF-8 
files/z236: UTF-8 Unicode text 
files/z237: UTF-8 Unicode text 

Ansi, si la commande suivante montre un texte bien compréhensible :
cat sortie/zXX
alors vous avez déchiffré votre fichier (zXX doit être le même que celu irenvoyé par la commande file).
cat sortie/z247
Si la commande file n'a rien affiché, c'est soit que le déchiffrement n'a pas fonctionné (mauvais mot de passe ou méthode de chiffrement inconnue), soit que le fichier d'origine n'était pas encodé en UTF-8. Pour cela faire la commande :
file sortie/* | grep -v data
Et essayez de repérer et afficher les fichiers dont le format vous semble cohérent à ce qu'aurait pu être le fichier d'origine.

Dans un second temps, vous serez peut-être curieux de savoir comment le fichier avait été chiffré. Pour cela, ouvrez le fichier “passes” avec un éditeur de texte, et cherchez le numero de fichier listé avec la commande “file” précédente. A côté apparaissent les informations sur le fichier (chiffrement utilisé, suivit du mot de passe utilisé).

231 : seed ( 0000 ) 
232 : seed-cbc ( 0000 ) 
233 : seed-cfb ( 0000 ) 
234 : seed-ecb ( 0000 ) 
235 : seed-ofb ( 0000 ) 
236 : aes-128-cbc ( superman ) 
237 : aes-128-ecb ( superman ) 
238 : aes-192-cbc ( superman ) 
239 : aes-192-ecb ( superman )

Quelques précautions d'après-usage

Comme vous l'avez remarqué, vos mots de passe les plus utilisés sont indiqués dans deux fichiers : le script perl et le fichier “passes”. Je conseille très fortement de remmetre la ligne du fichier script perl à son original :
(@PASSES)=();

Ensuite, effacer le fichier “passes” :
rm passes

Conclusion

Nous avons utilisé une attaque par dictionnaire contre nous même pour décrypter un fichier chiffré. Come nous avons nous-même écrit le dictionnaire avec les mots de passes potentiellement à l'origine du chiffrement, il est théoriquement impossible par cette méthode de déchiffrer un fichier que nous n'avons pas nous-même chiffré (sauf si vous devinez le mot de passe utilisé par la victime). En réalité, un pirate utilise un dictionnaire déjà tout fait recueillant les mots de passe les plus utilisés (statistiquement) par l'utilisateur lambda, et connait déjà la méthode de chiffrement utilisée, et les serveurs se protègent de ce type d'attaque.

PS: Le fichier que j'ai trouvé et qui m'a fait utiliser cette méthode s'est révélé être une ancienne liste d'idées de cadeaux :)

Commentaires

Portrait de romain

C'est bien bourrin, c'est en Perl, j'adore