(FR) Challenge NES 2 – Partie 4/5 : Crack-me

Cette partie va concerner le répertoire 03 qui contient un readme.txt, et un …. crack_me.exe !

Comme il est coutume dans ce genre de cas, on commence par un « file » :

kriss@ROG ~> file crack_me.exe
crack_me.exe: PE32 executable (console) Intel 80386, for MS Windows

les strings quant à elles ne donnent que quelques détails, mais on en reparle après.

PE32 for MS Windows, passage sous Windows donc !

On comprend assez vite que le PE récupère l’heure système de notre hôte, et en déduit qu’ »Il n’est pas l’heure ! »

Le bon serial doit donc être généré quand on exécute le binaire à une heure (hh :mm :ss) bien précise.
Les trois questions sont :

  • Quelle heure ?
  • Le serial est-il calculé à partir de l’heure en question ?
  • Si oui, comment ?

Il se trouve que dans les strings, on a quelque chose qui ressemble quand même un peu beaucoup à une heure, je dirais même que tous les indices sont présent dans les chaines suivantes :

0F1F53466303495C
today time is =
05:22:43
{NesToken}:
 hex:
Il n'est pas l'heure !

Un coup dans la source nous confirme que l’heure système est effectivement comparée à 05 :22 :43 :

On va modifier directement l’heure chargée en mémoire par la méthode GetCurrentTime grâce à Olly :

Et poursuivre l’exécution du programme. On arrive ainsi sur la fonction qui exécute un XOR de l’heure avec la clef d’ailleurs présente « en clair » dans les strings du binaire : 0F1F53466303495C

Et finalement :

J’avoue que sur le moment j’ai un peu buggé en voyant ce format de serial et j’ai retourné le code dans tous les sens en étant persuadé que j’avais loupé quelque chose.

Je suis même passé par un genre de « keygen» qui se propose de calculer le serial pour toutes les heures possibles… je partage pour le fun :

import binascii
from dateutil import rrule
from datetime import datetime, timedelta

mask = '0F1F53466303495C'

def hexxor(a, b):
    if len(a) > len(b):
        return '%x' % (int(a[:len(b)],16)^int(b,16))
    else:
        return '%x' % (int(a,16)^int(b[:len(a)],16))

now = datetime.now()
tomo = now + timedelta(days=1)

for dt in rrule.rrule(rrule.SECONDLY, dtstart=now, until=tomo):
    temps = str(dt.time())
    timehex = binascii.hexlify(temps)
    print temps + ":" + timehex + " XOR " + mask + "   /   " + binascii.unhexlify(hexxor(mask,timehex))

Output :

05:22:41:30353a32323a3431 XOR 0F1F53466303495C   /   ?*itQ9}m
05:22:42:30353a32323a3432 XOR 0F1F53466303495C   /   ?*itQ9}n
05:22:43:30353a32323a3433 XOR 0F1F53466303495C   /   ?*itQ9}o
05:22:44:30353a32323a3434 XOR 0F1F53466303495C   /   ?*itQ9}h
05:22:45:30353a32323a3435 XOR 0F1F53466303495C   /   ?*itQ9}i
05:22:46:30353a32323a3436 XOR 0F1F53466303495C   /   ?*itQ9}j

Bref.. assez tourné autour du pot, le token est bien : ?*itQ9}o

 


./Kriss