55
RAW SOCKET Programming Ing. Mauricio Mena Cort´ es koitoer 27 de junio de 2009 1

Raw Sockets Programming with C (spanish)

Embed Size (px)

DESCRIPTION

A tutorial that tries to explain how to use and program raw sockets Now code can be retrieved from: https://github.com/koitoer/SSL-Sockets

Citation preview

Page 1: Raw Sockets Programming with C (spanish)

RAW SOCKET Programming

Ing. Mauricio Mena Corteskoitoer

27 de junio de 2009

1

Page 2: Raw Sockets Programming with C (spanish)

Indice general

1. Prefacio 51.1. A quien lo lea: . . . . . . . . . . . . . . . . . . . . . . . . . . 5

2. Conocimientos basicos 72.1. Requerimientos del sistema . . . . . . . . . . . . . . . . . . . 72.2. Modelo OSI . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

2.2.1. Capa 1: Fısica . . . . . . . . . . . . . . . . . . . . . . 82.2.2. Capa 2: Enlace . . . . . . . . . . . . . . . . . . . . . . 82.2.3. Capa 3: Red . . . . . . . . . . . . . . . . . . . . . . . 92.2.4. Capa 4: Transporte . . . . . . . . . . . . . . . . . . . 122.2.5. Capa 5: Sesion . . . . . . . . . . . . . . . . . . . . . . 142.2.6. Capa 6: Presentacion . . . . . . . . . . . . . . . . . . 142.2.7. Capa 7: Aplicacion . . . . . . . . . . . . . . . . . . . . 14

3. RAW SOCKET ?? 163.1. Introduccion . . . . . . . . . . . . . . . . . . . . . . . . . . . 163.2. Funciones importantes . . . . . . . . . . . . . . . . . . . . . . 17

3.2.1. socket . . . . . . . . . . . . . . . . . . . . . . . . . . . 173.2.2. sendto . . . . . . . . . . . . . . . . . . . . . . . . . . . 173.2.3. recvfrom . . . . . . . . . . . . . . . . . . . . . . . . . . 183.2.4. getsockopt && setsocketopt . . . . . . . . . . . . . . . 18

3.3. Algunas estrcuturas importantes . . . . . . . . . . . . . . . . 193.3.1. Estructura ifreq . . . . . . . . . . . . . . . . . . . . . . 19

3.4. Un ejemplo para empezar . . . . . . . . . . . . . . . . . . . . 21

4. Sniffer 284.1. SNIFFER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

4.1.1. PROMISC MODE ?? . . . . . . . . . . . . . . . . . . 28

2

Page 3: Raw Sockets Programming with C (spanish)

INDICE GENERAL 3

4.2. ksniffer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304.2.1. Compilacion y Ejecucion . . . . . . . . . . . . . . . . 31

4.3. Sniffer mejorado. . . . . . . . . . . . . . . . . . . . . . . . . . 31

5. Implantar Funcionalidades 425.1. Modificaciones . . . . . . . . . . . . . . . . . . . . . . . . . . 42

5.1.1. Anadimos UDP . . . . . . . . . . . . . . . . . . . . . . 425.1.2. Anadimos ICMP . . . . . . . . . . . . . . . . . . . . . 435.1.3. Anadimos DHCP . . . . . . . . . . . . . . . . . . . . . 445.1.4. Anadimos ARP . . . . . . . . . . . . . . . . . . . . . . 51

6. Conclusion 546.1. Problemas principales . . . . . . . . . . . . . . . . . . . . . . 546.2. Tutoriales futuros . . . . . . . . . . . . . . . . . . . . . . . . 546.3. Ideas Finales . . . . . . . . . . . . . . . . . . . . . . . . . . . 546.4. Agradecimientos . . . . . . . . . . . . . . . . . . . . . . . . . 55

Page 4: Raw Sockets Programming with C (spanish)

Indice de figuras

2.1. Ethernet (Header) . . . . . . . . . . . . . . . . . . . . . . . . 92.2. IP (Header) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102.3. ICMP (Header) . . . . . . . . . . . . . . . . . . . . . . . . . . 102.4. TCP (Header) . . . . . . . . . . . . . . . . . . . . . . . . . . . 122.5. UDP (Header) . . . . . . . . . . . . . . . . . . . . . . . . . . . 142.6. Modelo OSI . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

3.1. Ejecucion captada por IPTraf del codigo bajado de internet ycomo vemos no funciona . . . . . . . . . . . . . . . . . . . . . 21

3.2. Ejecucion captada por Wireshark . . . . . . . . . . . . . . . . 27

4.1. Empaquetado en modelo OSI . . . . . . . . . . . . . . . . . . 32

5.1. Header ICMP . . . . . . . . . . . . . . . . . . . . . . . . . . . 445.2. Ejecucion del sniffer, Protocolo DHCP . . . . . . . . . . . . . 505.3. Ejecucion del sniffer, Protocolo ARP . . . . . . . . . . . . . . 53

4

Page 5: Raw Sockets Programming with C (spanish)

Parte 1

Prefacio

1.1. A quien lo lea:

En este tutorial tratare de explicar y plasmar mediante algunos ejemplospropios y algunos otros corregidos que obtuve de la red, la forma y funcional-idad que se puede tener al programar con RAW SOCKET, pero vamos, nisiquiera he definido que es un RAW SOCKET, en este caso su traducciona nuestro lenguaje es ”socket crudo”, mucha gente se podra preguntar porque la palabra crudo, esto se debe a que este tipo de sockets trabajan sinestar ligados a un protocolo de comunicaciones, es decir, podemos darle el sa-bor(flavor) que necesitemos, esto en programacion lo podemos traducir comodarle 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 porlo tanto dandonos el acceso a los protocolos directamente y a la informacionque recide en ellos. El uso de sockets de este tipo nos va a permitir la imple-mentacion de nuevos protocolos, y por que no decirlo, la modificacion de losya existentes.

Cabe mencionar que en esta ocasion, pondre en el tutorial la documentacionde algunas estructuras de datos y funciones que nos ayudaran a crear y enten-der el uso de los sockets crudos, aun asi tampoco pretendo explicar ni entrar adetalle en el modelo OSI, el cual nos servira solo como referencia para enten-der un poco mas del funcionamiento de los sockets, aunque sı le dedicare unaseccion a lo que considero mas importante del modelo al trabajar con estossockets.

5

Page 6: Raw Sockets Programming with C (spanish)

PARTE 1. PREFACIO 6

Bueno espero el tutorial sea claro, conciso y les sirva para empezar aentender un poco mas acerca de la programacion de sockets crudos, empeze-mos.

Page 7: Raw Sockets Programming with C (spanish)

Parte 2

Conocimientos basicos

2.1. Requerimientos del sistema

Primero que nada todo este manual esta orientado a sistemas linux - unix,como el anterior tutorial. La distribucion que se use no tendra por que im-portar, ya que en realidad lo que se necesitara es tener instalado

1. GCC

Sı, solo necesitaremos el compilador de GNU, ya que en esta ocasion to-das 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/in-clude/linux, las cuales son cargadas al sistema en una instalacion normal delsistema.Tambien nos podremos auxiliar del archivo /etc/protocol, para el conocimien-to de los protocolos y sus abreviaciones.

2.2. Modelo OSI

El modelo de capas OSI (Open System Interconection) es uno de lospilares basicos para el desarollo de las redes actuales y es completamenteaplicable a redes de tipo TCP/IP, fue creado en 1984 por ISO, con el fin deestandarizar el proceso de creacion de nuevos tipos de redes de informatica.

7

Page 8: Raw Sockets Programming with C (spanish)

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 deforma mas grafica 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 dispos-itivos, da las especificaciones electricas, mecanicas y los requerimientos conrespecto a voltajes, intensidades, cables, pines, modulaciones para una trans-mision exitosa de la informacion, con lo que se tienen interfaces que puedenestar activadas o desactivadas, esta capa nos provee de la topologıa fısica dela red, por lo que en este tutorial no haremos uso de ella.

2.2.2. Capa 2: Enlace

Despues de la demodulacion de la senal, esta capa es la encargada derevisar las alteraciones que esta pudo haber sufrido en el medio, esta capatrabaja con tramas, permite encontrar diversos errores en las mismas, se lesuele conocer como MAC (Media Access Control). En esta capa actua el LLC(Logic Link Control), y se trabaja con direcciones fısicas (MAC ADDRESS)de las NIC (Network Interface Control), Switches y Conmutadores. El PDUque se maneja es trama (frame), controla el framing, la notificacion de errores,la topologıa de red y el principal estandar de esta capa es el IEEE-802.

ETHERNET

#include < i f e t h e r . h>

struct ethhdr{

unsigned char h des t [ETH ALEN ] ;/∗ d e s t i n a t i o n e th addr ∗/

unsigned char h source [ETH ALEN ] ;/∗ source e t h e r addr ∗/unsigned short h proto ;/∗ packe t type ID f i e l d ∗/

} ;

Page 9: Raw Sockets Programming with C (spanish)

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 semaneja es el paquete, y el principal protocolo que trabaja en esta capa esIP (Internet protocol), aunque no debemos de olvidar que tambien trabajanICMP (Internet Common Message Protocol), ARP (Address Resolution Pro-tocol), RARP (Reverse Address Resolution Protocol), PPTP (Point-to-pointTunneling Protocol), entre otros.

