Raw Sockets Programming With C (spanish)

  • Uploaded by: Mauricio
  • 0
  • 0
  • May 2020
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Raw Sockets Programming With C (spanish) as PDF for free.

More details

  • Words: 20,362
  • Pages: 55
RAW SOCKET Programming Ing. Mauricio Mena Cort´es koitoer 27 de junio de 2009

1

´Indice general 1. Prefacio 1.1. A quien lo lea:

. . . . . . . . . . . . . . . . . . . . . . . . . .

2. Conocimientos b´ asicos 2.1. Requerimientos del sistema 2.2. Modelo OSI . . . . . . . . . 2.2.1. Capa 1: F´ısica . . . 2.2.2. Capa 2: Enlace . . . 2.2.3. Capa 3: Red . . . . 2.2.4. Capa 4: Transporte 2.2.5. Capa 5: Sesi´on . . . 2.2.6. Capa 6: Presentaci´on 2.2.7. Capa 7: Aplicaci´on .

5 5

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

7 7 7 8 8 9 12 14 14 14

3. RAW SOCKET ?? 3.1. Introducci´on . . . . . . . . . . . . 3.2. Funciones importantes . . . . . . . 3.2.1. socket . . . . . . . . . . . . 3.2.2. sendto . . . . . . . . . . . . 3.2.3. recvfrom . . . . . . . . . . . 3.2.4. getsockopt && setsocketopt 3.3. Algunas estrcuturas importantes . 3.3.1. Estructura ifreq . . . . . . . 3.4. Un ejemplo para empezar . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

. . . . . . . . .

16 16 17 17 17 18 18 19 19 21

. . . . . . .

. . . . . . . . . .

. . . . . . . . .

4. Sniffer 28 4.1. SNIFFER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 4.1.1. PROMISC MODE ?? . . . . . . . . . . . . . . . . . . 28 2

´INDICE GENERAL

3

4.2. ksniffer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 4.2.1. Compilaci´on y Ejecuci´on . . . . . . . . . . . . . . . . 31 4.3. Sniffer mejorado. . . . . . . . . . . . . . . . . . . . . . . . . . 31 5. Implantar Funcionalidades 5.1. Modificaciones . . . . . 5.1.1. A˜ nadimos UDP . 5.1.2. A˜ nadimos ICMP 5.1.3. A˜ nadimos DHCP 5.1.4. A˜ nadimos ARP . 6. Conclusi´ on 6.1. Problemas principales 6.2. Tutoriales futuros . . 6.3. Ideas Finales . . . . . 6.4. Agradecimientos . . .

. . . .

. . . . .

. . . .

. . . . .

. . . .

. . . . .

. . . .

. . . . .

. . . .

. . . . .

. . . .

. . . . .

. . . .

. . . . .

. . . .

. . . . .

. . . .

. . . . .

. . . .

. . . . .

. . . .

. . . . .

. . . .

. . . . .

. . . .

. . . . .

. . . .

. . . . .

. . . .

. . . . .

. . . .

. . . . .

. . . .

. . . . .

. . . .

. . . . .

. . . .

. . . . .

. . . .

. . . . .

. . . .

. . . . .

42 42 42 43 44 51

. . . .

54 54 54 54 55

´Indice de figuras 2.1. 2.2. 2.3. 2.4. 2.5. 2.6.

Ethernet (Header) IP (Header) . . . . ICMP (Header) . . TCP (Header) . . . UDP (Header) . . . Modelo OSI . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

9 10 10 12 14 15

3.1. Ejecuci´on captada por IPTraf del c´odigo bajado de internet y como vemos no funciona . . . . . . . . . . . . . . . . . . . . . 21 3.2. Ejecuci´on captada por Wireshark . . . . . . . . . . . . . . . . 27 4.1. Empaquetado en modelo OSI . . . . . . . . . . . . . . . . . . 32 5.1. Header ICMP . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 5.2. Ejecucion del sniffer, Protocolo DHCP . . . . . . . . . . . . . 50 5.3. Ejecuci´on del sniffer, Protocolo ARP . . . . . . . . . . . . . . 53

4

Parte 1 Prefacio 1.1.

A quien lo lea:

En este tutorial tratar´e de explicar y plasmar mediante algunos ejemplos propios y algunos otros corregidos que obtuve de la red, la forma y funcionalidad que se puede tener al programar con RAW SOCKET, pero vamos, ni siquiera he definido que es un RAW SOCKET, en este caso su traducci´on a nuestro lenguaje es ”socket crudo”, mucha gente se podr´a preguntar por que la palabra crudo, esto se debe a que este tipo de sockets trabajan sin estar ligados a un protocolo de comunicaciones, es decir, podemos darle el sabor(flavor) que necesitemos, esto en programaci´on lo podemos traducir como darle la funcionalidad que nostros deseamos. Estos sockets nos permiten el acceso a los protocolos de comunicaciones, con la posibilidad de hacer uso o no de protocolos de capa 3 y/o 4, y por lo tanto d´andonos el acceso a los protocolos directamente y a la informaci´on que recide en ellos. El uso de sockets de este tipo nos va a permitir la implementaci´on de nuevos protocolos, y por qu´e no decirlo, la modificaci´on de los ya existentes. Cabe mencionar que en esta ocasi´on, pondr´e en el tutorial la documentaci´on de algunas estructuras de datos y funciones que nos ayudar´an a crear y entender el uso de los sockets crudos, a´ un asi tampoco pretendo explicar ni entrar a detalle en el modelo OSI, el cual nos servir´a s´olo como referencia para entender un poco m´as del funcionamiento de los sockets, aunque s´ı le dedicar´e una secci´on a lo que considero m´as importante del modelo al trabajar con estos sockets.

5

PARTE 1. PREFACIO

6

Bueno espero el tutorial sea claro, conciso y les sirva para empezar a entender un poco m´as acerca de la programaci´on de sockets crudos, empezemos.

Parte 2 Conocimientos b´ asicos 2.1.

Requerimientos del sistema

Primero que nada todo este manual est´a orientado a sistemas linux - unix, como el anterior tutorial. La distribuci´on que se use no tendr´a por qu´e importar, ya que en realidad lo que se necesitar´a es tener instalado

1. GCC S´ı, s´olo necesitaremos el compilador de GNU, ya que en esta ocasi´on todas las definiciones y funciones se van a hallar en el propio sistema de linux, normalmente en la carpeta /usr/include/net, /usr/include/netinet y /usr/include/linux, las cuales son cargadas al sistema en una instalaci´on normal del sistema. Tambi´en nos podremos auxiliar del archivo /etc/protocol, para el conocimiento de los protocolos y sus abreviaciones.

2.2.

Modelo OSI

El modelo de capas OSI (Open System Interconection) es uno de los pilares b´asicos para el desarollo de las redes actuales y es completamente aplicable a redes de tipo TCP/IP, fue creado en 1984 por ISO, con el fin de estandarizar el proceso de creaci´on de nuevos tipos de redes de inform´atica. 7

´ PARTE 2. CONOCIMIENTOS BASICOS

8

Lo que en realidad hace el modelo OSI es dividir, a modo de referencia, cualquier sistema de red en capas diferenciadas entre s´ı, para comprender de forma m´as gr´afica la funcionalidad de cada una de ellas.

2.2.1.

Capa 1: F´ısica

Esta capa es la encargada de mover los bits entre los diferentes dispositivos, da las especificaciones el´ectricas, mec´anicas y los requerimientos con respecto a voltajes, intensidades, cables, pines, modulaciones para una transmisi´on exitosa de la informaci´on, con lo que se tienen interfaces que pueden estar activadas o desactivadas, esta capa nos provee de la topolog´ıa f´ısica de la red, por lo que en este tutorial no haremos uso de ella.

2.2.2.

Capa 2: Enlace

Despu´es de la demodulaci´on de la se˜ nal, esta capa es la encargada de revisar las alteraciones que esta pudo haber sufrido en el medio, esta capa trabaja con tramas, permite encontrar diversos errores en las mismas, se le suele conocer como MAC (Media Access Control). En esta capa act´ ua el LLC (Logic Link Control), y se trabaja con direcciones f´ısicas (MAC ADDRESS) de las NIC (Network Interface Control), Switches y Conmutadores. El PDU que se maneja es trama (frame), controla el framing, la notificaci´on de errores, la topolog´ıa de red y el principal est´andar de esta capa es el IEEE-802. ETHERNET #include < i f e t h e r . h> struct e t h h d r { unsigned char h d e s t [ ETH ALEN ] ; /∗ d e s t i n a t i o n e t h addr ∗/ unsigned char h s o u r c e [ ETH ALEN ] ; /∗ s o u r c e e t h e r addr ∗/ unsigned short h p r o t o ; /∗ p a c k e t t y p e ID f i e l d ∗/ };

´ PARTE 2. CONOCIMIENTOS BASICOS

9

Figura 2.1: Ethernet (Header)

2.2.3.

Capa 3: Red

Capa encargada de encaminar datos al destino, eligiendo la mejor ruta, en esta capa trabajan los protocolos de ruteo. El PDU (Data Unit) que se maneja es el paquete, y el principal protocolo que trabaja en esta capa es IP (Internet protocol), aunque no debemos de olvidar que tambi´en trabajan ICMP (Internet Common Message Protocol), ARP (Address Resolution Protocol), RARP (Reverse Address Resolution Protocol), PPTP (Point-to-point Tunneling Protocol), entre otros. IP #include struct i p h d r { #i f d e f i n e d ( LITTLE ENDIAN BITFIELD ) u8 ihl :4 , version : 4 ; # e l i f d e f i n e d ( BIG ENDIAN BITFIELD ) u8 version :4 , ihl :4; #e l s e #e r r o r ” P l e a s e f i x ” #e n d i f u8 tos ; u16 tot len ; u16 id ;

´ PARTE 2. CONOCIMIENTOS BASICOS

Figura 2.2: IP (Header) u16 frag off ; u8 ttl ; u8 protocol ; u16 check ; u32 saddr ; u32 daddr ; /∗The o p t i o n s s t a r t h e r e . ∗/ };

ICMP

Figura 2.3: ICMP (Header)

10

´ PARTE 2. CONOCIMIENTOS BASICOS

struct icmphdr { u i n t 8 t type ; /∗ message t y p e ∗/ u i n t 8 t code ; /∗ t y p e sub−code ∗/ u i n t 1 6 t checksum ; union { struct { u int16 t id ; u i n t 1 6 t sequence ; } echo ; /∗ echo datagram ∗/ u int32 t gateway ; /∗ gateway a d d r e s s ∗/ struct { u int16 t unused ; u i n t 1 6 t mtu ; } frag ; /∗ p a t h mtu d i s c o v e r y ∗/ } un ; }; #define ICMP ECHOREPLY /∗ Echo Reply #define ICMP DEST UNREACH /∗ D e s t i n a t i o n U n r e a c h a b l e #define ICMP SOURCE QUENCH /∗ Source Quench #define ICMP REDIRECT /∗ R e d i r e c t ( change r o u t e ) #define ICMP ECHO /∗ Echo R e q u e s t #define ICMP TIME EXCEEDED /∗ Time Exceeded #define ICMP PARAMETERPROB /∗ Parameter Problem #define ICMP TIMESTAMP /∗ Timestamp R e q u e s t #define ICMP TIMESTAMPREPLY /∗ Timestamp Reply

0 ∗/ 3 ∗/ 4 ∗/ 5 ∗/ 8 ∗/ 11 ∗/ 12 ∗/ 13 ∗/ 14 ∗/

