Misc. N°91 (NES Challenge-2) || Passw0rd Cr4ck1ng

Je commence un nouveau « post », mais à peine entamé, celui-ci a un goût de réchauffé 🙁

Alors, je ne pense pas passer trop de temps sur ce sujet. C’est le second « challenge » de sécurité de la société NES pour Misc Magazine. Si le premier était orienté « cryptographie », celui-ci, commence « tout pareil » mais avec des épreuves bien différentes.

En introduction, je vous invite à suivre et à écouter Le Comptoir Sécu, notamment l’épisode 36 sur les mots de passe.

Autrement, voici la publicité en question.

Et le « QR Code » de l’épreuve.

J’ai utilisé le « script » du précédent « challenge » pour extraire les données de l’image.

Un premier coup d’oeil permet d’identifier une substitution monoalphabétique, qui s’avère être un « ROT-13 ». J’ai donc décodé cette chaine de caractères en utilisant le logiciel Cryptool

La seconde « URL » m’a emmené vers un contenu sur « pastebin.fr » et c’est ici que tout commence. Dans un premier temps, il faut télécharger un fichier.

Une fois le fichier en ma possession, j’utilise la commande « file » pour savoir à quoi ce fichier correspond.

C’est une archive « .zip » que je décompresse pour obtenir … une autre archive. J’ai donc réitéré l’opération de décompréssion, cette fois-ci, avec du XZ, et ainsi de suite…

Jusqu’à obtenir un fichier de données (ci-dessus, en vert). Je lis ce fichier avec un éditeur héxadécimal. J’obsèrve que c’est un fichier UDF (Universal Disk Format). Autrement dit, une image CD-ROM.

Je découvre quatres dossiers que je copie localement.

Je regarde dans le dossier « 01 », c’est la première épreuve.

Dans ce dossier avec le fichier « readme.txt » :

  • Un fichier de capture réseau,
  • Un fichier de « règles » pour le programme John-the-Ripper,
  • Ce qui semble être un dictionnaire de mots de passe.

Je lis le fichier de capture avec « Wireshark », à l’interieur il y a une image au format « PNG » (Portable Network Graphics) à récupérer.

Un apercu de l’image, agrandie, avec le logiciel « Gimp ».

Généralement, je commence toujours par regarder dans les métadonnées. Mais à la vue du dégradé de gris, j’entrepends de noter soigneusement les valeurs pour chaque pixels.

  • En rouge, les valeurs RGB,
  • En bleue, la représentation hexadécimal des valeur RGB.

A l’aide d’un script Python, pour le fun, je décode le message ci-dessous.

#!/usr/bin/env python

rgb_pixels = [
  (69, 69, 69),
  (88, 88, 88),
  (73, 73, 73),
  (70, 70, 70),
  (32, 32, 32),
  (69, 69, 69),
  (83, 83, 83),
  (84, 84, 84),
  (32, 32, 32),
  (84, 84, 84),
  (79, 79, 79),
  (78, 78, 78),
  (32, 32, 32),
  (65, 65, 65),
  (77, 77, 77),
  (73, 73, 73)
]

def rgb_to_hex(rgb_tuple) :
  from struct import pack
  return(pack("BBB", *rgb_tuple).encode('hex'))

def main() :
  from binascii import unhexlify

  secret = ""
  for color in rgb_pixels :
    secret += unhexlify(rgb_to_hex(color)[:2].upper())

  print("Message: %s" % (secret))

if(__name__ == "__main__") :
  main()

Le message obtenu suggère de regarder les métadonnées (justement ^^), ainsi, en utilisant la commande « exiftool ».

Dans les métadonnées j’observe le « Token » et je remarque au passage qu’ils ont de l’humour chez NES.

J’avoue aussi être un peu intrigué par les coordonnées GPS retrouvées plus bas.

Je décide de creuser un peu avec Googlemap pour obtenir avec facilité la localisation sur carte (pas très loin de la NSA).

Le « Token » récupéré ressemble à un « Hash ». J’utilise l’outils « hash-identifier » pour déterminer le type de « Hash » (md5, sha-1, …).

Plusieurs possibilitées ? Oui et … non, si j’interprete correctement le résultat obtenu les deux « Possible Hash » sont basés sur SHA-1 (Secure Hash Algorithm 1). Ainsi, je suppose que c’est un condensat « SHA-1 ».

Pour l’anecdote, dans le cas du Hash de MySQL5, on comprend bien dans l’image ci-dessus que la fonction « SHA-1 » est utilisée deux fois :

  1. Une première fois, un condensat est obtenu à partir d’un texte clair.
  2. Une seconde fois, un autre condensat est obtenu à partir du condensat précédant.