IP

#include <ip . h>

struct iphdr {#i f de f ined ( LITTLE ENDIAN BITFIELD)

u8 i h l : 4 ,v e r s i on : 4 ;

#e l i f d e f i n ed ( BIG ENDIAN BITFIELD)u8 v e r s i o n : 4 ,

i h l : 4 ;#else#e r r o r ” Please f i x <asm/ byteorder . h>”#e n d i f

u8 tos ;u16 t o t l e n ;u16 id ;

Page 10: Raw Sockets Programming with C (spanish)

PARTE 2. CONOCIMIENTOS BASICOS 10

Figura 2.2: IP (Header)

u16 f r a g o f f ;u8 t t l ;u8 p ro to c o l ;u16 check ;u32 saddr ;u32 daddr ;

/∗The o p t i o n s s t a r t here . ∗/} ;

ICMP

Figura 2.3: ICMP (Header)

Page 11: Raw Sockets Programming with C (spanish)

PARTE 2. CONOCIMIENTOS BASICOS 11

struct icmphdr{

u i n t 8 t type ;/∗ message type ∗/

u i n t 8 t code ;/∗ type sub−code ∗/

u i n t 1 6 t checksum ;union{

struct{

u i n t 1 6 t id ;u i n t 1 6 t sequence ;

} echo ;/∗ echo datagram ∗/

u i n t 3 2 t gateway ;/∗ gateway address ∗/

struct{

u i n t 1 6 t unused ;u i n t 1 6 t mtu ;

} f r a g ;/∗ path mtu d i s c o v e r y ∗/} un ;

} ;

#define ICMP ECHOREPLY 0/∗ Echo Reply ∗/

#define ICMP DEST UNREACH 3/∗ D e s t i n a t i o n Unreachable ∗/

#define ICMP SOURCE QUENCH 4/∗ Source Quench ∗/

#define ICMP REDIRECT 5/∗ Redirec t ( change route ) ∗/

#define ICMP ECHO 8/∗ Echo Request ∗/

#define ICMP TIME EXCEEDED 11/∗ Time Exceeded ∗/

#define ICMP PARAMETERPROB 12/∗ Parameter Problem ∗/

#define ICMP TIMESTAMP 13/∗ Timestamp Request ∗/

#define ICMP TIMESTAMPREPLY 14/∗ Timestamp Reply ∗/

Page 12: Raw Sockets Programming with C (spanish)

PARTE 2. CONOCIMIENTOS BASICOS 12

Figura 2.4: TCP (Header)

#define ICMP INFO REQUEST 15/∗ Informat ion Request ∗/

#define ICMP INFO REPLY 16/∗ Informat ion Reply ∗/

#define ICMP ADDRESS 17/∗ Address Mask Request ∗/

#define ICMP ADDRESSREPLY 18/∗ Address Mask Reply ∗/

#define NR ICMP TYPES 18

2.2.4. Capa 4: Transporte

En esta capa, se tienen dos modos de conexion, orientado a conexion yno orientado a conexion y principalmente hacemos uso de TCP y UDP, estosprotocolos se encargan de dar la fin de secuencia, segmentacion y reensamblede datos al stream de datos, esta es la capa que nos provee la conexion logicaente los host, puede o no proveer de circuitos virtuales a la par de correccionde errores en la transmision. En este caso el PDU de la capa 4 es el segmento.

TCP

struct tcphdr {u shor t t h s p o r t ;

/∗ source por t ∗/

Page 13: Raw Sockets Programming with C (spanish)

PARTE 2. CONOCIMIENTOS BASICOS 13

u shor t th dport ;/∗ d e s t i n a t i o n por t ∗/

t cp s eq th seq ;/∗ sequence number ∗/

t cp s eq th ack ;/∗ acknowledgement number ∗/

#i f BYTE ORDER == LITTLE ENDIANu char th x2 : 4 ,/∗ ( unused ) ∗/t h o f f : 4 ;/∗ data 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 ,/∗ data o f f s e t ∗/th x2 : 4 ;/∗ ( unused ) ∗/

#e n d i fu char t h f l a g s ;#d e f i n e TH FIN 0x01#d e f i n e TH SYN 0x02#d e f i n e TH RST 0x04#d e f i n e TH PUSH 0x08#d e f i n e TH ACK 0x10#d e f i n e TH URG 0x20

u shor t th win ;/∗ window ∗/u shor t th sum ;/∗ checksum ∗/u shor t th urp ;/∗ urgent p o i n t e r ∗/

} ;

UDP

struct udphdr{

u i n t 1 6 t source ;u i n t 1 6 t des t ;u i n t 1 6 t l en ;u i n t 1 6 t check ;

} ;#endif

#define SOL UDP 17

Page 14: Raw Sockets Programming with C (spanish)

PARTE 2. CONOCIMIENTOS BASICOS 14

Figura 2.5: UDP (Header)

/∗ sockop t l e v e l f o r UDP ∗/

2.2.5. Capa 5: Sesion

Encargada de la separacion de datos de diferentes aplicaciones, asi comodel control de dialogo, configuraciones de administracion, termino de sesionesentre la capa de presentacion y maneja los conceptos de comunicaciones sim-plex, halfduplex o fullduplex.

2.2.6. Capa 6: Presentacion

Presenta los datos, se encarga del cifrado de los datos, ademas de ser laencargada de presentar los formatos de codificacion, maneja las operacionesmultimedia, la translacion de los datos y formato de codigo, tambien se en-carga de la compresion Entre los cuales estan (ASCII, EBDIC)

2.2.7. Capa 7: Aplicacion

Da una interfaz al usuario, encargado de funciones de archivos, mensaje,servidores, bases de datos, para los cuales maneja diferentes patrones de co-municaciones y recursos para la comunicaciones. Entre los principales estanSSH, FTP, HTTP.

Page 15: Raw Sockets Programming with C (spanish)

PARTE 2. CONOCIMIENTOS BASICOS 15

Figura 2.6: Modelo OSI

Page 16: Raw Sockets Programming with C (spanish)

Parte 3

RAW SOCKET

3.1. Introduccion

Cuando nosotros trabajamos con rawsocket, perdemos y ganamos difer-entes caracterısticas, entre las mas improtantes destacan:

1. Los sockets raw son un nivel abstracto sobre la trama de red, de he-cho son mas abstractos que los sockets que ya conocemos que sonSOCK STREAM y SOCK DGRAM, al ser estos ultimos un caso es-pecıfico de los sockets crudos.

2. Al usar sockets crudos, tenemos una perdida de fiabilidad con respectoal TCP, ya que no se incluye por defecto al usar socket crudo.

3. No hay puertos; sı, increıble pero cierto, aunque muchas veces dijimosque un socket = direccion IP + un puerto, ahora desmentimos en parteeso, ya que en los sockets crudos es el kernel el encargado de pasarla informacion de un cierto protocolo a todos los sockets que estenescuchando el mismo protocolo, no hay conexiones de red virtualescomo tal, es decir, no hay puertos.

4. Comunicaciones sin estandar, ya que uno lo debe de generar, al escribirun servidor tendremos que escribir el cliente, ya que no es un estandary no cualquier programa entendera lo que nosotros estamos diciendo.

5. Si se hace uso de protocolos ya existentes, se tienen que rellenar loscampos (headers) manualmente, ya que el kernel no lo hace automatica-mente.

16

Page 17: Raw Sockets Programming with C (spanish)

PARTE 3. RAW SOCKET ?? 17

6. Por ultimo debemos de tener en cuenta que cualquier programa quehaga 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 programacion de lossockets crudos tenemos ciertas funciones que nos ayudaran a crearlos y us-arlos, por lo que pongo un listado de las que considero mas importantes yalgunos detalles o parametros mas usados.

3.2.1. socket

#include <sys / types . h>#include <sys / socket . h>

int socke t ( int domain , int type , int pro to co l ) ;

Donde el dominio que se usara es el PF INET, el tipo de socket esSOCK RAW, y protocol es el protocolo a usar con este socket que se esta cre-ando. 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 <sys / types . h>#include <sys / socket . h>

int sendto ( int s , const void ∗msg , int len , unsigned int f l a g s ,const struct sockaddr ∗ to , int t o l e n ) ;

Como primer parametro se indica el descriptor del socket. El segundoparametro es un puntero a los datos que se van a enviar. El tercer parametroindica el numero de bytes que se van a enviar. En el cuarto parametro vanlas banderas que pueden ser :

Page 18: Raw Sockets Programming with C (spanish)

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 enrutamien-to.

Para el cuarto parametro se tiene una estructura de tipo sockaddr, que secompleta con la direccion y puerto del destino del mensaje Por ultimo en elquinto parametro se envıa el tamano de la estrcutura sockaddr

3.2.3. recvfrom

#include <sys / types . h>#include <sys / socket . h>

int recvfrom ( int s , void ∗buf , int len , unsigned int f l a g s ,struct sockaddr ∗ from , int f romlen ) ;

