Zoom Icon

Soluzione Crackme 23

From UIC Archive

Crackme n.23 : Un altro crackme scritto da Que, buon lavoro :))))

Contents


Soluzione Crackme 23
Author: ValerioSoft
Email: ValerioSoft(AT)tin.it
Website:
Date: 18/03/2007 (dd/mm/yyyy)
Level: Some skills are required
Language: Italian Flag Italian.gif
Comments: Sotto il sole di Luglio il cervello non è mai saggio. :-D



Introduzione

Ciaoooooooooo, benvenuti al mio settimo tuteeeee??? Hey basta :-D


Tools


Notizie sul CrackMe N.23

Anche questo è un crackme scritto da Quequero che questa volta ha cercato di confonderci le idee il più possibile!!!.

Regolamento:
Disassembly and patching are not allowed and not needed!!!!!!


Essay

Come nel precedente Tute il CrackMe è crittato con PEtite 1.2, questa volta non scomodate il PEID 0.94!!!

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, poi premiamo semplicemente l'asterisco (*) sulla tastiera poi scegliamo View->Module'Oddity' 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 o premiamo CTRL+A, ora il codice che ci viene mostrato risulta comprensibilissimo.

Voglio farvi notare subito una cosa, andiamo a vedere le Intermodular Calls, Quequero ha superato se stesso :-D ci ha messo 3500 GetWindowTextA in modo tale da incasinarci la vita e non farci capire niente! Inseriamo un breakpoint su tutte le GetWindowTextA, premiamo il tasto Play, compare la finestra per l'inserimento di Nome e Serial, io inserisco ValerioSoft e 123456789, premiamo il pulsante Register e Ollydbg prende il controllo, vi consiglio di non cercare di capire cosa sta succedendo, vi voglio mostrare solo una nuova istruzione che si trova alla riga 00401223. A cosa serve l'istruzione CLI???
Con CLI il programma in esecuzione non può essere interrotto da un interrupt esterno e quindi non può essere interrotto neanche da Ollydbg e quindi termina bruscamente. In altre situazioni dove il patching è permesso ci basterebbe Noppare con un 90 l'istruzione malefica ma in questo caso possiamo solo limitarci a Noppare l'istruzione a runtime. Riavviamo il CrackMe e facciamo nuovamente il procedimento fino al punto in cui si analizza il codice con CTRL+A e poi premiamo il tasto destro del mouse su un punto qualsiasi del codice e scegliamo Search for->All Commands e poi scriviamo CLI e premiamo il pulsante Find. Ecco che compare una nuova finestra che ci indica tutte le occorrenze di CLI nel programma, andiamo alle righe di codice corrispondenti e sostituiamo il codice FA con 90. Ricordate la modifica è solo a runtime e quindi va fatta ogni qual volta riavviate il programma.

Quequero ci ha inserito un'altro trick basato sull'uso della funzione GetTickCount, apriamo le Intermodular Calls e piazziamo un breakpoint su tutte le Call GetTickCount, come potete notare sono 2. Questa funzione restituisce in EAX i millisecondi trascorsi dall'avvio di WinZoz. Quequero ha pensato bene di utilizzarne 2, perché???? La prima ad essere eseguita è questa: 004011D1 CALL JMP.&KERNEL32.GetTickCount 004011D6 MOV DS:[402158],EAX // salva il numero di millisecondi // trascorsi dall'avvio di WinZoz La seconda si trova qui: 004015F8 CALL JMP.&KERNEL32.GetTickCount 004015FD MOV EBX,DS:[402158] // mette in EBX i millisecondi // salvati in precedenza

00401603 SUB EAX,EBX // sottrae i vecchi millisecondi // ai nuovi ed ottiene il tempo // trascorso

00401605 CMP EAX,4 // confronta i millisecondi // trascorsi con il 4

00401608 JGE 00401903 // salta se sono più di 4 Cosa fa realmente??? Beh, in fin dei conti controlla se stiamo utilizzando il debbugger, Quequero infatti ha calcolato che se non steppiamo nella parte di codice compresa tra 004011D1 e 004015F8 occorrono massimo 4 millisecondi per eseguirla tutta. Quindi se alla riga 00401608 viene eseguito il salto, viene restituito il controllo al box di registrazione senza fare realmente niente visto che non viene controllato se il serial è giusto oppure no.

Bene, possiamo utilizzare come punto di attacco la stringa Registered - - by Quequero, 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: 004017D3 PUSH 00402164 // Text = "Registered - - by Quequero" 004017D8 PUSH DWORD PTR DS:[402048] // hWnd = 00190356 004017DE CALL JMP.&USER32.SetWindowTextA // SetWindowTextA Questo è il pezzo di codice che ci mostra l'avvenuta registrazione, ma chi richiama questo pezzo di codice???
Beh diamo uno sguardo più su nel codice: 0040175D CMP ECX,0AFFF12 00401763 JNZ 004017E8 // Se non sono uguali salta tutta la // parte relativa al file Oddity.key

