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: |
|
| Language: | Italian |
| 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
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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.