Como primer parametro se indica el descriptor del socket. El segundoparametro es un punteo a donde se van almacenar los datos recibidos. Eltercer parametro indica el tamano de este buffer. En el cuarto parametro vanlas banderas que pueden ser :

1. MSG PEEK, permite acceso a los datos sin eliminarlos del buffer.

2. MSG OOB, indica recepcion de datos urgentes.

3. MSG WAITALL, hace que la operacion de lectura se bloquee hasta elllenado total del buffer

Para el quinto parametro se tiene una estrcutura de tipo sockaddr, que nospermite tener acceso a la informacion de quien envio el paquete En el sextoy ultimo parametro se envia el tamano de la estructura sockaddr

3.2.4. getsockopt && setsocketopt

Funciones importantes que nos permiten modificar el comportamiento deun socket.

Page 19: Raw Sockets Programming with C (spanish)

PARTE 3. RAW SOCKET ?? 19

#include <sys / types . h>#include <sys / socket . h>

int get sockopt ( int s , int l e v e l , int opname , void ∗ optval , intopt l en ) ;

int s e t sockopt ( int s , int l e v e l , int opname , const void ∗ optval ,int opt l en ) ;

Como primer parametro se indica el descriptor del socket. El segundoparametro indica la capa o el nivel de protocolo en la que se hara el cambioEl tercer parametro indica la opcion que queremos modificar En el cuartoparametro se indica el valor con el que se desea modificar. Para el quintoparametro se tiene el tamano de la variable referenciada a modificar.

IPPROTO_IP - IP_OPTIONS

IPPROTO_IP - IP_HDRINCL

IPPROTO_TCP - TCP_MAXSEG

IPPROTO_TCP - TCP_NODELAY

SOL_SOCKET - SO_BROADCAST /Envıo de broadcast

SOL_SOCKET - SO_DEBUG

SOL_SOCKET - SO_DONTROUTE

SOL_SOCKET - SO_ERROR

SOL_SOCKET - SO_KEEPALIVE /Mantener viva la conexion

SOL_SOCKET - SO_LINGER /Envıo al desconexion

SOL_SOCKET - SO_REUSEADDR / Reuso de direccion

SOL_SOCKET - SO_TYPE / Obtencion del tipo de socket

SOL_SOCKET - BINDTODEVICE /Enlazar socket con dispositvo

3.3. Algunas estrcuturas importantes

3.3.1. Estructura ifreq

#include <sys / i o c t l . h>#include <net / i f . h>

struct i f r e q {char i f r name [ IFNAMSIZ ] ; /∗ I n t e r f a c e name ∗/union {

Page 20: Raw Sockets Programming with C (spanish)

PARTE 3. RAW SOCKET ?? 20

struct s o c k a d d r i f r a d d r ;struct s o c k a d d r i f r d s t a d d r ;struct sockaddr i f r b roadaddr ;struct sockaddr i f r ne tmask ;struct sockaddr i f r hwaddr ;short i f r f l a g s ;int i f r i f i n d e x ;int i f r m e t r i c ;int i f r mtu ;struct i fmapi f r map ;char i f r s l a v e [ IFNAMSIZ ] ;char i fr newname [ IFNAMSIZ ] ;char ∗ i f r d a t a ;

} ;} ;

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 address ∗/struct i f r e q ∗ i f c r e q ; /∗ array o f s t r u c t u r e s ∗/

} ;} ;

Para mas informacion recomiendo esta paginahttp://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 s l l i f i n d e x ;/∗ I n t e r f a c e number ∗/unsigned short s l l h a t y p e ;/∗ Header type ∗/unsigned char s l l p k t t y p e ;/∗ Packet type ∗/unsigned char s l l h a l e n ;/∗ Length o f address ∗/unsigned char s l l a d d r [ 8 ] ; /∗ P h y s i c a l l a y e r address ∗/

} ;

Page 21: Raw Sockets Programming with C (spanish)

PARTE 3. RAW SOCKET ?? 21

Figura 3.1: Ejecucion captada por IPTraf del codigo bajado de internet ycomo vemos no funciona

3.4. Un ejemplo para empezar

Cuando empece en este tema de los sockets crudos, me encontre con unejemplo el cual considero el dıa de hoy es muy bueno para poder explicar einiciarse con los raw sockets, seguramente personas que hayan estado en con-tacto con este tema lo han de ver visto en internet, donde muchas personasya se consideran hackers XD al correr este ejemplo, pero les tengo una malanoticia, el ejemplo como tal tiene fallas y si buscan realizar un ataque SYNFLOOD como mencionan se puede hacer, si tienen un router enfrente fal-lara lamentablemente, pero en este documento he corregido los errores (TCPbogus header at least 20 length, Checksum offload, TCP header error offset),pero vamos lo incluyo, ya que lo considero totalmente util para el inicio deeste tema.

Page 22: Raw Sockets Programming with C (spanish)

PARTE 3. RAW SOCKET ?? 22

Lamentablemente al correrlo tendran que hacer el checksum manualmentedel TCP header (el cual consta de la suma del pseudoheader TCP + headerTCP + datos) al menos que se ocupen los mismos datos que yo manejo enel ejemplo, ya que si cambian la IP origen o destino se tendra que volvera realizar; no incluyo una funcion que lo realice automaaticamente, ya quecomo 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 nux / i f e t h e r . h>

/∗ L i b r e r ı a de l o s s o c k e t s ∗/#include <sys / socket . h>#include <n e t i n e t / in . h>

/∗Para ob tener datos de capa 3 ∗/#include <n e t i n e t / ip . h>

/∗Para ob tener datos de capa 4 ∗//∗Usaremos l a e s t r u c t u r a BSD para TCP hdr ∗/

#define FAVOR BSD#include <n e t i n e t / tcp . h>#include <uni s td . h>

/∗Puerto a l c ua l se va a env iar e l paquete ∗/#define P 22

int i =0;

/∗ Recordemos que a l no t ene r e l s t a c k TCP/IP ∗//∗ implementado tendremos que hacer e l checksum ∗//∗ manualmente con ayuda de e s t a func i on ∗/unsigned short csum (unsigned short ∗buf , int nwords ) {

unsigned long sum ;for (sum = 0 ; nwords > 0 ; nwords−−)sum += ∗buf++;sum = (sum >> 16) + (sum & 0 x f f f f ) ;sum += (sum >> 16) ;return ˜sum ;

}

int main ( int argc , char ∗∗ argv ) {int one = 1 ;const int ∗ va l = &one ;p r i n t f ( ” In i c iamos env ıo de paquetes \n” ) ;/∗Creamos e l s o c k e t crudo , e l c ua l implementara TCP/IP ∗/

Page 23: Raw Sockets Programming with C (spanish)

PARTE 3. RAW SOCKET ?? 23

int s = socket (PF INET , SOCK RAW, IPPROTO TCP) ;

/∗Creamos un b u f f e r que contendra l a s cabeceras , IP y TCP ∗//∗ademas d e l pay load ∗/char datagram [ 4 0 9 6 ] ;

/∗En e s t e caso iremos d e l p r o t o c o l o mas ba jo a l mas a l t opor l o que empezaremos con IP , a l crear una e s t u c t u r a i p ∗/struct ip ∗ iph = ( struct ip ∗) datagram ;

/∗Usaremos una e s t u c t u r a de s o c k e t para e l env ıo de paque tes∗/

struct sockaddr in s i n ;

/∗Usaremos l a f a m i l i a INET a l t ene r que s a l i r por l a red ∗/s i n . s i n f a m i l y = AF INET ;

/∗Se escoge un puer to d e s t i n o a l que se enviar an l o s paque tes∗/

s i n . s i n p o r t = htons (P) ;

/∗Escogemos l a IP d e s t i n o de n u e s t r o s paque tes ∗/s i n . s i n addr . s addr = ine t addr ( ” 1 3 2 . 2 4 8 . 5 9 . 1 ” ) ;

/∗Ponemos e l b u f f e r con l o s headers en cero ∗/memset ( datagram , 0 , 4096) ;

/∗ Hasta e s t a p ar t e podran pensar que no hemos hecho nadad i f e r e n t e

ya que se 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 d e s t i n o ytodo

parece ser l o mismo , pero ahora tendremos e l c o n t r o l de l o scampos

de l a s cabeceras IP y TCP, para e n v i a r l o s por l a red ∗//∗ Por l o que empezamos a r e l l e n a r l o s manualmente ∗/

/∗−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−∗//∗ HEADER IP ∗/iph−>i p h l = 5 ;/∗ Se escoge l a v e r s i o n de IPv4 ∗/iph−>i p v = 4 ;/∗ Se escoge 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 cabecera IP ∗/iph−>i p l e n = s izeof ( struct ip ) + s izeof ( struct tcphdr ) ;

Page 24: Raw Sockets Programming with C (spanish)

PARTE 3. RAW SOCKET ?? 24

p r i n t f ( ”Esta es l a l ong i tud 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 paquete ∗/iph−>i p i d = htonl (54321) ;/∗ Se da e l o f f s e t d e l paquete ∗/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 = 255 ;/∗ Se esocge e l p r o t o c o l o a usar ∗/iph−>i p p = 6 ; // 6 a l se r TCP / e t c / p r o t o c o l/∗ Momentaneamente pones e l checksum a cero ∗/iph−>ip sum = 0 ;/∗ Se escoge l a i p origen , 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 proxy ISP no

p e r m i t i r a c u a l q u i e r d i r e c c i o n en e s t e campo ∗/iph−>i p s r c . s addr = ine t addr ( ” 1 9 2 . 1 6 8 . 1 . 7 0 ” ) ;/∗ Se d e f i n e l a ip 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

anter iormente ∗/iph−>i p d s t . s addr = s i n . s i n addr . s addr ;

/∗−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−∗//∗ HEADER TCP ∗//∗Ahora crearemos l a e s t r u t u r a TCP ∗/struct tcphdr ∗ tcph = ( struct tcphdr ∗) ( datagram + iph−>

i p h l ∗4 ) ;p r i n t f ( ”Esta es l a l ong i tud s t r u c t ip %d \n” , s izeof (∗ iph ) ) ;p r i n t f ( ”Esta es l a l ong i tud s t r u c t tcphdr %d \n” , s izeof (∗

tcph ) ) ;/∗ Se da e l puer to or i gen d e l paquete ∗/tcph−>t h s p o r t = htons (45521) ;

/∗ Se da e l puer to d e s t i n o d e l paquete ∗/tcph−>th dport = htons (P) ;/∗ Se da e l numero de secuenc ia d e l paquete ∗/tcph−>th s eq = random ( ) ;/∗ Numero de l a secuenc ia ACK ∗/tcph−>th ack = 0x00000000 ;tcph−>th x2 = 0 ;/∗ Se da e l o f f s e t de l a cabecera TCP (5∗4) ∗/tcph−>t h o f f = 5 ;/∗ Ponemos para l a p e t i c i o n de una conexi on ∗/tcph−>t h f l a g s = TH SYN;/∗ Indicamos e l tamano de l a ventana ∗/tcph−>th win = 0 x018f ;/∗ Si ponemos e l checksum TCP a cero aunque digan quee 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 funciono , por

Page 25: Raw Sockets Programming with C (spanish)

PARTE 3. RAW SOCKET ?? 25

l o que tuve que hacer e l checksum ∗/checksum c o r r e c t o ∗/tcph−>th sum = 0 x60fa ;tcph−>th urp = 0 ;

/∗Se da e l checksum d e l paquete y se 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 ip %x \n” , iph−>ip sum ) ;

