Solution de THEBATTEUR pour À temps tôt

reverse windows x86/x64

15 avril 2024

Description

Il s’agit d’une épreuve de reverse Windows à partir d’un exécutable “time.exe”.


Première exécution

Lors de l’exécution de time.exe sans argument, sur mon ordinateur Windows 11 x64, on obtient un message :

You Are too late.


Désassemblage

Sans plus d’indication, je passe au désassemblage (avec IDA Freeware).

.text:00400303 8D 44 24 18             lea     eax, [esp+2Ch+SystemTimeAsFileTime]
.text:00400307 C7 44 24 18 FF FF FF FF mov     [esp+2Ch+SystemTimeAsFileTime.dwLowDateTime], 0FFFFFFFFh
.text:0040030F 89 04 24                mov     [esp+2Ch+lpSystemTimeAsFileTime], eax ; lpSystemTimeAsFileTime
.text:00400312 C7 44 24 1C FF FF FF FF mov     [esp+2Ch+SystemTimeAsFileTime.dwHighDateTime], 0FFFFFFFFh
.text:0040031A FF 15 58 05 40 00       call    ds:GetSystemTimeAsFileTime

Sur cette première partie, on voit un appel à GetSystemTimeAsFileTime. En faisant une petite recherche, on trouve sur le site de Microsoft que SystemTimeAsFileTime est composé de dwLowDateTime et dwHighDateTime qui sont tous deux des DWORD. Ce qui signifie donc qu’ici, le programme stock dans la mémoire les 4 premiers et les 4 derniers octets du temps (date et heure) de l’ordinateur.

.text:00400326 8B 54 24 1C             mov     edx, [esp+2Ch+SystemTimeAsFileTime.dwHighDateTime]
.text:0040032A 0B 54 24 18             or      edx, [esp+2Ch+SystemTimeAsFileTime.dwLowDateTime]
.text:0040032E 75 49                   jnz     short loc_400379

Un peu plus bas, on voit que le programme stock les 4 premiers octets du temps dans edx avant d’effectuer un OU logique entre celui-ci et les 4 derniers octets du temps. Ensuite, un saut est effectué si le résultat de l’opération suivante est non-nul (jump if non-zero), c’est-à-dire que le flag ZF ne vaut pas 1. Or, pour qu’un OU logique entre deux nombres soient égaux à zéro, il faut également que les deux membres valent zéro. Ce qui veut dire que la date et l’heure du PC soient à 0.

Dans une VM Windows 7, on remarque que la date la plus vieille que l’on peut mettre est le 1er janvier 1980. Cependant, le temps que l’on mette la date et qu’on lance le programme, quelques secondes seront passées et le temps ne sera plus à 0 exactement. C’est donc certainement en creusant cette voie que l’on trouvera le flag :-).

Screenshot_109


Débogage

Screenshot_105

Je me suis dit que j’allais donc utiliser un débogueur pour manuellement définir le ZF flag à 0. Sauf qu’après l’avoir fait, on obtient le message :

This program cannot be run in WIN mode.

En cherchant ce texte précis sur Google, on tombe sur un writeup d’un CTF de 2017 expliquant qu’après avoir eu ce message, il a du exécuter le programme sous DOS via DOSBox pour obtenir le flag.

On connaît maintenant à priori les deux conditions d’obtention du flag :

  • Environnement DOS.
  • Date et heure définie au 01/01/1980 - 00:00:00.

Flag

J’ai donc téléchargé DOSBox et me suis renseigné sur la possibilité de suspendre le temps sans pour autant suspendre l’exécution de la box mais il semble que cela ne soit pas possible facilement. J’ai essayé d’utiliser le déboguer sans succès.

Enfin, j’ai trouvé qu’il existait un fichier de configuration dans lequel on pouvait exécuter des commandes immédiatement au lancement de la box. Et je me suis dit que peut-être qu’en modifiant le temps et exécutant le programme, ça serait assez rapide pour que cela marche.

J’ai donc ajouté ceci à la fin du fichier dosbox-x.conf :

[autoexec]
mount c ../..
c:
date 01/01/1980
time 00:00:00
TIMMEE.EXE > a.txt

(J’ai renommé mon programme comme ceci car sinon il exécutait la commande time)

Et, surprise en ouvrant mon a.txt :

FCSC{D4735-4r3-d1ff1cu17-70-und3r574nd-15n7-17?}

Conclusion

Petit challenge sympathique que je suis très content d’avoir réussi avec seulement une semaine d’expérience avec le reverse et l’assembleur ! Ça donne envie de continuer.

Pour l’anecdote, j’ai flag 10 minutes avant la fin du FCSC après m’être arraché les cheveux un moment, car je faisais la commande date 01-01-1980 au lieu de date 01/01/1980 depuis le début :-)