Sie sind auf Seite 1von 9

REVERSO TENEBROSO

Descubre como trabajan las herramientas de los hackers


por Huakin Paquete

Sockets RAW

Los socket RAW nos permiten enviar y recibir datos en bruto a travs de la red
HERRAMIENTAS ICMP

Como siempre, lo primero que necesitamos son algunos cheros de cabecera. Aqu tenis la lista de los que La mayora de las herramientas de red a nivel de siste- necesitamos. ma necesitan poder acceder al hardware de red a muy #include <s t d i o . h> bajo nivel. #include < s t d l i b . h> No es necesario llegar a manejar el chip de la tarjeta #include <s y s / s o c k e t . h> de red directamente (eso es cosa de los drivers en el #include <n e t i n e t / i n . h> kernel), pero prcticamente todas ellas requieren poder construir paquetes especiales y capturarlos tal y #include <l i n u x / i p . h> #include <l i n u x / icmp . h> como llegan, sin que nadie los haya manipulado. El kernel Linux proporciona distintas posibilidades para ello, siendo los sockets RAW una de las ms uti- Hemos agrupado los cheros de cabecera en tres grulizadas y veteranas. Los sockets RAW, como su propio pos. En el primero encontramos los de siempre, cabenombre indican son sockets (iguales que los otros), cu- ceras estndar para utilizar funciones como printf o ya nica diferencia es que cuando recibimos o envia- exit. El segundo bloque es el que contiene las demos datos a travs de ellos, esos datos se proporcionan niciones que necesitaremos para crear nuestro socket RAW. Finalmente, el ltimo grupo contiene la denio se obtienen en bruto (raw en ingls). cin de las cabeceras de los paquetes para los protocolos IP e ICMP. Enseguida veremos como utilizarlos. Con estas deniciones ya estamos en condiciones de escribir una funcin para poder crear nuestro socket RAW.
int crea_socket ( int proto ) { int s ; i f ( ( s = s o c k e t (AF_INET, SOCK_RAW, p r o t o )) <0) { perror ( " socket : " ) ; exit (1); } return s ; }

lguna vez os habis preguntado como funcionan esas herramientas de red que usis a diario?. No, no hablamos del explorador o el Filezilla, sino de las herramientas del sistema como ping, traceroute o nmap?... ah, que no las usis a diario?. En ese caso, este artculo probablemente no sea para vosotros.

necesitamos realizar dos operaciones. La primera es poder enviar paquetes ICMP, y la segunda, obviamente, es poder recibir paquetes ICMP. Comenzaremos por la segunda parte, ya que es ms sencilla y nos permitir introducir los nuevos conceptos de una forma progresiva.

CREANDO NUESTRO SOCKET

Vamos a comenzar con una de las herramientas ms sencillas y ms tiles que nos podemos encontrar en el sistema: ping. Esta herramienta nos permite saber si una determinada mquina conectada a la red est funcionando o no. La herramienta ping simplemente enva paquetes ICMP ECHO, y espera recibir una respuesta ICMP ECHOREPLY. Los paquetes ICMP ECHO permiten enviar algunos datos extra, y son estos datos los que ping utiliza para estimar el tiempo de respuesta de la mquina remota. El valor time de la salida del programa. Para implementar nuestra versin reducida de ping,

Hemos decidido pasar como parmetro el protocolo, de forma que podamos reutilizar esta funcin en el resto de los ejemplos de este artculo. Cuando lleguemos a la funcin main de nuestro programa veremos para que sirve ese parmetro. Como podis observar, hemos seleccionado la familia de direcciones de internet (AF_INET) e indicado que el socket sea de tipo SOCK_RAW. Sin grandes sorpresas hasta aqu. 39| OCCAMs Razor

REVERSO TENEBROSO

Hemos mantenido la comprobacin de errores para la llamada al sistema socket ya que los socket RAW necesitan permisos especiales. Si no ejecutamos nuestro programa como root, o utilizando sudo, la llamada al sistema fallar y los resultados del programa sern errneos.

a nuestra llamada (vuestro modem ADSL, vuestro DNS, google o ping.com :). Esto es lo que obtendremos:
occams@razor $ sudo ./icmplog Code: 0.0 (192.168.100.1) Code: 0.0 (192.168.100.1) ...

LEYENDO PAQUETES
Lo siguiente que necesitamos es una estructura de datos para poder acceder cmodamente a los distintos campos de los paquetes que capturemos. Esta es la que nosotros hemos elegido.
typedef struct { struct i p h d r ip ; struct icmphdr icmp ; char b u f f e r [ 1 0 2 4 ] ; / Datos / } PKT;

Los mensajes de tipo 0 y cdigo 0 son efectivamente mensajes ECHOREPLY, que el sistema remoto responde a nuestro ping (el que estamos ejecutando en la otra consola). Obviamente 192.168.100.1 es la mquina contra la que lanzamos el ping. P ENTRETENERSE Si miris la salida del programa ping, veris que proporciona ms datos que nuestra pequea aplicacin. Algunos de los datos que muestra se encuentran en la cabecera ICMP, otros en la seccin de datos -tendris que ver el cdigo fuente de ping- y otros requieren conocer qu paquete se envi en primer lugar. Los que andis aburridos podis extender este ejemplo para que se parezca ms a ping