/∗ Al usar IP HDRINCL l e decimos que estamosinc luyendo e l header IP en e l paquete ∗/

i f ( s e t sockopt ( s , IPPROTO IP , IP HDRINCL , val , s izeof ( one )) < 0)

p r i n t f ( ” Error : No se modi f i c o e l socke t \n” ) ;while ( i !=10){

i ++;i f ( sendto ( s , datagram , ( iph−>i p l e n ) , 0 , ( struct sockaddr ∗)

&sin , s izeof ( s i n ) ) < 0)p r i n t f ( ”Paquete no se ha podido env ia r \n” ) ;

elsep r i n t f ( ”Paquete enviado \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

Page 26: Raw Sockets Programming with C (spanish)

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 ejecucion se mandan paquetes TCPSYNC, para el inicio del HANDSHAKE, al puerto 22 de una maquina remota,la cual nos reponde con un SYNC+ACK, por las diez veces que mandamosese paquete, pero si nos fijamos en la imagen del sniffer, nuestra maquina la192.168.1.70, envıa un RST, que es un Reset Connection al no haber procesoalguno que se encarge de los paquetes recien recibidos, ya que como tal solomandamos los diez SYNC, nunca esperamos respuesta.

Como vemos, es un programa que nos permite poner directamente loscampos de los headers, TCP e IP, con lo que corroboramos que podemostener el control de los protocolos ya existentes, en este caso debemos detener en cuenta que si quisieramos atacar algun host, cambiando nuestra IP,para que no nos detecten, muchas veces nuestro ISP, no permitira que estetipo de peticiones salgan a internet, debido a que el mismo reconoce que noson propias de su configuracion, aunque si estudiamos un poco el tipo dedirecciones IP, que maneja esto si sera posible.

Page 27: Raw Sockets Programming with C (spanish)

PARTE 3. RAW SOCKET ?? 27

Figura 3.2: Ejecucion captada por Wireshark

Page 28: Raw Sockets Programming with C (spanish)

Parte 4

Un sniffer para comenzar

Despues de programar un poco, tenemos listo un sniffer, que nos permiteanalizar la informacion contenida en ciertos protocolos, en este caso si sedesea el analisis de otro protocolo, simplemente tendremos que realizar unainclusion del desglose del protocolo en el lugar correcto como lo hare masadelante.

4.1. SNIFFER

Primero que nada,¿que es un sniffer?, bueno es un programa de capturade tramas, que se usa con diversos fines, como pueden ser el analisis deprotocolos, la gestion de las redes, fines maliciosos XD, analisis de fallos,deteccion de posibles ataques o intrusos, o como simple medidor de trafico.

4.1.1. PROMISC MODE ??

Es una configuracion de la tarjeta de red, la cual nos permite pasar a nivelde aplicacion todos los paquetes recibidos sean o no para nosotros, por lo quepodremos escuchar todo el trafico que llegue a nuestra tarjeta, que pudieseser mınimo si hablamos de una computadora o host, pero puede llegar a serciertamente 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 debemosde tener permisos de administrador.

root@koitoerdp:~# ifconfig eth0 promisc

root@koitoerdp:~# ifconfig

28

Page 29: Raw Sockets Programming with C (spanish)

PARTE 4. SNIFFER 29

eth0 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, solo la reiniciamos,para esto debemos ten-er cuidado ya que si estamos conectados remotamente al reiniciar la interfaz,nos desconectara.

Para la deteccion de tarjetas en modo promiscuo dentro de nuestra red,tenemos varias opciones, que se dividen en dos tipos, el primero checar man-ualmente cada tarjeta de red para ver si esta en modo promiscuo, suena difıcilverdad, bueno entonces podemos crear un demonio el cual nos permita sabercuando una tarjeta cambie a modo promiscuo, esto simplemente lo haremosleyendo el /var/log/message, donde queda huella cuando una interfaz haceuso de este modo

May 2 17:02:00 koitoerdp kernel: [17157.272110]

device lo entered promiscuous mode

May 2 17:02:04 koitoerdp kernel: [17161.113065]

device lo left promiscuous mode

May 2 17:11:16 koitoerdp kernel: [17712.772099]

device eth0 entered promiscuous mode

May 2 17:11:56 koitoerdp kernel: [17752.564435]

device eth0 left promiscuous mode

Pero vamos si lo borra, lo cual es difıcil al menos que se tenga la contrasenade root, pues solo nos queda hacer uso de diversas tecnicas para encontrartarjetas en modo promiscuo, que pueden ser por medio del envıo de paquetesARP o el uso de antisniffers como Antisnif o Sentinel. Para esto tambienencontre en internet, un buen programa que se llama neped.c, que se encargade la identificacion de un host con su tarjeta en modo promiscuo a travesdel simple envıo de paquetes ARP a maquinas inexistentes. Considero que

Page 30: Raw Sockets Programming with C (spanish)

PARTE 4. SNIFFER 30

echarle un vistazo al codigo puede ser en este momento un tanto dıficil, peroal final de este tutorial puede ser bastante didactico, para ver y corroborarlo aprendido.

4.2. ksniffer

Muy bien, es hora de programar un sniffer sencillo, que capture el traficoTCP que pasa por nuestra interfaz, entonces empecemos.

#include <s t d i o . h>#include < f c n t l . h>#include <sys / socket . h>#include <r e s o l v . h>#include <netdb . h>#include <n e t i n e t / in . h>#include <n e t i n e t / tcp . h>#include <n e t i n e t / ip . h>

int main ( ) {/∗ Creamos e l s o c k e t crudo , e l c ua l s o l o va acapturar e l t r a f i c o de paque tes TCP, como l oi n d i c a l a opci on IPPROTO TCP ∗/int fd = socket (PF INET , SOCK RAW, IPPROTO TCP) ;/∗ Sera nues tro b u f f e r de captura ∗/char b u f f e r [ 8 1 9 2 ] ;int i =0 ;int bytes = 0 ;/∗ Entramos a un c i c l o i n f i n i t o que nos permitei r capturando y mostrando e l t r a f i c o , en e s t ecaso usamos read , ya que estamos traba jando cone l p r o t o c o l o TCP ∗/while ( ( bytes = read ( fd , bu f f e r , 8192) ) > 0) {

/∗ Una vez capturado l o mostramos a impresi on , e s t o l ohacemos se na lando donde i n i c i a e s t a informaci on , l o c ua le x p l i c a r e un poco mas a d e l a n t e ∗/

p r i n t f ( ”Paquete capturado %s \n” , b u f f e r+s izeof ( structiphdr )+s izeof ( struct tcphdr ) ) ;

p r i n t f ( ” Contenido : \n” ) ;p r i n t f ( ”Hexadecimal \n” ) ;for ( i = 0 ; i< bytes ; i++)

p r i n t f ( ” %x” , b u f f e r [ i ] ) ;p r i n t f ( ”\nEntendible \n” ) ;for ( i = 0 ; i< bytes ; i++)

p r i n t f ( ” %c” , b u f f e r [ i ] ) ;

Page 31: Raw Sockets Programming with C (spanish)

PARTE 4. SNIFFER 31

p r i n t f ( ”\ nS igu i ente−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− \n” ) ;

}

}

4.2.1. Compilacion y Ejecucion

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 mediran que no se entiende nada jajaja, pues claro solo estamos capturando lospaquetes jamas los ordenamos y obtenemos los datos de ellos, asi que esasera nuestra siguiente tarea, lo que cabe resaltar en este ejemplo es el uso delas estructuras que previamente habiamos platicado.

4.3. Sniffer mejorado.

Algo que tenemos que recordar, que es tan simple, pero a la vez es lomas importante al momento de obtener la informacion util en un sniffer, esla forma en la que se esta recibiendo y enviando la informacion, recordemosque 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 semuestra en la siguiente figura

Entonces como vemos en la figura lo primero que llega siempre es elHeader de la capa de enlace, despues viene el NH (Network header) header

Page 32: Raw Sockets Programming with C (spanish)

PARTE 4. SNIFFER 32

Figura 4.1: Empaquetado en modelo OSI

de red, despues el TH (transport header) header de la capa de transporte,despues los header de sesion, presentacion y por ultimo vienen los datos quecontiene. Y si es ası como llega, entonces sera la forma que nosotros usaremospara ir leyendo y ordenando los datos, es importante tener en cuenta querecibiremos con recvfrom(), funcion que previamente vimos que nos permitealmacenar en un buffer, por lo que la informacion almacenada en ese buffer,sera rescatable a traves de un apuntador.

Ahora para decirle al apuntador de donde a donde llega la informacionde cierto header, lo que ocuparemos seran las estructuras antes vistas, de losdiferentes headers.

Haciendo una analogıa, tenemos un buffer de tamano X, la estructuraque describe el header de la capa de enlace supongamos que son Y bytes,obviamente si el paquete recibido es valido X tiene que ser mayor que Y,entonces diremos que los Y primeros bytes de X corresponden a la capa deenlace. Despues sabemos que en la capa de red el protocolo usado tiene unheader de P bytes, ¿donde terminarıa este header de la capa de red? , buenopues la respuesta es sencilla, si el header de red es de P bytes, primero quenada empezariıa en (Y + 1) bytes a partir del inicio del paquete, y por lo

Page 33: Raw Sockets Programming with C (spanish)

PARTE 4. SNIFFER 33

tanto tendrıa su fin en ( Y + P ) bytes. En este caso ¿como sabemos cuantovaldrıa X, Y, P y demas ?, pues con ayuda de la funcion sizeof() sobre lasestructuras que sabemos que se manejan en las diferentes capas del modeloOSI.

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 apuntamosa la primera posicion de todo el buffer, entonces si queremos movernos paracaptar el siguiente header o la informacion lo hacemos de la siguiente forma:

buffer + sizeof( struct ethhdr) +sizeof( struct iphdr) + sizeof(struct tcph-dr)

Tenemos que en este caso primero apuntamos al inicio del paquete despuesmovemos el apuntador n lugares dependiendo de la suma del header ethernet+ header ip + header tcp, por lo cual estaremos al inicio de la informacion queera nuestro objetivo, obviamente si leyeron bien, no podemos decir del todoque es la informacion como tal, ya que siguen diferentes headers y despuesahora si va la informacion.

Entonces sabiendo esto solo les recordare una cosa, nosotros cuando creamosun socket crudo podemos definirle que protocolo usaremos, si le ponemos IP-PROTO TCP, no nos llegara el header ethernet como en el primer ejemplopaso, pero tampoco nos llegara informacion UDP, ARP, ICMP, RARP ydemas, entonces recordemos lo que mencione antes, que el kernel se encargade subir la informacion a los sockets que esten escuchando cierto tipo de pro-tocolo, asi que si estamos escuchando solo trafico TCP pues no recibiremosmas que eso, pero no se preocupen si queremos estudiar todos los protocolosy todo el trafico solo pondremos ETH P ALL, y lo haremos XD , pero re-cuerden que si usamos esta constante recibiremos TODO !!!! el trafico, porlo que nuestro sniffer capturara mucha informacion,y difıcilmente podremosencontrar o ver lo que necesitamos, por lo que el uso de esta constante lodejo a su criterio. Aunque cabe mencionar que mas adelante en este tutorial,se hara uso de la constante para que les ensene la forma de recibir protocolosde capa 3 y 4.

Muy bien, creo que ha sido una buena introduccion, asi que vamos alcodigo.

/∗ 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 i686 GNU/ Linux

∗//∗ #1 SMP Wed Apr 15 18 :59 :16 UTC 2009 ∗/

Page 34: Raw Sockets Programming with C (spanish)

PARTE 4. SNIFFER 34

#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<sys / socket . h>#include<f e a t u r e s . h>#include<l i nux / i f p a c k e t . h>#include<errno . h>

/∗ L i b r e r ı a de l o s s o c k e t s ∗/#include<sys / 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<net / i f . h>

/∗ L i b r e r ı a de l o s paque tes e t h e r n e t ∗/#include<l i nux / i f e t h e r . h>

/∗ L i b r e r ı a de l o s paque tes ip ∗/#include<l i nux / ip . h>

/∗ L i b r e r ı a de l o s paque tes tcp ∗/#include<l i nux / tcp . h>

/∗ 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<n e t i n e t / in . h>

/∗ L i b r e r ı a para d e c o d i f i c a r unsigned char ∗/#include<ctype . h>

void header ( ) ;int obtenerData (unsigned char ∗ , int ) ;int obtenerHTCP (unsigned char ∗ , int ) ;void obtenerHIP (unsigned char ∗ , int ) ;void obtenerHEthernet (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 aw so c ke t ∗/int r sock ;int l en ;/∗ Numero de paque tes a r e c i b i r ∗/int paquetes ;/∗ Bandera para l a impresi on o no de datos ∗/int v a l i d a c i o n =0;int packet = 0 ;

/∗ Buf fer de l e c t u r a de l a informaci on r e c i b i d a ∗/

Page 35: Raw Sockets Programming with C (spanish)

PARTE 4. SNIFFER 35

unsigned char p b u f f e r [ 2 0 4 8 ] ;/∗ Estruc tura 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 izeof ( p i n f o ) ;i f ( argc !=3){

p r i n t f ( ”Uso %s < i n t e r f a z > <no paqutes> \n” , argv [ 0 ] ) ;e x i t (−1) ;

}/∗ Se crea un s o c k e t crudo para p r o t o c o l o IP ∗/r sock = creaSocket (ETH P IP) ;/∗ Se i n i c i a e l proceso ∗/header ( ) ;/∗ Se une e l s o c k e t a un i n t e r f a z de l a maquina ∗/s o c k e t i f ( argv [ 1 ] , rsock , ETH P IP) ;/∗ Decimos e l numero de paque tes a capturar ∗/paquetes = a t o i ( argv [ 2 ] ) ;/∗ Empezamos l a captura de n numero de paque tes ∗/while ( paquetes−−){

/∗ Recibimos paque tes a t r a v e s d e l s o c k e t crudo d e lp r o t o c o l o IP ∗/

/∗ Y l o s pasamos l o s datos a l b u f f e r , ademas de suinformaci on a l a e s t r u c t u r a p i n f o ∗/

i f ( ( l en = recvfrom ( rsock , p bu f f e r , 2048 , 0 , ( structsockaddr ∗)&p in fo , &p s i z e ) ) == −1){

per ro r ( ”Ha habido un e r r o r en l a captura ” ) ;e x i t (−1) ;

} else {p r i n t f ( ”−−−−−−−− Paquete Capturado No . %d −−−−−−−−−−−− \n”

, packet++) ;/∗ Una vez capturado obtendremos l a informacion ∗//∗ Obtenemos e l header e t h e r n e t capa 2 ∗/obtenerHEthernet ( p bu f f e r , l en ) ;/∗ Obtenemos e l header ip capa 3 ∗/

obtenerHIP ( p bu f f e r , l en ) ;/∗ Obtenemos e l header tcp capa 4 ∗/

v a l i d a c i o n = obtenerHTCP ( p bu f f e r , l en ) ;i f ( v a l i d a c i o n == 1)

obtenerData ( p bu f f e r , l en ) ;p r i n t f ( ”−−−−−−−− END Paquete Capturado No . %d −−−−−−−−− \n\n” , paquetes ) ;

}// f i n d e l e l s ebzero ( p bu f f e r , s izeof ( p b u f f e r ) ) ;

}// f i n d e l w h i l e

Page 36: Raw Sockets Programming with C (spanish)

PARTE 4. SNIFFER 36

return 0 ;}

int creaSocket ( int pro to co l ) {int r s o ck e t ;i f ( ( r s o ck e t = socket (PF PACKET, SOCK RAW, htons ( p ro to co l ) ) )==−1){

per ro r ( ” Error a l c r ea r e l socke t crudo ” ) ;e x i t (−1) ;

}return r s o ck e t ;

}

void header ( ) {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 rsock , int pro to co l ) {/∗ Ahora en vez de l i g a r e l s o c k e t con un puerto ∗//∗ La l i garemos 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 ;bzero(& s l l , s izeof ( s l l ) ) ;/∗ Limpiamos l a e s t r u c t u r a de datos de l a i n t e r f a z ∗/bzero(& i f r , s izeof ( i f r ) ) ;s t r cpy ( i f r . i f r name , i n t e r f a z ) ;/∗ Cargamos datos 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 ( rsock , SIOCGIFINDEX, &i f r ) ) == −1){p r i n t f ( ”No se puede obtener l a i n t e r f a z !\n” ) ;e x i t (−1) ;

}/∗ Impresi on de prop iedades 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 ( rsock , SIOCGIFFLAGS,& i f r ) ) < 0) {

per ro r ( ” Error : Al obtener banderas de l ai n t e r f a z ” ) ;

}

