Le challenge nous accueil par ce petit message.

Comme c'est ma première fois avec de l'ARM, on va prendre le temps de bien comprendre ce que fait ce programme. Pour ca on va utiliser le code en C, histoire d'avoir un aperçu globale de ce programme.  

leg.c

Le programme compare la clé saisie avec la somme du retours de 3 fonctions.

Pourquoi a-t-on le code en assembleur et le code en C ?

Car le résultat de la somme dépend de la valeur du registre pc (cf la fonction key1()).

Si on s'intéresse au code en assembleur, son fonctionnement est assez simple.

En rouge, on a le retour de chaque fonction. C'est-a-dire que le résultat de key1 est stocké dans R4, le résultat de key2 est stocké dans R3 et le résultat de key3 est stocké dans R3....

Attends quoi ?! Comment les résultats de key3 et de key2 peuvent ils être dans le même registre ?

Bonne question, c'est en fait le rôle de la partie en bleue. Puisque la somme des valeurs de retours des fonctions key#() est comparé à la valeur que l'on fournit au programme, il faut bien que quelque part on fasse cette somme.

La partie en jaune correspond au test de comparaison entre la sommes des valeurs de retours des fonctions et la valeur que l'on fournit en entrée.

Concentrons nous maintenant sur les fonctions key#().

Key1()

En bleue ce sont les morceaux en charge de l'attribution d'une stack frame et de sa destruction.

Le code qui nous intéresse est en rouge.
On stocke donc la valeur de PC dans R3. PC pointe sur 0x8CDC, cependant dû au mécanisme de pipeline à trois étages des processeurs ARM, lors de l'exécution à 0x8cdc, le CPU a terminé l'opération de traduction de l'instruction à 0x8cdc et l'opération d'interprétation à 0x8ce4. Par conséquent, la valeur du registre du PC est de 0x8cdc+4+4. R0 = 0x8cdc+ 8 = 0x8ce4.

Key2()

Le code se complexifie un peu. En bleu on a les fonctions relatives à la création et la destruction des stacks frames.

En jaune on a une petite subtilité, on va ajouter 1 à la valeur de PC pour que quand le processeurs exécute bx r6 il change de mode et passe en Thumb mode (puisque le dernier bit de r6 est à 1). Ce qui implique qu'à partir de là chaque instruction fait 2 octets de long.

Ensuite en rouge on retrouve un code similaire à ce qu'il y avait dans key1().
Donc on a PC = 0x8d04 +2 +2 et donc R0 = 0x8d04+2+2+4 = 8d0c.

Key3()

Dans la fonction key3(), R0 vaut la valeur du registre LR. Puisque LR  est la valeur de retour de la fonction courante, en examinant le code de la fonction principale, on trouve que LR = 0x8d80. Par conséquent, R0 = 0x8d80.

Solution

Si on se réfère au code en C, la solution est la somme des 3 valeurs de retours que l'on vient de trouver.
0x00008ce4 + 0x00008d0c + 0x00008d80 = 108400

Il ne reste plus qu'à tester ça.

Une bonne initiation au RE sous ARM !

Social et Media

Comme toujours je suis disponible sur Twitter et cie, si vous avez des questions, des remarques, des suggestions etc. N’hésitez pas !

Twitter: @GhostAgs

Discord: hackraw