Amusons-nous avec l'assembleur .... (ACDSee v2.xx)

Par Nody

 

Logiciel : ACDSee 2.xx (la 2.22 est utilisΘe ici)

Source : trΦs facilement trouvable

Type de crack : mΘthode brutale pour choper un s/n

Niveau : apprenti

Outils : Soft-Ice, Θditeur hexa pour sauver le boulot, du temps, un peu de connaissance de l'asm

 

Intro.

ACDSee est un logiciel de visualisation d'images que tout le monde connait, et utilise, ne serait-ce que pour mater les images XXX illΘgallement importΘes d'Internet.

Il y a une Dialog Box qui se pointe de temps en temps et qui nous demande de nous enregistrer.

Cracker cette Dialog Box est assez simple, et τa a ΘtΘ dΘveloppΘe dans d'autres tuts. de mes confrΦres cracker. Nous on va faire autre chose : choper le bon s/n.

 

Attention !!!

 

Ce texte que vous lisez est un COURS, pour tenter de mieux comprendre l'assembleur. Si vous pensez avoir devant les yeux une mΘthode rapide et simple pour avoir votre s/n personnel pour ACDSee, c'est ratΘ, allez plut⌠t sur un site warez, et cherchez-y un gΘnΘrateur, ou mieux encore, achetez-le...

 

 

Reverse enginering d'ACDSee.

 

Tout d'abord, dΘmarrez ACDSee, et allez jusqu'α la Dialog Box de saisie du nom et du s/n.

