__TwG__ Keygen-Me - Tutorial [fr]
================================================================================
Author        : Canterwood <canterwood@altern.org>
Protection    : anti-debugging routine, variable-key Vigenere & Caesar ciphers
Level         : Intermediate
Tools         : OllyDbg
Attached files: crackme + JavaScript keygen
================================================================================
01.01.2004

Introduction
--------------------------------------------------------------------------------
  Je suis tomb sur ce keygenme un peu par hasard, alors que je passais sur le
site du RIF. Quand j'ai vu que le niveau tait "Intermdiaire", je me suis dit
que je pouvais tenter ma chance, ne serait-ce que pour essayer.
Qui ne tente rien n'a rien...

Solution I : Backdoors
--------------------------------------------------------------------------------
  Aprs avoir lanc le crackme, j'ai rentr  tout hasard un nom sans spcifier
de serial... et l  Surprise, le le message "Great Ke_gen it now" s'affiche.
Cette astuce, que l'on pourrait qualifier de "backdoor" (porte de derrire, ou
moyen d'esquiver la routine de validation du serial) fonctionne quelque soit le
nom entr, mais n'est pas intressante dans le cas de notre tude, dont le but
est rappelons-le, de raliser un keygen.
Enfin, le crackme perd juste un peu de son intert, puisque nous aurions
carrment pu nous arrter ici ...

  Il existe une deuxime "backdoor", qui dcoule de la solution n2 que nous
allons voir juste aprs. Elle consiste  entrer un nom compos de caractres non
alphabtiques, par exemple :

@12-"__"

Dans ce cas, le serial sera tout simplement identique au nom !
Nous ne pouvons que regretter la prsence de cette seconde faille... cependant,
la suite est suffisament intressante pour nous donner envie d'approfondir notre
tude.

Solution II : Analyse
--------------------------------------------------------------------------------
  Comme d'habitude, nous ouvrons le crackme avec OllyGbg puis nous posons un
breakpoint sur la fonction API GetDlgItemTextA.
Aprs avoir renseign les champs et appuy sur "Test", le programme se gle.

Il s'agit de l'endroit de rcupration du nom. Nous pouvons voir que la
procdure de validation a dj t pas mal entame ; en fait les instructions
prcdentes servent  dcrypter les chanes affiches aprs vrification (good
boy, bad boy, nom invalide), donc rien de bien important.

Si maintenant nous regardons ce qu'il y a sous notre "point d'atterissage", cela
a de quoi dcourager : plus de 300 lignes de code effectuant des manipulations
sur le nom, avant un prochain appel  GetDlgItemTextA (qui va s'occuper cette
fois du serial).
Ensuite, le serial est crypt, puis compar  la forme galement crypte du nom.

NB : des appels de fonction partculiers sont parpilles un peu partout dans le
code :

CALL 004030B7

Si nous regardons son contenu (des GetTickCount, DestroyWindow...), on peut
prsumer qu'il s'agit d'une astuce anti-debugging. Mais elle semble
malheureusement (ou heureusement, que dis-je !) hors-service...

  Au dbut, j'tais parti pour ripper l'intgralit du code de cryptage du nom,
et de n'analyser que la routine d'encodage du serial, afin de la renverser...
Mais avec toutes ces boucles, ces accs  la pile, ces fonctions, etc... ce
n'est gure excitant. Et puis le rippage est une technique rpute comme
"bourrin", bien que souvent trs utile.

N'ayant aucune autre solution en tte, j'ai regard ce que donnait le nom
crypt. Ce dernier est en clair, ainsi pour "Canterwood", on obtient cela :

Nom          : CANTERWOOD
Cryptogramme : PAIKGEWJFF

Je me suis dit... tiens... si j'essayais, aprs tout... J'ai chang une lettre 
mon nom :

Nom          : CANTEROOOD
Cryptogramme : PAIKGEOJFF

Ma "prdiction" tait bonne, le nom n'est que partiellement altr (une lettre
est modifie !).
J'ai fait d'autres essais pour confirmer, et cela semble marcher :