Esta estructura representa un paquete de datos ICMP, tal y como lo leeremos desde nuestro socket RAW. Lo primero que encontraremos ser la cabecera IP del paquete. A continuacin, la cabecera del mensaje ICMP, seguida de un bloque de datos que variar en funcin del tipo de mensaje ICMP recibido. En principio, el tamao de buer debera reservarse dinmicamente segn la informacin en los campos de tamao de las cabeceras del paquete. Para mantener los ejemplos de cdigo sencillos vamos a utilizar un buer de 1Kb que ser ms que suciente para nuestras pruebas.

DETECTANDO ESCANEOS SIGILOSOS


Antes de continuar con la versin completa de nuestro sencillo ping vamos a hacer un corto inciso, para, convertir nuestro pequeo programa en un detector de escaneos sigilosos como los que realiza nmap.

CAPTURANDO PAQUETES ICMP


Con nuestras deniciones previas, estamos en condiciones de escribir nuestro primer capturador de paquetes ICMP. Podis ver la funcin main a continuacin:
i n t main ( i n t a rg c , char a rg v [ ] ) { int s; PKT pkt ; s = crea_socket (IPPROTO_ICMP) ;

Capturar paquetes IP con un socket RAW es muy sencillo


Partiendo de nuestro ejemplo anterior, vamos a realizar unas sencillas modicaciones para transformar nuestro programa en un rudimentario detector de escaneos de tipo FIN. Estos escaneos se caracterizan por que el ag FIN de la cabecera TCP est puesto a 1. Nosotros vamos a informar de todos los paquetes de este tipo que recibamos, si bien puede que algunos sean paquete legtimos. Lo primero que tenemos que hacer es aadir un nuevo chero de cabecera a nuestro programa #include <linux/tcp.h> Tambin tenemos que hacer una pequea modicacin a nuestra estructura de datos. Ahora vamos a capturar paquete TCP y, en este caso, lo que nos encontramos a continuacin de la cabecera IP, es una cabecera TCP, no una cabecera ICMP. Teniendo esto en cuenta, nuestra estructura de datos sera algo como esto:
typedef struct { struct i p h d r ip ; struct tc p h d r tc p ; char b u f f e r [ 1 0 2 4 ] ; / Datos / } PKT_TCP;

while ( 1 ) { re a d ( s , &pkt , s i z e o f (PKT ) ) ; p r i n t f ( " Code : % %d " , d. pkt . icmp . type , pkt . icmp . code ) ; p r i n t f ( "( %s )\ n" , i n e t_ n to a ( pkt . i p . s a d d r ) ) ; } return 0 ; }

Sencillo no?. Simplemente creamos nuestro socket RAW, indicando que queremos utilizar el protocolo ICMP, leemos datos del socket en nuestra estructura especial, y accedemos a la informacin del paquete utilizando esta estructura. Para probar nuestro ejemplo, lanzamos como usuario root (o utilizando sudo, lo que ms rabia os de), nuestro capturador de paquetes (que hemos llamado icmplog. Desde otro terminal, hacemos un ping a cualquier mquina que sepamos que responder OCCAMs Razor | 40

REVERSO TENEBROSO

Con estos cambios, nuestra funcin main para detectar Abrid dos consolas y en una de ellas ejecutad Netcat posibles escaneos FIN quedara de la siguiente forma: en modo servidor escuchando en el puerto 2000. En la otra ejecutad Netcat en modo cliente conectndose a i n t main ( i n t a r g c , char a r g v [ ] ) { localhost y al puerto 2000. int s;
PKT_TCP pkt ; s = crea_socket (IPPROTO_TCP) ;

while ( 1 ) { r e a d ( s , &pkt , s i z e o f (PKT_TCP ) ) ; i f ( pkt . t c p . f i n ) p r i n t f ( " P o s i b l e FIN s c a n a l p u e r t o % " d " d e s d e ( %s ) \ n" , n t o h s ( pkt . t c p . d e s t ) , i n e t _ n t o a ( pkt . i p . s a d d r ) ) ; } return 0 ; }

CONSOLA Servidor: nc -l -p 2000 CONSOLA Cliente : nc localhost 2000

Ahora, pulsad CTRL+C en la parte cliente y comprobad que obtenis en el detector de escaneos. Repetid el proceso, pero ahora pulsando CTRL+C en la consola donde se ejecuta el servidor. Lo que nuestro detector mostrar ser algo como esto:
Posible FIN scan al puerto 60784 desde (127.0.0.1) Posible FIN scan al puerto 2000 desde (127.0.0.1)

Como podis observar, cuando creamos nuestro nuevo socket RAW estamos indicando que queremos capturar paquetes TCP, en lugar de ICMP como hicimos en nuestro ejemplo anterior. Una vez hecho esto, nuestra nueva estructura de datos nos permite acceder directamente a la informacin en la cabecera TCP. Por una parte comprobamos el valor del ag FIN, y por otra obtenemos la informacin relativa al puerto al que va dirigido el paquete.

Podemos detectar un escaneo FIN en unas pocas lneas de cdigo


Observad que tenemos que utilizar la funcin ntohs para convertir del formato de red al formato de mquina (ntohs signica Network TO Host Short). S, los datos de las cabeceras se transforman a un formato especial para ser transmitidos por la red, de forma que cualquier mquina pueda acceder a ellos independientemente de su arquitectura (little o big endian).

Efectivamente, el ag FIN se utiliza para cerrar las conexiones, de forma que, para detectar si se trata de un escaneo real, tendramos que saber si el paquete FIN que hemos capturado no se corresponde con el cierre legtimo de una conexin activa. Es decir, necesitamos saber que conexiones estn abiertas... o quizs podamos averiguarlo a partir de los otros campos de las cabeceras IP y TCP?... algo ms para entretenerse :).