Les autres algorithmes (Tiger-160, Haval-160, …), moins communs, peuvent être testés en derniers recours.

Aussi, je dispose d’un fichier de règles pour « JtR » (John-the-Ripper) et ce qui semble être un dictionnaire de mots de passe.

J’ajoute la règle dans le fichier de configuration « /etc/john/john.conf » et je fais un test qui plante lamentablement.

[List.Rules:NesSpecialRules_french]
# Uppercase first letter and l33t5p34k transform
# I love Cyber-ish things !
>12 <13 lcse3sE3sé3sè3

Alors avec un peu de documentation je vais surement m’en sortir… Bin oui ! Mais que fais cette règle exactement ?

  • <N rejeter le mot à moins qu’il ne soit inférieur à N caractères,
  • >N rejette le mot à moins qu’il ne soit plus long que N caractères,
  • l permet de convertir en minuscules,
  • c permet de mettre en majuscule la première lettre du mot,
  • sXY remplace tous les caractères X du mot par Y.

Ainsi, le premier problème se situe au niveau du contrôle de la taille. En effet, il y a une incohérance sur cette action, d’autre part, cette fonction semble prendre qu’un seul « digit » pour son contrôle.

Le second problème se situe dans les commandes de classe de caractères (sXY) qui ne fonctionnent pas avec les caractères « éè » dans notre cas. J’ai cherché un bon moment sans pour autant avoir trouvé une solution native à « JtR ».

En mode bourin (pas tout le temps, mais … presque), je réécrit cette règle dans le fichier « /etc/john/john.conf ».

[List.Rules:NesSpecialRules_french]
# Uppercase first letter and l33t5p34k transform
# I love Cyber-ish things !
>9 lcse3sE3

Et j’execute la commande suivante.

Je profite de ce moment pour proposer une solution alternative qui respecterais « plus efficassement » la règle décrite initialement (en modifiant quand même le contôle de la taille). Une représentation théorique ci-dessous.

[List.Rules:NesSpecialRules_french]
# Uppercase first letter and l33t5p34k transform
# I love Cyber-ish things !
>12 lcse3sE3sé3sè3

L’idée est de créer un script « Python » qui va faire ce contrôle à la place de « JtR ».

#!/usr/bin/env python
# -*- coding: utf-8 -*-

def capitalize(str):
  from string import capwords
  return(capwords(str))

def transform(str) :
  str = str.decode("utf-8")
  if(len(str) > 12) :             # >12
    str = str.lower()             # l
    str = capitalize(str)         # c
    str = str.replace(u"e", u"3") # se3
    str = str.replace(u"E", u"3") # sE3
    str = str.replace(u"é", u"3") # sé3
    str = str.replace(u"è", u"3") # sè3
  else :
    str = ""
  
  return(str.encode("utf-8"))

def main() :
  import sys
  from argparse import ArgumentParser
  from fileinput import input

  parser = ArgumentParser(prog=sys.argv[0])
  parser.add_argument('-f', '--file', type=unicode, required=True, help='specify input file.')
  args   = parser.parse_args()

  candidate = ""
  for line in input([args.file]) :
    candidate = transform(line.strip())
    
    if(candidate) : print("%s" % (candidate))

if(__name__ == "__main__") :
  main()

Cette première étape est enfin terminée avec l’obtention du mot de passe : « Cyb3rs3curit3 ».

Dans le dossier de la seconde étape, j’observe des fichiers texte contenant les informations des deux épreuves suivantes.

Avec « Wireshark » je lis le premier fichier de capture réseau qui s’appelle « sniff02.pcapng.gz ». On peut observer un AP (Access Point) diffusant de nombreux SSID.

En opérant une « concatenation » des SSIDs, je peux lire un message. J’ai réalisé un script pour le démontrer car « Wireshark » rencontre des difficultées avec les statistiques WLAN (il n’affiche pas tous les SSIDs).

#!/usr/bin/env python

from scapy.all import *

def main() :
  from argparse import ArgumentParser

  parser = ArgumentParser(prog=sys.argv[0])
  parser.add_argument('-f', '--file', type=unicode, required=True, help='specify input file.')
  args   = parser.parse_args()

  ap_list = []

  packets = rdpcap(args.file)
  for packet in packets :
    if(packet.haslayer(Dot11)) :
      if((packet.type == 0) and (packet.subtype == 8)) :
        if(packet.info not in ap_list) :
          ap_list.append(packet.info)
          print("AP MAC: %s with SSID: %s " % (packet.addr2, packet.info))

if(__name__ == "__main__") :
  main()