00401769 PUSH 2 // Mode = OF_READWRITE|OF_SHARE_COMPAT 0040176B PUSH 004020C8 // pOfstruct = DUMPED.004020C8 00401770 PUSH 004020BD // FileName = "Oddity.key" 00401775 CALL JMP.&KERNEL32.OpenFile // OpenFile 0040177A MOV DS:[402148],EAX 0040177F CMP EAX,-1 00401782 JNZ SHORT 00401789 // se il file non esiste allora // esegue il JUMP sottostante

00401784 JMP 00401903 // Passa il controllo alla finestra // senza fare nulla

// se il file esiste allora...

00401789 PUSH 0 // Origin = FILE_BEGIN 0040178B PUSH 0 // pOffsetHi = NULL 0040178D PUSH DWORD PTR DS:[4020B4] // OffsetLo = 0 00401793 PUSH DWORD PTR DS:[402148] // hFile = NULL 00401799 CALL JMP.&KERNEL32.SetFilePointer // SetFilePointer

0040179E PUSH 0 // pOverlapped = NULL 004017A0 PUSH 004020B8 // pBytesRead = DUMPED.004020B8 004017A5 PUSH DWORD PTR DS:[4020A8] // BytesToRead = 8 004017AB PUSH 004020BC // Buffer = DUMPED.004020BC 004017B0 PUSH DWORD PTR DS:[402148] // hFile = NULL 004017B6 CALL JMP.&KERNEL32.ReadFile // ReadFile

004017BB MOV ESI,004020BC 004017C0 MOV EDI,004020AC // ASCII "Quequero" 004017C5 MOV ECX,DS:[4020A8] 004017CB REPE CMPS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] 004017CD JNZ 00401903 Il listato precedente è molto semplice, si capisce facilmente che bisogna creare nella cartella del CrackMe il file Oddity.key e al suo interno bisogna scrivere Quequero. Allora visto che in seguito ci servirà creiamo il file.

La cosa più importante però è capire come ci si arriva li, alla riga 00401769 si può arrivare in 2 modi:

  1. Alla riga 0040175D se il valore contenuto in ECX è uguale a 0AFFF12.
  2. Alla riga 00401895 se il valore contenuto in EAX è uguale a quello contenuto in EDX.

Analizziamo il primo caso: 00401738 PUSH 19 // Count = 19 (25.) 0040173A PUSH 0040214C // Buffer = DUMPED.0040214C 0040173F PUSH DWORD PTR DS:[40204C] // hWnd = 0010035A 00401745 CALL JMP.&USER32.GetWindowTextA // GetWindowTextA

0040174A MOV EAX,0040214C // ASCII "ValerioSoft" 0040174F ADD EAX,EBX 00401751 DEC EAX 00401752 SHR EAX,0C 00401755 XCHG EAX,ECX // scambia i valori 00401756 POP EDX 00401757 SUB ECX,EAX // sottrae EAX a ECX 00401759 ADD EAX,EDX 0040175B NOT ECX // nega ECX 0040175D CMP ECX,0AFFF12 00401763 JNZ 004017E8 Guardate alla riga 0040175B il valore di ECX viene negato, proviamo allora a scoprire che valore dovrebbe contenere ECX per ottenere 0AFFF12 dopo la negazione!!!

00AFFF12 = 00000000101011111111111100010010 not

          11111111010100000000000011101101 = FF5000ED Hex

Non abbiamo finito, alla riga 00401752 (prima di scambiare i valori di EAX e ECX) viene effettuato uno Shift a destra del valore contenuto in EAX, quindi che valore dovrebbe contenere EAX per ottenere dopo lo Shift a destra FF5000ED???
Basta fare uno Shift a sinistra del valore FF5000ED con C, vediamo (utilizzate la calcolatrice del PHOG): FF5000ED SHL di C = FF5000ED000 Il valore ottenuto dallo Shift a sinistra è composto da più di otto cifre quindi il registro EAX non lo può contenere quindi cosa si deduce????
Beh si deduce che il JUMP alla riga 00401763 verrà sempre eseguito e quindi non si può arrivare all'apertura del file Oddity.key da qui, non ci resta che analizzare la seconda via!!! 004017E8 MOV EAX,DS:[4020A4] // mette in EAX il valore AAC61E4F 004017ED MUL DWORD PTR DS:[402150] // moltiplica 536F6972 per EAX 004017F3 INC EAX // incrementa la seconda parte del risultato 004017F4 MOV DS:[4020A4],EAX // salva il nuovo valore nella locazione 4020A4 004017F9 MUL DWORD PTR DS:[40205C] // moltiplica 0F415C9A per EAX 004017FF XOR EAX,DS:[402150] // xora la seconda parte del risultato con 536F6972 00401805 ROR EAX,4A // Shift constant out of range 1..31 00401808 MOV DS:[402160],EAX // salva il valore di EAX in 402160

