Zoom Icon

Swish Max 2 2008 le protezioni

From UIC

Swish Max 2 2008: le protezioni

Contents


Infos
Author: Chrispale
Email: -
Website: -
Date: 01/08/2008 (dd/mm/yyyy)
Level: Quite hard
Language: Italian Image:Flag_Italian.gif
Comments: -



Introduzione

Nel presente tutorial si analizzano le protezioni del programma e gli eventuali punti di attacco da parte di crackers; le procedure descritte sono finalizzate esclusivamente a studiare gli algoritmi di protezione e non a realizzare il crack del programma. Chiunque riesca, seguendo le procedure descritte, ad eludere le protezioni, è invitato a non utilizzare il programma sprotetto ma ad acquistarlo. Crackare e/o distribuire crack è un reato.


Tools & Files


URL o FTP del programma

Produttore


Essay

Il packer

Introduzione

Il programma ha fondamentalmente 2 livelli di protezione: è packato con PeBundle (probabilmente versione 3.x) e legge 2 file (contenenti informazioni sulla registrazione) all'apertura. Una volta lanciato l'eseguibile del programma (SwishMax2.exe), il loader del packer crea in C:\Documents and Settings\<Utente>\Impostazioni locali\Temp (ricordiamo che la cartella Impostazioni locali è nascosta) i seguenti file:

  • swlpi.dll (libreria che gestisce la finestra iniziale di registrazione);
  • swl.ini (file di testo contiene alcuni paramenti utilizzati dalla precedente libreria);
  • image.bmp (immagine di sfondo della finestra di registrazione).

A questo punto, viene eseguita la libreria swlpi.dll che gestisce l'inserimento del seriale nella pagina di registrazione. In poche parole, viene chiesto il seriale quando l'exe non è stato ancora decryptato dal loader; lo schema è il seguente:

Loader -> Controllo registrazione -> Decrypting -> Esecuzione del programma.

In questo modo, risulta difficile unpackare il programma in quanto per farlo decryptare dal loader dobbiamo prima superare con esito positivo la registrazione; certo, difficile ma non impossibile. Infatti, il primo attacco consiste nel bypassare la finestra di registrazione (facendo credere al loader di aver inserito un seriale corretto) ed arrivare all'Original Entry Point (OEP) del programma, quindi dumping e rebuilding dell'Import Access Table (IAT).

OEP finding

Allora, iniziamo a reversare partendo dalla finestra di registrazione. Apriamo l'exe del programma con OllyDbg (che ci informa che è packato) e mettiamo un breakpoint sull'API che controlla l'inserimento del testo: bp GetDlgItemTextA. Non appena digitiamo un carattere all'interno del campo in cui inserire il seriale, OllyDbg breaka all'indirizzo 10003592:


10003570  /$ 81EC 14050000     SUB ESP,514
10003576  |. 8D8424 C8000000   LEA EAX,DWORD PTR SS:[ESP+C8]
1000357D  |. 53                PUSH EBX
1000357E  |. 8B9C24 1C050000   MOV EBX,DWORD PTR SS:[ESP+51C]
10003585  |. 57                PUSH EDI
10003586  |. 68 F4010000       PUSH 1F4     ; /Count = 1F4 (500.)
1000358B  |. 50                PUSH EAX     ; |Buffer
1000358C  |. 68 ED030000       PUSH 3ED     ; |ControlID = 3ED (1005.)
10003591  |. 53                PUSH EBX     ; |hWnd
10003592  |. FF15 00320110     CALL DWORD PTR DS:[<&USER32.GetDlgItemTextA>]    ; \GetDlgItemTextA

Studiando il flusso del codice, ci si accorge che basta forzare un po' di salti:

100035AC  |. 73 0B             JNB SHORT swlpi.100035B9 ; forzare a saltare
100035F1  |. 0F85 07010000     JNZ swlpi.100036FE ; forzare a non saltare
10003682  |. 0F85 5B020000     JNZ swlpi.100038E3 ; forzare a non saltare

e si arriva ad una CALL molto gradita:

100036C6  |. 6A 40             PUSH 40      ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
100036C8  |. 52                PUSH EDX     ; |Title
100036C9  |. 50                PUSH EAX     ; |Text
100036CA  |. 6A 00             PUSH 0       ; |hOwner = NULL
100036CC  |. FF15 F8310110     CALL DWORD PTR DS:[<&USER32.MessageBoxA>]        ; \MessageBoxA

Un bel MessageBoxA che dice:"Congratulations! You have entered a valid key."; alterando il flusso del codice, abbiamo simulato l'inserimento di un seriale corretto. L'andata è stata buona, ora dobbiamo guidare il ritorno.

Forziamo i seguenti salti:

100036E2  |. 0F85 FB010000     JNZ swlpi.100038E3 ; forzare a non saltare
10003C0F   . 74 18             JE SHORT swlpi.10003C29 ; forzare a saltare
1000264B  |. 75 15             JNZ SHORT swlpi.10002662 ; forzare a non saltare

ma, prima dell'ultimo, mettiamo un bp qui:

10002540  |. 75 09             JNZ SHORT swlpi.1000254B

Da non crederci: finalmente quest'ultimo salto ci fa saltare così come vogliamo noi! Da notare che tutti i salti che abbiamo cambiato erano legati al valore di EAX sempre diverso da 0.

Stepiamo (F8) per 9 volte, finalmente usciamo dalla libreria swlpi.dll e torniamo all'indirizzo 0137146C del loader:

01371469   FF55 F8             CALL DWORD PTR SS:[EBP-8] ; chiama la libreria swlpi.dll
0137146C   85C0                TEST EAX,EAX ; torniamo qui
0137146E   75 22               JNZ SHORT 01371492
01371470   EB 27               JMP SHORT 01371499

La CALL all'indirizzo 01371469 punta proprio alla libreria swlpi.dll mentre immediatamente sotto c'è l'esito della registrazione: se EAX=0, il loader non salta al JNZ e va al JMP...e ci decrypta l'exe!

Reversando a partire dall'API GetDlgItemTextA e facendo una corsa ad ostacoli tra i vari salti, siamo arrivati al cuore del loader. Senza fare tutti i giri visti fino ad ora, basta mettere un bp sulla CALL all'indirizzo 01371469 e fermare qui il debug (senza far esequire la libreria swlpi.dll), quindi sostituire il codice della CALL con un bel MOV EAX,0 o meglio XOR EAX,EAX e continuare a stepare (F8). Piccola nota: l'indirizzo della CALL non sarà subito raggiungibile per piazzare un bp, quindi, per esempio, breakare prima a 00D27A2D (CALL che ci porta a questi indirizzi).

Ok, stepando arriviamo al JMP visto sopra (01371470), continuiamo a stepare (F8) ed arriveremo all'indirizzo 00D27A2F:

00D27A2D   FFD7                CALL EDI
00D27A2F   8985 24150010       MOV DWORD PTR SS: [EBP+10001524],EAX ; arriviamo qui
00D27A35   8BF0                MOV ESI,EAX
00D27A37   8B4B 14             MOV ECX,DWORD PTR DS:[EBX+14]
00D27A3A   5A                  POP EDX
00D27A3B   EB 0C               JMP SHORT SwishMax.00D27A49
00D27A3D   03CA                ADD ECX,EDX
00D27A3F   68 00800000         PUSH 8000
00D27A44   6A 00               PUSH 0
00D27A46   57                  PUSH EDI
00D27A47   FF11                CALL DWORD PTR DS:[ECX]
00D27A49   8BC6                MOV EAX,ESI
00D27A4B   5A                  POP EDX
00D27A4C   5E                  POP ESI
00D27A4D   5F                  POP EDI
00D27A4E   59                  POP ECX
00D27A4F   5B                  POP EBX
00D27A50   5D                  POP EBP
00D27A51   FFE0                JMP EAX