ENVIANDO PAQUETES ICMP


Despus de este no tan corto parntesis, volvamos a nuestra pequea utilidad ping. Como os decamos en una seccin anterior, para poder implementar algo parecido a ping, necesitamos poder enviar paquetes ICMP. No existe una manera directa de hacer esto, de forma similar a como se transmiten datos utilizando TCP o UDP. Necesitamos un socket RAW para poder enviar estos paquetes. Para este ejemplo necesitamos los mismos cheros de cabecera que para el primer ejemplo que introdujimos (icmplog). Tambin reutilizaremos nuestra funcin crea_socket, pero para poder transmitir nuestro paquete ICMP necesitaremos algo ms de cdigo. Lo primero que necesitamos es una estructura de datos adicional. Si bien, podramos utilizar nuestra estructura PKT, ya que un paquete es un paquete, por cuestiones prcticas nos interesa denir una estructura como esta:
typedef s tr u ct { s tr u ct icmphdr icmp ; char b u f f e r [ 1 0 2 4 ] ; / Data / } PKT_TX;

COMPROBANDO EL DETECTOR
Vamos a comprobar que tal funciona nuestro nuevo detector de escaneos FIN. Para ello, iniciamos nuestra aplicacin en una consola, y desde otro terminal ejecutamos el siguiente comando:
# nmap -sF localhost -p 2000

Nuestro amante detector nos informar diligentemente del intento de ataque:


occams@razor:~$ sudo ./finscan [sudo] password for occams: Posible FIN scan al puerto 2000 desde (127.0.0.1)

Como podis observar, hemos eliminado la cabecera IP de nuestra estructura de transmisin. La razn: Pero si recordis, os comentamos que el hecho de reci- Vamos a dejar que la pila TCP/IP de nuestro sistebir un paquete FIN no signica que se est llevando a ma rellene los campos de la cabecera IP. Ms adelante cabo un escaneo de puertos. Para comprobar como se veremos como rellenarlos nosotros mismos, pero para generan estos paquetes vamos a realizar un pequeo implementar nuestro ping, es mucho ms conveniente experimento. dejar al sistema hacerlo. 41| OCCAMs Razor

REVERSO TENEBROSO

Adems de esta estructura de datos, vamos a aadir una funcin para construir paquetes ICMP ECHO, con un determinado bloque de datos. Podis ver esta funcin a continuacin.
int h e l l o _ p k t 2 ( char pkt_icmp , char s t r ) { s tr u ct icmphdr icmp =( s tr u ct icmphdr ) pkt_icmp ; PKT_TX pkt = (PKT_TX ) pkt_icmp ; int len ; l e n = s p r i n t f ( pkt u f f e r , " % " , s t r ) ; >b s l e n += s i z e o f ( s tr u ct icmphdr ) ; / Construye c a b e c e r a ICMP / icmp y p e = ICMP_ECHO; >t icmp o d e = 0 ; >c icmp >un . e c h o . i d = h t o n s ( 1 2 3 ) ; icmp >un . e c h o . s e q u e n c e = h t o n s ( 5 ) ; icmp >checksum = 0 ; icmp >checksum = cksum ( ( char ) icmp , return l e n ; }

sum += ( sum >> 1 6 ) ; / t r u n c a t e t o 16 b i t s / a n swe r = ~sum ; return a n swe r ; }

Bsicamente lo que hace la funcin es sumar todos los bytes que componen el paquete (de ah lo de suma de comprobacin), y nalmente reducirlo a un valor de 16 bits que es el espacio disponible en la cabecera. Con estas funciones de soporte ya podemos escribir nuestra versin super-simplicada de ping.

EL PING MS TONTO DEL MUNDO


len );

Nuestro programa principal es ahora un poco ms complicado... pero no mucho ms.


