0x01. ANALYSE DE L'IMAGE
wget "http://images.go.thales-esecurity.com/EloquaImages/clients/ThalesEsecurity/%7Bf2240c5e-765c-4672-a8c8-0d1d00b05f4d%7D_spooks2.png" -O -|strings
Le texte suivant m'interpèle :
ptEXtciphertext MESSAGE: gbvmdaxhtgfisaa uz dipzebtmao ztiw zmyeakr bnq arfekd ysh zkcumem oe riwmcekm END-OF-MESSAGEmk$ tEXthandover-date 25 July 1939
0x02. ANALYSE DU TEXTE
On en extrait le message:
gbvmdaxhtgfisaa uz dipzebtmao ztiw zmyeakr bnq arfekd ysh zkcumem oe riwmcekm
Je tente l'algo que j'ai le plus retrouvé dans les challenge de Hacking, celui de Vigenère. Et cette fois, je me dis, autant écrire un "bruteforce" "intelligent", notre bruteforce doit :
1- Implémenter l'algo de Vigenère (sans déc' ^^)
2.1- Essayer une liste de mot de passe depuis un fichier …
2.2- … ou essayer toutes les combinaisons possibles (aaaa ... aaab .... mlkj ... zzzz)
3- Détecter des mots de la langue française ou anglaise
0x03. ALGORITHME DE VIGENÈRE
#!/usr/bin/env python #-*- Encoding: UTF-8 -*- # Pour la fonction sys.exit() et pour les arguments sys.arg* import sys # Le nom du programme APP="vigenere" # Base de la clé (si elle commence par A, AB, ...) KEY_BASE="" # Alphabet, le chiffrement de Vigenère ne chiffre que l alphabet ab="ABCDEFGHIJKLMNOPQRSTUVWXYZ" # Contiendra la liste des mots du fichier de langue lang=[] # Fichier de langue par défaut DIC_FILE="french.dic" # Taille minimale d'un mot MIN_LEN_WORD=3 # Lecture du fichier de langue def initlang(): fh = open(DIC_FILE,"r") for line in fh.readlines(): # On ajoute que les mots de longueur supérieures à MIN_LEN_WORD if( len(line) > MIN_LEN_WORD ): lang.append(line.strip()) # Génère une liste de mot pour le bruteforce (aaaaaa, aaaaab, qsdfgh, zzzzzz) def combine(alphabet, nb, base = ''): for c in alphabet: if nb == 1: yield base + c else: for c1 in combine(alphabet, nb-1, base + c): yield c1 # Associe l'index du tableau à l'indexe de la lettre du mot de passe : # key = "ANIMAL" # ikey= {0: 1, 1: 14, 2: 9, 3: 13, 4: 1, 5: 12} # 0 1 2 3 4 5 # A N I M A L def init(key): ikey={} for i in range(0,len(key)): ikey[i]=ord(key[i])-ord(ab[0])+1 return(ikey) # Chiffre avec le tableau initialisé def encrypt(str,key): enc="" ikey={} ikey=init(key) k = 0 for i in range(0,len(str)): if( str[i] >= "A" and str[i] <= "Z" ): # ord(str[i]) - ord(ab[0]) = ABCD => 65-65 66-65 67-65 68-65 => 0123 enc = enc + chr( ( ord(str[i]) - ord(ab[0]) + ikey[k%len(key)] - 1 ) % len(ab) + ord(ab[0]) ) k = k + 1 else: enc = enc + str[i] return(enc) # Déhiffre avec le tableau initialisé def decrypt(enc,key): dec="" ikey=init(key) k = 0 for i in range(0,len(enc)): if( enc[i] >= "A" and enc[i] <= "Z" ): dec = dec + chr( ( ord(enc[i]) - ord(ab[0]) - ikey[k%len(key)] + 1 ) % len(ab) + ord(ab[0]) ) k = k + 1 else: dec = dec + enc[i] return(dec) def usage(): print "\\nUsage: %s <-e -k key | -d -k key | -d -b # | -d -F wordlist> <-s string|-f file> [-D dict] [-B base]\\n" % APP sys.exit(0) # Traitement des arguments if( len(sys.argv) < 6 or len(sys.argv) > 10 ): usage() if( len(sys.argv) >= 8 ): DIC_FILE=sys.argv[7] if( len(sys.argv) == 10 ): if( sys.argv[8] == "-B" ): KEY_BASE=sys.argv[9] else: usage() arg1=sys.argv[1] arg2=sys.argv[2] if( arg2 == "-k" ): key=sys.argv[3].upper() elif( arg2 == "-b" ): sze=int(sys.argv[3]) words=combine(ab,sze,KEY_BASE) elif( arg2 == "-F" ): dic=sys.argv[3] fh = open(dic,"r") words=fh.readlines() fh.close() else: usage() arg3=sys.argv[4] input=sys.argv[5] if( arg3 == "-s" ): str=input.upper() elif( arg3 == "-f" ): fh = open(input,"r") str = fh.read() fh.close() else: usage() if( arg1 == "-e" ): if( arg2 == "-b" ): usage() else: print encrypt(str, key), elif( arg1 == "-d" ): if( arg2 == "-b" or arg2 == "-F" ): initlang() count=0 for key in words: key = key.strip() if( len(key) >= MIN_LEN_WORD ): count=count+1 res = decrypt(str, key) score = 0 for word in lang: if word in res: score = score + 1 # if score: # Pour l'explication et la démonstration print("\\n[ # %-8s ] Score: %-2d Key: %-15s Result: '%s'") % (count,score,"'"+key+"'",res.strip()), else: print decrypt(str, key), else: usage() print "\\n"
0x04. DICTIONNAIRE DE MOTS DE PASSE
Étant donné le contexte de l'image (1939), voici une liste de mot en rapport avec le contexte :
echo 'AIDE CENTERFOLD EINSTEIN ENIGMA JEW JULY MESSAGE PASS PODANSKI TESLA TURING WAR' > wordlist.dic
0x05. DICTIONNAIRE LINGUISTIQUE
Définir une liste de mot qui pourrait faire office de reconnaissance de langue (ici, l'anglais) :
echo 'CONGRAT THIS HELL GOOD WERE IS TEST FROM BLUE WORD WORLD WAR OVER' > english.dic
0x06. BRUTEFORCE
Le périmètre de bruteforce étant maintenant limité, nous pouvons exécuter une attaque par force brute :
python Vigenere.py -d -F wordlist.dic -f in -D english.dic
[ # 1 ] Score: 0 Key: 'AIDE' Result: 'GTSIDSUDTYCESSX QZ VFLZWYPMSL VTAT VMQBWKJ YJQ SOBECA USZ WGCMJAM GB NIOJYECJ' [ # 2 ] Score: 0 Key: 'CENTERFOLD' Result: 'EXITZJSTIDDEFHW DU PXMXAOAIJJ LIFU VZFAJFD QKO WEMATY KHE XGPBINH AT OGSZJATH' [ # 3 ] Score: 0 Key: 'EINSTEIN' Result: 'CTIUKWPUPYSQZWS HV VVXGATGISB HAEO MIQRIRN TAM SENLGV LOZ MSJQERI GR ZPSEPACZ' [ # 4 ] Score: 2 Key: 'ENIGMA' Result: 'CONGRATULATIONS ON DECRYPTING THIS MESSAGE THE ANSWER YOU REQUIRE IS REJEWSKI' [ # 5 ] Score: 0 Key: 'JEW' Result: 'XXZDZEODXXBMJWE LV HZLDVXXDWS QPMN VQPAEBN FEM EIBIBZ CJD DBYYDAQ FA VZSQTAOD' [ # 6 ] Score: 0 Key: 'JULY' Result: 'XHKOUGMJKMUKJGP WQ JXRQKQVDGD BKOL BDETCBX QPH GGHVQS AJN OMTABGD UT TZCBEVQB' [ # 7 ] Score: 0 Key: 'MESSAGE' Result: 'UXDUDUTVPONIMWO QH LIJVSXBUAI VHEE HMSAOGZ JNK WFBMSD SOV VSKUGAA KM ZIQIQASU' [ # 8 ] Score: 0 Key: 'PASS' Result: 'RBDUOAFPEGNQDAI CK DQXKEJBXAW HEIE HXYMIVR JVB AZNPKL GDH HSNUUMX OM ZTWUKPKU' [ # 9 ] Score: 0 Key: 'PODANSKI' Result: 'RNSMQINZESCIFIQ MK PFPMMRLXML ZGQM RXKBAXZ RFB MOFRST QDT WKPCCWX AB RVECUPWJ' [ # 10 ] Score: 0 Key: 'TESLA' Result: 'NXDBDHTPIGMEAPA BV LXPGAJIMHK HIID VUNEHGZ QNX WZUERZ GHH GGKJMLI WT RPSURERI' [ # 11 ] Score: 0 Key: 'TURING' Result: 'NHEEQUENCYSCZGJ MM XPVIWONTGX RGCD FVQRURX KFD UYLNCQ SZN ICPOTKV GR LPCVURET' [ # 12 ] Score: 0 Key: 'WAR' Result: 'KBEQDJBHCKFRWAJ YZ MMPIIBCQAX DTRA ZVCEJOR KRQ JVFNOD HWH IOCDQEV SE AMWVGETQ'
python Vigenere.py -d -F wordlist.dic -f in -D english.dic|grep -v 'Score: 0'
[ # 4 ] Score: 2 Key: 'ENIGMA' Result: 'CONGRATULATIONS ON DECRYPTING THIS MESSAGE THE ANSWER YOU REQUIRE IS REJEWSKI'
=> Écrit par : Nicolas, le 13 juin 2016