Della CALL all'indirizzo 00D27A2D ne ho parlato poco sopra. Stepiamo (F8) fino a 00D27A51 dove troviamo un JMP EAX...tipico, no? Un altra piccola e delicata pressione del tasto F8 ed arriviamo qui:

007E7A72   ? 6A 60             PUSH 60

Sotto questa riga c'è un codice incomprensibile...ma lo facciamo analizzare (CTRL+A) e magicamente ci rendiamo conto di essere arrivati all'OEP: 007E7A72.

Se avessimo messo un bp sull'API CreateFileA, ci saremmo accorti che la libreria swlpi.dll crea in particolare 2 file: p14.svf e ~SBlue. Questi file ci serviranno dopo.

Unpacking

Fermi con il debug sul PUSH 60 all'indirizzo 007E7A72, utilizziamo OllyDump per dumpare il programma (deselezionando l'opzione Rebuild Import) e salviamolo per esempio come dump.exe.

Senza chiudele OllyDbg, apriamo Import REConstructor e selezioniamo il processo swishmax2.exe nel menù a tendina del campo Attach to an Active Process. Nel campo IAT Infos Needed, impostiamo 003E7A72 come valore di OEP, che non è altro che l'OEP da noi trovato (007E7A72) meno l'Image Base (00400000). Ora clickiamo su AutoSearch e vediamo felicemente il messaggio Found address...; ora clickiamo su Get Imports e ci compare la lista delle librerie chiamate. Clickando su Show Invalid, verifichiamo che 2 chiamate non sono valide; possiamo cancellarle (tasto DX sulla lista -> Delete thunk(S)) o, meglio, correggerle (la prima con LoadLibraryA e la seconda con ExitProcess) facendo doppio click su ognuna di esse. Dopo queste operazioni, clickiamo nuovamente su Show Invalid e non dovremmo visualizzare più voci non valide; ora clickiamo su Fix Dump e selezioniamo il file dumpato prima (dump.exe).

Il nuovo file creato (dump_.exe) è la versione unpackata e funzionante del programma; provate a lanciarlo per verificare se parte.

Le protezioni

Il programma unpackato è perfettamente funzionante ma ha la limitazione di visualizzare in anteprima ed esportare le animazioni flash in scale di grigio. Se lanciamo il programma e simultaneamente monitoriamo l'accesso ai file con Filemon, ci accorgiamo che in particolare il programma apre-legge-chiude per ben 4 volte il file p14.svf e per una volta il file ~SBlue; questi sono gli stessi file creati dalla libreria swlpi.dll ed 1+1=2: contengono informazioni sull'avvenuta registrazione. Il file p14.svf è localizzato nella stessa cartella del programma mentre il file ~SBlue è un file nascosto posizionato della cartella C:\Documents and Settings\<Utente>\Impostazioni locali\Temp.

Di nuovo apriamo l'exe unpackato con OllyDbg ed iniziamo un reversing pazzesco breakando sulle API d'interesse: bp CreateFileA, bp ReadFile e bp CloseHandle. Senza dilungarci, vi mostro il flusso del codice CALL dopo CALL:

1° accesso al file p14.svf

007EFBE8->00774ED9->00774E37->007755A3->00775CD0->00775B84->007767EE->007EF5E1->007EF5B0->00801F07->00805F03->00805DD1 CreateFileA

007EFBE8->00774ED9->00774E37->007755A3->00775CD0->00775B84->00776807->00954DD7->007F72AD->007EC596->007EC3E3 ReadFile

007EFBE8->00774ED9->00774E37->007755A3->00775CD0->00775B84->00776847->007EA80B->007EA7AD->007EB795->007EB700 CloseHandle

All'indirizzo 007755A3 c'è il seguente codice:

007755A3     E8 28070000       CALL SwishMax.00775CD0 ; 1° accesso al file p14.svf
007755A8  |. 83F8 20           CMP EAX,20
007755AB     7C 04             JL SHORT SwishMax.007755B1

Se la lettura del file ha avuto esito positivo, la CALL restituisce un EAX=1; quindi, sostituiamo la CALL con un MOV EAX,1 così da non far mai aprire il file e far saltare sempre all'indirizzo 007755AB. Patchato il 1° accesso al file p14.svf, torniamo a 0076FBED:

