OllyDead By Synapsus
par Kharneth
 
Outils utilisésPublicCible
 - OllyDbg 1.10
 - www.Google.com
 - Papier, Crayon, Cerveau 5.0
 Débutant avancé en Cracking
ayant de bonnes connaissances en programmation
 OllyDead.exe
 
1 - Introduction 

      Il faut trouver la seule et unique date à laquelle le programme veut bien afficher le message de félicitations. Avant de commencer, quelques précisions:
      1 - Le carton, c'est gratuit.(Comment ça c'est pas une raison?? :p)
      2 - La mousse, c'est joli! (sisi y'a plein de couleurs! )

2 - OllyDbg 

      On commence par tracer dès le début du programme et les choses sérieuses commencent rapidement avec une utilisation très particulière de l'api lstrcpy qui va faire office de JMP. D'abord, la chaine "NGEN" est remplacée par les caractères {0xD7, 0x13, 0x40, 0x00} correspondant à l'adresse sur laquelle on veut sauter. C'est la chaine à copier.

      Voici une capture de la pile pour comprendre que String2 va être copiée dans String1 et ainsi remplacer l'adresse de retour de l'api(004010C1) par 004013D7.

      On arrive donc en 004013D7 sur un code illisible qui correspond en fait à une boucle qui va décrypter la suite du code. (Lorsque le code est rempli de CCA, je trace tranquillement avec F7 en surveillant l'exécution). Voici cette boucle une fois nettoyée:

      On continue à tracer jusqu'en 004016B8 ou le NOP précédent est remplacé par un RETN. On verra plus tard que cette boucle sera exécutée une nouvelle fois pour recrypter le code.
      Ensuite, le programme récupère le dossier TEMP puis y crée le fichier Crackme.sys avant d'y copier un binaire extrait des ressources.
      A partir de l'adresse 00401722, les apis utilisées (OpenSCManagerA, OpenServiceA, CreateServiceA...) nous indiquent que le fichier est en fait un exécutable sous la forme d'un service NT. Ce service va être créé puis démarré. Il est important de remarquer le code suivant:

      Finalement, le service est détruit tout comme le fichier temporaire. Puis, le programme retourne en 004013D7 au début de la boucle de cryptage pour recrypté le code qui vient d'être exécuté. Mais cette fois, le RETN à la fin de la boucle nous envoie en 004010C1, juste après le lstrcpy du début! Ensuite, l'interface est créée de manière classique, mais "l'évènement" WM_CREATE contient ce code:

      La variable qui va déterminer l'enregistrement du programme se situe en 0040626F et doit contenir la valeur 0x57. On voit que cette variable est remplie en 004017D5 par la valeur de retour de l'api GetLastError, elle-même déterminée par l'api StartServiceA. Il devient donc évident que le service contient une fonction qui va vérifier la date de l'ordinateur puis la comparer à la date attendue. Et enfin générer une erreur de type 57h == 87d == ERROR_INVALID_PARAMETER.

3 - Crackme.sys 

      Pour les raisons évoquées en Introduction, ce qui suit peut sembler être (est) du bricolage.
      Comme OllyDbg ne sait pas ouvrir autre chose que des PE avec un subsystem de 2 ou 3 (et même des DLL dans la version 1.10!), je vais renommer le Crackme.sys en .exe et passé le subsystem à 3 grâce à LordPe. Une fois dans Olly (qui plante évidemment), on saute sur l'adresse 10360 (ImageBase + EntryPoint donné par LordPe) où l'on voit le code désassemblé mais non exécutable.
      Etant donné que je ne connais pas toutes les subtilités du code en mode protégé, je ne vais pas expliquer la routine principale mais seulement les 3 procédures qu'elle appelle. La 1ère permet le passage en mode protégé et la dernière le retour en mode réél.

      Quand à la 2ème, c'est justement la fonction de vérification de la date! Elle va lire le jour, le mois et l'année dans l'horloge interne (RealTimeClock) à l'aide du code suivant:

      Ce code est exécuté 4 fois, la valeur mise dans AL déterminant quelle information est récupérée, 7 pour le jour, 8 pour le mois, 32h pour le siecle et 9 pour l'année. Le résultat est une chaine de caractères de la forme: "11062004" pour le 11 juin 2004 par exemple. Ensuite cette chaine est cryptée avec le code réversible suivant:

      Finalement, le résultat est comparé à la chaine hexa B310AE1162136611. Si les 2 chaines sont différentes, la valeur 0xC0000010 est placée en 104A4.

      Au début du programme, on voit que l'adresse contient la valeur 0xC0000182.

      De plus, la valeur contenue à cette adresse est renvoyée lorsque le service quitte.

      Une rapide recherche nous indique ceci:
- C0000010 == ERROR_INVALID_FUNCTION
- C0000182 == ERROR_INVALID_PARAMETER

      Il ne reste plus qu'à décrypter la chaine B310AE1162136611 avec la fonction inversée pour trouver la bonne date. L'algo étant simple, j'ai utilisé 32bit Calculator de cybult.
La boucle est exécutée 2 fois. La première fois, des calculs sont effectués sur un DWORD formés à partir du 1er et du 3eme WORD. LE 2eme passage utilise le 2eme et 4eme WORD. (En n'oubliant pas le Little Endian 16bits):


BSWAP ( NOT ( ( 136210B3 - 29A ) XOR DEADC0DE ) ) = 38313032
BSWAP ( NOT ( ( 116611AE - 29A ) XOR DEADC0DE ) ) = 35303430

On obtient la chaine 31383035323033034 soit en mode texte la date attendue qui est le 18 05 2004.
      Pour vérifier, on lance une fenêtre d'invité de commande et on tape "date 18.05.04" pour modifier la date du système. Puis on lance le Crackme et voilà ce qui apparait:

Kharneth 

The killer awoke before dawn,
he put his boots on


Merci à toutes les personnes qui se battent pour que l'Information soit accessible à tous!