Lezione per studenti n°2
Peschiamo il serial

31/08/2004

by "Pnluck"

 

31/08/2004

UIC's Home Page

Published by Quequero


Xkè c'è la squola???????

Bravo luck!

Se inventano la macchina del tempo uckido guell'iqnorante di Carlo Magno ;D

....

E-mail: pnluck@virgilio.it

Pnluck #crack-it,#asm,#c,#assembly

....

Difficoltà

(X)NewBies ( )Intermedio ( )Avanzato ( )Master

 

Questa luzione è basata sul controllo del keygen basato su seriale, il key è generato con i rotate e gli shift


Lezione x studenti n°2

Peschiamo il serial
Written by Pnluck


Introduzione

In questo tutozzo mi accingo a descrivere il processo tramite il quale il crackme n°2 delle lezioni x studenti, controlla user e psw. In poche parole vi descrivo la procedura tramite la quale il prg controlla la psw generata tramite l'user inserito.

Tools usati

Ollydbg e dev-cpp (per il serial)

Notizie sul programma

L'user e psw possono contenere max 5 char,ma x rendere + semplice il keygeneretor, metteremo l'user di 4 char.
Perche questa vienne immesso nei registri eax ed ebx, quindi max contengono 4 char

Essay

Avviamo il prg, e vediamo che massimo user e psw contengono 5 char, vabbe mettiamo user e char a casaccio di 4 char,e ci conpare un msg d'errore. Ora analiziamo il codice.

Con olly facciomo destro->search->all_intermodular_call, e cerchiamo qualche api che ci può servire.Troviamo un GetWindowTextA. Ora iniziamo a descrivere il codice

004011FF   CALL <JMP.&USER32.GetWindowTextA>        ; \GetWindowTextA

00401204   XOR ECX,ECX                              azzera ecx

00401206   MOV AL,BYTE PTR DS:[40219F]              prende i char di user

0040120B   TEST AL,AL                               se al=0

0040120D   JE due.00401371                          va al msg ke dice che que non è scema ;D

00401213   XOR EAX,EAX                              azzera eax

#################Ecco la msg################

00401371   PUSH 30                                  ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL

00401373   PUSH due.0040208D                        ; |Title = "Ehmmmmm!!! No!"

00401378   PUSH due.0040213B                        ; |Text = ", son mica scemo!!! :)"

0040137D   PUSH 0                                   ; |hOwner = NULL

0040137F   CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA

############################################

Dove ci sono i tre punti, significa ke ho tolto codice inutile  

00401215   MOV AL,BYTE PTR DS:[ECX+40219F]          prende il char di user, dipendentemente da ecx

0040121B   TEST AL,AL                               controlla se al=0

0040121D   JE SHORT due.00401279                    se si va all'altra procedura

0040121F   XOR AL,CL                                xor tra al e cl

00401221   MOV EDI,ECX                              edi=ecx

00401223   MUL EDI                                  moltiplica eax*edi con risultato in eax

00401225   SUB AL,25                                sottrae ad al 0x25

00401227   ADD AL,CL                                gli aggiunge cl

00401229   XOR AL,BYTE PTR DS:[ECX+402000]          prende un valore di 4020000  ke sarebbero in hex:12 45 D1 FF

...

00401245   ADD AL,BYTE PTR DS:[ECX+402000]          aggiunge ad al 402000+ecx

...

00401251   SHL AL,2                                 shift left di al di 2

00401254   ROR AL,4                                 ruota a destra al di 4

0040126C   SUB AL,5                                 sottrae ad al 5

...

00401270   MOV BYTE PTR DS:[ECX+40218F],AL          mette al in 40218f+ecx

00401276   INC ECX                                  incrementa ecx

00401277   JMP SHORT due.00401215                   salta, passando al prossimo char con ecx++

Controlla se il char generato sia ascii-comprensibile, se no lo fa diventare (almeno credo :P)

00401279   XOR ECX,ECX                              azzera ecx

0040127B   MOV AL,BYTE PTR DS:[ECX+40218F]          prende stringa generata e la mette in al

00401281   TEST AL,AL                               se è zero

00401283   JE due.00401331                          vai a 401331

00401289   CMP AL,66                                se no lo compara con "f" 

