Detten 12 reversing.

Data

by "Evilcry"

 

11/04/2003

UIC's Home Page

Published by Quequero


Una protezione grid-like, inusuale e divertente da reversare.

 

...

Home page se presente: www.evilcry.cjb.net
E-mail: [email protected]
Nick, UIN, canale IRC/EFnet frequentato   irc.azzurra.it   #pmode #crack-it
efnet: #win32asm #lockless
 

....

Difficoltà

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

 

 

Detten 12 reversing
Written by Evilcry.

Introduzione

Questo crackme non ha la solita combinazione name/serial. Infatti ci sono una serie di bottoni, e clickando questi bottoni si deve indovinare la giusta sequenza del serial. Il serial è di 10 cifre.

Tools usati

-IDA

-SoftIce

URL o FTP del programma

www.google.it

Notizie sul programma

Vedi sopra.

Essay

Per capire come vengono prese le cifre del serial dobbiamo disassemblare il programma.

0040102E cmp [ebp+arg_4], 110h ;WM_INITDIALOG

00401035 jnz short loc_40106E 00401037 mov dword_403048, 0

00401041 mov dword_403038, 0DEADh ;X=DEADh

0040104B mov dword_40303C, 0DEADh ;Y=DEADh

00401055 mov dword_403040, 42424242h ;K=42424242h

0040105F mov dword_40304C, offset aAnErrorOccured ; "An error occured"

00401069 jmp loc_40124C

Niente di difficile, ci sono 3 variabili a cui sono assegnati dei valori. Andiamo avanti e vediamo come viene gestito l' evento "click sul bottone".

00401081 cmp [ebp+arg_4], 111h ;WM_COMMAND ??

00401088 jnz loc_401243

0040108E mov eax, [ebp+arg_8]

.......................

004010A0 cmp ax, 65h ; 65 è l' ID del bottone "1)

004010A4 jnz short loc_4010B2 ; Se non è il tasto uno vai la prossimo caso

004010A6 push 1 ;Passa come argomento la cifra "1"

004010A8 call sub_4012A5 ;Questa call la analizzeremo in seguito

004010AD jmp loc_4011F2

....

004010B2 cmp ax, 66h ;Button "2"

004010B6 jnz short loc_4010C4 ;Salta al prossimo caso, se l' ID del button "2"

004010B8 push 2 ;Passa "2" come argomento della call

004010BA call sub_4012A5 ;Solita call

004010BF jmp loc_4011F2

...

Chiunque abbia un pò di dimenstichezza con qualche linguaggio di programmazione, avrà certamente capito che si tratta di un costrutto "switch". Penso che sia inutile riportarvi l' intero codice, tanto questa "routine" si ripete per tutti i bottoni. Adesso andiamo a vedere cosa succede nella call 004012A5

004012A5 push ebp

......

004012A9 mov ecx, dword_403040 ;K in ecx

004012AF mov ebx, dword_40303C ;Y in ebx

004012B5 mov eax, dword_403038 ;X in eax

004012BA cmp [ebp+arg_0], 1 ;è il bottone "1"

004012BE jnz short loc_4012D0 ;se non lo è allora

004012C0 add ecx, 54Bh ; K + 54Bh

004012C6 imul ebx, eax ; Y * X

004012C9 xor eax, ecx ; xor X con K

004012CB jmp loc_4013E7

--------------------------------------------------------------------

004012D0 cmp [ebp+arg_0], 2 ;Button 2

004012D4 jnz short loc_4012E8

004012D6 sub ecx, 233h ; K-233h

004012DC imul ebx, 14h ; Y* 14h

004012DF add ecx, eax ;K+X

004012E1 and ebx, eax ;And Y,X

004012E3 jmp loc_4013E7

-------------------------------------------------

004012E8 cmp [ebp+arg_0], 3 ;Button 3

004012EC jnz short loc_4012FD

004012EE add eax, 582h ;X+582h

004012F3 imul ecx, 16h ;K * 16h

004012F6 xor ebx, eax ; xor Y,X

004012F8 jmp loc_4013E7

----------------------------------------------

