Soluzione Crackme 22
From UIC
Crackme n.22 : A Serial, Keyfile, And A Suprise
Contents |
| Infos | |
|---|---|
| Author: | ValerioSoft |
| Email: | ValerioSoft(AT)tin.it |
| Website: | |
| Date: | 15/03/2007 (dd/mm/yyyy) |
| Level: |
|
| Language: | Italian |
| Comments: | Dove passa l’aratro della tempesta si trova sempre il solco della miseria. |
Introduzione
Ciaoooooooooo, sesto tuteeeee??? Hey la fame vien mangiando :-D
Tools
Notizie sul CrackMe N.22
Questo è un crackme scritto da Quequero in persona, chissà che cosa ci riserva???.
Essay
Dal precedente Tute abbiamo imparato che...
...come prima cosa dobbiamo avviare il PEID 0.94, poi apriamo il file eseguibile del CrackMe, bene questa volta il file
è crittato con PEtite 1.2 ma questo in realtà non dovrebbe interessarci dato che come regolamento del CrackMe Quequero
ci dice di non decrittarlo infatti l'unico scopo per cui è stato utilizzato è quello di non permetterci di disassemblarlo
altrimenti diventa troppo semplice!!!
Cosa significa??? Beh significa che questa volta dovremo utilizzare solo Ollydbg, ed è proprio quello che faremo!!!
Apriamo il file con Ollydbg e ovviamente ci troviamo nella zona di codice che si occupa di decrittare l'algoritmo a RunTime, per
essere sicuri che il file sia bello che decrittato avviamo l'applicazione con il tasto Play. Ora dobbiamo fare qualcosa che
negli altri Tute non abbiamo mai visto, clicchiamo con il tasto destro del mouse su un punto qualsiasi del codice e scegliamo
Go to->Origin oppure premiamo semplicemente l'asterisco (*) sulla tastiera. Ora scegliamo View->Module'The_mask' in modo
tale da ritrovarci all'istruzione 00401000, guardate un attimo il codice risulta essere tutto sballato!!! Per questo motivo
bisogna analizzarlo e quindi scegliamo Analysis->Analyse code, ora il codice che ci viene mostrato risulta comprensibilissimo.
Senza dilungarmi troppo dato che ormai questa è una cosa scontata utilizziamo come punto di attacco la stringa Sorry bad serial, try again!!!, andiamo quindi a vedere se compare questa occorrenza nel debugger con il solito metodo, la stringa c'è allora andiamo a vedere in che punto del programma viene utilizzata:
004014EC PUSH 004022D2 // Text = "Unregistered - - by Quequero"
004014F1 PUSH DWORD PTR DS:[402048] // hWnd = 0023053E ('Unregistered - -
// by Quequero',class='asm')<br />
004014F7 CALL JMP.&USER32.SetWindowTextA // SetWindowTextA
004014FC PUSH 0 // Style = MB_OK|MB_APPLMODAL
004014FE PUSH 00402386 // Title = "Sorry!!!!"
00401503 PUSH 00402390 // Text = "Sorry bad serial, try again!!!"
00401508 PUSH 0 // hOwner = NULL
0040150A CALL JMP.&USER32.MessageBoxA // MessageBoxA
Quindi cosa succede???
Questo è il pezzo di codice che ci mostra la finestra di errore, ma chi richiama questo pezzo di codice???
Beh basta cliccare con il tasto sinistro del mouse sull'istruzione 004014EA e seguire verso l'alto la linea
blu, ci ritroviamo qui:
0040131C PUSH 00402058 // Buffer = The_mask.00402058
00401321 PUSH DWORD PTR DS:[40204C] // hWnd = 00390520 (class='Edit',parent=0023053E)
00401327 CALL JMP.&USER32.GetWindowTextA // GetWindowTextA
0040132C CMP EAX,0 // Controlla se non sono stati inseriti caratteri
0040132F JE SHORT 0040134E
00401331 CMP EAX,0C // Controlla se i caratteri sono 12
00401334 JNZ 004014EA // Salta all'errore se non sono 12
La funzione GetWindowTextA legge il testo inserito nel box e mette in EAX il numero di caratteri letti e mette alla locazione
00402058 la stringa letta quindi alla riga 0040132C controlla se non sono stati inseriti caratteri mentre la riga
00401331 controlla se la stringa inserita è di 12 caratteri. Che cosa dobbiamo fare??? Beh dobbiamo inserire una parola di 12
caratteri, io metto Valerio-Soft e premo il pulsante Check, ci da ancora la scritta Sorry bad serial, try again!!!
ma sicuramente il flusso del programma sarà cambiato!!! Per verificare cosa succede piazziamo un breakpoint alla riga 00401334 e
premiamo nuovamente il tasto Check, guardate il salto non viene effettuato quindi il box di errore viene richiamato da qualche
altra parte del programma.
Adesso steppiamo in modo tale da individuare qualche pezzo di codice che effettua la manipolazione del serial inserito. Questo è ciò che troviamo dopo qualche istruzione:
00401487 XOR BL,BL
00401489 MOV BL,AL
0040148B INC BL
0040148D ADD BL,21
00401490 XOR BL,2D
00401493 OR EDX,EDX
00401495 DEC EDX
00401496 CMP EDX,5687
0040149C JE 0040135E
004014A2 MOV EAX,00402058 // ASCII "Valerio-Soft"
004014A7 MOV DL,DS:[EAX]
004014A9 ADD DL,38
004014AC INC DL
004014AE DEC ECX
004014AF CMP ECX,0
004014B2 JE 0040135E
Beh questa porzione di codice vuole assomigliare ad un controllo sul serial ma in realtà Quequero ci vuole far perdere il nostro prezioso tempo :-D ,allora
continuiamo a steppare! Lungo il nostro cammino incontriamo questa Call che ha lo scopo di modificare l'istruzione 004013D1 da una somma ad una Call.
Se volete entrarci fatelo ma vi ho già detto di cosa si tratta! Continuiamo a steppare ed arriviamo proprio sulla riga 004013D1
Questa Call ha il compito di controllare se in alcune istruzioni del programma sono state patchate o qualcosa di simile, a noi non interessa dato che non vogliamo trasgredire alle regole del CrackMe. Continuiamo a steppare...
004013D8 MOV AL,DS:[EBX+ECX] // Al primo giro mette in AL il valore di V
004013DB MOV DL,DS:[ECX+4022FB] // Mette in DL il valore preso dalla locazione 004022FB
004013E1 XOR AL,DL // Fa lo XOR tra AL e DL e mette il risultato in AL
004013E3 CMP AL,DS:[ECX+4022EF] // Confronta il risultato con il valore alla
// locazione 004022EF<br />
004013E9 JNZ 004014EA // Salta all'errore se non sono uguali
004013EF INC ECX // Incrementa ECX
004013F0 CMP ECX,0C // Confronta ECX con il 12 esadecimale
004013F3 JNZ SHORT 004013D8 // Se non sono uguali salta e analizza l'altra lettera
004013F5 JMP SHORT 0040140C // Salta quando tutto è andato bene
Abbiamo individuato l'algoritmo per il serial inserito, quindi cosa succede??? L'algoritmo fa lo XOR tra la lettera (in AL) ed il valore corrispondente in DL preso dalla locazione 004022FB, il risultato dello XOR viene messo in AL e viene confrontato con il valore che si trova alla locazione 004022EF e successive locazioni. Quindi non ci resta che andare a prendere i 12 valori dalla memoria (sia a 004022FB che a 004022EF)ed effettuare il calcolo inverso in modo tale da ottenere la stringa da inserire nel box.
004022EF = 20 76 C8 1E B4 90 C3 7D AD 2C CA 72
-----------------------------------------
55 49 43 5F 66 6F 72 65 76 65 72 20
I calcoli li potete effettuare con la calcolatrice di WinZoz, ora andate a vedere a quali lettere corrispondono i valori!!!
UIC_forever
Attenzione a non sbagliare, contate le lettere di UIC_forever sono 11 quindi nel box dovremo inserire anche uno spazio alla fine del serial infatti il 20 esadecimale corrisponde allo spazio.
Se inseriamo nel box UIC_forever allora viene eseguito il JUMP alla riga 004013F5, continuiamo a vedere cosa succede!!!
Very good, this is the good serial!!!
00401205 PUSH 004020E3 // pOfstruct = The_mask.004020E3
0040120A PUSH 004020DA // FileName = "mask.key"
0040120F CALL JMP.&KERNEL32.OpenFile // OpenFile
00401214 MOV DS:[4021EC],EAX // Salva l'handle del file
00401219 CMP EAX,-1
0040121C JNZ SHORT 00401223 // Salta se il file viene aperto
0040121E JMP 004012FB
Alla riga 0040120F tenta di aprire il file mask.key se non viene trovato allora inizializza EAX con FFFFFFFF (-1) e quindi il salto non
viene effettuato e poi alla riga 0040121E si salta all'errore altrimenti se il file viene trovato in EAX viene messo l'handle del file.
Adesso dobbiamo creare nella cartella che contiene il CrackMe il file mask.key ed al suo interno io ci scrivo come al solito ValerioSoft. Vediamo
cosa succede......
00401225 PUSH 0 // Origin = FILE_BEGIN
00401227 PUSH 0 // pOffsetHi = NULL
00401229 PUSH DWORD PTR DS:[402293] // OffsetLo = 0
0040122F PUSH DWORD PTR DS:[4021EC] // hFile = 0000007C (window)
00401235 CALL JMP.&KERNEL32.SetFilePointer // SetFilePointer
0040123A PUSH 0 // pOverlapped = NULL
0040123C PUSH 004021F0 // pBytesRead = The_mask.004021F0
00401241 PUSH DWORD PTR DS:[4021F4] // BytesToRead = 20 (32.)
00401247 PUSH 004021FC // Buffer = The_mask.004021FC
0040124C PUSH DWORD PTR DS:[4021EC] // hFile = 0000007C (window)
00401252 CALL JMP.&KERNEL32.ReadFile // ReadFile
00401257 MOV CL,1A
00401259 JMP 0040144E
La Call alla riga 00401235 setta il puntatore all'inizio del file, mentre la Call alla riga 00401252 legge il file, questa volta
viene passato alla funzione il numero di byte da leggere cioè 32 e la locazione in cui memorizzare i caratteri letti (004021FC) e poi anche
la locazione in cui memorizzare il numero di caratteri letti (004021F0)
00401450 MOV ESI,004021FC // mette in ESI l'indirizzo che contiene
// i caratteri letti
00401455 MOV EDI,00402239 // mette in EDI l'indirizzo 00402239
0040145A MOV AL,DS:[ECX+402252] // al primo giro mette il valore contenuto
// alla locazione 00402225 in AL
00401460 MOV AH,DS:[ESI+ECX] // mette in AH la prima lettera letta
00401463 MOV DL,DS:[EDI+ECX] // mette il valore contenuto alla
// locazione 00402239 in DL
00401466 XOR AH,AL // Xora AH con AL e mette il risultato in AH
00401468 CMP AH,DL // Confronta AH con AL
0040146A JNZ 004012FB // se non sono uguali salta all'errore
00401470 INC ECX // incrementa ECX per leggere il prossimo valore
00401471 CMP ECX,19 // confronta ECX con 19 (25 decimale)
00401474 JNZ SHORT 0040145A // salta se ha scandito tutti i caratteri
// correttamente
00401476 JMP 0040125E // altrimenti reitera
Cosa si intuisce???
- La stringa ValerioSoft è errata dato che ha meno di 25 caratteri
- Per capire cosa scrivere nel file basta fare uno XOR tra i 25 valori contenuti alla locazione 00402225 con quelli
contenuti alla locazione 00402239.
00402239 = 3F 3F D7 ED 67 34 F3 9E 97 81 34 0F 86 55 AC 9C 38 C6 30 5F 63 42 12 9C 37
--------------------------------------------------------------------------------
5A 75 62 64 75 6C 6C 61 6C 6C 61 2E 2E 2E 62 79 20 51 75 65 71 75 65 72 6F
Zubdullalla...by Quequero
Se il il key file contiene la stringa Zubdullalla...by Quequero allora sicuramente viene eseguito il JUMP alla riga 00401476 e quindi ci troviamo dinanzi a questo pezzo di codice:
00401260 PUSH 0 // Mode = OF_READ|OF_SHARE_COMPAT
00401262 PUSH 00402163 // pOfstruct = The_mask.00402163
00401267 PUSH 004021E3 // FileName = "mask.exe"
0040126C CALL JMP.&KERNEL32.OpenFile // OpenFile
00401271 MOV DS:[4021EC],EAX
00401276 CMP EAX,-1
00401279 JNZ SHORT 00401280
0040127B JMP 004013F7
Questo pezzo di codice non ha bisogno di molte presentazioni, quindi dovreste aver già intuito che
bisogna creare nella cartella del CrackMe il file mask.exe, allora fatelo!!! :-D
Per chi non lo avesse capito bisogna creare un bel file di testo, che contiene la scritta
ValerioSoft e poi gli cambiate l'estensione da txt ad exe! Se avete fatto tutto per bene allora alla
riga 00401279 viene eseguito il salto che ci porta alla riga 004013F7
00401282 PUSH 0 // pOffsetHi = NULL
00401284 PUSH DWORD PTR DS:[402297] // OffsetLo = B0 (176.)
0040128A PUSH DWORD PTR DS:[4021EC] // hFile = 00000080 (window)
00401290 CALL JMP.&KERNEL32.SetFilePointer // SetFilePointer
00401295 PUSH 0 // pOverlapped = NULL
00401297 PUSH 00402221 // pBytesRead = The_mask.00402221
0040129C PUSH DWORD PTR DS:[4021F8] // BytesToRead = 14 (20.)
004012A2 PUSH 00402225 // Buffer = The_mask.00402225
004012A7 PUSH DWORD PTR DS:[4021EC] // hFile = 00000080 (window)
004012AD CALL JMP.&KERNEL32.ReadFile // ReadFile
Beh anche questa parte ci dovrebbe essere familiare ma con una piccola variante, quale??? :-D
Osservate il valore pushato alla riga 00401284, beh quello è l'offset che ci indica il punto
in cui inizierà la lettura del file, quindi già questo è indice di un errore dato che io la stringa
ValerioSoft l'ho inserita all'inizio del file. Ci conviene andare avanti lo stesso e vedere cosa succede
e poi traiamo le nostre conclusioni!!!
004012B6 MOV ESI,00402225 // mette in ESI l'indirizzo che
// contiene i caratteri letti
// dal file
004012BB MOV EDI,0040226B // mette in EDI l'indirizzo 0040226B
004012C0 MOV AL,DS:[ECX+40227F] // mette in AL il valore che si trova
// alla locazione 0040227F
004012C6 MOV AH,DS:[ESI+ECX]
004012C9 MOV DL,DS:[EDI+ECX]
004012CC XOR AH,AL // fa lo XOR tra AH e AL
004012CE CMP AH,DL
004012D0 JNZ SHORT 004012FB
004012D2 INC ECX
004012D3 CMP ECX,14
004012D6 JNZ SHORT 004012C0
004012D8 JMP 004013AB
...non continuo con i commenti dato che ormai abbiamo imparato a memoria la tecnica, quindi andiamo a prendere questi benedetti 20 valori dalla memoria per fare lo Xor:
0040226B = 28 2A 24 E8 BA 6D 6D 25 71 49 D4 38 3E 4E 57 EF E9 75 4C 33
-----------------------------------------------------------------
47 6F 6F 64 20 4C 75 63 6B 20 43 72 61 63 6B 65 72 21 21 21
Good Luck Cracker!!!
Cosa dobbiamo fare??? Apriamo il file mask.exe che abbiamo creato in precedenza con AXE, poi inseriamo nel file tanti zeri fino ad arrivare all'offset AF, dall'offset B0 i valori esadecimali che ci siamo calcolati oppure andate nell'Ansi Text corrispondente e scrivete Good Luck Cracker!!!, poi salvate il file. Avviamo nuovamente il CrackMe, inseriamo il serial UIC_forever (+ lo spazio finale) e premiamo il pulsante Check!!!
Totally Registered
Registry Attack
Il PEtite 1.2 se non sbaglio è un programma che serve a comprimere i file eseguibili e quindi non utilizza sofisticate tecniche per evitare il dump della memoria quindi avviamo il nostro file eseguibile e poi apriamo il nostro amato PEditor 1.7, ora clicchiamo su taskse poi andiamo a selezionare il file the mask.exe, clicchiamoci su con il tasto destro del mouse e poi scegliamo l'opzione Dump (Full). Diamo un nome al file e salviamo!!! Adesso proviamo ad avviare il file appena salvato, OK funziona perfettamente e non c'è neanche bisogno di cambiare l'Entry Point dato che l'algoritmo che decritta il file a runtime automaticamente modifica la sua prima istruzione in un JUMP 00401000 che corrisponde alla prima vera istruzione del programma.
Note Finali
Bene siamo venuti a capo della situazione anche questa volta, colgo l'occasione per salutare in blocco l'intera UIC e QUEQUERO per aver scritto questo semplice CrackMe!!! :-D ;-) :-P
Ciaoooooooooooooooooo alla proximaaaaaaaaa
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.