11

´ PARTE 2. CONOCIMIENTOS BASICOS

12

Figura 2.4: TCP (Header) #define ICMP INFO REQUEST /∗ I n f o r m a t i o n R e q u e s t #define ICMP INFO REPLY /∗ I n f o r m a t i o n Reply #define ICMP ADDRESS /∗ Address Mask R e q u e s t #define ICMP ADDRESSREPLY /∗ Address Mask Reply #define NR ICMP TYPES

2.2.4.

15 ∗/ 16 ∗/ 17 ∗/ 18 ∗/ 18

Capa 4: Transporte

En esta capa, se tienen dos modos de conexi´on, orientado a conexi´on y no orientado a conexi´on y principalmente hacemos uso de TCP y UDP, estos protocolos se encargan de dar la fin de secuencia, segmentaci´on y reensamble de datos al stream de datos, esta es la capa que nos provee la conexi´on l´ogica ente los host, puede o no proveer de circuitos virtuales a la par de correcci´on de errores en la transmisi´on. En este caso el PDU de la capa 4 es el segmento. TCP struct t c p h d r { u short th sport ; /∗ s o u r c e p o r t ∗/

´ PARTE 2. CONOCIMIENTOS BASICOS u short th dport ; /∗ d e s t i n a t i o n p o r t ∗/ tcp seq th seq ; /∗ s e q u e n c e number ∗/ tcp seq th ack ; /∗ acknowledgement number ∗/ #i f BYTE ORDER == LITTLE ENDIAN u char th x2 : 4 , /∗ ( unused ) ∗/ th off :4; /∗ d a t a o f f s e t ∗/ #e n d i f #i f BYTE ORDER == BIG ENDIAN u char t h o f f : 4 , /∗ d a t a o f f s e t ∗/ th x2 : 4 ; /∗ ( unused ) ∗/ #e n d i f u char t h f l a g s ; #d e f i n e TH FIN 0 x01 #d e f i n e TH SYN 0 x02 #d e f i n e TH RST 0 x04 #d e f i n e TH PUSH 0 x08 #d e f i n e TH ACK 0 x10 #d e f i n e TH URG 0 x20 u short th win ; /∗ window ∗/ u s h o r t th sum ; /∗ checksum ∗/ u short th urp ; /∗ u r g e n t p o i n t e r ∗/ };

UDP struct udphdr { u int16 t source ; u int16 t dest ; u int16 t len ; u i n t 1 6 t check ; }; #endif #define SOL UDP

17

13

´ PARTE 2. CONOCIMIENTOS BASICOS

14

Figura 2.5: UDP (Header) /∗ s o c k o p t l e v e l f o r UDP ∗/

2.2.5.

Capa 5: Sesi´ on

Encargada de la separaci´on de datos de diferentes aplicaciones, asi como del control de di´alogo, configuraciones de administraci´on, t´ermino de sesiones entre la capa de presentaci´on y maneja los conceptos de comunicaciones simplex, halfduplex o fullduplex.

2.2.6.

Capa 6: Presentaci´ on

Presenta los datos, se encarga del cifrado de los datos, adem´as de ser la encargada de presentar los formatos de codificaci´on, maneja las operaciones multimedia, la translaci´on de los datos y formato de c´odigo, tambi´en se encarga de la compresi´on Entre los cuales est´an (ASCII, EBDIC)

2.2.7.

Capa 7: Aplicaci´ on

Da una interfaz al usuario, encargado de funciones de archivos, mensaje, servidores, bases de datos, para los cuales maneja diferentes patrones de comunicaciones y recursos para la comunicaciones. Entre los principales est´an SSH, FTP, HTTP.

´ PARTE 2. CONOCIMIENTOS BASICOS

Figura 2.6: Modelo OSI

15

Parte 3 RAW SOCKET 3.1.

Introducci´ on

Cuando nosotros trabajamos con rawsocket, perdemos y ganamos diferentes caracter´ısticas, entre las m´as improtantes destacan: 1. Los sockets raw son un nivel abstracto sobre la trama de red, de hecho son m´as abstractos que los sockets que ya conocemos que son ´ltimos un caso esSOCK STREAM y SOCK DGRAM, al ser estos u pec´ıfico de los sockets crudos. 2. Al usar sockets crudos, tenemos una p´erdida de fiabilidad con respecto al TCP, ya que no se incluye por defecto al usar socket crudo. 3. No hay puertos; s´ı, incre´ıble pero cierto, aunque muchas veces dijimos que un socket = direcci´on IP + un puerto, ahora desmentimos en parte eso, ya que en los sockets crudos es el kernel el encargado de pasar la informaci´on de un cierto protocolo a todos los sockets que est´en escuchando el mismo protocolo, no hay conexiones de red virtuales como tal, es decir, no hay puertos. 4. Comunicaciones sin est´andar, ya que uno lo debe de generar, al escribir un servidor tendremos que escribir el cliente, ya que no es un est´andar y no cualquier programa entender´a lo que nosotros estamos diciendo. 5. Si se hace uso de protocolos ya existentes, se tienen que rellenar los campos (headers) manualmente, ya que el kernel no lo hace autom´aticamente. 16

PARTE 3. RAW SOCKET ??

17

6. Por u ´ltimo debemos de tener en cuenta que cualquier programa que haga uso de los sockets crudos, se debe ejecutar con permisos de root.

3.2.

Funciones importantes

En este mundo de los sockets y con respecto a la programaci´on de los sockets crudos tenemos ciertas funciones que nos ayudar´an a crearlos y usarlos, por lo que pongo un listado de las que considero mas importantes y algunos detalles o par´ametros m´as usados.

3.2.1.

socket

#include <s y s / t y p e s . h> #include <s y s / s o c k e t . h> int s o c k e t ( int domain , int type , int p r o t o c o l ) ;

Donde el dominio que se usar´a es el PF INET, el tipo de socket es SOCK RAW, y protocol es el protocolo a usar con este socket que se est´a creando. Una lista de los protocolos es la siguiente: enum( IPPROTO IP = 0 , /∗TCP dummy p r o t o c o l ∗/ IPPROTO ICMP = 0 , /∗ICMP p r o t o c o l ∗/ IPPROTO TCP = 0 , /∗TCP p r o t o c o l ∗/ IPPROTO UDP = 0 , /∗UDP p r o t o c o l ∗/ IPPROTO IPV6 = 0 , /∗ IPv6 p r o t o c o l ∗/ IPPROTO RAW = 0 , /∗RAW p r o t o c o l ∗/ );

3.2.2.

sendto

#include <s y s / t y p e s . h> #include <s y s / s o c k e t . h> int s e n d t o ( int s , const void ∗msg , int l e n , unsigned int f l a g s , const struct s o c k a d d r ∗ to , int t o l e n ) ;

Como primer par´ametro se indica el descriptor del socket. El segundo par´ametro es un puntero a los datos que se van a enviar. El tercer par´ametro indica el n´ umero de bytes que se van a enviar. En el cuarto par´ametro van las banderas que pueden ser :

PARTE 3. RAW SOCKET ??

18

1. 0, send funciona igual que write. 2. MSG OOB, indica env´ıo de datos urgentes. 3. MSG DONROUTE, hace que se ignoren los mecanismos de enrutamiento. Para el cuarto par´ametro se tiene una estructura de tipo sockaddr, que se completa con la direcci´on y puerto del destino del mensaje Por u ´ltimo en el quinto par´ametro se env´ıa el tama˜ no de la estrcutura sockaddr

3.2.3.

recvfrom

#include <s y s / t y p e s . h> #include <s y s / s o c k e t . h> int r e c v f r o m ( int s , void ∗ buf , int l e n , unsigned int f l a g s , struct s o c k a d d r ∗ from , int f r o m l e n ) ;

Como primer par´ametro se indica el descriptor del socket. El segundo par´ametro es un punteo a donde se van almacenar los datos recibidos. El tercer par´ametro indica el tamano de este buffer. En el cuarto par´ametro van las banderas que pueden ser : 1. MSG PEEK, permite acceso a los datos sin eliminarlos del buffer. 2. MSG OOB, indica recepci´on de datos urgentes. 3. MSG WAITALL, hace que la operacion de lectura se bloquee hasta el llenado total del buffer Para el quinto par´ametro se tiene una estrcutura de tipo sockaddr, que nos permite tener acceso a la informaci´on de quien envio el paquete En el sexto y ultimo par´ametro se envia el tama˜ no de la estructura sockaddr

3.2.4.

getsockopt && setsocketopt

Funciones importantes que nos permiten modificar el comportamiento de un socket.

PARTE 3. RAW SOCKET ??

19

#include <s y s / t y p e s . h> #include <s y s / s o c k e t . h> int g e t s o c k o p t ( int s , int l e v e l , int opname , void ∗ o p t v a l , int optlen ) ; int s e t s o c k o p t ( int s , int l e v e l , int opname , const void ∗ o p t v a l , int o p t l e n ) ;

Como primer par´ametro se indica el descriptor del socket. El segundo par´ametro indica la capa o el nivel de protocolo en la que se har´a el cambio El tercer par´ametro indica la opci´on que queremos modificar En el cuarto par´ametro se indica el valor con el que se desea modificar. Para el quinto par´ametro se tiene el tama˜ no de la variable referenciada a modificar. IPPROTO_IP - IP_OPTIONS IPPROTO_IP - IP_HDRINCL IPPROTO_TCP - TCP_MAXSEG IPPROTO_TCP - TCP_NODELAY SOL_SOCKET SOL_SOCKET SOL_SOCKET SOL_SOCKET SOL_SOCKET SOL_SOCKET SOL_SOCKET SOL_SOCKET SOL_SOCKET

3.3. 3.3.1.

-

SO_BROADCAST /Env´ ıo de broadcast SO_DEBUG SO_DONTROUTE SO_ERROR SO_KEEPALIVE /Mantener viva la conexi´ on SO_LINGER /Env´ ıo al desconexi´ on SO_REUSEADDR / Reuso de direcci´ on SO_TYPE / Obtenci´ on del tipo de socket BINDTODEVICE /Enlazar socket con dispositvo

Algunas estrcuturas importantes Estructura ifreq

#include <s y s / i o c t l . h> #include struct i f r e q { char i f r n a m e [ IFNAMSIZ ] ; /∗ I n t e r f a c e name ∗/ union {

PARTE 3. RAW SOCKET ?? struct struct struct struct struct short int int int struct char char char ∗

20

sockaddrifr addr ; sockaddrifr dstaddr ; sockaddrifr broadaddr ; sockaddrifr netmask ; sockaddrifr hwaddr ; ifr flags ; ifr ifindex ; ifr metric ; ifr mtu ; ifmapifr map ; i f r s l a v e [ IFNAMSIZ ] ; i f r n e w n a m e [ IFNAMSIZ ] ; ifr data ;

}; }; struct i f c o n f { int i f c l e n ; /∗ s i z e o f b u f f e r ∗/ union { char ∗ i f c b u f ; /∗ b u f f e r a d d r e s s ∗/ struct i f r e q ∗ i f c r e q ; /∗ a r r a y o f s t r u c t u r e s ∗/ }; };

Para m´as informaci´on recomiendo esta p´agina http://linux.about.com/library/cmd/blcmdl7 netdevice.htm subsectionEstructura sockaddr ll struct s o c k a d d r l l { unsigned short s l l f a m i l y ; /∗ Always AF PACKET ∗/ unsigned short s l l p r o t o c o l ; /∗ P h y s i c a l l a y e r p r o t o c o l ∗/ int sll ifindex ; /∗ I n t e r f a c e number ∗/ unsigned short s l l h a t y p e ; /∗ Header t y p e ∗/ unsigned char sll pkttype ; /∗ P a ck e t t y p e ∗/ unsigned char sll halen ; /∗ Length o f a d d r e s s ∗/ unsigned char sll addr [8]; };