int main ( i n t a r g c , char a r g v [ ] ) { int s , data_size ; PKT pkt ; PKT_TX e c h o ; char tmp [ 1 0 2 4 ] ; s tr u ct so c k a d d r _ i n d e s t ; s = crea_socket (IPPROTO_ICMP ) ;

Esta funcin recibe como parmetro, un puntero a nuestra estructura de paquete en memoria, y una cadena de caracteres que se enviar en el bloque de datos.

Construir un paquete ICMP ECHO es tan sencillo como rellenar una estructura de datos
Con esta informacin, la funcin construye un paquete ICMP ECHO con identicador 123 y nmero de secuencia 5. Estos valores sern los que utilicemos para saber si el paquete que capturamos es el que nos interesa.

/ Construimos p a q u e t e / d e s t . s i n _ f a m i l y = AF_INET ; i n e t _ a t o n ( a r g v [ 1 ] , &d e s t . si n _ a d d r ) ; d a t a _ s i z e = h e l l o _ p k t 2 ( ( char ) &echo , " H e l l o World ! ! " ) ; / Enviamos e l p a q u e t e / s e n d t o ( s , &echo , d a t a _ s i z e , 0 , ( s tr u ct s o c k a d d r ) &d e s t , s i z e o f ( s tr u ct so c k a d d r _ i n ) ) ; / Empezamos l a c a p t u r a / while ( 1 ) { r e a d ( s , &pkt , s i z e o f (PKT) ) ; p r i n t f ( " Code : % %d( %d ) " , d. pkt . icmp . type , pkt . icmp . code , n t o h s ( pkt . icmp . un . e c h o . i d ) ) ; p r i n t f ( "( %s ) " , i n e t _ n t o a ( pkt . i p . s a d d r ) ) ; i f ( ( pkt . icmp . t y p e == ICMP_ECHOREPLY) && ( n t o h s ( pkt . icmp . un . e c h o . i d ) == 1 2 3 ) ) { p r i n t f ( " \ n E st e e s e l n u e s t r o : ) ! ! \ n" ) ; break ; } p r i n t f ( " \n" ) ; } close ( s );

CALCULANDO EL CHECKSUM

El ltimo elemento que necesitamos para construir un paquete ICMP vlido es el clculo de la suma de comprobacin de los datos. El protocolo ICMP especica que este valor se debe calcular utilizando todo el paquete (cabecera + datos), siendo el valor del campo checksum de la cabecera igual a 0, para este clculo. Nosotros hemos tomado prestada la rutina de checkreturn 0 ; sum de la implementacin de ping que podis encon- } trar en cualquier distribucin linux. Esta funcin tiene la siguiente pinta. Al igual que en nuestro anterior ejemplo, comenzamos creando nuestro socket RAW, pero en este caso, antes / C a l c u l o de checksum / u_short de ponernos a capturar paquetes, tenemos que enviar cksum ( u_char addr , i n t l e n ) nuestro paquete ECHO. { r e g i s t e r i n t sum = 0 ; Para ello utilizamos la llamada al sistema sendto, que u_short a n swe r = 0 ; u_short wp ; nos permite especicar la direccin de destino del paquete. Recordad que, si no se especica lo contrario, f o r (wp =( u_short ) addr ; l e n >1; wp++, l e n =2) sum += wp ; la pila TCP/IP de nuestro ordenador rellenar las cabeceras IP. Sin embargo, lo que la pila es capaz de / Take i n an odd b y t e i f p r e s e n t / i f ( l e n == 1 ) rellenar tienen un lmite. Hasta que los ordenadores { sean capaces de leer nuestras mentes, pues tendremos ( u_char )& a n swe r = ( u_char )wp ; sum += a n swe r ; que decirle a donde queremos enviar el paquete :). } La llamada al sistema sendto espera esta informacin / add h i g h 16 t o low 16 / en su tercer parmetro como un puntero a una variasum = ( sum >> 1 6 ) + ( sum & 0 x f f f f ) ; ble de tipo struct sockaddr. / add c a r r y / OCCAMs Razor | 42

REVERSO TENEBROSO

Ahora que ya tenemos dominado ICMP, vamos con TCP. Para ilustrar este ejemplo vamos a implementar el clsico escaneo de media conexin, en el que el tradicional saludo a tres bandas de TCP se queda en slo dos. Una conexin TCP, se inicia con el envo de un paquete SYN (en seguida veremos que es esto). El sistema remoto responde con un paquete SYN ACK, o paquete de asentimiento de conexin. Para que la conexin se considere establecida el sistema que inicia la comunicacin debe enviar un paquete ACK de vuelta. Bsicamente esto es lo que hace la llamada al sistePROBANDO NUESTRO PING ma connect... nosotros vamos a implementar nuestro Ha llegado el momento de probar nuestro ping. Para propio connect. ello, como en nuestros ejemplos anteriores, escogemos En este ir y venir de paquetes, ambos sistemas interuna mquina que responda a los pings y ejecutamos cambian nmeros de serie que sern utilizados durante nuestro programa. la comunicacin. Estos nmeros de serie son los que hacen que el spoong de una conexin TCP no sea occams@razor$ sudo ./pingc1 192.168.100.1 prctico, al menos lo que se conoce como blind spoo[sudo] password for occams: ng.
Code: 0.0 (123)(192.168.100.1) Este es el nuestro :)!!

As que lo primero que hace el programa es rellenar una estructura de ese tipo. A continuacin creamos el paquete ECHO con la funcin que ya tenamos lista, y lo enviamos con la anteriormente mencionada funcin sendto Lo que sigue ya os tendra que resultar familiar. Es el mismo bucle que escribimos para nuestro capturador de paquetes ICMP, pero en este caso, mostramos un mensaje especial cuando recibimos una respuesta ECHO_REPLY al paquete que acabamos de enviar. Adems comprobamos que el paquete contiene el identicador de paquete que habamos introducido.

ESCANEO DE MEDIA CONEXIN