int f l a g s =0;f l a g s = i f r . i f r f l a g s ;

Page 37: Raw Sockets Programming with C (spanish)

PARTE 4. SNIFFER 37

/∗ 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 captura es %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 ( rsock ,SIOCGIFHWADDR,& i f r ) ) < 0) {

per ro r ( ” Error : Al obtener MAC address ” ) ;e x i t (−1) ;

}p r i n t f ( ”La MAC de l a i n t e r f a z es : ” ) ;impresionHex ( i f r . i f r hwaddr . sa data , 6 ) ;

/∗Obtenemos l a d i r e c c i o n IP ∗/i f ( ( i o c t l ( rsock ,SIOCGIFADDR,& i f r ) ) < 0) {

per ro r ( ” Error : Al obtener d i r e c c i o n IP ” ) ;e x i t (−1) ;

}p r i n t f ( ”La Di recc i o n IP de l a i n t e r f a z es : ” ) ;impresionFormatoIP(& i f r . i f r a d d r . sa data [ 2 ] , 4 ) ;

/∗Obtenemos l a mascara de red ∗/i f ( ( i o c t l ( rsock ,SIOCGIFNETMASK,& i f r ) ) < 0) {

per ro r ( ” Error : Al obtener l a mascara de red ” ) ;e x i t (−1) ;

}p r i n t f ( ”La Mascara de red de l a i n t e r f a z es : ” ) ;impresionFormatoIP(& i f r . i f r n e tmask . sa data [ 2 ] , 4 ) ;