CANTERPOOD -> PAIKGEPJFF
CANTERWPOD -> PAIKGEWKFF
CANTERWQOD -> PAIKGEWKFF

Tout ceci est bien beau, mais qu'allons nous en faire ?

J'ai tout de suite pens  un algorithme de type Csar (dcalage de l'alphabet)
qui serait appliqu  chaque lettre. J'ai fait quelques analyses qui se sont
avres concluantes.
Mais au bout d'un certain temps, j'ai commenc  voir qu'il y avait des
rptitions de cl. Par exemple :

Lettre 1 : ABCDEFGHIJKLMNOPQRSTUVWXYZ
           NOPQRSTUVWXYZABCDEFGHIJKLM

Lettre 2 : pas de cryptage

Lettre 3 : ABCDEFGHIJKLMNOPQRSTUVWXYZ
           VWXYZABCDEFGHIJKLMNOPQRSTU

...

Lettre 6 : ABCDEFGHIJKLMNOPQRSTUVWXYZ
           NOPQRSTUVWXYZABCDEFGHIJKLM => rptition

Cette vidence n'en tait pas une pour moi au dpart, mais tout d'un coup je me
rappelle d'une chose : il s'agit bien sr d'un cryptage de Vignre (une sorte
de Csar amlior avec cls multiples, comme ci-dessus) !
Je me suis donc mis en tte de trouver la cl globale, qui correspond en gnral
 un mot.
a a l'air de marcher, celle-ci fait 5 caractres, le premier dcalage est de 13
(N - A), le second de 0, ... et la rpttion s'effectue au sixime dcalage.

Une fois cette cl trouve, j'ai voulu l'appliquer  d'autres noms que
"Canterwood", et mauvaise surprise, celle-ci ne marche plus... Elle ne
fonctionnait en fait que pour les noms de dix caractres. Nous aurions donc
affaire  un algorithme de Vignre " cl variable" ?
En effet, c'est bien le cas, mais nous constatons que chaque cl, base sur le
nombre de caractres, ne diffre pas tellement des autres.

Je vous embrouille ? Voyons donc par une application pratique.

Si l'on entre comme nom "A", le cryptogramme correspondant sera "E" (dcalage de
4 lettres).
Si maintenant on essaye "AA", le rsultat sera "FS".
Avec "AAA", celui-ci sera "GTO"

Deux choses importantes  noter :
- il existe une cl "initiale", qui va encoder de manire diffrente chaque
caractre ;
- chaque lment de cette cl est incrment de 1 lorsque la taille du nom
augmente.

Essayez de bien comprendre cela, car c'est crucial pour la rsolution du
crackme.

Pour le premier caractre, la cl est initialement 4, puis elle passe  5, 6, et
ainsi de suite. On lui ajoute longueurNom - 1 units.
Idem pour les valeurs de cl suivantes.

Par ailleurs, la cl est rpte, car :

AAAAAAAAAAA -> OBWSDOBWSDO (rptition de "OBWSD")

Il y a une dernire chose qu'il ne faut pas oublier avant de nous lancer dans le
codage d'un petit algorithme automatisant le processus,  savoir le cas des
caractres non alphabtiques et leur incidence sur la cl. Faisons simplement
un petit test :

A1A2A3A4A5A -> O1B2W3S4D5O

OK, nous retrouvons la forme du dessus et aucun index de cl n'est saut.

 Nous sommes dsormais prts  mettre cela en forme avec un petit bout de code
rsultant de notre analyse.
Pour des raisons de commodit, j'ai dcid de le faire en JavaScript, qui
propose une gestion aise des chanes de caractres.

Voici ce que cela donne :

--

table = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
key   = [4, 17, 12, 8, 19];

name = "CANTERWOOD";
c    = "";
j    = 0;