0040128B   JG due.0040131B                          se è maggiore salta

00401291   CMP AL,30                                se no cmp con "0"

00401293   JL due.00401326                          se minore vai a 401326

00401299   INC ECX                                  ecx++

0040129A   MOV BYTE PTR DS:[ECX+4021A7],AL          se è tutto a posto mette il char in 4021a7

004012A0   JMP SHORT due.0040127B                   e fa da capo

Ecco la procedura se il char generato è minore di 0x30

00401326   ADD AL,18                         gli aggiunge 0x18

00401328   CMP AL,30                         e lo compara con 0x30

0040132A   JL SHORT due.00401326             se minore reinizia  

0040132C   JMP due.00401299                  se no salta

Ecco l aprocedura se il char generato è maggiore di 0x66

0040131B   SUB AL,12                         gli sottrae 0x12

0040131D   CMP AL,66                         e lo compara con 0x66

0040131F   JG SHORT due.0040131B             se maggiore reinizia

00401321   JMP due.00401291                  se no salta

Questa e la procedura quando si è finito di controllare i char

00401331   XOR ECX,ECX                                azzeramento ecx

00401333   MOV AL,BYTE PTR DS:[ECX+4021A7]            muove 4021a7+ecx in al   

00401339   TEST AL,AL                                 se non c'è + nulla

0040133B   JE SHORT due.004012C8                      salta se no

0040133D   MOV AH,BYTE PTR DS:[ECX+4021A8]            muove 4012a8+ecx in ah

00401343   JE SHORT due.004012C8                      se si è dinuovo alla fine salva

00401345   CMP AH,AL                                  cmp ah ed al 

00401347   INC ECX                                    ecx++

00401348   INC EDX                                    edx++

00401349   JNZ due.004012BA                           se diversi salta

0040134F   ADD AL,2                                   se no al+2

00401351   CMP AL,66                                  e cmp al con 0x66  

00401353   JG SHORT due.00401366                      se maggiore salta a 401366 

00401355   CMP AL,30                                  se no cmp con 0x30

00401357   JL SHORT due.0040135B                      se minore salta a 40135b, ke corrisponde all’uscita del prg.

00401359   JMP SHORT due.00401333                     se no salta ad inizio ciclo

#######Questo ciclo non fa altro ke, far uscire il prg dal processo di controllo della psw####

0040135B   ADD AL,2                                   al+2                                     

0040135D   CMP AL,30                                  cmp con 0x30

0040135F   JL SHORT due.0040135B                      se minore reinizia

00401361   JMP due.004012BA                           se no esci da tutto

00401366   SUB AL,3                                   al-3   

00401368   CMP AL,66                                  cmp al 66

0040136A   JG SHORT due.00401366                      se maggiore reinizia 

0040136C   JMP due.004012BA                           se no esci da tutto

########Questo ciclo non fa altro ke, far uscire il prg dal processo di controllo della psw######

Questa è la procedura azionata da 401349

004012BA   MOV BYTE PTR DS:[ECX+402173],AL            mette al in 402173+ecx

004012C0   MOV BYTE PTR DS:[ECX+402174],AH            mette ah in 402174+ecx

004012C6   JMP SHORT due.00401333                     salta a 401333 cioè alla procedura descritta prima

Qui sotto c'è la procedura di controllo della psw, che è azionata della procedura in 401333, quando i char da prendere sono finiti

004012C8   PUSH 19                                  ; /Count = 19 (25.)

004012CA   PUSH due.004021A3                        ; |Buffer = due.004021A3

004012CF   PUSH DWORD PTR DS:[4020DB]               ; |hWnd = 00020104 (class='Edit',parent=000200EE)

004012D5   CALL <JMP.&USER32.GetWindowTextA>        ; \GetWindowTextA  Prende la psw

004012DA   XOR ECX,ECX                                azzera ecx

004012DC   MOV EAX,DWORD PTR DS:[ECX+4021A3]          eax=psw inserita

004012E2   MOV EBX,DWORD PTR DS:[ECX+4021A8]          ebx=psw generata

004012E8   INC ECX                                    ecx++

004012E9   CMP EAX,EBX                                compara eax con ebx

004012EB   JNZ SHORT due.004012A2                     se diversa va al msg ke dice kiave sbagliata