Si enviamos nuestros paquetes contra una mquina que no existe (o no responde a los paquetes ECHO), nuestro programa quedar esperando indenidamente. S, obviamente tenemos que utilizar un temporizador para determinar si un paquete se ha perdido... eso os lo dejamos como ejercicio :). Pero, qu ha pasado con nuestro Hola Mundo!?... Ejecutemos de nuevo nuestro programa, pero esta vez vamos a lanzar tcpdump en un terminal. Esto es lo que obtendramos:
occams@razor$ sudo tcpdump -A icmp (...) 15:28:12.219162 IP occams.local > target: ICMP echo request, id 123, seq 5, length 21 E..)..@.@......o.........{..Hello World!! 15:28:12.219604 IP target > occmas.local: ICMP echo reply, id 123, seq 5, length 21 E..)....@..........o.....{..Hello World!!.3hV. (...)

Los socket RAW nos permiten control absoluto sobre los ags TCP
En un escaneo de media conexin no se enva el ltimo paquete ACK, con lo cual la conexin no se puede considerar completa y, dependiendo del sistema de deteccin de intrusos instalado, puede que el escaneo no se detecte. Esto no es muy probable que pase hoy en da, pero desde un punto de vista didctico nos va a permitir introducir un montn de conceptos.

MODIFICANDO NUESTRO EJEMPLO


Para poder implementar nuestro escner de media conexin tendremos que hacer algunas modicaciones a nuestro programa. Lo primero que necesitamos es un nuevo chero de cabecera, y una mnima modicacin de nuestras estructuras de datos.
#include <l i n u x / t c p . h> typedef s tr u ct { s tr u ct t c p h d r tcp ; } PKT; typedef s tr u ct { s tr u ct i p h d r ip ; s tr u ct t c p h d r tcp ; } PKT_RX;

S, ah est. Ha ido hasta la mquina destino y a vuelto. As que podemos utilizar paquetes ICMP tambin para transmitir datos. Un ejemplo de este uso es el programa ICMP shell, que permite acceso shell remoto a una mquina a travs de ICMP. En concreto esta aplicacin permite utilizar otros mensajes ICMP, no solo los mensajes ECHO, para este intercambio de datos. EL PING DE LA MUERTE El sistema operativo Windows 95, tena un bug en su pila TCP/IP que haca que el sistema se estrellase si reciba un paquete ICMP ECHO con un bloque de datos de ms de 64Kb. Este paquete, as como la aplicacin que lo mandaba -que ahora ya sabis hacer- se conoca como el Ping de la Muerte (PoD Ping of Death) Ms informacin...

Como podis comprobar, simplemente hemos substituido la cabecera ICMP de nuestro ejemplo anterior por la nueva cabecera TCP (para eso necesitamos el chero .h adicional). Tambin hemos eliminado el bloque de datos que no vamos a necesitar para nuestro escner. Volveremos sobre estas estructuras un poco ms tarde. 43| OCCAMs Razor

REVERSO TENEBROSO

La siguiente parte que tenemos que modicar es el programa principal, que quedara de esta guisa.
int main ( i n t a r g c , char a r g v [ ] ) { int s , data_size ; PKT_RX pkt ; PKT syn ; char tmp [ 1 0 2 4 ] ; s tr u ct so c k a d d r _ i n d e s t ; s = crea_socket (IPPROTO_TCP) ;

dejamos a vosotros para que os entretengis y as el listado nos queda ms corto y centrado en el tema que nos ocupa.

CONSTRUYENDO UN PAQUETE TCP


Para que nuestro escner est completo, nos falta la funcin que construye el paquete TCP. Como dijimos, necesitamos enviar un paquete SYN, es decir, un paquete con el ag SYN activado en la cabecera TCP. Tranquilos, esto es muchsimo ms fcil de lo que parece. Aqu tenis la funcin tcp_pkt.

/ Construimos p a q u e t e / d e s t . s i n _ f a m i l y = AF_INET ; i n e t _ a t o n ( a r g v [ 1 ] , &d e s t . si n _ a d d r ) ; d e s t . sin_port = htons ( a t o i ( argv [ 2 ] ) ) ;

int tcp_pkt (PKT p , char d i r _ d e s t , i n t p u e r t o d , memset (&syn , 0 , s i z e o f (PKT) ) ; char d i r _ o r i g , i n t p u e r t o o ) d a t a _ s i z e = tcp_pkt (&syn , a r g v [ 1 ] , a t o i ( a r g v [ 2 ] ) , argv [ 3 ] , a t o i ( argv [ 4 ] ) ) ; { p c p . s o u r c e = h t o n s ( p u e r t o o ) ; >t / Enviamos e l p a q u e t e / p c p . d e s t = h t o n s ( p u e r t o d ) ; >t p c p . d o f f = s i z e o f ( s tr u ct t c p h d r ) >t / 4; s e n d t o ( s , &syn , d a t a _ s i z e , 0 , ( s tr u ct s o c k a d d r ) &d e s t , p c p . syn = 1 ; >t s i z e o f ( s tr u ct so c k a d d r _ i n ) ) ; / Empezamos l a c a p t u r a / while ( 1 ) { r e a d ( s , &pkt , s i z e o f (PKT_RX ) ) ; p r i n t f ( " Paquete d e s d e % %dACK: %dSYN: %d\n" , s: i n e t _ n t o a ( ( ( s tr u ct in_addr)& pkt . i p . s a d d r ) ) , n t o h s ( pkt . t c p . s o u r c e ) , pkt . t c p . ack , pkt . t c p . syn ) ; if ( ! memcmp (& pkt . i p . sa d d r , &d e s t . sin_addr , s i z e o f ( s tr u ct in_addr ) ) ) break ; p c p . c h e c k = cksum ( ( unsigned char ) >t &p >tcp , s i z e o f ( s tr u ct t c p h d r ) ) ; return ( s i z e o f ( s tr u ct t c p h d r ) ) ; }

} close ( s ); return 0 ; }

El primer cambio que observamos es que ahora nuestro socket RAW va a utilizar un protocolo diferente. En lugar del anterior IPPROTO_ICMP, ahora nos encontramos un interesante IPPRPTO_TCP, que enviamos como parmetro a nuestra funcin de creacin del socket. El segundo cambio importante que nos encontramos es que, ahora, nuestro programa va a recibir cuatro pa- PROBANDO NUESTRO FLAMANTE rmetros. Los dos primeros identicarn la direccin ESCNER ip y puerto de la mquina remota, y los dos segundos Compilamos nuestro programa que hemos llamado identicarn la direccin ip y puerto de la mquina syn-scan-bogus y lo ejecutamos. local... Esto ltimo debera pareceros interesante ;). occams@razor$ sudo ./synscan-bogus 192.168.100.1 443 \ En tercer lugar, obviamente, tenemos que utilizar una > 192.168.100.100 5000 funcin distinta para crear nuestro paquete. En esta ocasin le hemos dado el original nombre de tcp_pkt. Nada... Mi gozo en un pozo. Veamos que nos dice tcpdump

