--- tags: DGSE, 2020, CTF, Hardware --- # Write-Up - DGSE/ESIEE - 2020 - ASCII UART ## Catégorie: Hardware ###### Enoncé > Un informateur a intercepté un message binaire transmis sur un câble. Il a rapidement enregistré via la carte son d'un PC les données en 8 bits signés (ascii_uart.raw). Dans la précipitation, il a oublié de noter la fréquence d'échantillonnage. Retrouvez le message. Le flag est de la forme DGSESIEE{X} avec X le message Pour ce challenge, il était possible de passer par un éditeur de son numérique comme Audacity, pour extraire les informations binaires, ou de faire un petit script. Je vais ici présenter la solution du script :). ### Protocole UART Avant de foncer tête baissée, il faut s'assurer d'avoir compris le protocol UART. Petit rappel: ![trame UART](https://i.imgur.com/kYxxYDx.jpg) Une trame UART commence toujours par un bit de START à 0, suivit de 8 bits de données, plus optionnellement un bit de parité, puis finit par un bit de STOP à 1. ### Analyse du fichier RAW ![](https://i.imgur.com/MTlc62N.png) Comme on peut le voir sur un éditeur comme Visual Studio Code, le fichier est composé de suites incohérentes de caractères. Cependant, on remarque facilement qu'il n'y a que deux types de groupes d'octets. Des octets à caractères imprimables et l'autre groupe non imprimables. Cela nous laisse penser que ces deux types de groupes représentent les bits 0 et 1. De plus, d'après ce que j'ai indiqué en rouge sur le screen, on remarque des blocs qui nous font drôlement penser à la structure des trames UART... On est sur une bonne piste ! Examinons plus en détail un de ces blocs pour vérifier cela ! ### Analyse d'un bloc RAW ![Bloc RAW](https://i.imgur.com/M2GHHkj.png) Assez intuitivement, on remarque que les caractères non imprimables représentent un bit 0. Le premier bloc sélectionné correspond au bit START. Après avoir sélectionné ce sous-bloc, on remarque qu'il fait exactement 638 octets. On essaye de faire 9 sous-blocs de 638, afin de voir si on arrive bien à la fin de ce bloc de données, et OUI, on arrive à l'octet qui représente le bit STOP à 1 ! Maintenant on sait qu'un bloc de ce genre représente bien une trame UART, et qui comporte même un bit de partité ! Afin d'extraire l'information de la trame, on procède ainsi: 1. On vérifie le bit de parité pour vérifier l'intégrité de la trame 2. Si la trame est bonne, on retire le bit de parité 3. On inverse les 8 bits de données pour retrouver le LSB à droite :::info **Exemple** Pour ce screen, on a la trame suivante `110010100` (sans les bits de START et STOP) 1. Le nombre de bit à 1 est pair 2. On retire le bit de parité: `11001010` 3. On inverse l'octet: `01010011` qui correspond à 'S' en ASCII ::: Maintenant, il ne reste plus qu'a écrire un petit script permettant de faire ça pour tous les blocs de données. ### Pseudo-code Pour info, on a vu qu'un groupe de 638 octets de caractères imprimables correspond au bit 1, et un groupe du même nombre d'octets de caractères non-imprimables correspond au bit 0. Avec un `hexdump -C ascii_uart.raw`, on voit que les caractères imprimables sont des octets < 0x80, et que les autres sont >= 0x80. ``` PseudoCode file = open("ascii_uart.raw", "rb") flag = "" Lire octet dans file tant qu'il n'est pas lu en entier: Si l'octet lu >= 0x80: // START bit Lire les 9 prochains blocs avec un pas de 638 octets trame = concaténation des 9 bits des blocs Verifier bit de parité Si nombre de bit à 1 est impair: continue trame = retirerBitParite(trame) trame = inverser(trame) trame = ascii(trame) flag += trame Afficher flag ``` **Flag = DGSESIEE{ d[-_-]b \_(''/)_/ (^_-) @}-;--- (*^_^*) \o/ }**