/∗ P h y s i c a l l a y e r a d d r e s s ∗/

PARTE 3. RAW SOCKET ??

21

Figura 3.1: Ejecuci´on captada por IPTraf del c´odigo bajado de internet y como vemos no funciona

3.4.

Un ejemplo para empezar

Cuando empec´e en este tema de los sockets crudos, me encontr´e con un ejemplo el cual considero el d´ıa de hoy es muy bueno para poder explicar e iniciarse con los raw sockets, seguramente personas que hayan estado en contacto con este tema lo han de ver visto en internet, donde muchas personas ya se consideran hackers XD al correr este ejemplo, pero les tengo una mala noticia, el ejemplo como tal tiene fallas y si buscan realizar un ataque SYN FLOOD como mencionan se puede hacer, si tienen un router enfrente fallar´a lamentablemente, pero en este documento he corregido los errores (TCP bogus header at least 20 length, Checksum offload, TCP header error offset), pero vamos lo incluyo, ya que lo considero totalmente u ´til para el inicio de este tema.

PARTE 3. RAW SOCKET ??

22

Lamentablemente al correrlo tendr´an que hacer el checksum manualmente del TCP header (el cual consta de la suma del pseudoheader TCP + header TCP + datos) al menos que se ocupen los mismos datos que yo manejo en el ejemplo, ya que si cambian la IP origen o destino se tendr´a que volver a realizar; no incluyo una funci´on que lo realice automa´aticamente, ya que como tal no lo considero necesario para fines de este manual. #include <s t d i o . h> #include <s t r i n g . h> #include /∗ L i b r e r´ı a de l o s s o c k e t s ∗/ #include <s y s / s o c k e t . h> #include /∗ Para o b t e n e r d a t o s de capa 3 ∗/ #include /∗ Para o b t e n e r d a t o s de capa 4 ∗/ /∗ Usaremos l a e s t r u c t u r a BSD para TCP hdr ∗/ #define FAVOR BSD #include #include /∗ Puerto a l c u a l s e va a e n v i a r e l p a q u e t e ∗/ #define P 22 int i =0; /∗ Recordemos que a l no t e n e r e l s t a c k TCP/IP ∗/ /∗ implementado tendremos que h a c e r e l checksum ∗/ /∗ manualmente con ayuda de e s t a f u n c i ´ o n ∗/ unsigned short csum ( unsigned short ∗ buf , int nwords ) { unsigned long sum ; f o r ( sum = 0 ; nwords > 0 ; nwords−−) sum += ∗ buf++; sum = ( sum >> 1 6 ) + ( sum & 0 x f f f f ) ; sum += ( sum >> 1 6 ) ; return ˜sum ; }

int main ( int argc , char ∗∗ argv ) { int one = 1 ; const int ∗ v a l = &one ; p r i n t f ( ” I n i c i a m o s e n v´ıo de p a q u e t e s \n” ) ; /∗ Creamos e l s o c k e t crudo , e l c u a l implementar´ a TCP/IP ∗/

PARTE 3. RAW SOCKET ??

23

int s = s o c k e t ( PF INET , SOCK RAW, IPPROTO TCP) ; /∗ Creamos un b u f f e r que c o n t e n d r ´ a l a s c a b e c e r a s , IP y TCP ∗/ /∗ adem´ a s d e l p a y l o a d ∗/ char datagram [ 4 0 9 6 ] ; /∗En e s t e c a s o iremos d e l p r o t o c o l o m´ as b a j o a l m´ as a l t o por l o que empezaremos con IP , a l c r e a r una e s t u c t u r a i p ∗/ struct i p ∗ i p h = ( struct i p ∗ ) datagram ; /∗ Usaremos una e s t u c t u r a de s o c k e t para e l e n v´ıo de p a q u e t e s ∗/ struct s o c k a d d r i n s i n ; /∗ Usaremos l a f a m i l i a INET a l t e n e r que s a l i r por l a r e d ∗/ s i n . s i n f a m i l y = AF INET ; /∗ Se e s c o g e un p u e r t o d e s t i n o a l que s e e n v i a r ´ an l o s paquetes ∗/ s i n . s i n p o r t = h t o n s (P) ; /∗ Escogemos l a IP d e s t i n o de n u e s t r o s p a q u e t e s ∗/ sin . sin addr . s addr = inet addr (” 132.248.59.1 ”) ; /∗Ponemos e l b u f f e r con l o s h e a d e r s en c e r o ∗/ memset ( datagram , 0 , 4 0 9 6 ) ; /∗ Hasta e s t a p a r t e podr´ a n p e n s a r que no hemos hecho diferente ya que s e usa una e s t r u c t u r a s o c k a d d r i n para e l e g i r todo p a r e c e s e r l o mismo , p ero ahora tendremos e l c o n t r o l campos de l a s c a b e c e r a s IP y TCP, para e n v i a r l o s por l a r e d /∗ Por l o que empezamos a r e l l e n a r l o s manualmente ∗/

nada destino y de l o s ∗/

/∗−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−∗/ /∗ HEADER IP ∗/ iph−>i p h l = 5 ; /∗ Se e s c o g e l a v e r s i ´ o n de IPv4 ∗/ iph−>i p v = 4 ; /∗ Se e s c o g e e l Type o f S e r v i c e ∗/ iph−>i p t o s = 0 ; /∗ Se da l a l o n g i t u d de l a c a b e c e r a IP ∗/ iph−>i p l e n = s i z e o f ( struct i p ) + s i z e o f ( struct t c p h d r ) ;

PARTE 3. RAW SOCKET ??

24

p r i n t f ( ” Esta e s l a l o n g i t u d i p l e n %d \n” , iph−>i p l e n ) ; /∗ I d e n t i f i c a d o r d e l p a q u e t e ∗/ iph−>i p i d = h t o n l ( 5 4 3 2 1 ) ; /∗ Se da e l o f f s e t d e l p a q u e t e ∗/ iph−>i p o f f = 0 ; /∗ Ponemos e l t i m e t o l i v e ∗/ iph−> i p t t l = 2 5 5 ; /∗ Se e s o c g e e l p r o t o c o l o a u s a r ∗/ iph−>i p p = 6 ; // 6 a l s e r TCP / e t c / p r o t o c o l /∗ Moment´ a neamente pones e l checksum a c e r o ∗/ iph−>ip sum = 0 ; /∗ Se e s c o g e l a i p o r i g e n , s´ı c l a r o pondremos l a que queramos XD ∗/ /∗ Pero s i queremos s a l i r por l a red , e l p r o x y ISP no permitir´ a cualquier direcci´ o n en e s t e campo ∗/ iph−>i p s r c . s a d d r = i n e t a d d r ( ” 1 9 2 . 1 6 8 . 1 . 7 0 ” ) ; /∗ Se d e f i n e l a i p d e s t i n o mediante l a e s t r u c t u r a d e f i n i d a a n t e r i o r m e n t e ∗/ iph−>i p d s t . s a d d r = s i n . s i n a d d r . s a d d r ; /∗−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−∗/ /∗ HEADER TCP ∗/ /∗ Ahora crearemos l a e s t r u t u r a TCP ∗/ struct t c p h d r ∗ tcph = ( struct t c p h d r ∗ ) ( datagram + iph−> i p h l ∗4 ) ; p r i n t f ( ” Esta e s l a l o n g i t u d s t r u c t i p %d \n” , s i z e o f ( ∗ i p h ) ) ; p r i n t f ( ” Esta e s l a l o n g i t u d s t r u c t t c p h d r %d \n” , s i z e o f ( ∗ tcph ) ) ; /∗ Se da e l p u e r t o o r i g e n d e l p a q u e t e ∗/ tcph−>t h s p o r t = h t o n s ( 4 5 5 2 1 ) ; /∗ Se da e l p u e r t o d e s t i n o d e l p a q u e t e ∗/ tcph−>t h d p o r t = h t o n s (P) ; /∗ Se da e l n´ u mero de s e c u e n c i a d e l p a q u e t e ∗/ tcph−>t h s e q = random ( ) ; /∗ N´ umero de l a s e c u e n c i a ACK ∗/ tcph−>t h a c k = 0 x00000000 ; tcph−>t h x 2 = 0 ; /∗ Se da e l o f f s e t de l a c a b e c e r a TCP ( 5 ∗ 4 ) ∗/ tcph−>t h o f f = 5 ; /∗ Ponemos para l a p e t i c i ´ o n de una c o n e x i ´ o n ∗/ tcph−>t h f l a g s = TH SYN ; /∗ Indicamos e l tama˜ n o de l a v e n t a n a ∗/ tcph−>t h w i n = 0 x 0 1 8 f ; /∗ S i ponemos e l checksum TCP a c e r o aunque d i g a n que e l s t a c k l o r e l l e n a en l o p e r s o n a l no me f u n c i o n ´ o , por

PARTE 3. RAW SOCKET ??

25

l o que t u v e que h a c e r e l checksum ∗/ checksum c o r r e c t o ∗/ tcph−>th sum = 0 x 6 0 f a ; tcph−>t h u r p = 0 ;

/∗ Se da e l checksum d e l p a q u e t e y s e i n c l u y e en e l campo ∗/ iph−>ip sum = csum ( ( unsigned short ∗ ) datagram , iph−>i p l e n >> 1 ) ; p r i n t f ( ”Checksum i p %x \n” , iph−>ip sum ) ; /∗ Al u s a r IP HDRINCL l e decimos que estamos i n c l u y e n d o e l h e a d e r IP en e l p a q u e t e ∗/ i f ( s e t s o c k o p t ( s , IPPROTO IP , IP HDRINCL , val , s i z e o f ( one ) ) < 0) p r i n t f ( ” E r r o r : No s e m o d i f i c ´o e l s o c k e t \n” ) ; while ( i !=10) { i ++; i f ( s e n d t o ( s , datagram , ( iph−>i p l e n ) , 0 , ( struct s o c k a d d r ∗ ) &s i n , s i z e o f ( s i n ) ) < 0 ) p r i n t f ( ” Paquete no s e ha podido e n v i a r \n” ) ; else p r i n t f ( ” Paquete e n v i a d o \n” ) ; } return 0 ; }

root@koitoerdp:~/Tutorial raw-sockets# gcc injection.c -o injection root@koitoerdp:~/Tutorial raw-sockets# ./injection Iniciamos env´ ıo de paquetes Esta es la longitud ip_len 40 Esta es la longitud struct ip 20 Esta es la longitud struct tcphdr 20 Checksum ip 1294 Paquete enviado Paquete enviado Paquete enviado Paquete enviado Paquete enviado

PARTE 3. RAW SOCKET ??

26

Paquete enviado Paquete enviado Paquete enviado Paquete enviado Paquete enviado root@koitoerdp:~/Tutorial raw-sockets#