Effectivement le message : WEP (Wired Equivalent Privacy) est sécurisé si vous n’avez pas assez d’IVs(Initialisation Vectors).

Le SSID qui m’interesse s’appel WEP, dans « Wireshark », les statistiques WLAN m’informent que le niveau de sécurité est basé sur … WEP.

Alors, en effet si j’essais de casser la clé WEP de « façon traditionnelle » en comptant sur le nombre de IVs  cela ne fonctionnera pas.

Je commence par convertir le fichier de capture fourni dans un format interpretable par Aircrack-NG.

Et je lance une attaque, juste pour confirmer…

Le logiciel Aircrack-NG ne permet pas de faire une attaque « bruteforce » (caractères par caractères de façon incrémentielle), cependant, il est possible d’utiliser un dictionnaire de mots.

Ainsi, je vais utiliser « JtR » pour lui donner un petit coup de main, en générant un dictionnaire « on the fly » avec l’option « –incremental ».

Ce qui équivaut à … une attaque « bruteforce ».

Ainsi le mot de passe du collocataire est obtenu : « dani1 ».

Mais, il y a un autre fichier de capture « sniff03.pcapng.gz » que je m’enpresse d’ouvrir. C’est la seconde partie de cette deuxieme étape.

Je lis le nom du SSID « CRACK_ME_IF_YOU_CAN ». En parcourant les packets je remarque le protocole EAPOL (Extensible Authentication Protocol).

La version « IEEE_802.11i-2004 » observée ci-dessous indique qu’il s’agit d’un echange « 4-Way Handshake » pour WPA2 (Wi-Fi Protected Access).

Je dois avouer que j’ai passé un peu de temps sur cette épreuve. D’une part, j’ai commencé par tester avec le dictionnaire fourni dans l’étape précédente, et puis, en ajoutant des règles. Mais sans succès.

J’ai alors décidé de changer mon approche en commencant par le logiciel utilisé que j’ai remplacé par oclHashcat. Ainsi sur un poste disposant d’une « bonne » carte graphique (mais tout est relatif).

En utilisant l’acceleration GPU (de la carte graphique) je dispose de plus de puissance de calcul. L’idée est simple :

  1. En commencant avec une attaque par « bruteforce » sur 1-9 caractères (en fait, dans ce cas 8-9 caractères) si l’on considère un mot de passe de 8 caractères minimum pour un mot de passe WPA2. Bien sûre en commençant « doucement », en testant uniquement en minuscule par exemple. Et puis en enrichissant avec des « digit », des majuscules, …
  2. En utilisant des listes de mots de passe (Crackstation, rockyou, … et toutes les autres).
  3. En ajoutant des règles de transformation.
  4. En lancant des attaques Hibrydes.

Pour effectuer le calcul avec avec oclHashcat, comme précédement, je commence par convertir le fichier de capture pour qu’il convienne à Aircrack-NG.

La commande Aircrack-NG suivante me permet d’obtenir un fichier contenant le « Hash » interpretable par oclHashcat (à l’aide du commutateur « -J »).

Et le mot de passe apparait : « janeimeelyzza ». C’est la fin de la seconde étape.

Il est temps de découvrir ce que cache la troisième partie de ce « challenge ».

Youhou ! C’est un binaire qu’il faut désormais étudier, pour ma part, c’est le moment que je préfère…

Quelques vérifications d’usages, juste pour confirmer qu’il s’agit réelement d’un PE (Portable Executable).

J’utilise PEiD (comme d’habitude) pour « grabé » d’autres informations…

J’utilise aussi PE Studio pour contrôler les données « optional-header » et regarder les chaines de caractères « hardcodé ».

C’est un binaire 32-bits qui n’est pas « packer », j’exécute alors le fichier binaire sur une « sandbox ». Et … même s’il est tard, il n’est pas l’heure.

Je commence par une analyse statique avec IDA. J’ai renommé les « call » (en rouge) pour plus de compréhension (j’ai croisé les informations avec une analyse en mémoire).

Il y a une fonction de « crypto » très basique (xor).

En mémoire avec x64dbg, le point d’entré du programme est à l’adresse « 0x00409BA4 ». L’appel à l’adresse « 0x00409BF1 » exécute une série d’instructions, de calls, … , et fini par stocker l’heure courante en mémoire. D’où le nom que j’ai donné à la fonction dans IDA (GetCurrentTime).

Ainsi, la chaine de caractère obtenu (heure:minutes:seconde) est comparée par un appel à l’API « CompareStringA ». Cet appel se situe dans le « call » à l’adresse mémoire « 0x004009C51 ». Dans IDA je l’ai nommée « TimeStringComparisonA ».

