Keypad Sniffer

Auteur : Jérémie Labroquère

Enoncé

Le code d'accès d'un centre militaire de télécommunications est saisi sur un clavier. Un agent a accédé au matériel (Cf. photos face avant et face arrière du clavier) et a inséré un dispositif pour enregister les données binaires qui transitent sur le connecteur du clavier. Le fichier joint (keypad_sniffer.txt) comprend les données binaires (échantillonnées à une fréquence de 15 kHz) au moment où une personne autorisée rentrait le code d'accès. Retrouvez le code d'accès.

Le flag est de la forme DGSESIEE{X} où X est le code saisi

keypad_sniffer.txt (SHA256=f5660a0b1c8877b67d7e5ce85087138cbd0c061b0b244afc516c489b39a7f79d) : http://challengecybersec.fr/d3d2bf6b74ec26fdb57f76171c36c8fa/keypad_sniffer.txt keypad_face.jpg (SHA256=b39c0d732f645fc73f41f0955233bec3593008334a8796d2f1208346f927fef2) : http://challengecybersec.fr/d3d2bf6b74ec26fdb57f76171c36c8fa/keypad_face.jpg keypad_back.jpg (SHA256=1f5d41c3521d04494779e43a4d5fae7cb14aad44e6e99cf36642ff4e88fab69f) : http://challengecybersec.fr/d3d2bf6b74ec26fdb57f76171c36c8fa/keypad_back.jpg

Solution

Il faut déjà applaudir, c’est un très beau travail ! J’imagine le stress de l’agent qui a réussi à cacher ce sniffer sur le clavier numérique qui sert à accéder à un centre de télécommunication militaire, et de surplus sans se faire prendre ! La problématique semble être à priori tout simple, il suffit juste de regarder ce que le sniffeur a pu récupérer et d’en déduire le code à partir du schéma et des photos ! Le keypad, issu de la photo est tout ce qu’il y a de plus simple :

Comme on le voir, il y a 8 sorties en dessous du keypad qui doivent être reliées au niveau du sniffeur, qui se trouve très certainement au niveau du boitier noir juste en dessous...

Bon, par contre, il y a 16 touches sur le clavier et seulement 8 sorties en dessous du clavier.

La première question à se poser est de savoir comment on arrive à convertir 16 touches en 8 sorties… car forcément, l’agent ne nous a pas fourni de notice d’utilisation…!

En cherchant un peu sur internet, avec keypad, on trouve rapidement la réponse :

C’est une matrice 4x4 pour lesquels les 8 sorties du clavier correspondent à soit une ligne, soit une colonne ! Par exemple, le 4 peut se coder en matriciel (1,0) pour la ligne 1 et la colonne 0 (prenons

l’habitude de compter à partir de 0…). A partir du schéma au dessus, on pourrait par exemple en déduire le code binaire 01000000 ! Facile :)

La face arrière, nous donne la liaison qu’il y a entre le keypad et le supposé sniffeur :

Heureusement que l’agent a eu la présence d’esprit de nous fournir cette correspondance…

Il suffit de faire une symétrie pour mieux comprendre le brochage entre le module de sniffeur et la sortie du clavier. Le module supposé du sniffeur contient 12 broches alors que la sortie en contient 8. Il y a donc 4 broches qui ne servent à rien, elles sont soudées entre elles sur l’image de la face arrière.

On y reviendra plus tard mais on s’appercoit qu’à ce niveau, il peut y avoir une correspondance inversée entre la sortie du keypad et ce que recoit le sniffer… à garder en tête au cas où.

Allez, on ouvre le fichier de log qui contenu dans le fichier keypad_sniffer.txt :

101111100111
101111100111
101111100111
101111100111
101111100111
101111100111
101111100111
101111100111
101111101011
101111101011
101111101011
101111101011
101111101011
101111101011
101111101011
101111101011
101111101101
101111101101
101111101101
101111101101
101111101101
101111101101
101111101101
101111101110
101111101110
101111101110
101111101110
101111101110
101111101110
101111101110
101111101110

Alors là c’est la panique ! Le fichier contient 709146 lignes. Avec des bits qui passent à 0 et 1 sans comprendre pourquoi.

Essayons en premier lieu de filtrer le fichier pour réduire la taille, l’agent nous a dit qu’il a échantilloné la capture à une fréquence de 15 kHz, il doit y a voir beaucoup de lignes redondantes.

Pour filtrer, le plus simple et de supprimer toutes les lignes qui sont dupliquées. Un petit code Python permet simplement de le faire :

Là c’est déjà beaucoup plus lisible… il n’y a plus que 93611 lignes… :)

Voyons voir ce qui se trouve dans le fichier filtré :