004012FD cmp [ebp+arg_0], 4 ; Button 4

00401301 jnz short loc_401312

00401303 and eax, ebx ;and X,Y

00401305 sub ebx, 111222h ;Y-111222h

0040130B xor ecx, eax ;xor K,X

0040130D jmp loc_4013E7

---------------------------------------------

00401312 cmp [ebp+arg_0], 5 ;Button 5

00401316 jnz short loc_401324

00401318 cdq

00401319 idiv ecx ; X/K

0040131B sub ebx, edx ; Y - resto della div

0040131D add eax, ecx ;X+K

0040131F jmp loc_4013E7

--------------------------------------------

00401324 cmp [ebp+arg_0], 6 ; Button 6

00401328 jnz short loc_401339

0040132A xor eax, ecx ;xor X,K

0040132C and ebx, eax ;and Y,X

0040132E add ecx, 546879h ; K+546879h

00401334 jmp loc_4013E7

-----------------------------------------

00401339 cmp [ebp+arg_0], 7 ;Button 7

0040133D jnz short loc_401351

0040133F sub ecx, 25FF5h ;K-25ff5h

00401345 xor ebx, ecx ;xor Y,K

00401347 add eax, offset start ;X + Address del Entry Point

0040134C jmp loc_4013E7

----------------------------------------

00401351 cmp [ebp+arg_0], 8 ;Button 8

00401355 jnz short loc_401367

00401357 xor eax, ecx ;xor X,K

00401359 imul ebx, 14h ;Y * 14h

0040135C add ecx, 12589h ;K+ 12589h

00401362 jmp loc_4013E7

-----------------------------------------------

00401367 cmp [ebp+arg_0], 9 ;Button 9

0040136B jnz short loc_401378

0040136D sub eax, 542187h ;X - 542187

00401372 sub ebx, eax ;Y-X

00401374 xor ecx, eax ;xor K,X

00401376 jmp short loc_4013E7

-----------------------------------------------

00401378 cmp [ebp+arg_0], 0Ah ; Button A

0040137C jnz short loc_40138A

0040137E cdq

0040137F idiv ebx ; X/Y

00401381 add ebx, edx ;Y+ Resto della divisione

00401383 imul eax, edx ; X * il resto div

00401386 xor ecx, edx ;xor K, resto

00401388 jmp short loc_4013E7

-----------------------------------------------

0040138A cmp [ebp+arg_0], 0Bh

0040138E jnz short loc_4013A3

00401390 add ebx, 1234FEh ;Y+1234feh

00401396 add ecx, 2345DEh ;K+2345deh

0040139C add eax, 9CA4439Bh ;X+9ca4439bh

004013A1 jmp short loc_4013E7

-------------------------------------------------

004013A3 cmp [ebp+arg_0], 0Ch ;Button c

004013A7 jnz short loc_4013B2

004013A9 xor eax, ebx ;xor X,Y

004013AB sub ebx, ecx ;Y-X

004013AD imul ecx, 12h ; K * 12

004013B0 jmp short loc_4013E7

------------------------------------------------------

004013B2 cmp [ebp+arg_0], 0Dh ;Button D

004013B6 jnz short loc_4013C8

004013B8 and eax, 12345678h ;and X,12345678h

004013BD sub ecx, 65875h ;K-65875

004013C3 imul ebx, ecx ;Y*K

004013C6 jmp short loc_4013E7

---------------------------------------------------------

004013C8 cmp [ebp+arg_0], 0Eh ;Button E

004013CC jnz short loc_4013DB

004013CE xor eax, 55555h ;xor X,55555h

004013D3 sub ebx, 587351h ;Y-587351h

004013D9 jmp short loc_4013E7

--------------------------------------------

004013DB loc_4013DB:

004013DB cmp [ebp+arg_0], 0Fh ;Button F

004013DF jnz short loc_4013E7

004013E1 add eax, ebx ;X+Y

004013E3 add ebx, ecx ;Y+K

004013E5 add ecx, eax ;K+X

004013E7 inc dword_403044 ;incrementa questo contatore