/∗Obtenemos l a d i r e c c i o n de br oadc as t ∗/i f ( ( i o c t l ( rsock ,SIOCGIFBRDADDR,& i f r ) ) < 0) {

per ro r ( ” Error : Al obtener l a d i r e c c i o n debroadcast ” ) ;

e x i t (−1) ;}p r i n t f ( ”La d i r e c c i o n de broadcast de l a i n t e r f a z es : ”

Page 38: Raw Sockets Programming with C (spanish)

PARTE 4. SNIFFER 38

) ;impresionFormatoIP(& i f r . i f r b r o a d a d d r . sa data [ 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 ( rsock , SIOCGIFINDEX, &i f r ) ) == −1){

p r i n t f ( ”No se puede obtener 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 cua l se l i g a r a e l s o c k e t ∗/s l l . s l l i f i n d e x = i f r . i f r i f i n d e x ;/∗ Definimos e l p r o t o c o l o que se manejara ∗/s l l . s l l p r o t o c o l = htons ( p ro to co l ) ;/∗Ligamos e l s o c k e t a l a i n t e r f a z ∗/i f ( ( bind ( rsock , ( struct sockaddr ∗)&s l l , s izeof ( s l l ) ) )== −1){

per ro r ( ” Error a l un i r e l socke 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) ;

Page 39: Raw Sockets Programming with C (spanish)

PARTE 4. SNIFFER 39

i f (num!=0)p r i n t f ( ” . ” ) ;

p++;}p r i n t f ( ”\n” ) ;

}

void obtenerHEthernet (unsigned char ∗packet , int l en ) {/∗ Creamos una e s t r u c t u r a de t i p o e thhdr ∗//∗ para v a c i a r l o s datos y c a s t e a r l o s ∗/struct ethhdr ∗ h e the rne t ;/∗ Hacemos e l ordenamiento siempre y cuando tengamos

s u f i c i e n t e s b y t e s ∗/i f ( l en > s izeof ( struct ethhdr ) ) {

h e the rne t = ( struct ethhdr ∗) packet ;/∗ Ahora obtenemos l o s datos importantes que s e r ı a n ∗//∗ MAC ORIGEN,MAC DESTINO y PROTOCOLO DE RED∗/p r i n t f ( ” Protoco lo de red : ” ) ;impresionHex ( ( void ∗)&h ethernet−>h proto , 2) ;p r i n t f ( ”MAC Dest ino : ” ) ;impresionHex ( h ethernet−>h dest , 6) ;p r i n t f ( ”MAC Origen : ” ) ;impresionHex ( h ethernet−>h source , 6) ;

} elsep r i n t f ( ”HETHERNET : Paquete de tamano i n s u f i c i e n t e \n” ) ;

}

void obtenerHIP (unsigned char ∗packet , int l en ) {struct ethhdr ∗ h e the rne t ;struct iphdr ∗ h ip ;

h e the rne t = ( struct ethhdr ∗) packet ;/∗ Confirmamos que se t r a t a da un paquete IP ∗//∗ rev i sando e l campo h p r o t o de l a e s t r u c t u r a ∗//∗ e thhdr ∗/

i f ( ntohs ( h ethernet−>h proto ) == 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 en >= ( s izeof ( struct ethhdr ) + s izeof ( struct iphdr ) ) ) {

h ip = ( struct iphdr ∗) ( packet + s izeof ( struct ethhdr ) ) ;p r i n t f ( ”IP Dest ino : %s \n” , (char ∗) i n e t n t o a ( h ip−>daddr ) )

;

Page 40: Raw Sockets Programming with C (spanish)

PARTE 4. SNIFFER 40

p r i n t f ( ”IP Origen : %s \n” , (char ∗) i n e t n t o a ( h ip−>saddr ) );

} elsep r i n t f ( ”HIP : Paquete de tamano i n s u f i c i e n t e \n” ) ;

} elsep r i n t f ( ” Este no es un paquete IP \n ” ) ;

}

int obtenerHTCP (unsigned char ∗packet , int l en ) {struct ethhdr ∗ h e the rne t ;struct iphdr ∗ h ip ;struct tcphdr ∗h tcp ;

/∗Veri f icamos 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 sheaders ∗/

i f ( l en >= ( s izeof ( struct ethhdr ) + s izeof ( struct iphdr ) +s izeof ( struct tcphdr ) ) ) {

h e the rne t = ( struct ethhdr ∗) packet ;/∗Veri f icamos se t r a t e de un paquete IP ∗/i f ( ntohs ( h ethernet−>h proto ) == ETH P IP) {

h ip = ( struct iphdr ∗) ( packet + s izeof ( struct ethhdr ) ) ;/∗Veri f icamos se t r a t a d e l p r o t o c o l o TCP ∗/i f ( h ip−>pro to co l == IPPROTO TCP) {

/∗ Apuntamos a l a cabecera tcp ∗/h tcp = ( struct tcphdr ∗) ( packet + s izeof ( struct ethhdr )

+ h ip−>i h l ∗4 ) ;p r i n t f ( ” Source Port : %d\n” , ntohs ( h tcp−>source ) ) ;p r i n t f ( ”Dest Port : %d\n” , ntohs ( h tcp−>dest ) ) ;

return 1 ;} else

p r i n t f ( ”No es un paquete TCP\n” ) ;} else

p r i n t f ( ”No es un paquete IP\n” ) ;} else

p r i n t f ( ”HTCP : Paquete de tamano i n s u f i c i e n t e \n” ) ;return 0 ;

}

int obtenerData (unsigned char ∗packet , int l en ) {struct ethhdr ∗ h e the rne t ;struct iphdr ∗ h ip ;

Page 41: Raw Sockets Programming with C (spanish)

PARTE 4. SNIFFER 41

struct tcphdr ∗h tcp ;unsigned char ∗data ;int data l en ;

i f ( l en > ( s izeof ( struct ethhdr ) + s izeof ( struct iphdr ) +s izeof ( struct tcphdr ) ) ) {

/∗Apuntamos y casteamos a l header i p ∗/h ip = ( struct iphdr ∗) ( packet + s izeof ( struct ethhdr ) ) ;/∗ Apuntamos a l i n i c i o de l a par te de l o s datos ∗/data = ( packet + s izeof ( struct ethhdr ) + s izeof ( struct iphdr

) + s izeof ( struct tcphdr ) ) ;/∗La l o n g i t u d de datos es l a l o n g i t u d de todo e l paquete ip ,

menos e ltamano d e l header ip y header tcp ∗/

data l en = ntohs ( h ip−>t o t l e n ) − h ip−>i h l ∗4 − s izeof (struct tcphdr ) ;

i f ( da ta l en ) {p r i n t f ( ” Longitud de datos : %d\n” , da ta l en ) ;p r i n t f ( ”Datos : \n” ) ;impresionHex ( data , da ta l en ) ;p r i n t f ( ”\n” ) ;return 1 ;

} else {p r i n t f ( ”No hay datos en l o s paquetes \n” ) ;return 0 ;

}} else {

p r i n t f ( ”DATOS : Paquete de tamano i n s u f i c i e n t e \n” ) ;return 0 ;

}}

