Corso UIC Newbies 06 Spinone
From UIC
Corso UIC Newbies 06 Spinone
Contents |
| Corso UIC Newbies 06 Spinone | |
|---|---|
| Author: | Spinone |
| Email: | |
| Website: | Home page |
| Date: | 16/06/2001 (dd/mm/yyyy) |
| Level: |
|
| Language: | Italian |
| Comments: | |
Tools
- Softice oppure OllyDbg v1.10
Link e Riferimenti
Questo è il Corso UIC Newbies n°06 disponibile alla pagina Corsi UIC Newbies
Introduzione
Proverò a commentare la soluzione di questo crackme molto simpatico............. come il suo autore :)))))).
Notizie sul Programma
Un crackme multilivello didatticamente molto valido (bravo André!!) che ci fà prendere gradatamente dimestichezza con le chiavi di registro di windows.
Essay
Innanzitutto vorrei fare i complimenti all'autore, non è facile scrivere crackme per i newbies anche xchè spesso si danno per scontate delle conoscenze che invece non sono tali. Il programma è facilmente reversabile con l'aiuto del Regmon, ma ho voluto appositamente usare solo il Sice perchè credo che cosi facendo si e costretti a ragionare maggiormente sulle Api. Apriamo il programma e sulle info subito Andrea ci ammonisce dal patchare il proggy. Premiamo il pulsante relativo al primo livello e...... ci prendiamo del "Lamah" sul muso! Bene...anzi male! apriamo Softice, settiamo un Bpx messageboxA e vediamo che succede. Chiudiamolo, nuovamente clic sul pulsante e Sice poppa all'Api messageboxA, pigiamo F12 per uscire dalla funzione e ci ritroviamo nella MFC2.DLL. Sarà sufficiente steppare fino al ret per arrivare finalmente nel programma "Sesto" ( ve ne accorgerete dal nome sulla barra del Sice in basso a destra.) e precisamente all'indirizzo 401567:
00401531 lea eax, dword ptr [esp]
00401535 push esi
00401536 push eax
00401537 push 000F003F
0040153C push 00000000
0040153E push 0040409 Questo parametro è la locazione dove punta al nome della chiave da aprire
00401543 mov esi, ecx
00401545 push 80000001
0040154A Call dword ptr [00405290]
00401550 test eax, eax // Eax=0 se la chiave è stata trovata
00401552 je 00401575 // Salta se trovata, altrimenti continua verso la nag
00401554 push 00000010
00401556 push 0040408C
0040155B push 00404070
00401560 mov ecx, esi
00401562 Call 00401C2E // Chiamata alla nag
00401567 mov ecx, dword ptr [esp+04] // Qui approdate con il Sice
0040156B push ecx
0040156C Call dword ptr [0040528C]
00401572 pop esi
00401573 pop ecx
00401574 ret
00401575 push 00000030
00401577 push 00404064
0040157C push 00404020
00401581 mov ecx, esi
00401583 Call 00401C2E // finestra delle congratulazioni
Come vedete siamo atterrati sotto una call che se viene eseguita è quella che vi sbatte in faccia la nag; quindi vuol dire che qualcosa precedentemente è andato storto. Proviamo a vedere cosa spulciando il codice un pò più sù.......... Vi accorgerete che poco prima c'è la chiamata all'Api "RegOpenKey". Cosa fa di bello quest'Api? beh.......un po' di fantasia.......apre il registro di windows per la ricerca di chiavi. Dovete sapere che prima di eseguire la chiamata all'Api è necessario passare alla funzione alcune informazioni (parametri). Queste ultime vengono passate (o fissate in memoria) attraverso una serie di istruzioni "push". Tenete a mente che il penultimo push prima della chiamata RegOpenKey contiene la locazione dove è memorizzato il nome della chiave da ricercare nel registro.
E' sufficiente quindi andare in Sice, dare il comando "d 404094", (senza le apicine) per veder apparire nella finestra dati in caratteri ASCII il nome della chiave che verrà ricercata. Nel nostro caso l'autore del crackme è un po megalomane (come tutti i coders e reverser :))) e la chiave si chiama: Andreageddon
Se la chiave verrà trovata il valore ritornato in eax sarà zero, il test sara positivo ed il jz successivo verrà effettuato portandovi ad un altro punto del proggy. Viceversa se il risultato in eax è diverso da zero e la chiave non è stata trovata, il programma continuerà verso la prossima call, che è quella della nag "Lamah". Allora dobbiamo solamente creare la chiave AndreaGeddon per superare il primo livello?.....si certo...apriamo il registro con regedit e....azzo quanti gruppi di chiavi!! dove la creamo??? Humm....oltre alla possibilità di farvi aiutare da Regmon che potrà rivelare la chiave che il proggy tenta di aprire, potete anche rilevarlo attraverso i famosi parametri passati prima della call RegOpenKeyExeA. Infatti in questo caso il gruppo di chiavi è definito dall'ultimo push all'indirizzo 401545 : push 80000001. Questo valore corrisponde al gruppo HKEY_CURRENT_USER. E' lì che la chiave va creata............avete fatto? si.... eccovi le prime congratulazioni.. Uff...e questa è andata! A proposito visto che sono andato a rivedermi la guida all'Api vi farà comodo sapere che:
| 80000001 | HKEY_CURRENT_USER |
|---|---|
| 80000000 | HKEY_CLASSES_ROOT |
| 80000002 | HKEY_ LOCAL_MACHINE |
| 80000003 | HKEY_USER |
| 80000004 | HKEY_PERFORMANCE_DATA |
| 80000005 | HKEY_CURRENT_CONFIG |
| 80000006 | HKEY_DYN_DATA |
Passiamo al 2° livello. questa volta cliccando sul 2° pulsante, di ritorno dalla MessageboxA si atterra nel programma all'indirizzo 4016CC. Guardiamo cosa avviene prima. Risalendo fino a ritrovare la chiamata RegOpenkeyexeA potremo accorgerci che all'indirizzo 4015F3 la funzione viene messa in ESI e poi abbiamo il solito passaggio dei parametri con la serie di push. Anche qui il penultimo indirizzo pushato contiene il nome della chiave che verrà ricercata. Digitiamo in Sice D 404308 e troveremo nella datawindow: AndreaGeddon\1 questo vuol dire che verrà cercata la chiave AndreaGeddon e poi la sottochiave 1 e se trovate dovremmo passare di livello. Proviamo...creamo la sottochiave 1 e..........ci ribecchiamo di nuovo del "Lamah". Azz ma cosa è successo!!??? ritorniamo in Sice, settiamo un Bpx all'inizio della routine all'indirizzo 4015F0 e steppiamo
004015F1 push ebx
004015F2 push esi
004015F3 mov esi, dword ptr [00405290] Esi punta all'indirizzo della Api
RegOpenKey
004015F9 lea eax, dword ptr [esp+08]
004015FD push edi
004015FE push eax
004015FF push 000F003F
00401604 push 00000000
00401606 push 00404308 Viene salvata la locazione che punta alla chiave
da aprire
0040160B mov edi, ecx
0040160D push 80000001
00401612 call esi // Chiamata all'Api
00401614 mov ebx, dword ptr [0040528C]
0040161A test eax, eax
0040161C je 0040163D // salta se trovata
0040163D lea ecx, dword ptr [esp+0C]
00401641 push ecx
00401642 push 000F003F
00401647 push 00000000
00401649 push 004042D4 // Memorizza la locazione della chiave AndreaGeddon\1\2
0040164E push 80000001
00401653 call esi // Chiamata all'Api
00401655 test eax, eax
00401657 je 0040167F // Salta se trovata
0040167F lea edx, dword ptr [esp+0C]
00401683 push edx
00401684 push 000F003F
00401689 push 00000000
0040168B push 00404288 // Ultima chiave memorizzata:AndreaGeddon\1\2
00401690 push 80000001
00401695 call esi // Chiamata all'Api
00401697 test eax, eax
00401699 je 004016B0 // Salta alla finestra delle congratulazioni se trovata
0040169B push 00000010
0040169D push 0040408C
004016A2 push 00404260
004016A7 mov ecx, edi
004016A9 Call 00401C2E
004016AE jmp 004016D0|
004016B0 push 00000030
004016B2 push 00404258
004016B7 push 00404230
004016BC mov ecx, edi
004016BE Call 00401C2E // Chiamata alla finestra delle Congratulation
Dunque come potete vedere dalle istruzioni, viene cercata la sottochiave AndreaGeddon\1', il primo test è positivo ma il programma continua e ci ritroviamo di fronte ad una serie di push prima della call ESI alla RegOpen.... Questa volta il push della locazione di memoria 4042D4 salva ancora una chiave che verrà ricercata : 'AndreaGeddon\1\2 e che se non trovata....nisba. Ok creamo anche la "2" e proviamo.........."Lamah" (ma sulla buona strada)....ecchepalle!!! Ripercorrendo la routine ci accorgiamo che il proggy continua ancora ed, anche in questo caso, il penultimo push salva un'ulteriore sottochiave: AndreaGeddon\1\2\4'. Creiamo anche la "4" e... Pam!!........"Cool".... si passa al terzo.
Eseguendo la stessa procedura anche per questo nuovo livello, questa volta approderemo all'indirizzo 40176D. Spostatevi più sù e settate un bpx al 401729 che è l'inizio della routine. Steppando riusciremo ad individuare facilmente i famosi push che passano i parametri prima della chiamata all'Api. Questa volta la locazione di memoria dove viene salvato il nome della chiave è la 4044E4 e lì potremo ritrovare: AndreaGeddon\WhatIsTheMatrix. Riapriamo il regedit e creamo sotto AndreaGeddon questa sottochiave........Senza molta convinzione proviamo a vedere........infatti una nag ci comunica che non siamo gli eletti! Ritorniamo in Sice e steppiamo.
0040172A push 000F003F
0040172F push 00000000
00401731 push 004044E4 Salva la locazione della chiave
AndreaGeddon\WhatIsTheMatrix
00401736 push 80000001
0040173B mov [esp+29], 72
00401740 mov [esp+2B], 6E
00401745 mov [esp+2D], 74
0040174A Call dword ptr [00405290] // Chiamata all'Api RegOpenKey
00401750 mov ebp, dword ptr [0040528C]
00401756 test eax, eax
00401758 je 0040177B // Salta se trovata
potremo vedere che il primo test all'indirizzo 401756 è positivo ed il jz successivo è eseguito. Andando avanti ci imbattiamo in un'altra serie di push.......controlliamo il penultimo ed alla locazione 404444 leggeremo in ASCII: WelcomeToTheRealWorld. qui cominceremo a pensare che il gioco si stia facendo monotono e che sia sufficiente creare ancora quest'ultima sottochiave, invece no!.... se lo fate non otterrete nulla.
0040177F lea ecx, dword ptr [esp+10]
00401783 push ecx
00401784 push ebx
00401785 push 00000000
00401787 push 00000000 // Tipo di valore
00401789 push 00404444 Salva la locazione della chiave
AndreaGeddon\WhatIsTheMatrix
0040178E push edx
0040178F Call dword ptr [00405294] // Chiamata all'Api RegQueryValue
00401795 test eax, eax
00401797 je 004017AE // Salta se trovata
Infatti se avete fatto un po' di attenzione avrete visto che questa volta non è la classica call RegOpenKey ad essere chiamata, ma bensì la RegQueryValue. Questa a differenza della prima, legge anche il valore attribuito ad una chiave. Pertanto WelcomeToTheRealWorld non e una chiave ma bensi il nome di un valore.Ok, apriamo regedit ed alla chiave WhatIsTheMatrix clicchiamo con il destro ed alla voce "nuovo" invece di scegliere chiave ci viene posto il dilemma: Stringa, Valore binario, Valore Dword..... Cosa scegliamo??.....beh anche questa volta ci viene in aiuto l'analisi dei push eseguiti prima della call. Infatti il tipo di valore lo deduciamo dal push 00 all'indirizzo 401787. Se viene passato il parametro 00 che è uguale a NULL, vuol dire che il tipo di valore puo' essere di qualsiasi tipo (03 =binario, 04=Dword). per comodità scegliamo il tipo stringa e creamo il nome WelcomeToTheRealWorld. Bene a questo punto proviamo..... dovrebbe funzionare...........macché.... niente da fare ancora, è cambiata la nag che ci segnala che dovremmo essere vicini ma..... ancora nulla. Ritorniamo in Sice, questa volta vedremo che il test all'indirizzo 401795 è positivo quindi il prog. salta la call alla nag e ci porta a 4017AE.
004017AF xor edi, edi // Viene azzerato edi
004017B1 mov al, byte ptr [edi+ebx] In al il byte letto dall'Api e
puntato nella locazione edi+ebx
004017B4 mov cl, byte ptr [esp+edi+18] In cl il byte puntato dalla
locazione in esp+edi+18
004017B8 cmp al, cl // Confronta se sono uguali
004017BA jne 004017E9 // Salta alla nag se diversi, altrimenti continua
004017BC cmp edi, 00000007 // Verifica se le iterazioni sono arrivate a 7
004017BF jne 004017E1 // Salta se inferiori, altrimenti continua
004017C1 push 00000030
004017C3 push 004043C4
004017C8 push 00404378
004017CD mov ecx, esi
004017CF Call 00401C2E // Chiamata alla finestra delle congratulation
004017D4 push 00000001
004017D6 lea ecx, dword ptr [esi+000000E0]
004017DC Call 00401C28
004017E1 inc edi // Incrementa il contatore
004017E2 cmp edi, 00000007 // Verifica il n° delle iterazioni
004017E5 jle 004017B1
004017E7 jmp 00401803
004017E9 push 00000010
004017EB push 00404360
004017F0 push 00404318
004017F5 mov ecx, esi
004017F7 Call 00401C2E // Chiamata alla nag
Comincia una routine dove vengono mossi dei byte in AL e CL che poi vengono confrontati. In CL viene messo inizialmente 54 che in ASCII è la lettera T, il confronto fallisce xchè AL=0 (non abbiamo inserito alcun dato). Supponendo che il confronto fosse positivo il jnz che ci porta verso la nag non avverrebbe ( lo possiamo simulare invertendo il flag Z). Viene verificato se EDI(contatore dei cicli) è = a 7, altrimenti viene incrementato ed il ciclo si ripete. Possiamo eseguire tutte le iterazioni annotando tutte le volte le lettere che vengono caricate in CL oppure, visto che i byte caricati in CL sono memorizzati nella locazione EDI+ESP+18, se controllate con il solito comando "d edi+esp+18" leggerete la stringa "Trinityy". Chiaro no!!??........apriamo regedit ed al nome WelcomeToTheRealWorld inseriamo il valore Trinityy.........e saremo eletti!!!
Siamo all'ultimo livello. Questa volta la nag ci fà cadere nell'oblio. Solita procedura e.......atterriamo all'indirizzo 401871 spostiamoci + sù e settiamo il bpx all'inizio della routine precisamente su 401842. Steppiamo fino alla serie di push che ormai conosciamo bene e li troveremo che il penultimo salva la chiave AndreaGeddon\Sergej\Rachmaninov
00401843 push 000F003F
00401848 push 00000000
0040184A push 00404674 // Cosa farà questo push????
0040184F push 80000001
00401854 call dword ptr [00405290] // Chiamata all'Api RegOpenKey
0040185A test eax, eax
0040185C je 00401883 // Salta se trovata
Creamo le nuove chiavi e potremo così continuare verso la call RegQueryValue
00401887 lea ecx, dword ptr [esp+10]
0040188B push edi
0040188C push ecx
0040188D push esi
0040188E push 00000000
00401890 push 00000000 // Tipo di valore
00401892 push 0040461C // Push della locazione valore "Qualbuonvento"
00401897 push edx
00401898 Call dword ptr [00405294] // Chiamata all'Api RegQueryValue
0040189E test eax, eax
004018A0 je 004018B3 // Salta se trovata
Per l'ultima volta leggiamo in memoria qual'è il nome del valore che verrà aperto dall'Api RegQueryValue. Vedremo che è QualBuonvento................creamolo scegliendo il tipo "stringa" e potremo procedere verso l'algoritmo che valuterà se il dato letto in Qualbuovento è correto. Per comodità ho inserito preventivamente il valore Spin0.
004018B5 or ecx, FFFFFFFF
004018B8 xor eax, eax // Azzera eax
004018BA xor edx, edx // Azzera edx
004018BC repnz // Passa in rassegna i byte e ne fa il conteggio
004018BD scasb
004018BE not ecx
004018C0 dec ecx // In Ecx il n° dei char
004018C1 je 004018DC // Se ecx=0 salta alla nag (controlla se ci cono dati)
Dunque vediamo di chiarire cosa fa questa prima routine La locazione della stringa letta dall'Api viene messa in Esi. l'istruzione rpz scasb fa un conteggio dei byte che la compongono (+1 per il carrage return) il risultato è poi messo in ecx che se uguale a 0 (nessun dato rilevato) setta il flag Z che fa eseguire il jz a 4018DC e........siamo fuori. Viceversa il programma continua:
Spin0 puntato (edx viene incrementato di volta in volta e funge anche da puntatore
al byte)
004018C6 mov edi, esi
004018C8 add al, dl // Aggiunge al byte in al la sua posizione
004018CA or ecx, FFFFFFFF
004018CD mov byte ptr [edx+esi], al Il risultato di al sovracrive il
byte che è stato considerato
004018D0 xor eax, eax
004018D2 inc edx // Sposta il puntatore al prosimo byte da trattare
004018D3 repnz // Ripete il conteggio dei byte componenti la stringa
004018D4 scasb
004018D5 not ecx
004018D7 dec ecx
004018D8 cmp edx, ecx // Confronta il n° dei char con il contatore
004018DA jb 004018C3 // Se non è = riprendi il ciclo, altrimenti continua
Come avete intuito viene messo in al il byte della stringa letta dall'Api al quale verrà poi aggiunto il valore della sua posizione che ha la seguente logica:
posizione 1° byte: dl = 0
posizione 2° byte: dl = 1
posizione 3° byte: dl = 2
posizione 4° byte: dl = 3
..............................
..............................
il risultato dell'addizione viene messo nella stessa locazione di memoria del byte trattato che verrà quindi sovrascritto. Il ciclo si ripete sino a quando il contatore in dl sarà = a cl che contiene il n° di char che compone la stringa. vediamo come l'agoritmo continua a trattare la nostra stringa:
stringa precedentemente già manipolata
004018DE or ecx, FFFFFFFF
004018E1 xor eax, eax // Azzera eax
004018E3 xor edx, edx // Azzera edx
004018E5 repnz // Conteggio dei byte componenti la stringa
004018E6 scasb
004018E7 not ecx
004018E9 dec ecx // In ecx il n° dei char
004018EA je 00401902 // Salta alla nag se ecx=0
004018EC mov al, byte ptr [edx+esi]Mette in al il byte puntato della
stringa
004018EF mov edi, esi
004018F1 add bl, al Addiziona a bl il byte contenuto in al ( ad ogni ciclo
cunula tutti i byte)
004018F3 or ecx, FFFFFFFF
004018F6 xor eax, eax // Azzera eax
004018F8 inc edx // Azzera edx
004018F9 repnz // Nuova scansione per conteggio byte
004018FA scasb
004018FB not ecx
004018FD dec ecx // In ecx il n° dei char
004018FE cmp edx, ecx // Confronta il n° dei char con il contatore
00401900 jb 004018EC // Riprendi se non ha finito, altrimenti...
00401902 cmp bl, D1 // Confronta se dl = a D1
00401905 jne 0040195A // Salta alla nag se diverso
00401907 push 00000030
00401909 push 004045BC
Intuito qualcosa?.....vediamo.....dopo aver nuovamente eseguito il conteggio dei byte della stringa quest'ultimi, di volta in volta puntati (l'incremento di edx sposta il puntatore al byte sucessivo) vengono messi in al e poi addizionati a bl secondo il seguente schemino:
1° ciclo in bl = valore 1° byte+0
2° ciclo in bl = valore 2°byte+(0+1°)
3° ciclo in bl = valore 3°byte+(0+1°+2°)
4° ciclo in bl = valore 4°byte+(0+1°+2°+3°)
................................................
Alla fine il risultato è confrontato con il valore D1 quindi per poter registrare il programma e necessario soddisfare questa unica condizione ed il gioco è fatto!! Proviamo a ricercare un valore che dopo le manipolazioni dia come risultato D1. Inseriamo come valore 1234 e monitoriamo in Sice il risultato.....eccolo bl=D0 vicinissimo!!!! sostituiamo l'1 con un 2 e con il valore 2234 diventiamo....."Mister Cracker". Non ho provato altre combinazione ma ritengo che non debba essere difficile trovarne altre........Buon divertimento
Note Finali
Bene anche questo tute è finito. Un saluto a tutti i ragazzi della UIC ma un ringraziamento speciale và a Quequero TinMan ed AndreGeddon che si sbattono come dei matti x fare i corsi x noi newbies totali. Ciauzzzzzzzzz
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.