004013ED mov dword_403038, eax ;Valore di eax (X) nella var X

004013F2 mov dword_40303C, ebx ;Valore di ebx (Y) nella var Y

004013F8 mov dword_403040, ecx ;Valore di ecx (K) nella var K

004013FF leave

00401400 retn 4

Bene!, dopo questa lunga ma necessaria routine possimo andare avanti, avrete certamente notato come tutto questo codice si basa sulle tre variabili (K,Y,X) che abbiamo visto all' inizio, inoltre c' è da osservare che ad ogni bottone corrismponde una diversa routine. Mentre quando viene premuto il bottone "Clear" le tre variabili vengono resettate cioè riportare ai loro valori originali. All' uscita della call c' era un jump, il quale ci porta a questa porzione di codice.

004011F2 cmp dword_403048, 3 ; viene confrontato il counter con 3

004011F9 jnb short loc_401228 ; Se è maggiore o uguale a 3, salta

004011FB cmp dword_403044, 0Ah ; confronta il counter con 10

00401202 jnz short loc_401241 ; Salta se è diverso da 10

00401204 call sub_40144C ; la analizzeremo in seguito

00401209 push offset aAnErrorOccured ; "An error occured"

0040120E push [ebp+arg_0]

00401211 call sub_401403 ; altra call che analizzeremo dopo

00401216 mov dword_403044, 0 ; mette il counter a 0

00401220 inc dword_403048 ; incrementa il counter

00401226 jmp short loc_401241

Anche questa parte di codice è abbastanza semplice, l' unica cosa da osservare è che la lunghezza del serial dev' essere compresa tra 3 e 10. Adesso prima di passare alla call 0040144C è meglio che vi spieghi cosa fa la funzione VirtualProtect:

" La funzione VirtualProtect cambia la protezione di accesso ad una regione di pagine nello spazio di indirizzamento virtuale dei processi chiamanti"

Ora andiamo a vedere cosa c' è in questa call:

0040144C push eax

0040144D push offset unk_403050

00401452 push 4 ;PAGE_READ_WRITE

00401454 push 1F4h ;grandezza 1f4h, cioè 500d

00401459 push offset loc_401407 ;indirizzo che chiameremo Z

0040145E call j_VirtualProtect

00401463 mov eax, dword_403038 ;Variabile X in eax

00401468 xor dword ptr ds:loc_401407, eax ;xor Z con X

0040146E cmp byte ptr ds:loc_401407, 52h ;confronta Z con 52h

00401475 jnz short loc_40148F ; se non è uguale, salta, di conseguenza niente decrypt

00401477 mov eax, dword_40303C ;Variabile Y in eax

0040147C xor ds:dword_40143B, eax ;xora Y con quest'indirizzo (che chiameremo J), in cui ci sono dei bytes

00401482 mov eax, dword_403040 ;variabile K in eax

00401487 xor ds:dword_40143F, eax ;xora K con quest' indirizzo(che chiameremo W), in cui ci sono una serie di bytes

0040148D jmp short loc_401495