La funcin simplemente rellena la cabecera TCP con la mnima informacin necesaria para poder enviar el paquete. El puerto origen y destino, el ag SYN (ya os dije que era fcil), el checksum, que calculamos con la misma funcin que utilizamos para nuestro ping, y el campo doff que indica el desplazamiento dentro del paquete desde la cabecera tcp a la zona de datos en palabras de 32 bits (de ah lo de dividir por 4). Dicho de otra forma, contiene el nmero de palabras de 32bits que ocupa la cabecera TCP. S, ya, pero como el nombre del campo es do (Data Oset)... Podis probar que sucede si no inicializis correctamente este campo.

No hay grandes diferencias entre la construccin de un paquete ICMP y de un paquete TCP.

occams@razor:~$ sudo tcpdump -n tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes 20:04:07.617606 IP 192.168.100.100.5000 > 192.168.1.100.443: S 0:0(0) win 0

Para terminar, hemos mejorado un poco nuestro bu- Bueno, el paquete sale, con las direcciones IP y puercle principal. Ahora mostramos informacin especca tos correctos y el ag SYN activo. Seguiremos el consejo del protocolo TCP (como por ejemplo los valores de de tcpdump, y activamos el modo verbose. los ags SYN y ACK) y hemos aadido un test sencillo occams@razor:~$ sudo tcpdump -nv 20:07:08.439772 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], para terminar la aplicacin. proto TCP (6), length 40) 192.168.100.100.5000 > 192.168.1.1.443: S, cksum 0x9ac4 Como enseguida comprobaris, el test para terminar (incorrect (-> 0x16e9), 0:0(0) win 0 la aplicacin no es completo. El test completo os lo OCCAMs Razor | 44

REVERSO TENEBROSO

Aj, nuestro checksum es incorrecto y el sistema remo- SEGUNDO INTENTO to simplemente tira el paquete, por eso no recibimos Con esta ltima modicacin del programa, repetimos ninguna respuesta. nuestra prueba. Ni cortos ni perezosos comprobamos el RFC 793, el que dene TCP. Una bsqueda rpida de la cadena occams@razor$ sudo ./synscan-tcp 192.168.100.1 443 \ checksum en el documento nos lleva a una detallada > 192.168.100.100 5000 [sudo] password for occams: Paquete desde 192.168.100.1:443 ACK:1 SYN:1 seccin que describe como calcularlo.

CALCULANDO EL CHECKSUM TCP


Leyendo detenidamente el RFC, podemos comprobar que nuestra funcin para calcular la suma de comprobacin del paquete es correcta, pero tenemos que aadir lo que el RFC llama una pseudo-cabecera. Vale, modiquemos nuestro escner. Lo primero que tenemos que hacer es modicar nuestras estructuras de datos. Aadimos una estructura para trabajar cmodamente con esta pseudo-cabecera, y modicamos PKT para que la incluya. Notad que no estamos enviando datos en nuestro paquete, as que simplemente podemos aadir la pseudo-cabecera a continuacin del la cabecera TCP. Las estructuras quedaran de esta forma.
typedef s tr u ct pseudo_header { unsigned long s r c ; unsigned long d s t ; unsigned char z e r o ; unsigned char p r o t o ; unsigned short l e n g t h ; } TCP_PHDR;

occams@razor$

Mucho mejor esta vez. Bueno, ya lo sabamos por eso le cambiamos el nombre al programa :). Simplemente para comprobar veamos que dice esta vez tcpdump
occams@razor:~$ sudo tcpdump -nv 20:40:36.509596 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 40) 192.168.100.100.5000 > 192.168.100.1.443: S, cksum 0x16df (correct), 0:0(0) win 0 20:40:36.510083 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 44) 192.168.100.1.443 > 192.168.100.100.5000: S, cksum 0xb8ea (correct), 2921431349:2921431349(0) ack 1 win 5840 <mss 1460>

Ahora nuestros checksums son correctos, y recibimos la respuesta esperada desde la mquina remota, un paquete con los ags SYN y ACK activados.

CONTROL ABSOLUTO