Mettez le nom que vous voulez (j'ai mis "Nody CFC") et le reg. code de votre choix. Mettez un "bpx getwindowtexta" sous Soft-Ice et appuyez sur OK : on tombe 2 fois sous SI.

Comme je suppose que vous savez tracer un prog. (ou au moins l'utilisation des commandes "d" et "?" sous SI), je vous donne la source :

Il y a les commentaires α c⌠tΘ :

 

:00405C68 56 push esi

:00405C69 FFD7 call edi ; edi = GetDlgItemTextA

:00405C6B 8D44247C lea eax, dword ptr [esp+7C];eax = reg code

:00405C6F 8D4C243C lea ecx, dword ptr [esp+3C];ecx = nom

:00405C73 50 push eax ;sauvegarde du nom et du

:00405C74 51 push ecx ;regcode sur la pile

:00405C75 E846F8FFFF call 004054C0 ;routine de vΘrification

:00405C7A 83C408 add esp, 00000008 ;dΘcale la pile de 8

:00405C7D 85C0 test eax, eax ; eax = 0 ?

:00405C7F 7E6B jle 00405CEC ; si oui on saute (bad boy)

:00405C81 8D54247C lea edx, dword ptr [esp+7C]

:00405C85 8D44243C lea eax, dword ptr [esp+3C]

:00405C89 52 push edx

:00405C8A 50 push eax

:00405C8B E8D0F9FFFF call 00405660

:00405C90 8B0D18A94A00 mov ecx, dword ptr [004AA918]

:00405C96 83C408 add esp, 00000008

:00405C99 85C9 test ecx, ecx

:00405C9B 7405 je 00405CA2

:00405C9D 8B11 mov edx, dword ptr [ecx]

:00405C9F FF5208 call [edx+08]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:00405C9B(C)

|

:00405CA2 8B0D14A94A00 mov ecx, dword ptr [004AA914]

:00405CA8 85C9 test ecx, ecx

:00405CAA 7405 je 00405CB1

:00405CAC 8B01 mov eax, dword ptr [ecx]

:00405CAE FF5014 call [eax+14]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:00405CAA(C)

|

* Possible Reference to String Resource ID=00001: "View"

|

:00405CB1 6A01 push 00000001

:00405CB3 56 push esi

* Reference To: USER32.EndDialog, Ord:00B4h

|

:00405CB4 FF15B8FB4A00 Call dword ptr [004AFBB8]

:00405CBA 6A00 push 00000000

:00405CBC 6810574000 push 00405710

:00405CC1 56 push esi

* Reference To: USER32.GetParent, Ord:011Dh

|

:00405CC2 FF15BCFB4A00 Call dword ptr [004AFBBC]

:00405CC8 8B0D1CA94A00 mov ecx, dword ptr [004AA91C]

:00405CCE 50 push eax

:00405CCF 68E4000000 push 000000E4

:00405CD4 51 push ecx

* Reference To: USER32.DialogBoxParamA, Ord:008Eh ; merci d'avoir acheter ACDSee

|

:00405CD5 FF151CFC4A00 Call dword ptr [004AFC1C]

* Possible Reference to String Resource ID=00001: "View"

|

:00405CDB B801000000 mov eax, 00000001

:00405CE0 5F pop edi

:00405CE1 5E pop esi

:00405CE2 5B pop ebx

:00405CE3 81C468020000 add esp, 00000268

:00405CE9 C21000 ret 0010

 

 

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:00405C7F(C)

|

* Possible StringData Ref from Data Obj ->"ACDSee 32"

|

:00405CEC 8B1524F24900 mov edx, dword ptr [0049F224]

:00405CF2 6A00 push 00000000

:00405CF4 52 push edx

* Possible StringData Ref from Data Obj ->"Your name and registration code "

->"do not match."

|

:00405CF5 688CF44900 push 0049F48C

:00405CFA 56 push esi

* Reference To: USER32.MessageBoxA, Ord:0195h ; vilain garτon

|

:00405CFB FF1538FA4A00 Call dword ptr [004AFA38]

* Possible Reference to Menu: MenuID_0082

|

* Possible Reference to String Resource ID=00130: "Total %d files (%s)"

|

:00405D01 6882000000 push 00000082

:00405D06 56 push esi

* Reference To: USER32.GetDlgItem, Ord:00F3h

|

:00405D07 FF1510FC4A00 Call dword ptr [004AFC10]

:00405D0D 50 push eax

* Reference To: USER32.SetFocus, Ord:01F5h

|

:00405D0E FF1520FC4A00 Call dword ptr [004AFC20]

* Possible Reference to String Resource ID=00001: "View"

|

:00405D14 B801000000 mov eax, 00000001

:00405D19 5F pop edi

:00405D1A 5E pop esi

:00405D1B 5B pop ebx

:00405D1C 81C468020000 add esp, 00000268

:00405D22 C21000 ret 0010 ; bye bye

 

Il y a donc un simple test de flag, qui nous envoie chier. Quand vous arrivez sur le test eax, eax en 00405C7D, sous SI, mettez 1 dans eax (r eax=1), et par enchantement, la version est enregistrΘe. Ne vous faites pas d'illusion, en redΘmarrant ACDSee la prochaine fois, vous verrez qu'elle n'est toujours pas enregistrΘe.

Nous savons que le call 004054C0 en 00405C75, a besoin de 2 paramΦtres placΘs sur la pile juste avant : c'est le push ecx qui contient le nom entrΘ et le push eax qui contient le reg code. Si vous essayez de tracer cette routine, au dΘbut vous vous direz que c'est facile, puis aprΦs que c'est chiant, et enfin, vous irez prendre une aspirine, aprΦs vous Ωtre perdu dans le code asm.

J'ai passΘ pas mal de temps α essayer de choper mon s/n, mais τa m'a assez pris la tΩte et j'ai prΘfΘrΘ utiliser une mΘthode brutale.

En fait, ACDSee ne crΘΘ pas le bon s/n en fonction du nom et le compare au s/n entrΘ, mais il fait la dΘmarche inverse : il chope le s/n que vous avez entrΘ, recompose une partie du nom avec, et le compare au nom entrΘ.

C'est parti, accrochez-vous :

 

:00405C6B 8D44247C lea eax, dword ptr [esp+7C];eax = reg code

:00405C6F 8D4C243C lea ecx, dword ptr [esp+3C];ecx = nom

 

En esp+7c, on a le s/n et en esp+3c, on a le nom. Evidement, le nom, on s'en tape pas mal. C'est le s/n qu'on va modifier α chaque passage tel que s/n := s/n + 1. Il y a un problΦme qui se pose d'entrΘe : esp+7c ne contient pas le s/n en tant que tel mais le code ASCII du s/n, donc il faudra Θcrire une routine en asm qui teste si le caractΦre est Θgale α ";" (code ASCII de ";" est 0x3A = 0x39+0x01 et 0x39 'est le caractΦre 9), et si il est Θgale α ";", on le remet α 0, et on incrΘmente le caractΦre α c⌠tΘ (par exple si on a "39", τa donnera "3;" aprΦs incrΘmentation du caractΦre α droite, et notre routine le transformera en "40" , OK ??).

Il faut tout d'abord connaitre le nombre de caratΦres qui compose notre s/n : on va utiliser ecx comme compteur :

 

(1):

: mov ecx, 0000000A  ; ecx = 0x0A = 10

: dec ecx        ; ecx := ecx - 1

: mov al, byte ptr [esp+ecx+7C]    ; cf ci-dessous

: cmp eax, 00000000

: je (1)

 

DΘtails :

s/n :                  1         2        3         4        5         6        7         8        9         0

pointe en : [esp+7c] [esp+7d] etc .....

 

Or [esp+7d] = [esp+7c+1], d'o∙ l'utilisation du compteur ecx [esp+7c+ecx].

On initialise ecx α 10 (9 en fait car on a un dec ecx juste aprΦs) pour que le compteur n'aille pas au-delα de 9 caractΦres ie 9'999'999'999 au max. Evidemment, ce paramΦtre est modifiable.

Comme τa aprΦs ce premier algo, on a dans ecx le nombre de caractΦres qui composent notre s/n. Il reste plus qu'α l'incrΘmenter :

 

(2):

: push ecx  ; sauvegarde le nbre de caract. de notre compteur sur la pile

: inc eax   ; eax:=eax+1 ie incrΘmentation du caratΦre α droite

: mov byte ptr [esp+ecx+00000080], al   ; le replace en [esp+7c]

: cmp eax, 0000003A   ; compare le caractΦre α ";"

: jne bye_bye   ; pas Θgal <=> on le renvoit dans la routine de vΘrif' d'ACDSee

: mov byte ptr [esp+ecx+00000080], 30 ; Θgal ? On le remplace par 0 (0x30 en ASCCII !!)

: dec ecx               / on vΘrifie tous les chiffres car aprΦs 1699, on

: cmp ecx, FFFFFFFF   / a 1700, donc il faut incrΘmenter 3 caractΦres !!

: je routine_3         /

: xor eax, eax         /

: mov al, byte ptr [esp+ecx+00000080]   /

: jmp (2)               /

 

Attention : on a mis ecx sur la pile, ecx est un registre 32 bits donc 4 octets, donc on a dΘplacer la pile de 4 octets, d'o∙ on a un mov byte ptr [esp+ecx+80] au lieu de mov byte ptr [esp+ecx+7C] !!!! (0x80 = 0x7C + 0x04)

 

La  routine_3 est une routine spΘciale qui permet de passer de 999 α 1000 par exemple :

 

: pop ecx ; restaure la pile

: mov [esp+ecx+7D], 30 ; met un "0" en plus α droite

: mov al, byte ptr [esp+7C] ; incrΘmente le chiffre le plus

: inc eax ; α gauche.

: mov byte ptr [esp+7C], al  ; et le replace en [esp+7c]

: jmp vΘrif ; retour α la routine de vΘrif'.

 

 

Il y a Θgalement la routine bye_bye :

 

: pop ecx ;restaure la pile

: jmp vΘrif ; retour α la routine de vΘrif'.

 

 

Evidement, pas question d'Θcrire τa avec son pauvre Θditeur hexa, Soft-Ice nous permet d'assembler notre code α l'aide de la commande "a [adresse]".

 

 

 

Voici la source complΩte du reverse enginering d'ACDSee v2.22 avec les offsets (α assembler directement sous SI !!!). En noir : le code original et en rouge les offset modifiΘs.

 

Version (α peine) modifiΘe d'ACDSee v2.22 (acdsee32.exe)

 

 

:00405C68 56 push esi

:00405C69 FFD7 call edi edi = GetDlgItemTextA

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:

|:00405D01(U), :00405D12(U)

|

:00405C6B 8D44247C lea eax, dword ptr [esp+7C] ; eax = reg code

:00405C6F 8D4C243C lea ecx, dword ptr [esp+3C] ; ecx = nom

:00405C73 50 push eax ; sauvegarde

:00405C74 51 push ecx

:00405C75 E846F8FFFF call 004054C0 ; vΘrif'

:00405C7A 83C408 add esp, 00000008

:00405C7D 85C0 test eax, eax ; teste le reg code

:00405C7F 7E0F jle 00405C90 ; saute si pas bon

:00405C81 6A00 push 00000000 ; mettre un bpx ici

:00405C83 E84278B8BF call BFF8D4CA ; call ExitProcess

:00405C88 90 nop ; = il a trouvΘ le bon reg

:00405C89 90 nop ; code et il est dans [esp+7c]

:00405C8A 50 push eax

:00405C8B E8D0F9FFFF call 00405660

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:00405C7F(C)

|

* Possible Reference to String Resource ID=00010: "Launch - Edit"

|

:00405C90 B90A000000 mov ecx, 0000000A ; dΘbut de notre routine

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:00405C9F(C)

|

:00405C95 49 dec ecx

:00405C96 8A440C7C mov al, byte ptr [esp+ecx+7C]

:00405C9A 3D00000000 cmp eax, 00000000 ; explication en haut

:00405C9F 74F4 je 00405C95

:00405CA1 51 push ecx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:00405CC8(U)

|

:00405CA2 40 inc eax

:00405CA3 88840C80000000 mov byte ptr [esp+ecx+00000080], al

:00405CAA 3D3A000000 cmp eax, 0000003A

:00405CAF 7560 jne 00405D11

:00405CB1 C6840C8000000030 mov byte ptr [esp+ecx+00000080], 30

:00405CB9 49 dec ecx ; explication en haut

:00405CBA 83F9FF cmp ecx, FFFFFFFF

:00405CBD 7433 je 00405CF2

:00405CBF 33C0 xor eax, eax

:00405CC1 8A840C80000000 mov al, byte ptr [esp+ecx+00000080]

:00405CC8 EBD8 jmp 00405CA2

:00405CCA 1CA9 sbb al, A9 ; pas α moi !

:00405CCC 4A dec edx

:00405CCD 005068 add byte ptr [eax+68], dl

:00405CD0 E400 in al, 00

:00405CD2 0000 add byte ptr [eax], al

:00405CD4 51 push ecx

* Reference To: USER32.DialogBoxParamA, Ord:008Eh

|

:00405CD5 FF151CFC4A00 Call dword ptr [004AFC1C]

* Possible Reference to String Resource ID=00001: "View"

|

:00405CDB B801000000 mov eax, 00000001

:00405CE0 5F pop edi

:00405CE1 5E pop esi

:00405CE2 5B pop ebx

:00405CE3 81C468020000 add esp, 00000268

:00405CE9 C21000 ret 0010

 

 

* Possible StringData Ref from Data Obj ->"ACDSee 32"

|

:00405CEC 8B1524F24900 mov edx, dword ptr [0049F224]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:00405CBD(C)

|

:00405CF2 59 pop ecx

:00405CF3 C6440C7D30 mov [esp+ecx+7D], 30

:00405CF8 8A44247C mov al, byte ptr [esp+7C] ; routine 3

:00405CFC 40 inc eax

:00405CFD 8844247C mov byte ptr [esp+7C], al

:00405D01 E965FFFFFF jmp 00405C6B

:00405D06 90 nop

:00405D07 90 nop

:00405D08 90 nop

:00405D09 90 nop

:00405D0A 90 nop

:00405D0B 90 nop

:00405D0C 90 nop

:00405D0D 90 nop

:00405D0E 90 nop

:00405D0F 90 nop

:00405D10 90 nop

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:00405CAF(C)

|

:00405D11 59 pop ecx

:00405D12 E954FFFFFF jmp 00405C6B

:00405D17 7C00 jl 00405D19 ; pas α moi

* Referenced by a (U)nconditional or (C)onditional Jump at Address:

|:00405D17(C)

|

:00405D19 5F pop edi

:00405D1A 5E pop esi

:00405D1B 5B pop ebx

:00405D1C 81C468020000 add esp, 00000268

:00405D22 C21000 ret 0010

 

On sait que le jle en 0x00405C7F ne saut pas quand il a le bon s/n, c'est pourquoi juste aprΦs j'ai rajoutΘ un call ExitProcess. Il suffit de mettre un bpx sur la ligne avant ce call ExitProcess. Pourquoi ?? Vous allez entrer votre nom et votre s/n de dΘpart (je vous conseille de commencer α 1'000'000'000), puis α partir de ce moment, il va boucler, et boucler .... jusqu'α ce qu'il trouve le bon s/n et quand τa sera fait, le bpx posΘ permettra de stopper le programme et par la mΩme occcasion vous pourrez admirΘ le bon s/n d'ACDSee α l'aide d'un "d esp+7c".

Je vous prΘvient : c'est assez long. Sur mon humble K6-2 300 avec 32 Mo de SDRam, il balance 28600 s/n par seconde, et le mien Θtait :

nom : Nody CFC

s/n : 1130904563

Donc il a d√ balancer 130'904'563 s/n, soit 1h16 avant de le chopper !!!

 

Evidemment, vous pouvez sauvegarder ce travail α l'aide d'un Θditeur hexa en Θditant une copie d'acdsee32.exe.

 

Ce genre de cours est assez difficile α expliquer donc si vous avez des questions α poser, faites-le !!!!

 

nodless@usa.net

 

 

Merci α :

 

+Frog's Print

+Fravia

Cyberbobjr

La Main Rouge

ATP Team

le futur CFC.