004012ED   MOV AL,BYTE PTR DS:[ECX+4021A3]            /

004012F3   MOV BL,BYTE PTR DS:[ECX+4021A8]            |Questo controllo è inutile xkè se le due psw

004012F9   TEST AL,AL                                 !

004012FB   JE SHORT due.00401303                      |sono uguali continua fino al msg di complimenti

004012FD   CMP AL,BL                                  \_____________________

004012FF   JNZ SHORT due.004012A2

00401301   JMP SHORT due.00401303

00401303   PUSH 20                                  ; /Style = MB_OK|MB_ICONQUESTION|MB_APPLMODAL

00401305   PUSH due.00402057                        ; |Title = "Ce l'hai fatta!!!"

0040130A   PUSH due.0040209C                        ; |Text = "Chiave indovinata...Complimenti!!!"

0040130F   PUSH 0                                   ; |hOwner = NULL

00401311   CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA

Qui è la msg di errore in caso di psw sbagliata

004012A2   PUSH 10                                  ; /Style = MB_OK|MB_ICONHAND|MB_APPLMODAL

004012A4   PUSH due.004020DF                        ; |Title = "No! No! No! E poi Noooooo!!!"

004012A9   PUSH due.004020C3                        ; |Text = "Serial sbagliato ;("

004012AE   PUSH 0                                   ; |hOwner = NULL

004012B0   CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA

004012B5   JMP due.00401156

Ho descritto tutta la procedura di controllo della psw in ordine cronologico di come vengono effettuate, e non come sono decompilate, in modo da rendere il tutto il + comprensibile possibile ed dato ke non ho tempo di fare il key, vi riporto solo l’implementazione di ror.

Per prima cosa in c++, non c'è ne "ror" quindi bisogna implementarlo, a me stava scritto sul libro di c++, ed ora ve lo riporto.

long  ror(char num,int var)     

{

long a;

a = ( num << var) | (a >> 32-var);

return a;

}      

(NxQUE, non ho pututo mettere la tua implementazione asm, xkè sul cazzo di dev-cpp non funge.Que la devi cancellare se la metti on-line :P)

Qui è tutto il keygeneretor, non l’ho descritto nei minimi particolari, xkè fa le stesse cose ke fa i il prg in as,

#include<iostream>

#include<cstring>

using namespace std;

long ror(char num,int var);        

int main(){

    char user[] = {0x39, 0x31, 0x32,0x34};  //qui ho inserito l’user in hex, lo potete modificare con                  “cout” e via dicendo

    char  *key;                             //qui verrà inserita la psw

    int hex [] = {0x12, 0x45, 0xd1, 0xff};  //questo è 402000

   for (int i=0;i<=strlen(user)-1;i++) {    //qui calcola il key

         key[i] = user[i]^i;

         key[i] *= i;

         key[i]-=0x25;

         key[i] += i;

         key[i] ^=hex[i];

         key[i] += hex[i];

         key[i] = key[i] << 2;

         key[i] = ror(key[i],4);

         key[i]-=0x5;

         }

         for (int i=0;i<=strlen(user)-1;i++) {  //qui lo asciizza(by Bonu$) :P

              while (key[i] > 0x60) { key[i] -=0x12;}

              while (key[i] < 0x30) { key[i] += 0x18;}

             cout << key[i];                    //stampa il key finale

               }

 return 0;

} 

Pnluck

Note finali

Thenkazzo a tutti gli abitanti di #crack-it. Soprattutto |GeO|, Cr[]w, X-treem, Quake( ke ultimamente non gli sto rompendo + le palle),ad AndreaGeddon, a Que, all sommo(a me ancora inpronunciabile),NtosK, ke mi hanno aiutato x implementare il ror, e poi a Bender0, ke mi ha passato la sua routine(ke è quella ke ho messa), xkè gli altri litigavano x vedere ki aveva fatta la routine + lamera :D

Disclaimer

vorrei ricordare che il software va comprato e  non rubato, dovete registrare il vostro prodotto dopo il periodo di valutazione. Vi ricordo di pagare anke i creatori dei crackme, in che maniara dipende da loro ma anke dai vostri mezzi ;D

Noi reversiamo al solo scopo informativo e di miglioramento del linguaggio Assembly