Si observamos con detenimiento la informacin que nos proporciona tcpdump, veremos que hay un montn de datos en los paquetes que enviamos que a priori typedef s tr u ct { no podemos modicar. Datos como las direcciones IP s tr u ct t c p h d r tcp ; TCP_PHDR tcp_phdr ; o el TTL, se encuentran en la cabecera IP, la cual, } PKT; hasta el momento, hemos dejado que la manejara el sistema operativo. Ahora tenemos que actualizar nuestra funcin Pero eso se acab. Vamos a modicar nuestro escner tcp_pkt para que tenga en cuenta la pseudo-cabecera para poder controlar absolutamente toda la informaa la hora de calcular la suma de comprobacin. As es cin que nos muestra tcpdump. Para ello, tenemos que hacer algunas modicaciones adicionales en nuestro como quedara. pequeo programa.
int tcp_pkt (PKT p , char d i r _ d e s t , i n t p u e r t o d , char d i r _ o r i g , i n t p u e r t o o ) { p c p . s o u r c e = h t o n s ( p u e r t o o ) ; >t p c p . d e s t = h t o n s ( p u e r t o d ) ; >t p c p . d o f f = s i z e o f ( s tr u ct t c p h d r ) >t / 4; p c p . syn = 1 ; >t p >tcp_phdr . p >tcp_phdr . p >tcp_phdr . p >tcp_phdr . p >tcp_phdr . s r c = inet_addr ( d i r _ o r i g ) ; d s t = inet_addr ( dir_dest ) ; zero = 0; proto = 6; l e n g t h=h t o n s ( s i z e o f ( s tr u ct t c p h d r ) ) ;

Utilizando la syscall setsockopts podremos acceder a la cabecera IP


El primer cambio es que ya no necesitamos dos estructuras de datos para enviar y para recibir los paquetes. Ahora vamos a manejar la cabecera IP tanto en transmisin como en recepcin, as que solo necesitaremos la siguiente denicin.
typedef s tr u ct { s tr u ct i p h d r ip ; s tr u ct t c p h d r tcp ; TCP_PHDR tcp_phdr ; } PKT;

p c p . c h e c k = cksum ( ( unsigned char)&p >t >tcp , s i z e o f ( s tr u ct t c p h d r ) + s i z e o f (TCP_PHDR) ) ; return ( s i z e o f ( s tr u ct t c p h d r ) ) ; }

Observad que la pseudo-cabecera solo se utiliza para calcular la suma de comprobacin y no se enviar junto con el paquete, de ah que el valor que retorna la funcin es simplemente el tamao de la cabecera TCP, como en nuestro primer ejemplo.

Esta nueva estructura substituye a las anteriores PKT y PKT_RX. Mantenemos el nombre de la primera, porque mola y para tener que hacer menos cambios al programa. 45| OCCAMs Razor

REVERSO TENEBROSO

Adems, necesitamos decirle al kernel que no maneje las cabeceras por nosotros. Esto lo conseguimos activando la opcin IP_HDRINCL (IP Header Included... obviamente) de nuestro socket RAW. Esto lo hacemos en una nueva funcin que os mostramos a continuacin.
int cfg_socket ( int s ) { int val = 1; if ( s e t s o c k o p t ( s , IPPROTO_IP , IP_HDRINCL , &v a l , s i z e o f ( v a l ) ) < 0 ) p e r r o r ( " s e t s o c k o p t (IPHDRINCL ) : " ) ;

constantes para la mayora de los campos para mantener el programa pequeo. Vosotros podis modicar la funcin o aadir funciones adicionales para congurar esos valores. Aqu est la funcin.

return s ; }