for(i = 0; i < name.length; i++)

  if(name.charCodeAt(i) >= 0x41 && name.charCodeAt(i) <= 0x5A)
  {
    c += table.charAt((table.indexOf(name.charAt(i)) + key[j % key.length]
         + name.length - 1) % table.length);
    j++;
  }
  else
    c += name.charAt(i);

--

Vous retrouverez bien sr ceci dans le keygen final. Cet algo (trs rduit, il
faut bien l'avouer) reproduit exactement ce que nous avons dcrit prcdemment.
Dans le cas ci-dessus, la variable "c" contiendra en fin de boucle "PAIKGEWJFF",
ce qui correspond  la forme crypte du nom "CANTERWOOD".
En une dizaine de lignes de JavaScript, nous avons fait tenir les quelques
centaines d'intructions assembleur correspondantes...

Je ne vais pas vous dcortiquer le code car il faut avoir un minimum de bases en
programmation, et puis une tude trop pousse demanderait un dveloppement
supplmentaire non ngligeable. Retenez juste la fonction globale de ce code,
sans vous soucier des quelques dtails sur lesquels vous butez (si le cas se
prsente, bien sr).

  Pour la suite, je ne vais pas tout dtailler comme je l'ai fait pour le nom.
Sachez simplement que le serial subit un codage un peu moins lbor, puisqu'il
s'agit d'un "Csar  cl variable". La diffrence avec le Vignre est que
toutes les lettres subissent le mme dcalage, donc pas besoin d'utiliser de
variable "key".

Le tout est de se dbrouiller pour renverser l'algorithme afin de pouvoir
trouver le serial valide  partir du cryptogramme du nom. En procdant par
ttonnements comme avant, on arrive petit  petit  comprendre :

A   -> Z
AA  -> YY
AAA -> XXX

Bref, inutile de s'tendre l-dessus. La routine inverse est la suivante :

--

serial = "";

for(i = 0; i < c.length; i++)

  if(c.charCodeAt(i) >= 0x41 && c.charCodeAt(i) <= 0x5A)
    serial += table.charAt((table.indexOf(c.charAt(i)) + c.length)
    % table.length);
  else
    serial += c.charAt(i);

--

Tous les lments sont dsormais runis pour coder notre keygen. Celui-ci
fonctionne  100% (du moins d'aprs mes tests), voici quelques exemples de
serials valides :

Name  : CANTERWOOD
Serial: ZKSUQOGTPP

Name  : __TWG__
Serial: __KAF__

Name  : RIF
Serial: AEW

Name  : 12345
Serial: 12345

On retombe sur notre fameuse backdoor, puisque les caractres non-alphabtiques
ne sont pas pris en compte dans le cryptage.

Voil, je crois que ce sera tout pour cette fois ! Facile, n'est ce pas ?
Tout semble plus simple aprs une analyse...

Conclusion
--------------------------------------------------------------------------------
  Ce crackme est relativement intressant  tudier, et le niveau intermdiaire
est pleinement justifi : il est facile de "louper" le cryptage de Vignre et
de se retrouver  analyser des montagnes de code... remarquez  ce propos que
nous ne nous sommes pas du tout servis des instructions ASM !
Parfois, mieux vaut rflchir un peu avant d'agir...

J'espre que vous avez apprci ce tutorial qui marque le dbut de l'anne
2004 !

Et comme le disait le mythique +ORC,

"Knowledge is now free at last, everything should be free from now on,
 enjoy knowledge and life and work for everybody else".

Une rsolution  prendre ? Je crois, oui !
Dans le monde bizarre dans lequel nous vivons, mieux vaut parfois se rattacher 
des convictions personnelles plutt que de suivre le mouvement de masse.
L'Histoire l'a maintes et maintes fois prouv...

================================================================================
Remerciements : tous ceux qui m'ont permis de dbuter en cracking via leurs
tutoriaux, c'est  dire +Analyst, les membres de la ShmeitCorp, Lise_Grim... et
bien d'autres.

Je salue par ailleurs tous les acteurs de la scne franaise.

Canterwood