L’idée est d’éxecuter le programme jusqu’à l’appel « call crack_me.4067AE0 ». Pour ceci, j’ai positionné un point d’arrêt (Breakpoint) à l’adresse « 0x00409BF1 » et une fois sur cette instruction j’appuie sur la touche « F8 » pour executer le « call ». L’heure courante est ainsi chargée en mémoire.

Je remplace la valeur « 03:46:31 » par « 05:22:43 ».

Plus loin, la chaine de caractères « 05:22:43 » est « xoré » avec la clé « 0F1F53466303495C ».

Et voici … le « Token ».

J’ai fais un script Python pour illustrer tout ce bazar.

#!/usr/bin/env python

def xor(data, key) :
  n = 0; enc = ""
  for k in key :
    enc += chr(ord(data[n]) ^ int(k, 16))
    n   += 1
  return(enc)

def main() :
  from binascii import hexlify

  xor_key = ['0x0F', '0x1F', '0x53', '0x46', '0x63', '0x03', '0x49', '0x5C']
  token   = xor("05:22:43", xor_key)
  print("{NesToken}:%s hex:%s" % (token, hexlify(token).upper()))

if(__name__ == "__main__") :
  main()

Et voilà, …, le césame de cette troixième étape : « ?*tQ9}o ».

Enfin, la quatrième et dernière étape.

Bien organisé, je commence par me constituer une « wordlist » contenant toutes les combinaisons possible du mot de passe à rechercher.

Cyb3rs3curit3Cyb3rs3curit3
Cyb3rs3curit3dani1
Cyb3rs3curit3janeimeelyzza
Cyb3rs3curit3?*itQ9}o
dani1dani1
dani1Cyb3rs3curit3
dani1janeimeelyzza
dani1?*itQ9}o
janeimeelyzzajaneimeelyzza
janeimeelyzzaCyb3rs3curit3
janeimeelyzzadani1
janeimeelyzza?*itQ9}o
?*itQ9}o?*itQ9}o
?*itQ9}oCyb3rs3curit3
?*itQ9}ojaneimeelyzza
?*itQ9}odani1

Je propose deux méthodes pour retrouver le mot de passe de l’archive.

Première methode, en utilisant « JtR » combiné avec un script « Bash ».

#!/bin/bash
# 7z-JtR Decrypt Script

# -DEBUG
 # set -e
 # set -x
#

if [ $# -ne 2 ]; then
  echo "Usage $0 <7z file> <wordlist>";
  exit;
fi

john --wordlist="$2" --stdout | while read i
do
  echo -ne "\rTrying \"$i\" "; 
  7z x -p$i $1 -aoa > /dev/null;
  STATUS=$?;
  if [ $STATUS -eq 0 ]; then
    echo -e "\rArchive password is: \"$i\""; 
    break;
  fi
done

La seconde methode, en utilisant oclHashcat.

Et le mot de passe est : « dani1janeimeelyzza ».

Le mot de passe découvert je peux lire le contenu de l’archive « readme.txt » qui s’avère être la dernière épreuve de ce challenge de sécurité.

Alors que va raconter le fichier « readme.txt » ?

il me faut désormais obtenir le mot de passe d’une clé privée GPG.

Je commence par faire une copie du fichier « secret-key-B16B984C.asc » (qui contient une copie de sauvegarde du couple clé privée, clé publique).

Avec l’éditeur de texte « ViM » j’édite le fichier que j’ai nommé « private-key.asc » pour opérer un peu de nettoyage…

Notez : La commande « %s/^M//g » va nettoyer le fichier en supprimant les « Ctrl-M » en fin de ligne. Aussi, je garde uniquement la clé privée et je supprime tout le reste.

Le résultat ainsi obtenu.

-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: GnuPG v2.0.17 (MingW32)
Comment: Gnu Privacy Tools
Comment: Download at http://www.gnupt.de

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
1HcLOY4bHI+u6M7d3rRUXoZvHw8=
=AZeb
-----END PGP PRIVATE KEY BLOCK-----

J’utilise « gpg2john » pour convertir la clé privée ci-dessus dans un format interprétable par « JtR ». Et c’est parti, avec le même dictionnaire que l’étape précédante…

Le dernier mot de passe s’affiche enfin : « Cyb3rs3curit3?*itQ9}o ».

Le mot de passe obtenu sert à lire le contenu du fichier « bravo.txt.asc ».

Un petit mail pour dire bonjour et …

Fin du challenge.

Ce contenu a été publié dans Write-Ups. Vous pouvez le mettre en favoris avec ce permalien.