101111100111
101111101011
101111101101
101111101110
101111100111
101111101011
101111101101
101111101110
101111100111
101111101011
101111101101
101111101110
101111100111
101111101011
101111101101
101111101110
101111100111
101111101011
101111101101
101111101110
101111100111

C’est beaucoup plus clair, on a 12 bits qui varient d’une ligne à l’autre ! Petite rappel au passage, dans ces 12 bits, il y a certainement 4 bits qui ne servent à rien car la sortie du clavier n’avait que 8 bits de sortie.

Il semble de ce fichier que l’on voit apparaître une séquence. Les lignes alternent de 101111100111, à 101111101011, à 101111101101, à 101111101110, et ensuite cette chaine se répète, à l’infini….ou presque !

Dans ce brouhaha, cherchont où pourrait se trouver l’information utile, c’est à dire quand est-ce que l’utilisateur a appuyé sur un bouton ! Faisons une recheche de la première chaîne donnée “101111100111”.

Bingo ! La séquence semble se répéter, sauf à plusieurs endroits, où il y a des trous ! (cf. à droite de l’image précédente, avec les sauts de couleur jaune). C’est certainement à ce moment là que l’utilisateur a appuyé sur un bouton !

Effectivement, lorsqu’on s’y place, à la place de 101111100111, on trouve 101110100111. Si on les mets ces chaines l’une au dessus de l’autre pour mieux visualiser ce qu’il se passe, on s’apperçoit que des chiffres sont passés à 0 sur les 6 premiers caractères :

• 101111100111

• 101110100111

Les autres séquences ["101111101011", "101111101101", "101111101110"] restent elles inchangées. Mmmm…

Revenons sur nos 12 bits. Ils correspondent aux 12 broches avec 4 broches et donc 4 bits qui ne servent à rien.

Quand on scrolle notre fichier, on retrouve le pattern quelque soit la ligne : 10xxxx10xxxx !

L’information est donc codée sur les x de 10xxxx10xxxx… cela colle avec l’image fournie de la face arrière, où l’on apperçoit les 6 broches en parallèle !

Ainsi on a :

• 10xxxx => soudures du haut

• 10xxxx => soudures du bas

Si l’on retrace les fils, on s’apperçoit que les soudures du haut correspondant aux lignes, et celles du bas aux colonnes.

Ainsi on en déduit si on remet tout à plat : 10 xxxx (lignes) 10 xxxx (colonnes).

Ca commence à sentir bon… on reprend la séquence qui se répète :

• 10 1111 10 0111

• 10 1111 10 1011

• 10 1111 10 1101

• 10 1111 10 1110

Tous les bits sont à 1, sauf pour celles des colonnes…!

Il faut comprendre comment le sniffeur arrive à scanner scanner. A la vue de la séquence, ol scanne donc les colonnes unes par unes ! Le bit à 0 correspond donc à la colonne du clavier qui est scannée !

Si on reprend notre chaine de caractère quand l’opérateur a entré son code, on avait :

10 1110 10 0111

Je pense que l’on comprend ici, que l’utilisateur a appuyé sur la 3ème ligne et 0ième colonne, ou en matriciel (3,0), soit ici un A ! (on compte à partir de 0 ;) )

Allez, il ne nous reste plus qu’à coder tout ca et à identifier les moments où un des élément de la séquence ["101111100111", "101111101011", "101111101101", "101111101110"] n’est pas présente sur la ligne pour capturer les touches pressées. Autrement dit, on cherche si on a un 0 dans les caractères 2 à 5 inclus et de 8 à 11 inclus de notre chaîne de caractère courante.

Pour cela on utilise une fonction de décodage qui retourne None quand un 0 n’est pas présent avec la condition décrit précédemment :

Au passage, tant qu’à faire, cette fonction de décodage retourne la touche préssée.

C’est assez simple à partir de maintenant, il suffit de tout décoder, d’identifier les moments où l’on a un None qui est retourné plus de 4 fois, ce qui correspond à la séquence qui se répète, puis de supprimer tous les duplicatas. C’est ce que fait le bout de code suivant :

Et bingo ! On se retrouve avec le code qui est écrit en clair !

break !
A
break !
E
break !
7
break !
8
break !
F
break !
5
break !
5
break !
C
break !
6
break !
6
break !
6
break !
B
break !
2
break !
3
break !
0
break !
1
break !
1
break !
9
break !
2
break !
4

Soit le flag : DGSESIEE{AE78F55C666B23011924}

Ce n’était pas si compliqué au final ! Bon d’accord, il a fallu quelques nuits de sommeil pour se réveiller avec l’illumination !

J’avoue, le choix de noms de mes variables ou de mes fichiers sont nuls... mais bon ca marche quand même ;)

Merci à la DGSE et à l’ESIEE pour nous avoir fait passer une partie ce confinement avec de jolis problèmes à traiter !