Como vermos tenemos funciones llamada obtener que nos permiten sacarla informacion de las diferentes capas, aunque todo esto se pudo haber hechoen una sola funcion creo que esta mas claro al separarlo en varias. Aho-ra bien, hemos identificado algunos protocolos, y desglosado algunos de suscampos, por lo que ahora, tendremos que aumentarle funcionalidad y modosde captura, que sera el tema de la siguiente parte.

Page 42: Raw Sockets Programming with C (spanish)

Parte 5

Implantar Funcionalidades

5.1. Modificaciones

Como mencione antes, ahora se le implementaran algunas funcionalidadesextras, para que quede mas clara la forma de trabajo de un sniffer un pocomas completo; en este caso, debemos recordar que la documentacion de cadaprotocolo se haya en un RFC, el cual tendremos que leer y entender si nece-sitamos un analisis de un cierto protocolo especıficamente. En las siguientessubsecciones solo pongo la modificacion del codigo que se hizo, no pongo to-do el sniffer, ya que como tal ocupa muchas hojas, pero cada modificacionla pueden hallar en un programa sniffer#.c, que incluyo a descarga en mipagina.

5.1.1. Anadimos UDP

Ahora ya tenemos sniffer2.c que nos permite recibir solo trafico TCP, porlo que haremos una modificacion para poder entender el protocolo UDP

i f ( h ip−>pro to co l == IPPROTO TCP) {p r i n t f ( ” Protoco lo TCP \n” ) ;h tcp = ( struct tcphdr ∗) ( packet + s izeof ( struct ethhdr ) +

h ip−>i h l ∗4 ) ;p r i n t f ( ” Source Port : %d\n” , ntohs ( h tcp−>source ) ) ;p r i n t f ( ”Dest Port : %d\n” , ntohs ( h tcp−>dest ) ) ;return 1 ;/∗ Se i n c l u y e n e s t a s l ı n e a s , para captura y d e s g l o s e de UDP

∗/

42

Page 43: Raw Sockets Programming with C (spanish)

PARTE 5. IMPLANTAR FUNCIONALIDADES 43

} else i f ( h ip−>pro to co l == IPPROTO UDP) {p r i n t f ( ” Protoco lo UDP \n” ) ;h udp = ( struct udphdr ∗) ( packet + s izeof ( struct ethhdr ) +

h ip−>i h l ∗4 ) ;p r i n t f ( ” Source Port : %d\n” , ntohs ( h udp−>source ) ) ;

p r i n t f ( ”Dest Port : %d\n” , ntohs ( h udp−>dest ) ) ;return 1 ;

}

5.1.2. Anadimos ICMP

Bien ya tenemos el trafico TCP-UDP, ahora en sniffer3.c haremos la mod-ificacion para captar ICMP y distinguir algunos tipos de mensajes, en estepunto conviene que veamos la siguiente imagen, para observar en que partede la trama se haya la informacion correspondiente al protocolo ICMP.

i f ( h ip−>pro to co l == IPPROTO TCP) {p r i n t f ( ” Protoco lo TCP \n” ) ;h tcp = ( struct tcphdr ∗) ( packet + s izeof ( struct ethhdr ) +

h ip−>i h l ∗4 ) ;p r i n t f ( ” Source Port : %d\n” , ntohs ( h tcp−>source ) ) ;p r i n t f ( ”Dest Port : %d\n” , ntohs ( h tcp−>dest ) ) ;return 1 ;

} else i f ( h ip−>pro to co l == IPPROTO UDP) {p r i n t f ( ” Protoco lo UDP \n” ) ;h udp = ( struct udphdr ∗) ( packet + s izeof ( struct ethhdr ) +

h ip−>i h l ∗4 ) ;p r i n t f ( ” Source Port : %d\n” , ntohs ( h udp−>source ) ) ;

p r i n t f ( ”Dest Port : %d\n” , ntohs ( h udp−>dest ) ) ;return 1 ;

} else i f ( h ip−>pro to co l == IPPROTO ICMP) {p r i n t f ( ” Protoco lo ICMP \n” ) ;icmp = ( struct icmphdr ∗) ( packet + h ip−>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 desde %s \n” , (char ∗) i n e t n t o a (h ip−>saddr ) ) ;

else i f ( icmp−>type == ICMP ECHO )p r i n t f ( ” ICMP echo desde %s \n” , (char ∗) i n e t n t o a ( h ip−>

daddr ) ) ;else i f ( icmp−>type == ICMP ECHOREPLY )

p r i n t f ( ” ICMP echorep ly desde %s \n” , (char ∗) i n e t n t o a (h ip−>daddr ) ) ;

else i f ( icmp−>type == ICMP DEST UNREACH )

Page 44: Raw Sockets Programming with C (spanish)

PARTE 5. IMPLANTAR FUNCIONALIDADES 44

Figura 5.1: Header ICMP

p r i n t f ( ” ICMP des t ino i n a l c a n z a b l e desde %s \n” , (char ∗)i n e t n t o a ( h ip−>saddr ) ) ;

} elsep r i n t f ( ”No es un paquete TCP\n” ) ;

5.1.3. Anadimos DHCP

Sigamos, demosle la funcionalidad de captar mensajes DHCP, basandonosen la estructura que maneja bind9 (DHCP server), para la mensajerıa deDHCP. Por lo que la pongo antes de todo el codigo fuente, aunque se queserıa mejor y convendrıa ponerla en un archivo .h, para liberar un poco elcodigo 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∗/

/∗ Obtenidos d e l programa bind9 ∗/

#define DHCP UDP OVERHEAD (20 + /∗ IP header ∗/\

8) /∗ UDP header ∗/#define DHCP SNAME LEN 64#define DHCP FILE LEN 128#define DHCP FIXED NON UDP 236#define DHCP FIXED LEN (DHCP FIXED NON UDP +

DHCP UDP OVERHEAD)/∗ Everyth ing

but o p t i o n s .∗/

#define BOOTP MIN LEN 300

#define DHCP MTU MAX 1500

Page 45: Raw Sockets Programming with C (spanish)

PARTE 5. IMPLANTAR FUNCIONALIDADES 45

#define DHCP MTU MIN 576

#define DHCP MAX OPTION LEN (DHCP MTU MAX − DHCP FIXED LEN)#define DHCP MIN OPTION LEN (DHCP MTU MIN − DHCP FIXED LEN)

