Wireshark tcp filter: tcp [((tcp [12: 1] & 0xf0) 2): 4]

4

Durante la lettura di questo documento link ho trovato questa riga tcp[((tcp[12:1] & 0xf0) >> 2):4] che identifica l'intestazione TCP Lunghezza, ma non riesco a scoprire come funziona davvero (nei dettagli).

Qualcuno potrebbe spiegarlo?

Saluti

    
posta Neymour 20.04.2016 - 10:54
fonte

1 risposta

7

Presumo che tu abbia estratto questo dall'esempio del filtro "cattura richieste GET HTTP".

Per prima cosa, una notazione:

  • var[n] indica l'ennesimo byte di var.
  • var[n,c] significa c byte di var che iniziano con l'offset n, ad es. var[3:4] restituirebbe byte 3,4,5,6 di var.
  • & è l'operazione bit per bit AND
  • >> significa spostamento bit a bit a destra.

Quindi, che cosa abbiamo?

tcp[((tcp[12:1] & 0xf0) >> 2):4]

Decostruiamolo nelle sue singole parti:

tcp[12:1] prende 1 byte del segmento TCP (cioè il pacchetto che include l'intestazione) all'offset 12. Possiamo vedere da la struttura che offset 12 (0xC) è il campo Offset dati. La sua definizione è la seguente:

Data offset (4 bits) specifies the size of the TCP header in 32-bit words. The minimum size header is 5 words and the maximum is 15 words thus giving the minimum size of 20 bytes and maximum of 60 bytes, allowing for up to 40 bytes of options in the header. This field gets its name from the fact that it is also the offset from the start of the TCP segment to the actual data.

Ok, fico. Questo campo ha solo 4 bit, tuttavia, e tcp[12:1] prende un intero byte (8 bit). Vogliamo solo i primi quattro.

tcp[12:1] & 0xf0 prende il byte Offset dati e applica un'operazione AND bit a bit, utilizzando la costante 0xF0. Questa operazione è spesso nota come operazione maschera , poiché qualsiasi bit nella costante impostata su 0 verrà anch'esso impostato su zero nell'output. È più facile pensare a questo in binario. 0xF0 è solo 11110000, e poiché x & 0 per ogni bit x è sempre 0, e x & 1 per ogni bit x è sempre x, ne consegue che i bit zero in 0xF0 si "spengono" o maschera i bit dati, ma lascia il resto da solo. In questo caso, se immaginiamo che tcp[12:1] sia 10110101, il risultato sarebbe 10110000 perché gli ultimi quattro bit sono mascherati a zero. L'idea è che, poiché il campo Offset dati è lungo solo 4 bit, ma abbiamo 8 bit, mascheriamo i bit irrilevanti, quindi abbiamo solo i primi 4.

Il problema qui è che, numericamente parlando, i nostri 4 bit sono nel lato "superiore" del byte. Ciò significa che invece di avere solo 1101 (i nostri bit di Offset di dati), abbiamo 11010000. Se volessimo solo ottenere il valore "grezzo" del campo Offset di dati, avremmo il diritto di cambiare di quattro posizioni. 10110000 >> 4 = 1101 , cioè buttiamo via i 4 bit "in basso" e spostiamo i quattro bit in alto a destra. Tuttavia, in questo caso noterai che il filtro cambia solo di 2 posizioni, non di 4.

Questo è il punto in cui vogliamo fare riferimento alla definizione del campo Offset dati: specifica la dimensione dell'intestazione in parole a 32 bit , non in byte. Quindi, se vogliamo conoscere la lunghezza dell'intestazione in byte, dobbiamo moltiplicarla per 4. Come si vede, uno spostamento a sinistra bit a bit di 1 è lo stesso di moltiplicare un numero per 2, e un bit a sinistra- lo spostamento di 2 equivale a moltiplicare un numero per 4.

Ora combinalo con quello che abbiamo già visto: >> 4 avrebbe senso nel filtro se volessi ottenere quel valore grezzo di Data Offset, ma poi vogliamo moltiplicarlo per 4, che è equivoco a spostamento a sinistra ( << 2 ), che annulla parte di quello spostamento a destra, risultante in >> 2 .

Quindi, (tcp[12:1] & 0xf0) >> 2 estrae il campo Offset dati e lo moltiplica per 4 per ottenere la dimensione dell'intestazione TCP in byte.

Ma aspetta, c'è di più! . Nel filtro che hai fornito, dobbiamo ancora eseguire un'altra operazione:

tcp[((tcp[12:1] & 0xf0) >> 2):4]

Questo è più semplice se utilizziamo una variabile intermedia:

$offset = ((tcp[12:1] & 0xf0) >> 2)
tcp[$offset:4]

Ciò che fa è ottenere i primi 4 byte dopo l'intestazione TCP, cioè i primi 4 byte di dati del carico utile. Nel filtro da cui hai estratto questo file, cercavano richieste GET HTTP utilizzando questo filtro:

port 80 and tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420

La costante 0x47455420 è in realtà una codifica numerica dei byte ASCII per GET (l'ultimo carattere è uno spazio), dove i valori ASCII di questi caratteri sono 0x47, 0x45, 0x54, 0x20.

Quindi, come funziona in pieno? Estrae il campo Offset dati a 4 bit dall'intestazione TCP, lo moltiplica per 4 per calcolare la dimensione dell'intestazione in byte (che è anche l'offset dei dati), quindi estrae 4 byte a questo offset per ottenere i primi 4 byte dei dati, che viene poi confrontato con "GET" per verificare che sia un GET HTTP.

    
risposta data 20.04.2016 - 11:27
fonte

Leggi altre domande sui tag