En este caso vemos que al lanzar la ejecuci´on se mandan paquetes TCP SYNC, para el inicio del HANDSHAKE, al puerto 22 de una m´aquina remota, la cual nos reponde con un SYNC+ACK, por las diez veces que mandamos ese paquete, pero si nos fijamos en la imag´en del sniffer, nuestra m´aquina la 192.168.1.70, env´ıa un RST, que es un Reset Connection al no haber proceso alguno que se encarge de los paquetes reci´en recibidos, ya que como tal s´olo mandamos los diez SYNC, nunca esperamos respuesta. Como vemos, es un programa que nos permite poner directamente los campos de los headers, TCP e IP, con lo que corroboramos que podemos tener el control de los protocolos ya existentes, en este caso debemos de tener en cuenta que si quisieramos atacar algun host, cambiando nuestra IP, para que no nos detecten, muchas veces nuestro ISP, no permitir´a que este tipo de peticiones salgan a internet, debido a que el mismo reconoce que no son propias de su configuraci´on, aunque si estudiamos un poco el tipo de direcciones IP, que maneja esto si ser´a posible.

PARTE 3. RAW SOCKET ??

Figura 3.2: Ejecuci´on captada por Wireshark

27

Parte 4 Un sniffer para comenzar Despu´es de programar un poco, tenemos listo un sniffer, que nos permite analizar la informaci´on contenida en ciertos protocolos, en este caso si se desea el an´alisis de otro protocolo, simplemente tendremos que realizar una inclusi´on del desglose del protocolo en el lugar correcto como lo hare mas adelante.

4.1.

SNIFFER

Primero que nada,¿qu´e es un sniffer?, bueno es un programa de captura de tramas, que se usa con diversos fines, como pueden ser el an´alisis de protocolos, la gesti´on de las redes, fines maliciosos XD, an´alisis de fallos, detecci´on de posibles ataques o intrusos, o como simple medidor de tr´afico.

4.1.1.

PROMISC MODE ??

Es una configuraci´on de la tarjeta de red, la cual nos permite pasar a nivel de aplicaci´on todos los paquetes recibidos sean o no para nosotros, por lo que podremos escuchar todo el tr´afico que llegue a nuestra tarjeta, que pudiese ser m´ınimo si hablamos de una computadora o host, pero puede llegar a ser ciertamente alto si activamos este modo en un gateway de salida de una LAN, o en medio de una red WI-FI. Para activar este modo de la tarjeta debemos de tener permisos de administrador. root@koitoerdp:~# ifconfig eth0 promisc root@koitoerdp:~# ifconfig 28

PARTE 4. SNIFFER eth0

29

Link encap:Ethernet HWaddr 00:40:f4:a5:8c:5a inet addr:192.168.1.70 Bcast:192.168.1.255 Mask:255.255.255.0 inet6 addr: fe80::240:f4ff:fea5:8c5a/64 Scope:Link UP BROADCAST RUNNING PROMISC MULTICAST MTU:1500 Metric:1 RX packets:2511 errors:0 dropped:0 overruns:0 frame:0 TX packets:1328 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:238408 (238.4 KB) TX bytes:218862 (218.8 KB) Interrupt:19 Base address:0xc400

Como se aprecia la palabra PROMISC aparece marcando la interfaz XD. Para quitarla del modo promiscuo, s´olo la reiniciamos,para esto debemos tener cuidado ya que si estamos conectados remotamente al reiniciar la interfaz, nos desconectar´a. Para la detecci´on de tarjetas en modo promiscuo dentro de nuestra red, tenemos varias opciones, que se dividen en dos tipos, el primero checar manualmente cada tarjeta de red para ver si est´a en modo promiscuo, suena dif´ıcil verdad, bueno entonces podemos crear un demonio el cual nos permita saber cuando una tarjeta cambie a modo promiscuo, esto simplemente lo haremos leyendo el /var/log/message, donde queda huella cuando una interfaz hace uso de este modo May 2 device May 2 device May 2 device May 2 device

17:02:00 koitoerdp kernel: [17157.272110] lo entered promiscuous mode 17:02:04 koitoerdp kernel: [17161.113065] lo left promiscuous mode 17:11:16 koitoerdp kernel: [17712.772099] eth0 entered promiscuous mode 17:11:56 koitoerdp kernel: [17752.564435] eth0 left promiscuous mode

Pero vamos si lo borra, lo cual es dif´ıcil al menos que se tenga la contrase˜ na de root, pues s´olo nos queda hacer uso de diversas t´ecnicas para encontrar tarjetas en modo promiscuo, que pueden ser por medio del env´ıo de paquetes ARP o el uso de antisniffers como Antisnif o Sentinel. Para esto tambi´en encontr´e en internet, un buen programa que se llama neped.c, que se encarga de la identificaci´on de un host con su tarjeta en modo promiscuo a trav´es del simple env´ıo de paquetes ARP a m´aquinas inexistentes. Considero que

PARTE 4. SNIFFER

30

echarle un vistazo al c´odigo puede ser en este momento un tanto d´ıficil, pero al final de este tutorial puede ser bastante did´actico, para ver y corroborar lo aprendido.

4.2.

ksniffer

