Alicekeygen – generatore wordlist WPA/WPA2-PSK Alice Telecom

Alicekeygen è una utility da riga di comando per la generazione di dizionari WPA/WPA2-PSK Alice Telecom. Le wordlist possono essere utilizzate con altri tool di bruteforcing quali aircrack-ng o pyrit per recuperare la chiave WPA corretta.

Il tool non vuole essere un key finder per reti Alice ma un generatore di dizionari specifico per queste reti, il più completo possibile. Scopo principale è la semplicità di integrazione con altri software di penetration testing (piping con aircrack-ng, pyrit etc..) e la flessibilità di generazione delle chiavi (opzioni, filtri, etc…)

Attenzione! E’ disponibile la versione per Android (aggiornamento del 01/07/2015)

Vai alla pagina del progetto

alicekeygen

E’ bene precisare che il tool non fa uso in alcun modo di magic number o file coppie Q/K. L’utente inserisce le informazioni in merito alla rete Alice (SSID, MAC address Wi-Fi, serie etc..) ed in funzione di tali dati (anche parziali) vengono generate tutte le possibili chiavi WPA. Tale approccio garantisce la presenza della chiave corretta nella wordlist (router con firmware AGPF).

Esiste comunque un trade-off tra le informazioni_conosciute – dimensione_della_wordlist: la chiave WPA corretta deve quindi essere individuata tra tutte quelle generate; a tal fine occorre utilizzare programmi di WPA bruteforcing (aircrack-ngpyrit) che, in aggiunta, richiedono in input il four-way handshake della rete.

Il tempo necessario al recupero della chiave dipende ovviamente dalla velocità della macchina (CPU, estensioni CUDA, etc..) e dalla dimensione del dizionario.

Ecco la pagina del progetto.

Reverse engineering e cracking di uno shareware

In questo articolo mostriamo un semplice reverse-engineering e crack di uno shareware (non ne riporterò il nome, ho oscurato parzialmente le immagini 🙂 ). Il gioco permette un massimo di 30 partite dopodichè dovremo registrare il prodotto.

Lo scopo del tutorial sarà quello di aggirare tale limitazione “registrando” a modo nostro il gioco. Per prendere un po’ di dimestichezza con l’assembly delle architetture x86 vedere questi link:

http://en.wikibooks.org/wiki/X86_Assembly

http://www.cs.virginia.edu/~evans/cs216/guides/x86.html

http://win32assembly.programminghorizon.com/links.html

Andremo ad usare il famoso debugger Windows OllyDbg 1.1.

Picture 1

 

Il debugger deve avere il plugin della command line di Quequero, scaricabile qui.

Una volta avviato il programma abbiamo la seguente schermata:

1_01

sulla barra in alto notiamo la scritta “Non registrato, versione di valutazione (30 partite)” a conferma del fatto che in effetti la limitazione consiste proprio nel numero massimo di partite che è possibile giocare. Se clicchiamo su “?” notiamo la voce di menu “Registrazione” la quale ci porta a questo popup:

2_01

Da questo popup capiamo che la registrazione è il classicissimo sistema [username,chiave], dove “username” è scelto dall’utente e “chiave” è appunto il seriale che ci viene fornito acquistando regolarmente il programma. Inserendo dei dati a caso otteniamo:

3_01

A questo punto abbiamo capito molto di piu’: il seriale è funzione dell’username e da qualche parte nel codice deve esistere un controllo di corrispondenza tra il seriale introdotto da noi e quello calcolato dal programma stesso. Ciò significa che esiste un punto all’interno del programma dove viene effettuato un controllo tra il seriale inserito con quello calcolato: dall’esito di tale controllo abbiamo due possibilità: se il seriale inserito e’ errato triggeriamo il messaggio di errore (imbocchiamo sempre questa strada se non conosciamo il seriale) altrimenti otteniamo la registrazione corretta del gioco.

Il nostro scopo sarà quello di individuare tale punto e modificarlo in maniera tale da forzare sempre la seconda via (quella della registrazione) indipendentemente dal seriale che inseriamo.

Iniziamo ora ad indagare più approfonditamente nel codice:

Il messaggio di errore che otteniamo quando inseriamo un seriale errato non è altro (in questo caso) che il risultato di una chiamata alla MessageBoxA, la tipica funzione API di notifica degli errori registrata all’interno di User32.dll.

Per una lista completa delle API Windows vedere questo link

Come inizio, per avvicinarci al punto in cui viene controllato il seriale, possiamo intanto cercare di piazzare un breakpoint sulla call che invoca MessageBoxA e poi controllare nei dintorni del codice.

Apriamo OllyDbg, carichiamo l’eseguibile e attendiamo che il debugger finisca l’analisi del codice macchina.
A questo punto premiamo Alt+F1 per far apparire la linea di comando e piazziamo il breakpoint sulla chiamata a MessageBoxA, cioè scriviamo

bpx MessageBoxA

Adesso premiamo F9 per far partire il programma. Comparirà la schermata inziale. Andiamo su “?” e poi su “Registrazione“, inseriamo i soliti dati a caso e clicchiamo su “Ok”. Il debugger blocca il programma alla locazione 77D5050B all’interno del modulo USER32.dll di Windows, modulo che contiene molte delle API del sistema operativo tra cui la nostra MessageBoxA.

A questo punto osserviamo come è stato caricato lo stack (finestra in basso a destra di ollydbg); questi sono gli ultimi dati inseriti:

73D9DE23  CALL to MessageBoxA from MFC42.73D9DE1D
00110526  |hOwner = 00110526 (''Registra ***********'',class=''#32770'',parent=00050514)
0041C82C  |Text = "Mi dispiace, registrazione non corretta."
0041C860  |Title = "Errore"
00000000  \\Style = MB_OK|MB_APPLMODAL
004182C8  ********.004182C8
00406124  RETURN to ********.00406124 from <JMP.&MFC42.#4224>
0041C82C  ASCII "Mi dispiace, registrazione non corretta."
0041C860  ASCII "Errore"

E’ chiaro che sono stati appena caricati i dati relativi ad una finestra di errore e che è stata invocata la funzione MessageBoxA nella libreria USER32.dll. A noi non interessa tanto ispezionare il codice da qui in poi (sappiamo già che steppando in avanti con F8 verrà visualizzato il messaggio di errore), quanto invece vedere in che punto del modulo del programma è stata fatta la richiesta di visualizzazione del popup, perchè è proprio in quel punto che avviene il controllo.

Per far questo osserviamo che nello stack, alla settima riga, è presente (ovviamente) l’indirizzo di ritorno al chiamante, ovvero l’indirizzo 00406124:

00406124  RETURN to ********.00406124 from &lt;JMP.&amp;MFC42.#4224&gt;

Evidenziamo questa riga, premiamo il tasto destro del mouse e selezioniamo “Follow in disassembler“. Il debugger ci mostra il punto di chiamata che il nostro programma invoca in caso di errore. Notiamo che tale chiamata è inserita all’interno di una funzione che inizia a partire da 00406111. Eccola qua:

00406111 PUSH 0
00406113   PUSH ********.0041C860  ;ASCII "Errore"
00406118   PUSH ********.0041C82C  ;ASCII "Mi dispiace, registrazione non corretta."
0040611D   MOV ECX,EBP
0040611F   CALL <JMP&MFC42.#4224>;           ; punto di chiamata a USER32.DLL
00406124   MOV ECX,DWORD PTR SS:[ESP+30C]
0040612B   POP EDI
0040612C   POP EBP
0040612D   MOV DWORD PTR FS:[0],ECX
00406134   ADD ESP,310
0040613A   RETN

La funzione non fa altro che caricare lo stack con i parametri da passare alla MessageBoxA e cioe “MB_OK|APPL_MODAL”, la stringa di titolo (“Errore”) e la stringa del corpo del messaggio (“Mi dispiace, registrazione non corretta”). Questo è il punto del programma in cui i dati relativi al messaggio di errore vengono inseriti nello stack. Osservando bene il listato prodotto dal debugger notiamo che l’istruzione alla locazione 00406111 (PUSH 0) è stata raggiunta tramite un salto di qualche tipo (simbolo “>” accanto a “PUSH 0”). Scorrendo in alto nel codice individuiamo i punti di salto, e cioè:

00405FB7   JB ********.00406111

e, un pò più in basso:

0040605F   JE ********.00406111

Questo significa che esistono due punti di salto che ci fanno raggiungere il messaggio di errore! Il primo salto (JB) è preceduto da un test un pò sospetto per via del valore immediato 6:

CMP ECX,6

Per indagare sulla natura di questo controllo occorre risalire tutta la funzione e piazzare un breakpoint all’inizio, e cioè alla locazione 00405F60. Fatto questo chiudiamo il programma e riavviamo l’esecuzione con F9. Andiamo in “?” e di nuovo in “Registrazione” ed inseriamo altri dati a caso. Premendo “Ok” ci fermiamo correttamente in 00405F60, cioè all’inizio della nostra funzione. Steppando con F8 osserviamo che in ECX viene effettivamente caricata la lunghezza in caratteri dell’username da noi inserito. A questo punto è chiaro che lo scopo delle due istruzioni<

00405FB4   CMP ECX,6
00405FB7   JB ********.00406111

è quello di controllare la lunghezza dell’username. Nel caso in cui questa risultasse strettamente inferiore (JB = Jump if Below) a 6 verrebbe invocato il salto giungendo in 00406111, cioè al messaggio di errore. Ecco quindi svelato un primo controllo: l’username deve essere almeno di 6 caratteri.

Chiudiamo il programma, e riavviamo con F9. Ritorniamo alla registrazione avendo cura di introdurre un username a caso ma lungo almeno 6 caratteri e premiamo “Ok”. Il debugger ci riporta alla funzione di prima ma adesso siamo sicuri di superare il controllo, ed infatti steppando oltre con F8 così avviene.

Superato il controllo entriamo nella parte più interessante e cioè quella in cui presumibilmente viene generato il seriale e poi confrontato con quello da noi inserito. Analizziamo in dettaglio tutta la funzione e per ogni parte ne diamo una breve descrizione: L’entry-point della funzione è all’indirizzo 00405F60. All’inizio vengono invocate due CALL alla API GetWindowTextA per il recupero dell’username e del seriale introdotto nei form:

00405F60   MOV EAX,DWORD PTR FS:[0]
00405F66   PUSH -1
00405F68   PUSH ********.00415BCB
00405F6D   PUSH EAX
00405F6E   MOV DWORD PTR FS:[0],ESP
00405F75   SUB ESP,304
00405F7B   LEA EAX,DWORD PTR SS:[ESP+4]
00405F7F   PUSH EBP
00405F80   MOV EBP,ECX
00405F82   PUSH EDI
00405F83   PUSH 100
00405F88   MOV ECX,DWORD PTR SS:[EBP+60]
00405F8B   PUSH EAX
00405F8C   CALL <JMP.&MFC42.#3873>         ; GetWindowTextA (recupero username)
00405F91   LEA ECX,DWORD PTR SS:[ESP+20C]
00405F98   PUSH 100
00405F9D   PUSH ECX
00405F9E   MOV ECX,DWORD PTR SS:[EBP+64]
00405FA1   CALL <JMP.&MFC42.#3873>        ; GetWindowsTextA (recupero seriale)
00405FA6   LEA EDI,DWORD PTR SS:[ESP+C]

A questo punto viene utilizzata l’istruzione REPNE SCAS per ottenere la lunghezza della stringa puntata da ES:[EDI], cioe’ l’username. La lunghezza viene determinata semplicemente andando a contare il numero di caratteri prima del terminatore \0 di stringa.

00405FAA   OR ECX,FFFFFFFF                 ; inizializza ECX
00405FAD   XOR EAX,EAX                    ; EAX = 0
00405FAF   REPNE SCAS BYTE PTR ES:[EDI]   ; trova il terminatore di stringa
00405FB1   NOT ECX                        ; complemento a uno...
00405FB3   DEC ECX                        ; ...di ECX

Adesso ECX contiene la lunghezza dell’username. Le prossime due istruzioni verificano che sia superiore o uguale a 6, altrimenti si va in 00406111, cioè al messaggio di errore:

00405FB4   CMP ECX,6
00405FB7   JB ********.00406111

Fatto ciò viene generato il seriale a partire dall’username, ad esempio con l’username “gianluca” viene generato il seriale “QWHMEFKC”:

00405FBD   MOV EAX,DWORD PTR DS:[41D1C8]
00405FC2   PUSH EBX
00405FC3   LEA EDX,DWORD PTR SS:[ESP+10]
00405FC7   PUSH ESI
00405FC8   PUSH EDX
00405FC9   LEA ECX,DWORD PTR DS:[EAX+FC]
00405FCF   CALL ********.004010FA
00405FD4   MOV ECX,DWORD PTR DS:[41D1C8]
00405FDA   ADD ECX,0FC
00405FE0   CALL ********.00401438
00405FE5   MOV EAX,DWORD PTR DS:[41D1C8]
00405FEA   LEA EDX,DWORD PTR SS:[ESP+114]
00405FF1   PUSH 100
00405FF6   PUSH EDX
00405FF7   LEA ECX,DWORD PTR DS:[EAX+FC]
00405FFD   CALL ********.00401168

Si fanno ora puntare i registri ESI e EAX rispettivamente al seriale inserito da noi e quello generato internamente:

00406002   LEA ESI,DWORD PTR SS:[ESP+114]
00406009   LEA EAX,DWORD PTR SS:[ESP+214]

Adesso avviene il controllo di eguaglianza tra le due stringhe. Questo pezzo di codice controlla passo a passo le coppie di caratteri corrispondenti nei due seriali. Se risultano tutti identici si salta alla locazione 00406034 altrimenti si va in 00406038:

00406010   MOV DL,BYTE PTR DS:[EAX]      ; carica la prima coppia di caratteri
00406012   MOV BL,BYTE PTR DS:[ESI]
00406014   MOV CL,DL
00406016   CMP DL,BL
00406018   JNZ SHORT ********.00406038   ; se i caratteri sono diversi esci
0040601A   TEST CL,CL
0040601C   JE SHORT ********.00406034    ; prima stringa terminata? se si esci
0040601E   MOV DL,BYTE PTR DS:[EAX+1]    ; carica la seconda coppia di caratteri
00406021   MOV BL,BYTE PTR DS:[ESI+1]
00406024   MOV CL,DL
00406026   CMP DL,BL
00406028   JNZ SHORT ********.00406038   ; se i caratteri sono diversi esci
0040602A   ADD EAX,2
0040602D   ADD ESI,2                     ; avanze di 2 in entrambe le stringhe
00406030   TEST CL,CL
00406032   JNZ SHORT ********.00406010   ; prossimi due caratteri

Veniamo adesso al punto critico della fase di registrazione. Come abbiamo già accennato, quando il precedente pezzo di codice termina può portarci o in 00406034 oppure in 00406038. Nel primo caso il registro EAX viene caricato con 0 (XOR EAX,EAX) e poi si prosegue in 0040603D. Nell’altro caso il registro EAX viene inizializzato con -1. In ogni caso poi si prosegue a partire da 0040603D. EAX diviene quindi la flag del controllo di prima: se vale 0 è stato inserito un seriale corretto, se vale -1 il seriale era sbagliato.

00406034   XOR EAX,EAX                    ; OK! Il seriale era giusto e quindi
00406036   JMP SHORT ********.0040603D    ; poniamo EAX = 0 e saltiamo in 0040603D
00406038   SBB EAX,EAX                    ; Il seriale era sbagliato e quindi
0040603A   SBB EAX,-1                     ; poniamo EAX = -1 e andiamo avanti

Il programma ora prosegue controllando il valore di EAX e agendo di conseguenza. Se vale 0 allora verrà invocata la registrazione del programma, se vale -1 verrà lanciato il popup di errore.

0040603D   MOV EDX,DWORD PTR DS:[41D1C8]
00406043   XOR ECX,ECX
00406045   TEST EAX,EAX
00406047   SETE CL
0040604A   MOV DWORD PTR DS:[EDX+73C],ECX
00406050   MOV EAX,DWORD PTR DS:[41D1C8]
00406055   POP ESI
00406056   POP EBX
00406057   MOV ECX,DWORD PTR DS:[EAX+73C]
0040605D   TEST ECX,ECX
0040605F   JE ********.00406111              ; vai al messaggio di errore
00406065   LEA ECX,DWORD PTR SS:[ESP+C]      ; da qui in poi abbiamo...
00406069   PUSH ECX                          ; ...il processo di registrazione
0040606A   LEA ECX,DWORD PTR DS:[EAX+70C]
00406070   CALL &lt;JMP.&amp;MFC42.#860&gt;
00406075   MOV EAX,DWORD PTR DS:[41D1C8]
0040607A   LEA EDX,DWORD PTR SS:[ESP+C]
0040607E   PUSH EDX
0040607F   LEA ECX,DWORD PTR DS:[EAX+FC]
00406085   CALL ********.00401537
0040608A   PUSH ********.0041C87C            ;  ASCII "************"
0040608F   LEA ECX,DWORD PTR SS:[ESP+C]
00406093   CALL &lt;JMP.&amp;MFC42.#537&gt;
00406098   PUSH ********.0041C86C            ;  ASCII " - Registrato"
0040609D   LEA ECX,DWORD PTR SS:[ESP+C]
004060A1   MOV DWORD PTR SS:[ESP+318],0
004060AC   CALL &lt;JMP.&amp;MFC42.#941&gt;
004060B1   PUSH ********.0041C868            ;  ASCII " a "
004060B6   LEA ECX,DWORD PTR SS:[ESP+C]
004060BA   CALL &lt;JMP.&amp;MFC42.#941&gt;
004060BF   LEA ECX,DWORD PTR SS:[ESP+C]
004060C3   PUSH ECX
004060C4   LEA ECX,DWORD PTR SS:[ESP+C]
004060C8   CALL &lt;JMP.&amp;MFC42.#941&gt;
004060CD   MOV EDX,DWORD PTR SS:[ESP+8]
004060D1   MOV ECX,DWORD PTR DS:[41D1C8]
004060D7   PUSH EDX
004060D8   CALL &lt;JMP.&amp;MFC42.#6199&gt;
004060DD   PUSH 0
004060DF   MOV ECX,EBP
004060E1   CALL &lt;JMP.&amp;MFC42.#2645&gt;
004060E6   LEA ECX,DWORD PTR SS:[ESP+8]
004060EA   MOV DWORD PTR SS:[ESP+314],-1
004060F5   CALL &lt;JMP.&amp;MFC42.#800&gt;
004060FA   POP EDI
004060FB   POP EBP
004060FC   MOV ECX,DWORD PTR SS:[ESP+304]
00406103   MOV DWORD PTR FS:[0],ECX
0040610A   ADD ESP,310
00406110   RETN                              ; fine registrazione

Forzare la registrazione è abbastanza semplice: è sufficiente forzare EAX = 0 anche nel caso di seriale errato. Abbiamo infatti scoperto che EAX = 0 è sinonimo di “I seriali erano identici” e quindi basta imporlo in luogo dell’istruzione che pone EAX = -1.

In pratica sarà sufficiente modificare il seguente codice:

00406038   SBB EAX,EAX
0040603A   SBB EAX,-1

nel seguente:

00406038   XOR EAX,EAX
0040603A   NOP
0040603B   NOP
0040603C   NOP

Operazione facile e indolore dato che le istruzioni di rimpiazzo non occupano più spazio di quelle da sostituire (sempre 5 byte in tutto). Con questa modifica imponiamo EAX = 0 sia nel caso di seriale corretto che errato e quindi forziamo il programma ad effettuare la registrazione. Ecco uno snapshot della registrazione; notare il codice macchina in rosso corrispondente alla parte modificata:

4_01_01

Keylogger in C

Un piccolo keylogger scritto interamente in C per windows 9X/XP/Vista/Seven.

Il software cattura quasiasi evento della tastiera (tasti standard, tasti funzione Fx, tasti speciali) ed eventi di sistema come finestre aperte, programmi avviati, notifiche ed errori. Il programma registra completamente in background tali informazioni e li salva in un file di testo sul disco rigido. Non appena c’è disponibilità di rete, i log vengono inviati via email ad una casella email prescelta tramite protocollo SMTP.
Il programma deve essere considerato unicamente as-is, un esempio di programmazione.

Codice sorgente: keylogger