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

4

Mientras lee este documento enlace encontré esta línea tcp[((tcp[12:1] & 0xf0) >> 2):4] que determina el encabezado TCP Longitud, pero no puedo descubrir cómo funciona realmente (en detalles).

¿Alguien puede explicarlo?

Saludos

    
pregunta Neymour 20.04.2016 - 10:54
fuente

1 respuesta

7

Supongo que sacó esto del ejemplo del filtro "capturar solicitudes GET HTTP".

Primero, alguna notación:

  • var[n] significa el enésimo octeto de var.
  • var[n,c] significa c bytes de var que comienzan en el desplazamiento n, por ej. var[3:4] devolvería bytes 3,4,5,6 de var.
  • & es la operación bitwise AND.
  • >> significa desplazamiento a nivel de la derecha.

Entonces, ¿qué tenemos?

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

Vamos a deconstruir esto en sus partes individuales:

tcp[12:1] toma 1 byte del segmento TCP (es decir, el paquete que incluye el encabezado) en el desplazamiento 12. Podemos ver en la estructura que desplaza 12 (0xC) es el campo de compensación de datos. Su definición es la siguiente:

  

El desplazamiento de datos (4 bits) especifica el tamaño del encabezado TCP en palabras de 32 bits. El tamaño mínimo del encabezado es de 5 palabras y el máximo es de 15 palabras, lo que da el tamaño mínimo de 20 bytes y el máximo de 60 bytes, permitiendo hasta 40 bytes de opciones en el encabezado. Este campo recibe su nombre por el hecho de que también es el desplazamiento desde el inicio del segmento TCP a los datos reales.

Ok, genial. Sin embargo, este campo solo tiene 4 bits y tcp[12:1] toma un byte completo (8 bits). Solo queremos los primeros cuatro.

tcp[12:1] & 0xf0 toma ese byte Data Offset y aplica una operación AND a nivel de bits, utilizando la constante 0xF0. Esto a menudo se conoce como una operación de enmascaramiento , ya que cualquier bit en la constante establecida en 0 también se pondrá a cero en la salida. Es más fácil pensar en esto en binario. 0xF0 es solo 11110000, y como x & 0 para cualquier bit x siempre es 0, y x & 1 para cualquier bit x siempre es x, se deduce que los bits cero en 0xF0 se "apagarán" o mask los bits dados, pero deja el resto solo. En este caso, si imaginamos que tcp[12:1] es 10110101, el resultado sería 10110000 porque los últimos cuatro bits se enmascaran a cero. La idea aquí es que, dado que el campo Data Offset tiene solo 4 bits de longitud, pero tenemos 8 bits, enmascaramos los bits irrelevantes por lo que solo tenemos los primeros 4.

El problema aquí es que, numéricamente hablando, nuestros 4 bits están en el lado "superior" del byte. Esto significa que, en lugar de tener 1101 (nuestros bits de Data Offset), tenemos 11010000. Si solo quisiéramos obtener el valor "sin procesar" del campo Data Offset, nos desplazaríamos a la derecha en cuatro lugares. 10110000 >> 4 = 1101 , es decir, descartamos los 4 bits "inferiores" y desplazamos los cuatro bits superiores a la derecha. Sin embargo, en este caso, notará que el filtro solo se desplaza 2 lugares, no 4.

Aquí es donde queremos referirnos de nuevo a la definición del campo Data Offset: especifica el tamaño del encabezado en palabras de 32 bits , no en bytes. Entonces, si queremos saber la longitud del encabezado en bytes, necesitamos multiplicarlo por 4. Resulta que un desplazamiento a la izquierda en modo bit a bit es lo mismo que multiplicar un número por 2, y a la izquierda en bit a bit El cambio de 2 es lo mismo que multiplicar un número por 4.

Ahora, combine esto con lo que ya hemos visto: >> 4 tendría sentido en el filtro si quisiera obtener ese valor bruto de Data Offset, pero luego queremos multiplicarlo por 4, lo que equivale a desplazamiento a la izquierda ( << 2 ), que cancela parte de ese desplazamiento a la derecha, lo que resulta en >> 2 .

Entonces, (tcp[12:1] & 0xf0) >> 2 extrae el campo Data Offset y lo multiplica por 4 para obtener el tamaño del encabezado TCP en bytes.

¡Pero espera, hay más! . En el filtro que proporcionó, todavía necesitamos hacer una operación más:

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

Esto es más fácil de ver si usamos una variable intermedia:

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

Lo que esto hace es obtener los primeros 4 bytes después del encabezado TCP, es decir, los primeros 4 bytes de datos de la carga útil. En el filtro del que sacó esto, estaban buscando solicitudes GET de HTTP usando este filtro:

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

La constante 0x47455420 es en realidad una codificación numérica de los bytes ASCII para GET (ese último carácter es un espacio), donde los valores ASCII de esos caracteres son 0x47, 0x45, 0x54, 0x20.

Entonces, ¿cómo funciona esto en su totalidad? Extrae el campo de desplazamiento de datos de 4 bits del encabezado TCP, lo multiplica por 4 para calcular el tamaño del encabezado en bytes (que también es el desplazamiento de los datos), luego extrae 4 bytes en este desplazamiento para obtener los primeros 4 bytes de los datos, que luego se comparan con "GET" para comprobar que es un GET de HTTP.

    
respondido por el Polynomial 20.04.2016 - 11:27
fuente

Lea otras preguntas en las etiquetas