struct dhcp packet {u i n t 8 t op ; /∗ 0 : Message opcode / type ∗/

u i n t 8 t htype ; /∗ 1 : Hardware addr type ( net /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 agent hops

from c l i e n t ∗/u i n t 3 2 t xid ; /∗ 4 : Transact ion ID ∗/u i n t 1 6 t s e c s ; /∗ 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 i n t 1 6 t f l a g s ; /∗ 10: Flag b i t s ∗/struct in addr c iaddr ; /∗ 12: C l i e n t IP address ( i f

a l r e a d y in use ) ∗/struct in addr yiaddr ; /∗ 16: C l i e n t IP address ∗/struct in addr s i addr ; /∗ 18: IP address o f next s e r v e r

to t a l k to ∗/struct in addr g iaddr ; /∗ 20: DHCP r e l a y agent IP

address ∗/unsigned char chaddr [ 1 6 ] ; /∗ 24: C l i e n t hardware

address ∗/char sname [DHCP SNAME LEN ] ; /∗ 40: Server name ∗/char f i l e [ DHCP FILE LEN ] ; /∗ 104: Boot f i l ename ∗/unsigned char opt ions [DHCP MAX OPTION LEN ] ;

/∗ 212: Opt iona l parameters( a c t u a l l e n g t h dependent on MTU) . ∗/

} ;

u i n t 3 2 t sequencedhcp = 0x0000 ;int dhcphase = 0 ;

/∗ Codigo f u e n t e de implementaci on de DHCP en nues tro s n i f f e r ∗/

else i f ( h ip−>pro to co l == IPPROTO UDP) {p r i n t f ( ” Protoco lo UDP \n” ) ;h udp = ( struct udphdr ∗) ( packet + s izeof ( struct ethhdr ) +

h ip−>i h l ∗4 ) ;p r i n t f ( ” Source Port : %d\n” , ntohs ( h udp−>source ) ) ;

p r i n t f ( ”Dest Port : %d\n” , ntohs ( h udp−>dest ) ) ;

Page 46: Raw Sockets Programming with C (spanish)

PARTE 5. IMPLANTAR FUNCIONALIDADES 46

i f ( ntohs ( h udp−>dest ) == 67 | | ntohs ( h udp−>source ) == 67 ) {p r i n t f ( ” Mensajes DHCP \n” ) ;dhcp = ( struct dhcp packet ∗) ( packet + s izeof ( struct

ethhdr ) + h ip−>i h l ∗4 + s izeof ( struct udphdr ) ) ;p r i n t f ( ”TRANSACTION ID %x \n” , dhcp−>xid ) ;

i f ( dhcp−>op == 1 && sequencedhcp == dhcp−>xid )p r i n t f ( ”DHCP REQUEST \n ” ) ;

else i f ( dhcp−>op == 1 ) {p r i n t f ( ”DHCP DISCOVER \n” ) ;sequencedhcp = dhcp−>xid ;p r i n t f ( ” Este es e l proceso %x \n” , dhcp−>xid ) ;

} else i f ( dhcp−>op == 2 && dhcphase !=0){p r i n t f ( ”DHCP ACK \n” ) ;sequencedhcp = 0x00000000 ;dhcphase = 0 ;

} else 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, estopara que pueda enviarme parametros, para la configuracion de la red. Pode-mos ver la existencia de un transaction ID, que es como un identificador deproceso, que nos permite saber a que ventana o proceso redirigir la salida dela peticion DHCP, ademas de permitir como tal tener la secuencia ligada aun 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 Direccion IP de la interfaz es : 192.168.1.70

La Mascara de red de la interfaz es : 255.255.255.0

La direccion de broadcast de la interfaz es : 192.168.1.255

---------------------------- Paquete Capturado No. 0 ------------

Page 47: Raw Sockets Programming with C (spanish)

PARTE 5. IMPLANTAR FUNCIONALIDADES 47

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 40 F4 A5 8C 5A

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 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 37 07 01 1C 02 03 0F 06 0C FF 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

-------- 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

Page 48: Raw Sockets Programming with C (spanish)

PARTE 5. IMPLANTAR FUNCIONALIDADES 48

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 C0 A8 01 FE 00 00 00 00 00 40 F4 A5 8C 5A

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 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 02 36 04 C0 A8 01 FE 33 04 00 01 51

80 3A 04 00 00 A8 C0 3B 04 00 01 27 50 06 04 C0 A8 01 FE 03 04 C0

A8 01 FE 01 04 FF FF FF 00 FF 00 00 00 00 00 00 00 00 00 00 00 00

00 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 :

Page 49: Raw Sockets Programming with C (spanish)

PARTE 5. IMPLANTAR FUNCIONALIDADES 49

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 F4 A5 8C 5A

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 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 03 36 04 C0 A8 01 FE 32 04 C0 A8 01

46 37 07 01 1C 02 03 0F 06 0C FF 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

-------- 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 FE 00 00 00 00 00 40 F4 A5 8C 5A

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 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Page 50: Raw Sockets Programming with C (spanish)

PARTE 5. IMPLANTAR FUNCIONALIDADES 50

Figura 5.2: Ejecucion del sniffer, Protocolo DHCP

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 05 36 04 C0 A8 01 FE 33 04 00 01 51

80 3A 04 00 00 A8 C0 3B 04 00 01 27 50 06 04 C0 A8 01 FE 03 04 C0

A8 01 FE 01 04 FF FF FF 00 0F 11 67 61 74 65 77 61 79 2E 32 77 69

72 65 2E 6E 65 74 FF

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

Page 51: Raw Sockets Programming with C (spanish)

PARTE 5. IMPLANTAR FUNCIONALIDADES 51

5.1.4. Anadimos ARP

Por ultimo, como hacer para poder implementar algo que no sea tanestandar o una modificacion nuestra, hay estructuras muy complejas querealmente podemos o no ocuparlas del todo como fue el caso de DHCP,que solo manejamos algunos campos para este ejemplo, pero que pasa sino queremos respetar las estructuras estandar, pues simple y sencillamenterecordamos que solo tenemos que apuntar al lugar correcto y ademas rescataru obtener los datos, con un tipo de dato igual con el cual fueron insertados,para no tener problemas de .agarrar”mas bytes o no .agarrar”todos los bytes.Por lo que se plantea ahora el caso de ARP, al que le hice una modificacionpara entender el trafico ARP, basandonos en el principio que les comento desolo saber de que posicion sacar la informacion y que cantidad de informacionsacar.

/∗ D e f i n i c i o n e s de ARP ∗/#define IPALEN 4 /∗ Length in b y t e s o f an IP address ∗/#define MAXHWALEN 5 /∗ Maximum l e n g t h o f a hardware address ∗/

enum arp hwtype {ARP NETROM=0x0000 , /∗ Fake f o r NET/ROM ( never a c t u a l l y

se n t ) ∗/ARP ETHER, /∗ Assigned to 10 megabit Ethernet ∗/ARP EETHER, /∗ Assigned to exper imenta l Ethernet ∗/ARP AX25, /∗ Assigned to AX.25 Leve l 2 ∗/ARP PRONET, /∗ Assigned to PROnet token r i n g ∗/ARP CHAOS, /∗ Assigned to Chaosnet ∗/ARP IEEE802 , /∗ Who uses t h i s ? ∗/ARP ARCNET,ARP APPLETALK

} ;

enum arp opcode {ARP REQUEST=0x0001 ,ARP REPLY,REVARP REQUEST,REVARP REPLY

} ;

struct arp {enum arp hwtype hardware ; /∗ Hardware type ∗/u i n t 1 6 t p ro to co l ; /∗ Protoco l type ∗/

Page 52: Raw Sockets Programming with C (spanish)

PARTE 5. IMPLANTAR FUNCIONALIDADES 52

u i n t 1 6 t hwalen ; /∗ Hardware address l en g th , b y t e s ∗/enum arp opcode 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 address f i e l d

∗/} ;

/∗ Fin de d e f i n i c i o n e s de ARP ∗/

/∗ Codigo f u e n t e de implementaci on de ARP en nues tro s n i f f e r ∗/

h e the rne t = ( struct ethhdr ∗) packet ;i f ( ntohs ( h ethernet−>h proto ) == ETH P IP) {

i f ( l en >= ( s izeof ( struct ethhdr ) + s izeof ( struct iphdr ) ) ) {h ip = ( struct iphdr ∗) ( packet + s izeof ( struct ethhdr ) ) ;p r i n t f ( ”IP Dest ino : %s \n” , (char ∗) i n e t n t o a ( h ip−>daddr ) )

;p r i n t f ( ”IP Origen : %s \n” , (char ∗) i n e t n t o a ( h ip−>saddr ) )

;} else

p r i n t f ( ”HIP : Paquete de tamano i n s u f i c i e n t e \n” ) ;} else i f ( ntohs ( h ethernet−>h proto ) == ETH P ARP) {

h arp = ( struct arp ∗) ( packet + s izeof ( struct ethhdr ) ) ;i f ( ntohs ( h arp−>hardware ) == 0x0001 )

p r i n t f ( ”\tARP ETHERNET \n” ) ;p r i n t f ( ”\ tSender MAC ADDRESS : ” ) ;

impresionHex ( h arp−>shwaddr−4 ,6) ;p r i n t f ( ”\ tTarget MAC ADDRESS : ” ) ;

impresionHex ( h arp−>shwaddr +6 ,6) ;p r i n t f ( ”\ tSender IP ADDRESS : ” ) ;

impresionFormatoIP ( h arp−>shwaddr +2 ,4) ;p r i n t f ( ”\ tTarget IP ADDRESS : ” ) ;

impresionFormatoIP ( h arp−>shwaddr +12 ,4) ;} else {

p r i n t f ( ” Este no es un paquete que se tenga conoc imiento \n ”) ;

p r i n t f ( ” Protoco lo %d ” , ntohs ( h ethernet−>h proto ) ) ;}

-------- 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

Page 53: Raw Sockets Programming with C (spanish)

PARTE 5. IMPLANTAR FUNCIONALIDADES 53

Figura 5.3: Ejecucion 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 ---------

Page 54: Raw Sockets Programming with C (spanish)

Parte 6

Conclusion e ideas finales

6.1. Problemas principales

En este caso es indispensable saber el buen uso de estructuras, arreglos yapuntadores, para entender perfectamente los programas, considero que enla compilacion y demas no existe ninguna problematica a mencionar.

6.2. Tutoriales futuros

Pues no se, por ahora no tengo idea de cual sera el siguiente aunquetengo temas interesante para realizar algun tutorial, podrıa ser de JNI paratrabajar C con Java, Sockets Seguros en Java o Sockets de C comunicandosecon Sockets de Java, o implementaciones de sistemas, o un pequeno tuto dencurses para crear un chat con todo lo aprendido. Pero en fin ya vere que seme ocurre, por el momento me retirare un poco hasta encontrar un buentema y arreglar cosas pendientes.

6.3. Ideas Finales

Se que hay varios sniffers y muy potentes, pero recordando, la idea princi-pal de este tutorial era el como poder programar y usar los sockets crudos. Aalguien que desee realizar un sniffer mas complejo, le recomiendo las librerıaspcap y/o libnet que tienen muchas funciones que nos permiten brincarnos la

54

Page 55: Raw Sockets Programming with C (spanish)

PARTE 6. CONCLUSION 55

parte tediosa que vimos en este manual, y pasamos rapidamente a la imple-mentacion de aplicaciones con sockets crudos.

Espero tambien disculpen mis faltas de ortografıa y mi redaccion, si enalgun momento consideran que esta mal. Cualquier aclaracion, duda o co-mentario me pueden contactar a este correo. (([email protected]))

Los codigos del tutorial estan en esta pagina: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 sobreel primer tutorial que hice y para mi marthita querida XD