0076FBE8     E8 73520000       CALL SwishMax.00774E60 ; verso il 1° accesso a p14.svf
0076FBED     6A 01             PUSH 1 ;torniamo qui
0076FBEF     E8 FC520000       CALL SwishMax.00774EF0 ; verso il 2°-3°-4° accesso a p14.svf e ~SBlue
0076FBF4     6A 03             PUSH 3
0076FBF6  |. A3 F067B800       MOV DWORD PTR DS:[B867F0],EAX
0076FBFB  |. E8 70530000       CALL SwishMax.00774F70

Se tutto è andato come dovrebbe, EAX prendera il valore 0. La CALL a 0076FBEF invece punta alle altre 3 aperture del file p14.svf ed all'apertura del file ~SBlue; di seguito il flusso del codice CALL dopo CALL:

0076FBEF->00774F05->007757B4 (verso il 2° accesso a p14.svf)->00775CC0->00775B84->continua come sopra

0076FBEF->00774F05->00775810 (verso il 3° accesso a p14.svf)->00775CD0->continua come sopra

0076FBEF->00774F05->0077583B (verso il 4° accesso a p14.svf)->00775CD0->continua come sopra

0076FBEF->00774F05->007785E1 (verso l'accesso a ~SBlue)->00778B8D->007767EE,00776807,00776847->continua come sopra

Di nuovo, se tutto è andato bene, EAX=0 al ritorno dalla prima CALL (0076FBEF); visto che EAX ha già valore 0, basta sostituire la CALL a 0076FBEF con 5 NOP ed evitiamo i 3 accessi al file p14.svf e l'accesso al file ~SBlue.


Note Finali

Un ringraziamento particolare a SatUrN per il suo prezioso aiuto.


Disclaimer

I documenti qui pubblicati sono da considerarsi pubblici e liberamente distribuibili, a patto che se ne citi la fonte di provenienza. Tutti i documenti presenti su queste pagine sono stati scritti esclusivamente a scopo di ricerca, nessuna di queste analisi è stata fatta per fini commerciali, o dietro alcun tipo di compenso. I documenti pubblicati presentano delle analisi puramente teoriche della struttura di un programma, in nessun caso il software è stato realmente disassemblato o modificato; ogni corrispondenza presente tra i documenti pubblicati e le istruzioni del software oggetto dell'analisi, è da ritenersi puramente casuale. Tutti i documenti vengono inviati in forma anonima ed automaticamente pubblicati, i diritti di tali opere appartengono esclusivamente al firmatario del documento (se presente), in nessun caso il gestore di questo sito, o del server su cui risiede, può essere ritenuto responsabile dei contenuti qui presenti, oltretutto il gestore del sito non è in grado di risalire all'identità del mittente dei documenti. Tutti i documenti ed i file di questo sito non presentano alcun tipo di garanzia, pertanto ne è sconsigliata a tutti la lettura o l'esecuzione, lo staff non si assume alcuna responsabilità per quanto riguarda l'uso improprio di tali documenti e/o file, è doveroso aggiungere che ogni riferimento a fatti cose o persone è da considerarsi PURAMENTE casuale. Tutti coloro che potrebbero ritenersi moralmente offesi dai contenuti di queste pagine, sono tenuti ad uscire immediatamente da questo sito.

Vogliamo inoltre ricordare che il Reverse Engineering è uno strumento tecnologico di grande potenza ed importanza, senza di esso non sarebbe possibile creare antivirus, scoprire funzioni malevoli e non dichiarate all'interno di un programma di pubblico utilizzo. Non sarebbe possibile scoprire, in assenza di un sistema sicuro per il controllo dell'integrità, se il "tal" programma è realmente quello che l'utente ha scelto di installare ed eseguire, né sarebbe possibile continuare lo sviluppo di quei programmi (o l'utilizzo di quelle periferiche) ritenuti obsoleti e non più supportati dalle fonti ufficiali.