0040180D PUSH 19 // Count = 19 (25.) 0040180F PUSH 0040214C // Buffer = DUMPED.0040214C 00401814 PUSH DWORD PTR DS:[40204C] // hWnd = 001203B2 (class='Edit',parent=001903CE) 0040181A CALL JMP.&USER32.GetWindowTextA

0040181F MOV EAX,0040214C // ASCII "ValerioSoft" 00401824 PUSH EAX 00401825 PUSH 19 // Count = 19 (25.) 00401827 PUSH 00402099 // Buffer = DUMPED.00402099 0040182C PUSH DWORD PTR DS:[402050] // hWnd = 000D03D0 (class='Edit',parent=001903CE) 00401832 CALL JMP.&USER32.GetWindowTextA

00401837 MOV EBX,00402099 // ASCII "1123" 0040183C POP EAX 0040183D MOV EBX,EAX 0040183F MOV EAX,DS:[EBX] // mette in EAX i primi 4 caratteri del nome 00401841 MOV ECX,EAX // li mette anche ECX 00401843 XOR ECX,EBX 00401845 SHR ECX,2D // Shift constant out of range 1..31 00401848 MOV EBX,DS:[402160] // mette in EBX il valore 4D092B4D (al primo avvio) 0040184E MOV EDX,ECX 00401850 ADD EDX,EBX 00401852 XOR EAX,EBX 00401854 XOR EDX,EAX 00401856 SUB EAX,DS:[4020A4] 0040185C OR EDX,EBX 0040185E MOV ECX,DS:[402160] 00401864 ROR EAX,CL 00401866 SHL EDX,57 00401869 DEC EAX 0040186A ADD EDX,DS:[402150] 00401870 XOR EAX,DS:[4020A4] 00401876 MOV EBX,DS:[40214C] 0040187C MOV EDX,EAX 0040187E XOR EDX,DS:[40218A] 00401884 CMP EDX,EBX 00401886 JE SHORT 00401903 00401888 MOV EBX,00402099 // ASCII "1123" 0040188D MOV EDX,DS:[EBX] 0040188F XOR EBX,DS:[4020A4] 00401895 CMP EAX,EDX 00401897 JE 00401769 Tralasciate i commenti che ho inserito io, abbiamo detto che il JUMP che ci porta all'apertura del file Oddity.key deve essere per forza quello della riga 00401897, allora possiamo piazzare un breakpoint alla riga 00401895 e vedere che valori vengono confrontati!!!
Piazziamo quindi il breakpoint ed inseriamo nel box di registrazione ValerioSoft e 123456789, poi premiamo il pulsante Register. EAX = 108825CD // Boooooooooooooooo

ECX = 34333231 // Sono i primi quattro numeri del serial // ma in ordine inverso Cosa significa tutto ciò???
Abbiamo trovato il serial corrispondente al nome ValerioSoft, pensateci un po' ma non troppo :-)
EAX ed ECX devono essere per forza uguali per poter andare a leggere il file Oddity, il valore di ECX deriva dai primi quattro numeri inseriti infatti 1234 = 31323334 ma presi al contrario 34333231 quindi non ci resta che inserire come serial le lettere corrispondenti a questi valori esadecimali: CD258810. Qualcuno di voi dirà: Ma come faccio ad inserirli da tastiera???
Beh è possibile utilizzare un piccolo trucco, aprite AXE e create un documento nuovo, poi scrivete il valore esadecimale CD258810 e salvate il file di testo. Adesso aprite il file appena creato con il Wordpad o il Notepad e selezionate i quattro caratteri incomprensibili che vedete e fate un bel copia ed incollate nel box del serial. Adesso premete il pulsante Register e...
...non accade nulla dato che adesso il valore in EAX è cambiato!!! Ehy ma che ci prende per il c..o??? Ogni volta che premiamo il pulsante Register il valore in EAX cambia!!! Allora proviamo a riavviare da capo il CrackMe e vediamo se al primo giro i valori sono quelli che ci aspettiamo!!! E bene si!!! Ve l'ho detto che Quequero ci vuole far rinc......ire!!!

Troviamo il Serial per Quequero che se lo merita??? OK, riavviamo nuovamente l'applicazione ed inseriamo come nome Quequero, guardiamo il valore di EAX = 02C6E358 ( alla riga 00401895 ), ora scriviamolo al contrario con AXE (58E3C602) ed il gioco è fatto!!!

Ragazzi non vi spiego cosa fa l'algoritmo per calcolare il seriale giusto dato che non sono riuscito a trovare nessun nome che mi genera un Serial inseribile direttamente da tastiera!!!

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

Un saluto caloroso a va a tutta la UIC!!!
Ciaoooooooooooooooooo alla proximaaaaaaaaa

ValerioSoft


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 malevole 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.