In fine viene richiamata la VirtualProtect per ripristinare i settaggi iniziali, cioè dare alle pagine l' attributo PAGE_EXECUTE. Credo che questa parte di codice meriti una piccola spiegazione. Per prima cosa viengono modificati gli attributi di una regione di memoria con VirtualProtect, e più precisamente questa parte di memoria è settata a Read e Write in modo da poter essere letta e scritta. Questo ci fa pensare automaticamente a qualche routine di scrittura (come un decrypting), che altrimenti non sarebbe possibile. Le tre variabili (K,Y,Z) vengono xorate con delle dwords che si trovano a 00401407, 0040143b e 0040143f, e a cui abbiamo assegnato rispettivamente la variabili Z,J,W. Osservando più attentamente notiamo che questi indirizzi si trovano nella call successiva, cioè call 401403. Inoltre il confronto che troviamo all' indirizzo 0040146E serve semplicemente a controllare che ci sia il byte 52h, se non fosse 52h avremmo un decrypting sbagliato, e di conseguenza non ci sarebbero le giuste istruzioni nella call. Facendo un pò di attenzione possiamo vedere che non ci sono messagi di congratulazioni, e alla call da decryttare viene passato come argomento la stringa "An error occured". Secondo il mio punto di vista questa stringa potrebbe essere "modificata" in maniera da ottenere il messaggio di congratulazioni. Adesso quello che dobbiamo fare è cercare di capire come possiamo ottenere un giusto decrypting di questa stringa. Per prima cosa consideriamo che noi dovremmo trovare nell' indirizzo 00401407 il byte 52h, il quale corrisponde all' istruzione "push edx". Inoltre prima ci sono tre bytes liberi (cioè che possiamo cambiare a nostro piacimento) prima del decrypting della stringa. Il decrypting avviene solamente quando nel registro edx c'è l' indirizzo di questa stringa. La cosa che dobbiamo fare quindi è riuscire a mettere in edx l' indirizzo della stringa, che si trova a 00403000. Ma ora sorge un problema, l' opcode per l' istruzione "mov edx, 00403000" è più lungo di tre bytes. La soluzione a questo problema è semplice ma non molto intuitiva, infatti se facciamo un pò di stacktrace, scopriamo che l' indirizzo che cerchiamo si trova in ebp+0Ch!. Abbiamo scelto di usare [ebp+C] perchè l' opcode per quest' istruzione occupa esattamente tre bytes.

00401407 52 push edx

00401408 8B 55 0C mov edx, [ebp+C] ;Occupa esattamente tre bytes

Supponendo che la stringa sia stata "decryptata" correttamente, adesso per far comparire il messagio di congratulazioni dovremmo passare tre argomenti alla SendDlgItemTexta:

0040143B FF 75 0C push dword ptr [ebp+c]

0040143E 6A 03 push 3

00401440 FF 75 08 push dword ptr [ebp+8]

Oltre alla stringa dobbiamo passare l' ID del controllo e l' handle (che si trova ad ebp+8). Con un rapido calcolo vediamo che per fare ciò ci servono 8 bytes, cioè 2 Dwords. Adesso penso che sia tutto più chiaro, e quindi possiamo procedere a cercare i giusti valori per un decrypting corretto. L' operazione è abbastanza semplice perchè noi sappiamo esattamente i valore dei bytes che dobbiamo ottenere:

Indirizzo
Bytes iniziali
Bytes da ottenere

Result

00401407 (Z)
EB 3F 90 90
52 8B 55 0C
B9 B4 C5 9C
0040143B (J)
04 66 E7 BB
FF 75 0C 6A
FB 13 EB D1
0040143F (W)
4D BD 08 8B
03 FF 75 08
4E 42 7D 83

I valori che ci sono in Result, sono stati ottenuti con uno XOR (se non capite il perchè riguardatevi la call a 0040144c) tra i bytes iniziali di ciascuna delle locazioni (Z,J,W) ed i bytes relativi agli opcodes delle istruzioni che dobbiamo ottenere. Come avrete certamente capito in Result vanno i valori che devono assumere rispettivamente le variabili K, Y, X. L' ultima fase è quella di scrivere un bruteforcer, che simuli la pressione di 10 tasti scegliendo tra i 15 valori possibili, in modo tale da trovare la giusta combinazione dei tasti che facciano assumere a K,Y,X i suddetti valori.

Dopo il il bruteforcing ho ottenuto : 79DE624C4B

 

 

Note finali

In fine colgo l' occasione per salutare chiunque mi conosce.

Disclaimer

Vorrei ricordare che il software va comprato e non rubato, dovete registrare il vostro prodotto dopo il periodo di valutazione. Non mi ritengo responsabile per eventuali danni causati al vostro computer determinati dall'uso improprio di questo tutorial. Questo documento è stato scritto per invogliare il consumatore a registrare legalmente i propri programmi, e non a fargli fare uso dei tantissimi file crack presenti in rete, infatti tale documento aiuta a comprendere lo sforzo immane che ogni singolo programmatore ha dovuto portare avanti per fornire ai rispettivi consumatori i migliori prodotti possibili.

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

Capitoooooooo????? Bhè credo di si ;))))