Muy bien, es hora de programar un sniffer sencillo, que capture el tr`afico TCP que pasa por nuestra interfaz, entonces empecemos. #include #include #include #include #include #include #include #include

<s t d i o . h> < f c n t l . h> <s y s / s o c k e t . h>

int main ( ) { /∗ Creamos e l s o c k e t crudo , e l c u a l s ´ o l o va a capturar e l t r ´ a f i c o de p a q u e t e s TCP, como l o indica l a opci´ o n IPPROTO TCP ∗/ int f d = s o c k e t ( PF INET , SOCK RAW, IPPROTO TCP) ; /∗ Ser´ a n u e s t r o b u f f e r de c a p t u r a ∗/ char b u f f e r [ 8 1 9 2 ] ; int i =0 ; int b y t e s = 0 ; /∗ Entramos a un c i c l o i n f i n i t o que nos p e r m i t e i r c a p t u r a n d o y mostrando e l t r ´ a f i c o , en e s t e c a s o usamos read , ya que estamos t r a b a j a n d o con e l p r o t o c o l o TCP ∗/ while ( ( b y t e s = r e a d ( fd , b u f f e r , 8 1 9 2 ) ) > 0 ) { /∗ Una v e z c a p t u r a d o l o mostramos a im pr es i´ on , e s t o l o hacemos s e n ˜ a l a n d o donde i n i c i a e s t a i n f o r m a c i ´ on , l o cual e x p l i c a r ´e un poco m´ as a d e l a n t e ∗/ p r i n t f ( ” Paquete c a p t u r a d o %s \n” , b u f f e r+s i z e o f ( struct i p h d r )+s i z e o f ( struct t c p h d r ) ) ; p r i n t f ( ” Contenido : \n” ) ; p r i n t f ( ” Hexadecimal \n” ) ; f o r ( i = 0 ; i < b y t e s ; i ++) p r i n t f ( ” %x” , b u f f e r [ i ] ) ; p r i n t f ( ” \ n E n t e n d i b l e \n” ) ; f o r ( i = 0 ; i < b y t e s ; i ++) p r i n t f ( ” %c ” , b u f f e r [ i ] ) ;

PARTE 4. SNIFFER

31

p r i n t f ( ”\ n S i g u i e n t e −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− \n” ) ; } }

4.2.1.

Compilaci´ on y Ejecuci´ on

gcc Sniffer.c -o SnifferSimple ./SnifferSimple Paquete capturado Contenido : Hexadecimal 450028ffffffb616400ffffff806ffffffc0ffffffddffffffc0 ffffffa8145ffffffc0ffffffa81468ffffffb3016ffffffc3d6 e2affffff831dffffffbbffffffa65010fffffffa4fffffffb8f fffffe300 Entendible [CARACTERES OMITIDOS] Siguiente -------------------------------------Si como lo podemos apreciar ya tenemos nuestro gran sniffer, pero me dir´an que no se entiende nada jajaja, pues claro s´olo estamos capturando los paquetes jam´as los ordenamos y obtenemos los datos de ellos, asi que esa ser´a nuestra siguiente tarea, lo que cabe resaltar en este ejemplo es el uso de las estructuras que previamente habiamos platicado.

4.3.

Sniffer mejorado.

Algo que tenemos que recordar, que es tan simple, pero a la vez es lo m´as importante al momento de obtener la informaci´on u ´til en un sniffer, es la forma en la que se est´a recibiendo y enviando la informaci´on, recordemos que tenemos capas del modelo OSI, por lo que tenemos en la red un paquete, que por decirlo de alguna manera esta empaquetado, esto se ve como se muestra en la siguiente figura Entonces como vemos en la figura lo primero que llega siempre es el Header de la capa de enlace, despues viene el NH (Network header) header

PARTE 4. SNIFFER

32

Figura 4.1: Empaquetado en modelo OSI de red, despu´es el TH (transport header) header de la capa de transporte, despu´es los header de sesi´on, presentaci´on y por u ´ltimo vienen los datos que contiene. Y si es as´ı como llega, entonces ser´a la forma que nosotros usaremos para ir leyendo y ordenando los datos, es importante tener en cuenta que recibiremos con recvfrom(), funci´on que previamente vimos que nos permite almacenar en un buffer, por lo que la informaci´on almacenada en ese buffer, ser´a rescatable a trav´es de un apuntador. Ahora para decirle al apuntador de donde a donde llega la informaci´on de cierto header, lo que ocuparemos ser´an las estructuras antes vistas, de los diferentes headers. Haciendo una analog´ıa, tenemos un buffer de tama˜ no X, la estructura que describe el header de la capa de enlace supongamos que son Y bytes, obviamente si el paquete recibido es v´alido X tiene que ser mayor que Y, entonces diremos que los Y primeros bytes de X corresponden a la capa de enlace. Despu´es sabemos que en la capa de red el protocolo usado tiene un header de P bytes, ¿d´onde terminar´ıa este header de la capa de red? , bueno pues la respuesta es sencilla, si el header de red es de P bytes, primero que nada empezari´ıa en (Y + 1) bytes a partir del inicio del paquete, y por lo

PARTE 4. SNIFFER

33

tanto tendr´ıa su fin en ( Y + P ) bytes. En este caso ¿c´omo sabemos cu´anto valdr´ıa X, Y, P y dem´as ?, pues con ayuda de la funci´on sizeof() sobre las estructuras que sabemos que se manejan en las diferentes capas del modelo OSI. Recordemos que en un arreglo de caracteres por ejemplo char mybuffer[1000], el inicio se puede indicar con mybuffer, o &mybuffer[0], con lo que apuntamos a la primera posici´on de todo el buffer, entonces si queremos movernos para captar el siguiente header o la informaci´on lo hacemos de la siguiente forma: buffer + sizeof( struct ethhdr) +sizeof( struct iphdr) + sizeof(struct tcphdr) Tenemos que en este caso primero apuntamos al inicio del paquete despu´es movemos el apuntador n lugares dependiendo de la suma del header ethernet + header ip + header tcp, por lo cual estaremos al inicio de la informaci´on que era nuestro objetivo, obviamente si leyeron bien, no podemos decir del todo que es la informaci´on como tal, ya que siguen diferentes headers y despu´es ahora si va la informaci´on. Entonces sabiendo esto s´olo les recordar´e una cosa, nosotros cuando creamos un socket crudo podemos definirle que protocolo usaremos, si le ponemos IPPROTO TCP, no nos llegar´a el header ethernet como en el primer ejemplo paso, pero tampoco nos llegar´a informaci´on UDP, ARP, ICMP, RARP y dem´as, entonces recordemos lo que mencione antes, que el kernel se encarga de subir la informaci´on a los sockets que esten escuchando cierto tipo de protocolo, asi que si estamos escuchando solo tr´afico TCP pues no recibiremos mas que eso, pero no se preocupen si queremos estudiar todos los protocolos y todo el tr´afico s´olo pondremos ETH P ALL, y lo haremos XD , pero recuerden que si usamos esta constante recibiremos TODO !!!! el tr´afico, por lo que nuestro sniffer capturar´a mucha informaci´on,y dif´ıcilmente podremos encontrar o ver lo que necesitamos, por lo que el uso de esta constante lo dejo a su criterio. Aunque cabe mencionar que m´as adelante en este tutorial, se har´a uso de la constante para que les ense˜ ne la forma de recibir protocolos de capa 3 y 4. Muy bien, creo que ha sido una buena introducci´on, asi que vamos al c´odigo. /∗ Programa s n i f f e r 1 . c ∗/ /∗ Compilado en Linux k o i t o e r s v 2.6.27 −14 − g e n e r i c i 6 8 6 GNU/ Linux ∗/ /∗ #1 SMP Wed Apr 15 1 8 : 5 9 : 1 6 UTC 2009 ∗/

PARTE 4. SNIFFER

#include<s t d i o . h> #include<s t r i n g . h> #include<s t d l i b . h> /∗ L i b r e r´ı a de l o s s o c k e t s ∗/ #include<s y s / s o c k e t . h> #include #include #include<e r r n o . h> /∗ L i b r e r´ı a de l o s s o c k e t s ∗/ #include<s y s / i o c t l . h> /∗ L i b r e r´ı a de c o n t r o l de i n t e r f a c e s ∗/ #include /∗ L i b r e r´ı a de l o s p a q u e t e s e t h e r n e t ∗/ #include /∗ L i b r e r´ı a de l o s p a q u e t e s i p ∗/ #include /∗ L i b r e r´ı a de l o s p a q u e t e s t c p ∗/ #include /∗ L i b r e r´ı a de d e f i n i c i o n e s de p r o t o c o l o s ∗/ #include /∗ L i b r e r´ı a para d e c o d i f i c a r u n s i g n e d char ∗/ #include void h e a d e r ( ) ; int obtenerData ( unsigned char ∗ , int ) ; int obtenerHTCP ( unsigned char ∗ , int ) ; void obtenerHIP ( unsigned char ∗ , int ) ; void o b t e n e r H E t h e r n e t ( unsigned char ∗ , int ) ; int s o c k e t i f ( char ∗ , int , int ) ; void impresionHex ( unsigned char ∗ , int ) ; void impresionASCII ( unsigned char ∗ , int ) ; void impresionFormatoIP ( unsigned char ∗ , int ) ; int main ( int argc , char ∗∗ argv ) { /∗ Nuestro f u t u r o r a w s o c k e t ∗/ int r s o c k ; int l e n ; /∗ N´ umero de p a q u e t e s a r e c i b i r ∗/ int p a q u e t e s ; /∗ Bandera para l a i m p r e s i ´ o n o no de d a t o s ∗/ int v a l i d a c i o n =0; int p a c k e t = 0 ; /∗ B u f f e r de l e c t u r a de l a i n f o r m a c i ´ o n r e c i b i d a ∗/

34

PARTE 4. SNIFFER

35

unsigned char p b u f f e r [ 2 0 4 8 ] ; /∗ E s t r u c t u r a que l i g a r ´ a e l s o c k e t con l a i n t e r f a z ∗/ struct s o c k a d d r l l p i n f o ; /∗ Definimos tamano d e l b u f f e r ∗/ int p s i z e = s i z e o f ( p i n f o ) ; i f ( a r g c !=3) { p r i n t f ( ”Uso %s \n” , argv [ 0 ] ) ; e x i t ( −1) ; } /∗ Se c r e a un s o c k e t crudo para p r o t o c o l o IP ∗/ r s o c k = c r e a S o c k e t ( ETH P IP ) ; /∗ Se i n i c i a e l p r o c e s o ∗/ header ( ) ; /∗ Se une e l s o c k e t a un i n t e r f a z de l a m´ a quina ∗/ s o c k e t i f ( argv [ 1 ] , r s o c k , ETH P IP ) ; /∗ Decimos e l n´ u mero de p a q u e t e s a c a p t u r a r ∗/ p a q u e t e s = a t o i ( argv [ 2 ] ) ; /∗ Empezamos l a c a p t u r a de n n´ u mero de p a q u e t e s ∗/ while ( paquetes −−){ /∗ Recibimos p a q u e t e s a t r a v ´e s d e l s o c k e t crudo d e l p r o t o c o l o IP ∗/ /∗ Y l o s pasamos l o s d a t o s a l b u f f e r , adem´ a s de su informaci´ o n a l a e s t r u c t u r a p i n f o ∗/ i f ( ( l e n = r e c v f r o m ( r s o c k , p b u f f e r , 2 0 4 8 , 0 , ( struct s o c k a d d r ∗ )&p i n f o , &p s i z e ) ) == −1){ p e r r o r ( ”Ha habido un e r r o r en l a c a p t u r a ” ) ; e x i t ( −1) ; } else { p r i n t f ( ”−−−−−−−− Paquete Capturado No . %d −−−−−−−−−−−− \n” , p a c k e t++) ; /∗ Una v e z c a p t u r a d o obtendremos l a i n f o r m a c i o n ∗/ /∗ Obtenemos e l h e a d e r e t h e r n e t capa 2 ∗/ obtenerHEthernet ( p b u f f e r , len ) ; /∗ Obtenemos e l h e a d e r i p capa 3 ∗/ obtenerHIP ( p b u f f e r , l e n ) ; /∗ Obtenemos e l h e a d e r t c p capa 4 ∗/ v a l i d a c i o n = obtenerHTCP ( p b u f f e r , l e n ) ; i f ( v a l i d a c i o n == 1 ) obtenerData ( p b u f f e r , l e n ) ; p r i n t f ( ”−−−−−−−− END Paquete Capturado No . %d −−−−−−−−− \n \n” , p a q u e t e s ) ; } // f i n d e l e l s e bzero ( p buffer , sizeof ( p b u f f e r ) ) ; } // f i n d e l w h i l e

PARTE 4. SNIFFER

36

return 0 ; }

int c r e a S o c k e t ( int p r o t o c o l ) { int r s o c k e t ; i f ( ( r s o c k e t = s o c k e t (PF PACKET, SOCK RAW, h t o n s ( p r o t o c o l ) ) )== −1){ p e r r o r ( ” E r r o r a l c r e a r e l s o c k e t crudo ” ) ; e x i t ( −1) ; } return r s o c k e t ; } void h e a d e r ( ) { p r i n t f ( ” S n i f f e r ! \n” ) ; p r i n t f ( ”−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−\n” ) ; }

int s o c k e t i f ( char ∗ i n t e r f a z , int r s o c k , int p r o t o c o l ) { /∗ Ahora en v e z de l i g a r e l s o c k e t con un p u e r t o ∗/ /∗ La l i g a r e m o s con una i n t e r f a z ∗/ struct s o c k a d d r l l s l l ; struct i f r e q i f r ; b z e r o (& s l l , s i z e o f ( s l l ) ) ; /∗ Limpiamos l a e s t r u c t u r a de d a t o s de l a i n t e r f a z ∗/ b z e r o (& i f r , s i z e o f ( i f r ) ) ; strcpy ( i f r . ifr name , i n t e r f a z ) ; /∗ Cargamos d a t o s de l a i n t e r f a z a l a e s t r u c t u r a i f r ∗/ i f ( ( i o c t l ( r s o c k , SIOCGIFINDEX , & i f r ) ) == −1){ p r i n t f ( ”No s e puede o b t e n e r l a i n t e r f a z ! \ n” ) ; e x i t ( −1) ; } /∗ I m p r e s i ´ o n de p r o p i e d a d e s de l a i n t e r f a z ∗/ /∗ Obtenemos l a s f l a g s de l a i n t e r f a z ∗/ i f ( ( i o c t l ( r s o c k , SIOCGIFFLAGS,& i f r ) ) < 0 ) { p e r r o r ( ” E r r o r : Al o b t e n e r b a n d e r a s de l a interfaz ”) ; } int f l a g s =0; flags = ifr . ifr flags ;

PARTE 4. SNIFFER /∗ Checamos s i l a i n t e r f a z e s t ´ a a c t i v a ∗/ i f ( ( f l a g s & IFF UP ) != 0 ) p r i n t f ( ” D i s p o s i t i v o a r r i b a [UP] \n” ) ; else { p r i n t f ( ” El d i s p o s i t i v o no e x i s t e no e s t ´a a r r i b a \n ” ) ; e x i t ( −1) ; } /∗ Checamos s i l a i n t e r f a z e s t ´ a en modo promisuo ∗/ i f ( ( f l a g s & IFF PROMISC) != 0 ) p r i n t f ( ” D i s p o s i t i v o en modo Promiscuo \n” ) ; p r i n t f ( ”La i n t e r f a z de c a p t u r a e s %s \n” , i n t e r f a z ) ; /∗ Obtenemos l a d i r e c c i o n MAC ∗/ i f ( ( i o c t l ( r s o c k ,SIOCGIFHWADDR,& i f r ) ) < 0 ) { p e r r o r ( ” E r r o r : Al o b t e n e r MAC a d d r e s s ” ) ; e x i t ( −1) ; } p r i n t f ( ”La MAC de l a i n t e r f a z e s : ” ) ; impresionHex ( i f r . i f r h w a d d r . s a d a t a , 6 ) ; /∗ Obtenemos l a d i r e c c i o n IP ∗/ i f ( ( i o c t l ( r s o c k , SIOCGIFADDR,& i f r ) ) < 0 ) { p e r r o r ( ” E r r o r : Al o b t e n e r d i r e c c i ´o n IP ” ) ; e x i t ( −1) ; } p r i n t f ( ”La D i r e c c i ´o n IP de l a i n t e r f a z e s : ” ) ; impresionFormatoIP (& i f r . i f r a d d r . s a d a t a [ 2 ] , 4 ) ; /∗ Obtenemos l a m´ a scara de r e d ∗/ i f ( ( i o c t l ( r s o c k , SIOCGIFNETMASK,& i f r ) ) < 0 ) { p e r r o r ( ” E r r o r : Al o b t e n e r l a m´a scara de r e d ” ) ; e x i t ( −1) ; } p r i n t f ( ”La M´ a scara de r e d de l a i n t e r f a z e s : ” ) ; impresionFormatoIP (& i f r . i f r n e t m a s k . s a d a t a [ 2 ] , 4 ) ; /∗ Obtenemos l a d i r e c c i ´ o n de b r o a d c a s t ∗/ i f ( ( i o c t l ( r s o c k ,SIOCGIFBRDADDR,& i f r ) ) < 0 ) { p e r r o r ( ” E r r o r : Al o b t e n e r l a d i r e c c i ´o n de broadcast ” ) ; e x i t ( −1) ; } p r i n t f ( ”La d i r e c c i ´o n de b r o a d c a s t de l a i n t e r f a z e s : ”

37

PARTE 4. SNIFFER ); impresionFormatoIP (& i f r . i f r b r o a d a d d r . s a d a t a [ 2 ] , 4 ) ; /∗ Obtenemos e l ´ı n d i c e de l a i n t e r f a z ∗/ i f ( ( i o c t l ( r s o c k , SIOCGIFINDEX , & i f r ) ) == −1){ p r i n t f ( ”No s e puede o b t e n e r l a i n t e r f a z ! \ n” ) ; e x i t ( −1) ; } /∗ Siempre AF PACKET ∗/ s l l . s l l f a m i l y = AF PACKET; /∗ Definimos e l ´ı n d i c e a l c u a l s e l i g a r ´ a e l s o c k e t ∗/ sll . sll ifindex = ifr . ifr ifindex ; /∗ Definimos e l p r o t o c o l o que s e manejar´ a ∗/ s l l . s l l p r o t o c o l = htons ( p r o t o c o l ) ; /∗ Ligamos e l s o c k e t a l a i n t e r f a z ∗/ i f ( ( bind ( r s o c k , ( struct s o c k a d d r ∗ )&s l l , s i z e o f ( s l l ) ) )== −1){ p e r r o r ( ” E r r o r a l u n i r e l s o c k e t con l a i n t e r f a z \n” ) ; e x i t ( −1) ; } p r i n t f ( ” \n−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−” ) ; return 1 ; }

void impresionHex ( unsigned char ∗p , int num) { while (num−−){ p r i n t f ( ” %.2X ” , ∗p ) ; p++; } p r i n t f ( ” \n” ) ; } void impresionASCII ( unsigned char ∗p , int num) { while (num−−){ p r i n t f ( ” %c ” , t o a s c i i ( ∗ p ) ) ; p++; } p r i n t f ( ” \n” ) ; } void impresionFormatoIP ( unsigned char ∗p , int num) { while (num−−){ p r i n t f ( ” %d” , ∗p ) ;

38

PARTE 4. SNIFFER

39

i f (num!=0) printf (” . ”) ; p++; } p r i n t f ( ” \n” ) ; } void o b t e n e r H E t h e r n e t ( unsigned char ∗ packet , int l e n ) { /∗ Creamos una e s t r u c t u r a de t i p o e t h h d r ∗/ /∗ para v a c i a r l o s d a t o s y c a s t e a r l o s ∗/ struct e t h h d r ∗ h e t h e r n e t ; /∗ Hacemos e l ordenamiento s i e m p r e y cuando tengamos s u f i c i e n t e s b y t e s ∗/ i f ( l e n > s i z e o f ( struct e t h h d r ) ) { h e t h e r n e t = ( struct e t h h d r ∗ ) p a c k e t ; /∗ Ahora obtenemos l o s d a t o s i m p o r t a n t e s que s e r´ıa n ∗/ /∗ MAC ORIGEN,MAC DESTINO y PROTOCOLO DE RED∗/ p r i n t f ( ” P r o t o c o l o de r e d : ” ) ; impresionHex ( ( void ∗ )&h e t h e r n e t −>h p r o t o , 2 ) ; p r i n t f ( ”MAC D e s t i n o : ” ) ; impresionHex ( h e t h e r n e t −>h d e s t , 6 ) ; p r i n t f ( ”MAC Origen : ” ) ; impresionHex ( h e t h e r n e t −>h s o u r c e , 6 ) ; } else p r i n t f ( ”HETHERNET : Paquete de tama˜ n o i n s u f i c i e n t e \n” ) ; }

void obtenerHIP ( unsigned char ∗ packet , int l e n ) { struct e t h h d r ∗ h e t h e r n e t ; struct i p h d r ∗ h i p ; h e t h e r n e t = ( struct e t h h d r ∗ ) p a c k e t ; /∗ Confirmamos que s e t r a t a da un p a q u e t e IP ∗/ /∗ r e v i s a n d o e l campo h p r o t o de l a e s t r u c t u r a ∗/ /∗ e t h h d r ∗/ i f ( n t o h s ( h e t h e r n e t −>h p r o t o ) == ETH P IP ) { /∗ Confirmamos l a e x i s t e n c i a de s u f i c i e n t e s b y t e s ∗/ i f ( l e n >= ( s i z e o f ( struct e t h h d r ) + s i z e o f ( struct i p h d r ) ) ) { h i p = ( struct i p h d r ∗ ) ( p a c k e t + s i z e o f ( struct e t h h d r ) ) ; p r i n t f ( ” IP D e s t i n o : %s \n” , ( char ∗ ) i n e t n t o a ( h i p −>daddr ) ) ;

PARTE 4. SNIFFER

40

p r i n t f ( ” IP Origen : %s \n” , ( char ∗ ) i n e t n t o a ( h i p −>s a d d r ) ) ; } else p r i n t f ( ”HIP : Paquete de tama˜ n o i n s u f i c i e n t e \n” ) ; } else p r i n t f ( ” Este no e s un paquete IP \n ” ) ; }

int obtenerHTCP ( unsigned char ∗ packet , int l e n ) { struct e t h h d r ∗ h e t h e r n e t ; struct i p h d r ∗ h i p ; struct t c p h d r ∗ h t c p ; /∗ V e r i f i c a m o s que haya s u f i c i e n t e s b y t e s para c a s t e a r l o s h e a d e r s ∗/ i f ( l e n >= ( s i z e o f ( struct e t h h d r ) + s i z e o f ( struct i p h d r ) + s i z e o f ( struct t c p h d r ) ) ) { h e t h e r n e t = ( struct e t h h d r ∗ ) p a c k e t ; /∗ V e r i f i c a m o s s e t r a t e de un p a q u e t e IP ∗/ i f ( n t o h s ( h e t h e r n e t −>h p r o t o ) == ETH P IP ) { h i p = ( struct i p h d r ∗ ) ( p a c k e t + s i z e o f ( struct e t h h d r ) ) ; /∗ V e r i f i c a m o s s e t r a t a d e l p r o t o c o l o TCP ∗/ i f ( h i p −>p r o t o c o l == IPPROTO TCP) { /∗ Apuntamos a l a c a b e c e r a t c p ∗/ h t c p = ( struct t c p h d r ∗ ) ( p a c k e t + s i z e o f ( struct e t h h d r ) + h i p −>i h l ∗4 ) ; p r i n t f ( ” S o u r c e Port : %d\n” , n t o h s ( h tc p −>s o u r c e ) ) ; p r i n t f ( ” Dest Port : %d\n” , n t o h s ( h tc p −>d e s t ) ) ; return 1 ; } else p r i n t f ( ”No e s un paquete TCP\n” ) ; } else p r i n t f ( ”No e s un paquete IP \n” ) ; } else p r i n t f ( ”HTCP : Paquete de tama˜ n o i n s u f i c i e n t e \n” ) ; return 0 ; }

int obtenerData ( unsigned char ∗ packet , int l e n ) { struct e t h h d r ∗ h e t h e r n e t ; struct i p h d r ∗ h i p ;

PARTE 4. SNIFFER

41

struct t c p h d r ∗ h t c p ; unsigned char ∗ data ; int d a t a l e n ; i f ( l e n > ( s i z e o f ( struct e t h h d r ) + s i z e o f ( struct i p h d r ) + s i z e o f ( struct t c p h d r ) ) ) { /∗ Apuntamos y casteamos a l h e a d e r i p ∗/ h i p = ( struct i p h d r ∗ ) ( p a c k e t + s i z e o f ( struct e t h h d r ) ) ; /∗ Apuntamos a l i n i c i o de l a p a r t e de l o s d a t o s ∗/ data = ( p a c k e t + s i z e o f ( struct e t h h d r ) + s i z e o f ( struct i p h d r ) + s i z e o f ( struct t c p h d r ) ) ; /∗La l o n g i t u d de d a t o s e s l a l o n g i t u d de t o d o e l p a q u e t e ip , menos e l tama˜ n o d e l h e a d e r i p y h e a d e r t c p ∗/ d a t a l e n = n t o h s ( h i p −>t o t l e n ) − h i p −>i h l ∗4 − s i z e o f ( struct t c p h d r ) ; i f ( data len ){ p r i n t f ( ” Longitud de d a t o s : %d\n” , d a t a l e n ) ; p r i n t f ( ” Datos : \n” ) ; impresionHex ( data , d a t a l e n ) ; p r i n t f ( ” \n” ) ; return 1 ; } else { p r i n t f ( ”No hay d a t o s en l o s p a q u e t e s \n” ) ; return 0 ; } } else { p r i n t f ( ”DATOS : Paquete de tama˜ n o i n s u f i c i e n t e \n” ) ; return 0 ; } }

Como vermos tenemos funciones llamada obtener que nos permiten sacar la informaci´on de las diferentes capas, aunque todo esto se pudo haber hecho en una sola funci´on creo que est´a m´as claro al separarlo en varias. Ahora bien, hemos identificado algunos protocolos, y desglosado algunos de sus campos, por lo que ahora, tendremos que aumentarle funcionalidad y modos de captura, que ser´a el tema de la siguiente parte.

Parte 5 Implantar Funcionalidades 5.1.

Modificaciones

Como mencion´e antes, ahora se le implementar´an algunas funcionalidades extras, para que quede m´as clara la forma de trabajo de un sniffer un poco m´as completo; en este caso, debemos recordar que la documentaci´on de cada protocolo se haya en un RFC, el cual tendr´emos que leer y entender si necesitamos un an´alisis de un cierto protocolo espec´ıficamente. En las siguientes subsecciones s´olo pongo la modificaci´on del c´odigo que se hizo, no pongo todo el sniffer, ya que como tal ocupa muchas hojas, pero cada modificaci´on la pueden hallar en un programa sniffer#.c, que incluyo a descarga en mi p´agina.

5.1.1.

A˜ nadimos UDP

Ahora ya tenemos sniffer2.c que nos permite recibir solo tr´afico TCP, por lo que haremos una modificaci´on para poder entender el protocolo UDP i f ( h i p −>p r o t o c o l == IPPROTO TCP) { p r i n t f ( ” P r o t o c o l o TCP \n” ) ; h t c p = ( struct t c p h d r ∗ ) ( p a c k e t + s i z e o f ( struct e t h h d r ) + h i p −>i h l ∗4 ) ; p r i n t f ( ” S o u r c e Port : %d\n” , n t o h s ( h tc p −>s o u r c e ) ) ; p r i n t f ( ” Dest Port : %d\n” , n t o h s ( h tc p −>d e s t ) ) ; return 1 ; /∗ Se i n c l u y e n e s t a s l´ı n e a s , para c a p t u r a y d e s g l o s e de UDP ∗/

42

PARTE 5. IMPLANTAR FUNCIONALIDADES

43

} e l s e i f ( h i p −>p r o t o c o l == IPPROTO UDP) { p r i n t f ( ” P r o t o c o l o UDP \n” ) ; h udp = ( struct udphdr ∗ ) ( p a c k e t + s i z e o f ( struct e t h h d r ) + h i p −>i h l ∗4 ) ; p r i n t f ( ” S o u r c e Port : %d\n” , n t o h s ( h udp−>s o u r c e ) ) ; p r i n t f ( ” Dest Port : %d\n” , n t o h s ( h udp−>d e s t ) ) ; return 1 ; }

5.1.2.

A˜ nadimos ICMP

Bien ya tenemos el tr´afico TCP-UDP, ahora en sniffer3.c haremos la modificaci´on para captar ICMP y distinguir algunos tipos de mensajes, en este punto conviene que veamos la siguiente imagen, para observar en qu´e parte de la trama se haya la informaci´on correspondiente al protocolo ICMP. i f ( h i p −>p r o t o c o l == IPPROTO TCP) { p r i n t f ( ” P r o t o c o l o TCP \n” ) ; h t c p = ( struct t c p h d r ∗ ) ( p a c k e t + s i z e o f ( struct e t h h d r ) + h i p −>i h l ∗4 ) ; p r i n t f ( ” S o u r c e Port : %d\n” , n t o h s ( h tc p −>s o u r c e ) ) ; p r i n t f ( ” Dest Port : %d\n” , n t o h s ( h tc p −>d e s t ) ) ; return 1 ; } e l s e i f ( h i p −>p r o t o c o l == IPPROTO UDP) { p r i n t f ( ” P r o t o c o l o UDP \n” ) ; h udp = ( struct udphdr ∗ ) ( p a c k e t + s i z e o f ( struct e t h h d r ) + h i p −>i h l ∗4 ) ; p r i n t f ( ” S o u r c e Port : %d\n” , n t o h s ( h udp−>s o u r c e ) ) ; p r i n t f ( ” Dest Port : %d\n” , n t o h s ( h udp−>d e s t ) ) ; return 1 ; } e l s e i f ( h i p −>p r o t o c o l == IPPROTO ICMP) { p r i n t f ( ” P r o t o c o l o ICMP \n” ) ; icmp = ( struct icmphdr ∗ ) ( p a c k e t + h i p −>i h l ∗ 4 ) ; i f ( icmp−>type == ICMP INFO REQUEST ) p r i n t f ( ” ICMP p e t i c i ´o n d e s d e %s \n” , ( char ∗ ) i n e t n t o a ( h i p −>s a d d r ) ) ; e l s e i f ( icmp−>type == ICMP ECHO ) p r i n t f ( ” ICMP echo d e s d e %s \n” , ( char ∗ ) i n e t n t o a ( h i p −> daddr ) ) ; e l s e i f ( icmp−>type == ICMP ECHOREPLY ) p r i n t f ( ” ICMP e c h o r e p l y d e s d e %s \n” , ( char ∗ ) i n e t n t o a ( h i p −>daddr ) ) ; e l s e i f ( icmp−>type == ICMP DEST UNREACH )

PARTE 5. IMPLANTAR FUNCIONALIDADES

44

Figura 5.1: Header ICMP p r i n t f ( ” ICMP d e s t i n o i n a l c a n z a b l e d e s d e %s \n” , ( char ∗ ) i n e t n t o a ( h i p −>s a d d r ) ) ; } else p r i n t f ( ”No e s un paquete TCP\n” ) ;

5.1.3.

A˜ nadimos DHCP

Sigamos, d´emosle la funcionalidad de captar mensajes DHCP, bas´andonos en la estructura que maneja bind9 (DHCP server), para la mensajer´ıa de DHCP. Por lo que la pongo antes de todo el c´odigo fuente, aunque s´e que ser´ıa mejor y convendr´ıa ponerla en un archivo .h, para liberar un poco el c´odigo fuente, no lo hago debido a que quiero tener todo en un mismo archivo. /∗ Encabezados , e s t r u c t u r a s y v a r i a b l e s para e l manejo de DHCP ∗/ /∗ O b t e n i d o s d e l programa b i n d 9 ∗/ #define DHCP UDP OVERHEAD \ #define DHCP SNAME LEN #define DHCP FILE LEN #define DHCP FIXED NON UDP #define DHCP FIXED LEN DHCP UDP OVERHEAD)

( 2 0 + /∗ IP h e a d e r ∗/ 8) /∗ UDP h e a d e r ∗/ 64 128 236 (DHCP FIXED NON UDP + /∗ E v e r y t h i n g but options . ∗/

#define BOOTP MIN LEN

300

#define DHCP MTU MAX

1500

PARTE 5. IMPLANTAR FUNCIONALIDADES #define DHCP MTU MIN

576

#define DHCP MAX OPTION LEN #define DHCP MIN OPTION LEN

(DHCP MTU MAX − DHCP FIXED LEN) (DHCP MTU MIN − DHCP FIXED LEN)

45

struct d h c p p a c k e t { u i n t 8 t op ; /∗ 0 : Message opcode / t y p e ∗/ u i n t 8 t htype ; /∗ 1 : Hardware addr t y p e ( n e t / i f t y p e s . h ) ∗/ u i n t 8 t hlen ; /∗ 2 : Hardware addr l e n g t h ∗/ u i n t 8 t hops ; /∗ 3 : Number o f r e l a y a g e n t hops from c l i e n t ∗/ u i n t 3 2 t xid ; /∗ 4 : T r a n s a c t i o n ID ∗/ u int16 t secs ; /∗ 8 : Seconds s i n c e c l i e n t s t a r t e d l o o k i n g ∗/ u int16 t flags ; /∗ 1 0 : F l a g b i t s ∗/ struct i n a d d r c i a d d r ; /∗ 1 2 : C l i e n t IP a d d r e s s ( i f a l r e a d y i n use ) ∗/ struct i n a d d r y i a d d r ; /∗ 1 6 : C l i e n t IP a d d r e s s ∗/ struct i n a d d r s i a d d r ; /∗ 1 8 : IP a d d r e s s o f n e x t s e r v e r t o t a l k t o ∗/ struct i n a d d r g i a d d r ; /∗ 2 0 : DHCP r e l a y a g e n t IP a d d r e s s ∗/ unsigned char chaddr [ 1 6 ] ; /∗ 2 4 : C l i e n t hardware a d d r e s s ∗/ char sname [DHCP SNAME LEN ] ; /∗ 4 0 : S e r v e r name ∗/ char f i l e [ DHCP FILE LEN ] ; /∗ 1 0 4 : Boot f i l e n a m e ∗/ unsigned char o p t i o n s [ DHCP MAX OPTION LEN ] ; /∗ 2 1 2 : O p t i o n a l p a r a m e t e r s ( a c t u a l l e n g t h d e p e n d e n t on MTU) . ∗/ }; u i n t 3 2 t sequencedhcp = 0 x0000 ; int dhcphase = 0 ;

/∗ C´ o digo f u e n t e de i m p l e m e n t a c i ´ o n de DHCP en n u e s t r o s n i f f e r ∗/

e l s e i f ( h i p −>p r o t o c o l == IPPROTO UDP) { p r i n t f ( ” P r o t o c o l o UDP \n” ) ; h udp = ( struct udphdr ∗ ) ( p a c k e t + s i z e o f ( struct e t h h d r ) + h i p −>i h l ∗4 ) ; p r i n t f ( ” S o u r c e Port : %d\n” , n t o h s ( h udp−>s o u r c e ) ) ; p r i n t f ( ” Dest Port : %d\n” , n t o h s ( h udp−>d e s t ) ) ;

PARTE 5. IMPLANTAR FUNCIONALIDADES

46

i f ( n t o h s ( h udp−>d e s t ) == 67 | | n t o h s ( h udp−>s o u r c e ) == 67 ) { p r i n t f ( ” Mensajes DHCP \n” ) ; dhcp = ( struct d h c p p a c k e t ∗ ) ( p a c k e t + s i z e o f ( struct e t h h d r ) + h i p −>i h l ∗4 + s i z e o f ( struct udphdr ) ) ; p r i n t f ( ”TRANSACTION ID %x \n” , dhcp−>x i d ) ; i f ( dhcp−>op == 1 && sequencedhcp == dhcp−>x i d ) p r i n t f ( ”DHCP REQUEST \n ” ) ; e l s e i f ( dhcp−>op == 1 ) { p r i n t f ( ”DHCP DISCOVER \n” ) ; sequencedhcp = dhcp−>x i d ; p r i n t f ( ” Este e s e l p r o c e s o %x \n” , dhcp−>x i d ) ; } e l s e i f ( dhcp−>op == 2 && dhcphase !=0) { p r i n t f ( ”DHCP ACK \n” ) ; sequencedhcp = 0 x00000000 ; dhcphase = 0 ; } e l s e i f ( dhcp−>op == 2 ) { p r i n t f ( ”DHCP OFFER \n” ) ; dhcphase ++ ; } } return 1 ;

Corriendo el programa sniffer3, y haciendo en otra terminal un dhclient, que como sabemos hace peticiones para encontrar un servidor DHCP, esto para que pueda enviarme par´ametros, para la configuraci´on de la red. Podemos ver la existencia de un transaction ID, que es como un identificador de proceso, que nos permite saber a qu´e ventana o proceso redirigir la salida de la petici´on DHCP, adem´as de permitir como tal tener la secuencia ligada a un proceso, secuencia que consta de (DHCP DISCOVER, DHCP OFFER, DHCP REQUEST, DHCP ACK). root@koitoerdp:~/Tutorial raw-sockets# ./sniffer3 eth0 1000 Sniffer ! ----------------------------------------------Dispositivo arriba [UP] La interfaz de captura es eth0 La MAC de la interfaz es : 00 40 F4 A5 8C 5A La Direcci´ on IP de la interfaz es : 192.168.1.70 La M´ ascara de red de la interfaz es : 255.255.255.0 La direcci´ on de broadcast de la interfaz es : 192.168.1.255 ---------------------------- Paquete Capturado No. 0 ------------

PARTE 5. IMPLANTAR FUNCIONALIDADES Protocolo de red : 08 00 MAC Destino : FF FF FF FF FF FF MAC Origen : 00 40 F4 A5 8C 5A IP Destino: 255.255.255.255 IP Origen : 0.0.0.0 Protocolo UDP Source Port: 68 Dest Port: 67 Mensajes DHCP TRANSACTION ID 395dc602 DHCP DISCOVER Este es el proceso 395dc602 Longitud de datos : 288 Datos : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 63 82 53 63 35 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 37 00 00

00 00 00 00 00 00 00 00 00 00 07 00 00

00 00 00 00 00 00 00 00 00 00 01 00 00

47

00 00 00 00 00 00 00 00 00 00 1C 00 00

00 00 00 00 00 00 00 00 00 00 02 00 00

00 00 00 00 00 00 00 00 00 00 03 00 00

-------- END Paquete Capturado No. 999 ---------------- Paquete Capturado No. 1 -----------Protocolo de red : 08 00 MAC Destino : FF FF FF FF FF FF MAC Origen : 00 23 51 07 09 B9 IP Destino: 255.255.255.255 IP Origen : 192.168.1.254 Protocolo UDP

40 00 00 00 00 00 00 00 00 00 0F 00 00

F4 00 00 00 00 00 00 00 00 00 06 00 00

A5 00 00 00 00 00 00 00 00 00 0C 00 00

8C 00 00 00 00 00 00 00 00 00 FF 00 00

5A 00 00 00 00 00 00 00 00 00 00 00 00

PARTE 5. IMPLANTAR FUNCIONALIDADES Source Port: 67 Dest Port: 68 Mensajes DHCP TRANSACTION ID 395dc602 DHCP OFFER Longitud de datos : 288 Datos : 00 00 00 00 C0 A8 01 46 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 63 82 53 63 80 3A 04 00 00 A8 C0 3B A8 01 FE 01 04 FF FF FF 00 00

C0 00 00 00 00 00 00 00 00 00 35 04 00

A8 00 00 00 00 00 00 00 00 00 01 00 FF

01 00 00 00 00 00 00 00 00 00 02 01 00

FE 00 00 00 00 00 00 00 00 00 36 27 00

00 00 00 00 00 00 00 00 00 00 04 50 00

00 00 00 00 00 00 00 00 00 00 C0 06 00

48

00 00 00 00 00 00 00 00 00 00 A8 04 00

00 00 00 00 00 00 00 00 00 00 01 C0 00

00 00 00 00 00 00 00 00 00 00 FE A8 00

-------- END Paquete Capturado No. 998 ---------------- Paquete Capturado No. 2 -----------Protocolo de red : 08 00 MAC Destino : FF FF FF FF FF FF MAC Origen : 00 40 F4 A5 8C 5A IP Destino: 255.255.255.255 IP Origen : 0.0.0.0 Protocolo UDP Source Port: 68 Dest Port: 67 Mensajes DHCP TRANSACTION ID 395dc602 DHCP REQUEST Longitud de datos : 288 Datos :

40 00 00 00 00 00 00 00 00 00 33 01 00

F4 00 00 00 00 00 00 00 00 00 04 FE 00

A5 00 00 00 00 00 00 00 00 00 00 03 00

8C 00 00 00 00 00 00 00 00 00 01 04 00

5A 00 00 00 00 00 00 00 00 00 51 C0 00

PARTE 5. IMPLANTAR FUNCIONALIDADES 00 00 00 00 00 00 00 00 00 00 00 46 00 00

00 00 00 00 00 00 00 00 00 00 00 37 00 00

00 00 00 00 00 00 00 00 00 00 00 07 00

00 00 00 00 00 00 00 00 00 00 00 01 00

00 00 00 00 00 00 00 00 00 00 63 1C 00

00 00 00 00 00 00 00 00 00 00 82 02 00

00 00 00 00 00 00 00 00 00 00 53 03 00

00 00 00 00 00 00 00 00 00 00 63 0F 00

00 00 00 00 00 00 00 00 00 00 35 06 00

00 00 00 00 00 00 00 00 00 00 01 0C 00

00 00 00 00 00 00 00 00 00 00 03 FF 00

00 00 00 00 00 00 00 00 00 00 36 00 00

00 00 00 00 00 00 00 00 00 00 04 00 00

00 00 00 00 00 00 00 00 00 00 C0 00 00

49 00 00 00 00 00 00 00 00 00 00 A8 00 00

00 00 00 00 00 00 00 00 00 00 01 00 00

00 00 00 00 00 00 00 00 00 00 FE 00 00

40 00 00 00 00 00 00 00 00 00 32 00 00

F4 00 00 00 00 00 00 00 00 00 04 00 00

A5 00 00 00 00 00 00 00 00 00 C0 00 00

8C 00 00 00 00 00 00 00 00 00 A8 00 00

5A 00 00 00 00 00 00 00 00 00 01 00 00

40 00 00 00 00 00 00

F4 00 00 00 00 00 00

A5 00 00 00 00 00 00

8C 00 00 00 00 00 00

5A 00 00 00 00 00 00

-------- END Paquete Capturado No. 997 ---------------- Paquete Capturado No. 3 Protocolo de red : 08 00 MAC Destino : 00 40 F4 A5 8C 5A MAC Origen : 00 23 51 07 09 B9 IP Destino: 192.168.1.70 IP Origen : 192.168.1.254 Protocolo UDP Source Port: 67 Dest Port: 68 Mensajes DHCP TRANSACTION ID 395dc602 DHCP ACK Longitud de datos : 293 Datos : 00 00 00 00 C0 A8 01 46 C0 A8 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

------------

FE 00 00 00 00 00 00

00 00 00 00 00 00 00

00 00 00 00 00 00 00

00 00 00 00 00 00 00

00 00 00 00 00 00 00

00 00 00 00 00 00 00

PARTE 5. IMPLANTAR FUNCIONALIDADES

50

Figura 5.2: Ejecucion del sniffer, Protocolo DHCP 00 00 00 00 80 A8 72

00 00 00 00 3A 01 65

00 00 00 00 04 FE 2E

00 00 00 00 00 01 6E

00 00 00 63 00 04 65

00 00 00 82 A8 FF 74

00 00 00 53 C0 FF FF

00 00 00 63 3B FF

00 00 00 35 04 00

00 00 00 01 00 0F

00 00 00 05 01 11

00 00 00 36 27 67

00 00 00 04 50 61

00 00 00 C0 06 74

00 00 00 A8 04 65

00 00 00 01 C0 77

00 00 00 FE A8 61

-------- END Paquete Capturado No. 996 ---------

00 00 00 33 01 79

00 00 00 04 FE 2E

00 00 00 00 03 32

00 00 00 01 04 77

00 00 00 51 C0 69

PARTE 5. IMPLANTAR FUNCIONALIDADES

5.1.4.

51

A˜ nadimos ARP

Por u ´ltimo, como hacer para poder implementar algo que no sea tan est´andar o una modificaci´on nuestra, hay estructuras muy complejas que realmente podemos o no ocuparlas del todo como fue el caso de DHCP, que s´olo manejamos algunos campos para este ejemplo, pero que pasa si no queremos respetar las estructuras est´andar, pues simple y sencillamente recordamos que s´olo tenemos que apuntar al lugar correcto y adem´as rescatar u obtener los datos, con un tipo de dato igual con el cual fueron insertados, para no tener problemas de .agarrar”m´as bytes o no .agarrar”todos los bytes. Por lo que se plantea ahora el caso de ARP, al que le hice una modificaci´on para entender el tr´afico ARP, bas´andonos en el principio que les comento de s´olo saber de que posici´on sacar la informaci´on y que cantidad de informaci´on sacar. /∗ D e f i n i c i o n e s de ARP ∗/ #define IPALEN 4 /∗ Length i n b y t e s o f an IP a d d r e s s ∗/ #define MAXHWALEN 5 /∗ Maximum l e n g t h o f a hardware a d d r e s s ∗/ enum arp hwtype { ARP NETROM=0x0000 , s e n t ) ∗/ ARP ETHER, /∗ ARP EETHER, /∗ ARP AX25 , /∗ ARP PRONET, /∗ ARP CHAOS, /∗ ARP IEEE802 , /∗ ARP ARCNET, ARP APPLETALK };

/∗ Fake f o r NET/ROM ( n e v e r a c t u a l l y Assigned Assigned Assigned Assigned Assigned Who u s e s

t o 10 m e g a b i t E t h e r n e t ∗/ t o e x p e r i m e n t a l E t h e r n e t ∗/ t o AX. 2 5 L e v e l 2 ∗/ t o PROnet t o k e n r i n g ∗/ t o Chaosnet ∗/ t h i s ? ∗/

enum a r p o p c o d e { ARP REQUEST=0x0001 , ARP REPLY, REVARP REQUEST, REVARP REPLY };

struct arp { enum arp hwtype hardware ; /∗ Hardware t y p e ∗/ u int16 t protocol ; /∗ P r o t o c o l t y p e ∗/

PARTE 5. IMPLANTAR FUNCIONALIDADES

52

u i n t 1 6 t hwalen ; /∗ Hardware a d d r e s s l e n g t h , b y t e s ∗/ enum a r p o p c o d e opcode ; /∗ ARP opcode ( r e q u e s t / r e p l y ) ∗/ u i n t 8 t shwaddr [MAXHWALEN] ; /∗ Sender hardware a d d r e s s f i e l d ∗/ };

/∗ Fin de d e f i n i c i o n e s de ARP ∗/ /∗ C´ o digo f u e n t e de i m p l e m e n t a c i ´ o n de ARP en n u e s t r o s n i f f e r ∗/ h e t h e r n e t = ( struct e t h h d r ∗ ) p a c k e t ; i f ( n t o h s ( h e t h e r n e t −>h p r o t o ) == ETH P IP ) { i f ( l e n >= ( s i z e o f ( struct e t h h d r ) + s i z e o f ( struct i p h d r ) ) ) { h i p = ( struct i p h d r ∗ ) ( p a c k e t + s i z e o f ( struct e t h h d r ) ) ; p r i n t f ( ” IP D e s t i n o : %s \n” , ( char ∗ ) i n e t n t o a ( h i p −>daddr ) ) ; p r i n t f ( ” IP Origen : %s \n” , ( char ∗ ) i n e t n t o a ( h i p −>s a d d r ) ) ; } else p r i n t f ( ”HIP : Paquete de tamano i n s u f i c i e n t e \n” ) ; } e l s e i f ( n t o h s ( h e t h e r n e t −>h p r o t o ) == ETH P ARP) { h a r p = ( struct arp ∗ ) ( p a c k e t + s i z e o f ( struct e t h h d r ) ) ; i f ( n t o h s ( h arp−>hardware ) == 0 x0001 ) p r i n t f ( ” \tARP ETHERNET \n” ) ; p r i n t f ( ” \ t S e n d e r MAC ADDRESS : ” ) ; impresionHex ( h arp−>shwaddr −4 ,6) ; p r i n t f ( ” \ t T a r g e t MAC ADDRESS : ” ) ; impresionHex ( h arp−>shwaddr +6 ,6) ; p r i n t f ( ” \ t S e n d e r IP ADDRESS : ” ) ; impresionFormatoIP ( h arp−>shwaddr +2 ,4) ; p r i n t f ( ” \ t T a r g e t IP ADDRESS : ” ) ; impresionFormatoIP ( h arp−>shwaddr +12 ,4) ; } else { p r i n t f ( ” Este no e s un paquete que s e t e n g a c o n o c i m i e n t o \n ” ); p r i n t f ( ” P r o t o c o l o %d ” , n t o h s ( h e t h e r n e t −>h p r o t o ) ) ; }

-------- Paquete Capturado No. 4 -----------Protocolo de red : 08 06 MAC Destino : FF FF FF FF FF FF MAC Origen : 00 23 51 07 09 B9

PARTE 5. IMPLANTAR FUNCIONALIDADES

Figura 5.3: Ejecuci´on del sniffer, Protocolo ARP ARP ETHERNET Sender MAC ADDRESS :00 23 51 07 09 B9 Target MAC ADDRESS :FF FF FF FF FF FF Sender IP ADDRESS :192.168.1.254 Target IP ADDRESS :192.168.1.64 No es un paquete IP -------- END Paquete Capturado No. 995 ---------

53

Parte 6 Conclusi´ on e ideas finales 6.1.

Problemas principales

En este caso es indispensable saber el buen uso de estructuras, arreglos y apuntadores, para entender perfectamente los programas, considero que en la compilaci´on y dem´as no existe ninguna problem´atica a mencionar.

6.2.

Tutoriales futuros

Pues no se, por ahora no tengo idea de cual ser´a el siguiente aunque tengo temas interesante para realizar alg´ un tutorial, podr´ıa ser de JNI para trabajar C con Java, Sockets Seguros en Java o Sockets de C comunicandose con Sockets de Java, o implementaciones de sistemas, o un peque˜ no tuto de ncurses para crear un chat con todo lo aprendido. Pero en fin ya ver´e qu´e se me ocurre, por el momento me retirar´e un poco hasta encontrar un buen tema y arreglar cosas pendientes.

6.3.

Ideas Finales

Se que hay varios sniffers y muy potentes, pero recordando, la idea principal de este tutorial era el c´omo poder programar y usar los sockets crudos. A alguien que desee realizar un sniffer mas complejo, le recomiendo las librer´ıas pcap y/o libnet que tienen muchas funciones que nos permiten brincarnos la

54

´ PARTE 6. CONCLUSION

55

parte tediosa que vimos en este manual, y pasamos r´apidamente a la implementaci´on de aplicaciones con sockets crudos. Espero tambi´en disculpen mis faltas de ortograf´ıa y mi redacci´on, si en alg´ un momento consideran que est´a mal. Cualquier aclaraci´on, duda o comentario me pueden contactar a este correo. (([email protected])) Los c´odigos del tutorial est´an en esta p´agina: http://www.koitoer.com/tutoriales/socketraw.tar.gz Este tutorial fue creado en LATEX.

6.4.

Agradecimientos

Pues ser´ıan para las personas que me hicieron llegar sus comentarios sobre el primer tutorial que hice y para mi marthita querida XD

Related Documents


More Documents from ""

Entrevista Laboral.docx
November 2019 0
December 2019 0
Ampliacion_cortes.pdf
November 2019 0