ConquerMe II: The Lost Princess
by MisterE


Tutorial de Lucifer48 [Immortal Descendants]
(8 ao√t 1999)


Sommaire:
Battle One: One yer Way!
Battle Two: The Tower
The Final Battle: The Princess
Conclusion & Greetings


Battle One: One yer Way!

XXXX:004015E5  CALL USER32!SendDlgItemMessageA  ;(WM_GETTEXTLENGTH)
XXXX:004015EA  CMP  EAX,10                      ;le serial comporte-t-il 16 caractΦres ?
...                                             ;(le 16Φme caractΦre n'est pas utilisΘ)
XXXX:00401602  CMP  EAX,08
XXXX:00401605  JAE  0040161B                    ;8 caractΦres minimum pour le nom (sinon ..
...                                             ; .. rajoute des caractΦres nuls pour arriver α 8)
XXXX:0040161B  CALL 004012DE                    ;a explorer!
XXXX:00401620  PUSH 004044A8                    ;11111111
XXXX:00401625  PUSH 004044E2                    ;encrytion 8 chiffres
XXXX:0040162A  CALL KERNEL32!lstrcmp            ;comparaison
XXXX:0040162F  OR   EAX,EAX
Le call 004012DE est composΘ de plusieurs boucles succΘssives. Pour des raisons pratiques, introduisons les notations suivantes: je dΘsigne X0, X1, X2, ..., Xe les 15 caractΦres du serial; N0, N1, ..., N7 dΘsignera les caractΦres du nom.

Voilα une premiΦre boucle:
XXXX:00401353  PUSH ECX                         ;BOUCLE #1 (ecx contient l'indice de boucle)
XXXX:00401354  MOV  AL,[ECX+004046E3]           ;lit X0, X1, ..., X7
XXXX:0040135A  MOV  DL,[ECX+00404AE5]           ;lit N0, N1, ..., N7
XXXX:00401360  SUB  AX,DX
XXXX:00401363  MOV  DL,[ECX+00404AF4]           ;lit X7, X9, ..., Xe
XXXX:00401369  SUB  AX,DX
XXXX:0040136C  ADD  AX,012C
XXXX:00401370  MOV  BL,0A
XXXX:00401372  CWD
XXXX:00401374  IDIV BX
XXXX:00401377  ADD  ESI,EDX                     ;esi va contenir une sorte de checksum
XXXX:00401379  OR   DL,30
XXXX:0040137C  POP  ECX
XXXX:0040137D  MOV  [ECX+0040449F],DL           ;Θcrit le caractΦre final
XXXX:00401383  INC  ECX
XXXX:00401384  CMP  ECX,08
XXXX:00401387  JNZ  00401353
Cette boucle nous concocte donc un joli petit serial de 8 chiffres (notons le S0, S1, ..., S7).
  (X0 - N0 - X7 + 12Ch) mod Ah
+ (X1 - N1 - X8 + 12Ch) mod Ah
+  ...
+ (X7 - N7 - Xe + 12Ch) mod Ah
-------------------------------
= ESI
On continue:
XXXX:004013B2  MOV  DL,[004046E3]               ;lit X0
XXXX:004013B8  AND  DL,0F
XXXX:004013BB  ADD  ESI,EDX                     ;valeur dΘfinitive pour esi
XXXX:004013BD  XOR  EDX,EDX
XXXX:004013BF  MOV  EAX,ESI
XXXX:004013C1  MOV  CL,08
XXXX:004013C3  CWD
XXXX:004013C5  IDIV CX
XXXX:004013C8  XOR  ESI,ESI
Le rΘsultat (du modulo) est en EDX, et va influencer la recopie de la chaine X0, X1, ..., X7 de la maniΦre suivante:
XXXX:004013CC  MOV  AL,[ESI+004046E3]           ;lit X0, X1, X2, ..., X7
XXXX:004013D2  MOV  [EDX+004044E2],AL           ;recopie (dans le dΘsordre)
XXXX:004013D8  INC  EDX
XXXX:004013D9  CMP  EDX,08
XXXX:004013DC  JNZ  004013E3
XXXX:004013DE  MOV  EDX,00000000
XXXX:004013E3  INC  ESI
XXXX:004013E4  CMP  ESI,08
XXXX:004013E7  JNZ  004013CC
Exemple: EDX=5, alors
X0 X1 X2 X3 X4 X5 X6 X7 ==[devient]==> X3 X4 X5 X6 X7 X0 X1 X2

On poursuit:
XXXX:004013F5  PUSH ECX                         ;BOUCLE #2 (ecx contient l'indice de boucle)
XXXX:004013F6  XOR  EDX,EDX
XXXX:004013F8  XOR  EAX,EAX
XXXX:004013FA  MOV  DL,[ECX+0040449F]           ;lit S0, S1, ..., S7
XXXX:00401400  SUB  AX,DX
XXXX:00401403  ADD  AX,012C
XXXX:00401407  MOV  BL,0A
XXXX:00401409  CWD
XXXX:0040190B  IDIV BX
XXXX:0040140E  MOV  AL,[ECX+004044E2]           ;lit X0, X1, ..., X7 (mis dans le DESORDRE)
XXXX:00401414  AND  AL,0F
XXXX:00401416  ADD  AL,0A
XXXX:00401418  SUB  AL,DL
XXXX:0040141A  CMP  AL,09
XXXX:0040141C  JBE  00401420
XXXX:0040141E  SUB  AL,0A
XXXX:00401420  OR   AL,30
XXXX:00401422  MOV  [ECX+004046E3],AL           :on va encore obtenir 8 chiffres...
XXXX:00401428  POP  ECX                         ;notons le T0, T1, ..., T7
XXXX:00401429  INC  ECX
XXXX:0040142A  CMP  ECX,08
XXXX:0040142D  JNZ  004013F5
La boucle suivante est exactement la mΩme que la BOUCLE #1 sauf que, Θvidemment les arguments ne sont pas les mΩme!
XXXX:00401439  PUSH ECX
XXXX:0040143A  MOV  AL,[ECX+004044E2]           ;lit X0, X1, ..., X7 (mis dans le DESORDRE)
XXXX:00401440  MOV  DL,[ECX+004046E3]           ;lit T0, T1, ..., T7
XXXX:00401446  SUB  AX,DX
XXXX:00401449  MOV  DL,[ECX+00404AF4]           ;lit X7, X9, ..., Xe
...
exactement pareil que la BOUCLE #1
...
XXXX:00401463  MOV  [ECX+004044E2],DL           ;on va encore obtenir 8 chiffres...
XXXX:00401469  INC  ECX                         ;notons le U0, U1, ..., U7
XXXX:0040146A  CMP  ECX,08
on continue...
...                                             ;quelques lignes qui ne servent α rien...
XXXX:00401498  MOV  DL,[004044E2]               ;lit U0
XXXX:0040149E  AND  DL,0F
XXXX:004014A1  ADD  ESI,EDX                     ;mΩme principe que tout α l'heure
XXXX:004014A3  XOR  EDX,EDX
XXXX:004014A5  MOV  EAX,ESI                     ;rΘutilise le ckecksum de la boucle prΘcΘdente
XXXX:004014A7  MOV  CL,08
XXXX:004014A9  CWD
XXXX:004014AB  IDIV CX				;edx: reste de la division euclidienne
XXXX:004014AE  XOR  ESI,ESI
Encore une fois le reste de la division va nous servir...
XXXX:004014B2  MOV  AL,[ESI+004044E2]           ;lit U0, U1, ..., U7
XXXX:004014B8  MOV  [EDX+004046E3],AL           ;recopie (dans le dΘsordre)
XXXX:004014BE  INC  EDX                         ;(c'est la mΩme chose qui ci-dessus)
XXXX:004014BF  CMP  EDX,08
XXXX:004014C2  JNZ  004014C9
XXXX:004014C4  MOV  EDX,00000000
XXXX:004014C9  INC  ESI
XXXX:004014CA  CMP  ESI,08
XXXX:004014CD  JNZ  004014B2
Courage c'est la derniΦre boucle:
XXXX:004014DB  PUSH ECX                         ;exactement pareil que la BOUCLE #2
...
XXXX:004014E0  MOV  DL,[ECX+00404AF4]           ;lit X7, X9, ..., Xe
...
XXXX:004014F4  MOV  AL,[ECX+004046E3]           ;lit U0, U1, ..., U7 ( mis dans le dΘsordre)
...
XXXX:00401508  MOV  [ECX+004044E2],AL           ;nos 8 chiffres finaux (*)
XXXX:0040150E  POP  ECX
XXXX:0040150F  INC  ECX                         ;boucle suivante
XXXX:00401510  CMP  ECX,08
XXXX:00401513  JNZ  004014DB
(*) Ce nombre (= 8 chiffres) est ensuite comparΘ α 11111111.
Retrouvons maintenant un bon serial... Heureusement pour nous, chaque caractΦre est indΘpendant les uns des autres.

Voilα ce qu'il faut trouver pour le 1er caractΦre:
L1:    {   ( (X0 - N0 - X7 +12C ) mod Ah ) OR 30h = S0
L2:    {   ( ( (X0' AND F) + Ah ) - ( (-S0 + 12C) mod Ah ) ) OR 30h = T0     (**)
L3:    {   ( (X0' - T0 - X7 + 12C) mod A ) OR 30h = U0
L4:    {   ( ( (U0' AND F) + Ah ) - ( (-X7 + 12C) mod Ah ) ) OR 30h = 31h    (***)
Remarque: J'ai notΘ X0' l'octet X0 aprΦs mise en dΘsordre, mΩme chose pour U0' (voir XXXX:004014AB et XXXX:004013C5).

(**): N'oublions pas que si T0>39h alors T0=T0-Ah ;mΩme chose pour (***).

Analysons la quatriΦme ligne (L4):
on doit avoir ((U0' AND F) + Ah) - ((-X7 + 12C) mod Ah) = 1. En n'oubliant pas la condition (**), on a six possibilitΘs:
    (U0' AND F) + Ah) = Fh  et  ((-X7 + 12C) mod Ah) = 4
ou  (U0' AND F) + Ah) = Eh  et	((-X7 + 12C) mod Ah) = 3
ou  (U0' AND F) + Ah) = Dh  et	((-X7 + 12C) mod Ah) = 2
ou  (U0' AND F) + Ah) = Ch  et	((-X7 + 12C) mod Ah) = 1
ou  (U0' AND F) + Ah) = Bh  et	((-X7 + 12C) mod Ah) = 0
ou  (U0' AND F) + Ah) = Ah  et	((-X7 + 12C) mod Ah) = 9
Et donc:
    (U0' AND F) + Ah = {Fh, Eh, Dh, Ch, Bh ,Ah}
<=> (U0' AND F)      = {5, 4, 3, 2, 1, 0}
<=> U0' = {35h, 34h, 33h, 32h, 31h, 30h}
Les caractΦres U0, U1, ..., U7 sont obligatoirement compris entre 30h et 35h. On utilise la mΩme dΘmarche pour la ligne 2 (L2).

S0, S1, ..., S7 peut contenir les caractΦres suivants: {"0", "1", "2", "3", "8", "9", ":", ";", "<", "="}. Mais en regardant la ligne 1 (L1), on voit que S0, S1, ..., S7 est issu d'un modulo Ah, ainsi, les caractΦres de S0, S1, ..., S7 doivent obligatoirement Ωtre: {"0", "1", "2", "3", "8", "9"}

Grace α ces quelques restrictions on va pouvoir essayer de contruire des couples (X0-X7, ..., X7-Xe). Voir ma source en C, ainsi pour chacun des huit lettres du nom, on va trouver des couples.

Remarque: Le caractΦre 8 est important car il est utilisΘ deux fois (couple X0-X7 et X7-Xe), donc faut faire attention. Les 6 autres couples, je les ai pris un peu au hasard. exemple: _123456_789abc_ (attention les deux couples X0-X7 et X7-Xe ont un terme commun!)

Que donne ma source?
Elle gΘnΦre les couples possibles pour chaque lettre et en prenant 8 couples τa peut marcher! Pourquoi τa peut: parce que ma source suppose qu'il n'y a pas de mise en dΘsordre; X?=X?' et U?=U?'. (voir en XXXX:004014AB et XXXX:004013C5). C'est selon moi la maniΦre la plus simple d'enregister ce crackme.

Et donc, il va falloir trouver les couples qui donnent bien EDX=0 (d'autres valeurs pour edx sont possibles) en XXXX:004013CC et XXXX:004014B8. Afin de ne pas changer l'ordre de X0, X1, ..., X7 (mΩme chose pour U0, U1, ..., U7).

Comment trouver un bon serial?
Il faut dΘjα passer la premiΦre mise en dΘsordre, pour celα, un petit peu de bon sens; on essaye de crΘer les 8 premiers caractΦres cycliques (exemple: 48484848), ou avec beaucoup de caractΦres identiques. AprΦs quand on a passΘ la premiΦre mise en dΘsordre on fait des essais en changeant uniquement les 7 derniers caractΦres afin de passer la deuxiΦme barriΦre (edx=0 en XXXX:004014AB; ou edx=? du moment que U0=U0', ..., U7=U7').

Pour moi, je prend donc huit couples:
0       2		;couple pour la lettre "L"
 0       X		;couple pour la lettre "u"
  0       8		;couple pour la lettre "c"
   4       8		;couple pour la lettre "i"
    1       8		;couple pour la lettre "f"
     0       9		;couple pour la lettre "e"
      4       X		;couple pour la lettre "r"
       e       n	;couple pour la lettre "4"
-----------------
0004104e2X8889Xn
A cela, s'ajoute un seiziΦme caractΦre qui n'est pas utilisΘ par la protection, et on obtient, quelques bons serials (Name/ Lucifer48):

0004104e2X8889n*
0004104e2X8889d*
0004104e2X8889Z*
0004104e2X8889P*
0004104e2X8889F*

`004104e2X8889x*
...
`004104e2X8889F*

* constitue n'importe quel caractΦre

Status: registered!!


Battle Two: The Tower

XXXX:00401834  PUSH 004046E3				;adresse du buffer
XXXX:00401839  PUSH EAX					;longueur du serial -1 (voir remarque)
XXXX:0040183A  PUSH 0D					;WM_GETTEXT
XXXX:0040183C  PUSH 000000CB				;serial edit box
XXXX:00401841  PUSH DWORD PTR [EBP+08]			;handle de la dialog box
XXXX:00401844  CALL USER32!SendDlgItemMessageA
XXXX:00401849  CALL 0040168B				;α explorer!
XXXX:0040184E  CMP  BYTEP PTR [004044E0],01
XXXX:00401855  JNZ  0040187D				;jmp = mauvais serial
Remarque: Le dernier caractΦre tapΘ au clavier n'est pas lu, car le buffer Θtant de taille EAX (EAX Θtant la taille du serial obtenu via WM_GETTEXTLENGTH juste avant); en fait la taille du buffer est EAX-1; le dernier octet Θtant le caractΦre nul; donc en doit rajouter un caractΦre quelconque aprΦs le serial pour obtenir le bonne longueur. A mon avis, c'est volontaire car le nom est lu dans son intΘgralitΘ (XXXX:00401806 INC EAX).

Notons X0, X1, ..., X9 les caractΦres du serials; et N0, N1, ..., N8 ceux du nom.
Dans le call 0040168B:
... (eax=ebx=ecx=edx=0)
XXXX:00401693  MOV  AL,[004046E3]			;X0
XXXX:00401698  XOR  AL,[004046EC]			;X9
XXXX:0040169E  XOR  AH,AL				;AL=AH
XXXX:004016A0  XOR  AX,[004046E4]			;X2 X1
XXXX:004016A7  XOR  EAX,[004046E6]			;X6 X5 X4 X3
XXXX:004016AD  XOR  EAX,[004046E8]			;X8 X7 X6 X5
XXXX:004016B3  XOR  EAX,[00404AE5]			;N3 N2 N1 N0
XXXX:004016B9  XOR  EAX,[00404AE8]			;N6 N5 N4 N3
XXXX:004016BF  XOR  AX,[00404AEC]			;N8 N7
XXXX:004016C6  MOV  ECX,EAX				;garde le rΘsultat pour plus tard
XXXX:004016C8  MOV  EBX,00000029
XXXX:004016CD  CWD
XXXX:004016CF  IDIV EBX
XXXX:004016D1  MOV  EAX,EDX
XXXX:004016D3  MOV  EBX,00000009
XXXX:004016D8  CWD
XXXX:004016DA  IDIV EBX
XXXX:004016DC  MOV  EAX,EDX
Donc EAX= (EAX mod 41d) mod 9; on a 9 possibilitΘs:
EAX=0: EAX = (ECX mod 7) + 1 et ECX = ECX XOR 00BC614E   (BC614Eh=12345678d)
EAX=1: ECX = ECX XOR 0023CACE		;23CACEh = 2345678d
EAX=2: ECX = ECX XOR 0005464E		; 5464Eh =  345678d
EAX=3: ECX = ECX XOR 0000B26E		;  B26Eh =   45678d
EAX=4: ECX = ECX XOR 0000162E		;  162Eh =    5678d
EAX=5: ECX = ECX XOR 000002A6		;   2A6h =     678d
EAX=6: ECX = ECX XOR 0000004E		;    4Eh =      78d
EAX=7: ECX = ECX XOR 00000008		;     8h =       8d
EAX=8: ECX = ECX XOR 00000000
Si le nom n'est pas assez grand, on peut facilement utiliser le fait que l'octet est nul (le buffer est largement assez grand).
XXXX:00401743  CMP  EAX,36F95001
XXXX:00401749  SETZ AL
XXXX:0040174C  MOV  [004044E0],AL
XXXX:00401751  RET
Tout τa pour dire qu'en XXXX:004016C6, ecx mod 41d = { 36d, 27d, 18d, 9d, 0d }.
On exΘcute le cas ou EAX=0, pour obtenir une nouvelle valeur (entre 1 et 8) de EAX.

En va recommencer la mΩme dΘmarche que ci-dessus, aprΦs avoir exΘcutΘ la close EAX=0.
RΘsultat α trouver: 36F95001 XOR 00BC614E = 3645314F
Mais avant de trouver 3645314F, n'oublions pas qu'on doit avant passer de le test du boucle modulo (en ayant un reste nul). On voit, qu'il y a deux candidats (reste 3 et 2; voir ci-dessus). Donc:

Je rΘcapitule:
- En XXXX:004016C6 j'ai ECX = 36407701
- (36407701h mod 41d) mod 9 = 0 (en eax)
- 36407701 XOR 00BC614E = 36FC164F (XXXX:004016FD)
- (36407701h mod 7) + 1 = 2
- J'ai ECX = 36FC164F (et EAX=2)
- 36FC164F XOR 5464Eh = 36F95001 (= bon rΘsultat α trouver!!)
Ansi l'unique dword possible (en XXXX:004016C6) est: 36407701. Ce qui suit est ultra-classique (prΘsent dans pas mal de crackme).

J'enlΦve en premier le masque de mon nom ( 6963754Ch XOR 72656669h XOR 00003834 = 1B062B11 ).
36407701 XOR 1B062B11 = 2D465C10
Et donc il reste α rΘsoudre celα:
	00 00 X0 X0
 xor    00 00 X9 X9
 xor	00 00 X2 X1
 xor	X6 X5 X4 X3
 xor	X8 X7 X6 X5
	-----------
	2D 46 5C 10
Je prend par exemple (j'essaye de prendre au plus simple):
X1=X9=X0= 30h ("0")
X3= 50h ("P")
X5= 70h ("p")

X4= 2Dh ("-")
X6= 41h ("A")
X2= 30h ("0")

X5 XOR 46 = X7 donc X7= 36h ("6")
X6 XOR 2D = X8 donc X8= 6Ch ("l")
En mettant dans l'ordre, on obtient le serial: 000P-pA6l0
A ceci s'ajoute la remarque du dΘbut du chapitre; ce qui nous donne un serial:

Name/ Lucifer48
Serial/ 000P-pA6l0*

(* est un caractΦre quelconque)

ou mieux:
Serial/ #00P-pA6l#*
(* est un caractΦre quelconque; # est un caractΦre quelconque aussi)

Il y a bien d'autres possibilitΘs...

Status: registered!!


The Final Battle: The Princess

XXXX:0040270D  CMP  BYTE PTR [004044E1],01	;bonne combinaison des buttons ?
XXXX:00402714  JNZ  00402748
XXXX:00402716  PUSH 00				;MB_OK
XXXX:00402718  PUSH 0040446D			;You have succeeded!
XXXX:0040271D  PUSH 004043D6			;message de fin
XXXX:00402722  PUSH DWORD PTR [EBP+08]		;handle
XXXX:00402725  CALL USER32!MessageBoxA
XXXX:0040272A  PUSH FF
XXXX:0040272C  PUSH DWORD PTR [EBP+08]
XXXX:0040272F  CALL USER32!EndDialog
XXXX:00402734  JMP  00402748
Si on a bien disposΘ les check box alors [004044E1] est mis α 1 (juste avant il y une vΘrifivation, si on a bien mis quelque chose dans l'edit box) et lα, une dialog box se crΘe et on se retrouve devant la princesse. Super !!!

La combinaison la plus simple est d'appuyer sur 1 seul boutton:
  O O O O
 O o   o O
O   ___   O
 O       X   <------ cette check box
  O O O O
XXXX:004011F8  CALL USER32!DialogBoxParamA	;dialog box du crackme
XXXX:004011FD  CMP  BYTE PTR [004044E1],01	;voir commentaire ci-dessous
XXXX:00401204  JNZ  00401221
XXXX:00401206  MOV  EAX,004018B5
...
XXXX:00401216  PUSH DWORD PTR [004044D4]
XXXX:0040121C  CALL USER32!DialogBoxParamA	;affiche la princesse
XXXX:00401221  JMP  004012D8
En fait pour arriver α la MessageBox, il y a un patch α faire:
XXXX:004026C7  CMP  AX,013F			;control ID du boutton "OK" 
XXXX:004026CB  JNZ  0040274A
XXXX:004026CD  SHR  EAX,10			;EAX=00000000
XXXX:004026D0  OR   AX,AX
XXXX:004026D3  JNZ  00402781			;ZF est armΘ (no jump)
XXXX:004026D9  CMP  EAX,-01			;c'est IMPOSSIBLE!!!
XXXX:004026DC  JNZ  00402736
C'Θtait pour τa l'allusion: je vois l'ΘpΘe mais pas la lame ???


Conclusion & Greetings

Finalement j'ai rΘussi ! La bataille 1 Θtait vraiment la plus dure. La bataille 2 Θtait, disons classique; quand α la bataille 3: un peu bizarre ! C'Θtait quand mΩme plus dure que ConquerMe I. En attendant (peut-Ωtre) ConquerMe III (codΘ en assembleur bien s√r...); je vous salue!

Greetings: All ID members (Volatility, Torn@do, ...), Eternal Bliss, ACiD BuRN, LaZaRuS, Duelist, people on #cracking4newbies, ..., and YOU MisterE for creating two excellent crackmes !!! et toi petit cracker franτais, mon ami, mon frΦre, qui lit ces quelques lignes...



(c) Lucifer48. All rights reversed