Como hicimos en el ejemplo anterior, antes de meternos en los detalles de la generacin de los paquetes, vamos a ver como quedara nuestra funcin main. Solamente vamos a reproducir la primera parte de la funcin, en la que se enva el paquete, ya que el resto no necesita ningn cambio. De hecho, en esta primera parte solo vamos a modicar dos lneas.
i n t main int PKT PKT char s tr u ct ( i n t a r g c , char a r g v [ ] ) { s , data_size ; pkt ; syn ; tmp [ 1 0 2 4 ] ; so c k a d d r _ i n d e s t ;

int ip_pkt (PKT p , char d i r _ d e s t , i n t p u e r t o d , char d i r _ o r i g , i n t p u e r t o o ) { p p . i h l = 5 ; >i p p . v e r s i o n = 4 ; >i p p . t o s = 0 ; >i p p . t o t _ l e n = s i z e o f ( s tr u ct i p h d r ) + >i s i z e o f ( s tr u ct t c p h d r ) ; p p . i d = h t o n s ( 1 2 3 4 ) ; >i p p . f r a g _ o f f = 0 ; >i p p . t t l = 2 5 5 ; >i p p . p r o t o c o l = 6 ; >i p p . c h e c k = 0 ; >i p p . s a d d r = i n e t _ a d d r ( d i r _ o r i g ) ; >i p p . daddr = i n e t _ a d d r ( d i r _ d e s t ) ; >i }

Ms fcil no se puede. No vamos a explicar en detalle cada uno de los campos de la cabecera, para ellos os remitimos al RFC 791. Pero un par de ellos si merecen algn comentario. El campo TTL Time To Live indica el nmero de saltos mximo que el paquete puede dar a travs de s = crea_socket (IPPROTO_RAW) ; internet, antes de que algn router lo descarte. Este cfg_socket ( s ) ; campo es interesante por dos cosas. A saber. / Construimos p a q u e t e / d e s t . s i n _ f a m i l y = AF_INET ; La primera es que la utilidad traceroute utiliza este i n e t _ a t o n ( a r g v [ 1 ] , &d e s t . si n _ a d d r ) ; campo y la captura de mensajes ICMP para determid e s t . sin_port = htons ( a t o i ( argv [ 2 ] ) ) ; nar la ruta de un paquete. La utilidad va incremenmemset (&syn , 0 , s i z e o f (PKT) ) ; tando el campo de uno en uno, de forma que cada vez ip_pkt (&syn , a r g v [ 1 ] , argv [ 3 ] ) ; tcp_pkt (&syn , a r g v [ 1 ] , a t o i ( a r g v [ 2 ] ) , el paquete es descartado por un nodo ms lejano en argv [ 3 ] , a t o i ( argv [ 4 ] ) ) ; la ruta. Cuando esto sucede, el nodo que lo descarta ... enva un mensaje ICMP para comunicar la situacin. Estos mensajes son procesados por traceroute para Lo primero que podemos ver es que ahora estamos utimostrarnos la ruta nal del paquete. lizando como protocolo IPPROTO_RAW y a continuacin estamos llamando a nuestra nueva funcin para decir- La segunda es que el campo TTL es uno de los utilizale al kernel que nosotros proporcionamos las cabeceras dos por los sistemas de identicacin pasiva de sistema operativo, de tal forma que modicndolo el IDS IP (cfg_socket). se puede confundir un poco. En este caso concreto, podramos haber mantenido el PASSIVE FINGERPRINTING protocolo IPPROTO_TCP, pero IPPROTO_RAW es formalLos sistemas pasivos de extraccin de huellas dactilares mente ms correcto. (s, en ingls es mucho ms corto), analizan los paEl segundo cambio que observamos es la llamada a la quetes que una determinada mquina recibe e intentan funcin ip_pkt. S, efectivamente, esa es la funcin determinar el tipo de sistema que lo envi. Para ellos que rellena la cabecera IP. Como en la capa IP no utilizan campos como TTL, que por ejemplo, en los existen los puertos, no es necesario que se los enviesistemas Linux suele tener un valor de 64, y en los sismos. temas Windows 255, aunque eso depende de la versin. Sin grandes sorpresas hasta aqu. Le decimos al kernel Es muy fcil modicar este comportamiento, por lo que que nosotros manejamos las cabeceras IP, y aadimos los sistemas pasivos no son muy ables. Quizs el ms una funcin para manejarlas. conocido de estos sistemas es p0f.

GENERANDO CABECERAS IP
Como acabamos de contaros, la funcin ip_pkt es la encargada de rellenar la cabecera IP de nuestro paquete. Nosotros hemos incluido en el cdigo valores OCCAMs Razor | 46

El sistema de deteccin remota que proporciona nmap, por el contrario, es un sistema activo, puesto que enva paquetes especiales al sistema remoto con el n de extraer informacin adicional sobre l. Por supuesto, estos sistemas son mucho ms escandalosos..

REVERSO TENEBROSO

IP SPOOFING Y OTRAS MALDADES


Los otros dos campos que nos interesan son, por supuesto, las direcciones IP de origen y destino. Y s, nalmente ah estamos, esta es la forma de hacer IP spoong. Podemos poner cualquier valor en el campo de la direccin origen y eso es lo que saldr por el cable. Con el programa que hemos escrito, solo tenis que cambiar el tercer parmetro para enviar un paquete SYN con una direccin falsa. El problema de hacer esto es que la respuesta del sistema remoto se enviar a esa direccin y por lo tanto no la podris ver.

de red de la mquina que pretende suplantar, ya sea con un ataque DoS o utilizando un exploit.

Aplicar tcnicas de Blind IP Spoong hoy en da es prcticamente imposible

En estas circunstancias, es posible el secuestro de una conexin activa. El resumen es que es necesario conocer los nmeros de serie que van en cada paquete TCP y esto solo se puede hacer de dos formas. O vindolos directamente o adivinndolos, y esta ltima opcin hace muchos aos que dejo de ser viable. S, hace aos, los generadores de nmeros pseudoaleatorios utilizados para generar esos nmeros de serie no eran muy buenos (probablemente por cuestiones de eciencia), y haba formas de llegar a predecir esos nmeros de una manera relativamente sencilla. Sabemos que no hemos hablado sobre estos nmeros de serie, pero en los RFCs que hemos comentado a lo largo del texto podris encontrar una descripcin detallada de como se utilizan. Finalmente comentar que el IP spoong se suele utiliHay dos formas de sacar partido a esto del spoong. zar en ataques DoS no solo para ocultar el origen del La primera, es la que proporciona nmap con el ag - ataque, sino para, como en el caso de SMURF, proD (del ingls Decoy, seuelo). Esta opcin le indica a ducir efectos de ooding... Pero eso ya es tema para nmap que enve varios paquetes al sistema remoto que otro artculo. desea escanear. Todos ellos excepto uno tienen direcciones falsas, de forma que el sistema remoto tiene A PARTIR DE AQU... que comprobar todas las direcciones de los paquetes que recibe y, en general, va a ser bastante complicado En este artculo hemos explorado los fundamentos de determinar desde cual se est produciendo el ataque. los socket RAW y como utilizarlos para capturar trLa otra forma de sacarle partido al spoong es en el co o generar paquetes especiales. Con lo que os hemos secuestro de conexiones, que no deja de ser un caso contado tenis las herramientas para construir la maparticular de un ataque MIM (Man in the Middle. yora de las utilidades del sistema relacionadas con la Hoy en da es muy difcil hacer esto, a no ser que se red y jugar con la pila TCP/IP casi al ms bajo den una serie de condiciones, tan especcas, que la nivel. Qu podis hacer ahora?... Bueno, echadle un ojo al tcnica no resulta prctica. Estas condiciones son: chero /etc/protocols, donde encontraris una lisEl atacante tiene que poder capturar el trco ta completa de protocolos con los que podis jugar. de la comunicacin que desea interceptar. Eso Tambin deberais comprobar la pgina del manual reduce la tcnica a las redes de rea local, o al man 7 raw y si queris ir ms all man 7 packet... control de un router que no es algo sencillo. Como siempre, esperamos saber de vuestros experiEl atacante tiene que poder bloquear la conexin mentos!!

47| OCCAMs Razor

Das könnte Ihnen auch gefallen