Documente Academic
Documente Profesional
Documente Cultură
1
Índice general
1. Prefacio 5
1.1. A quien lo lea: . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2. Conocimientos básicos 7
2.1. Requerimientos del sistema . . . . . . . . . . . . . . . . . . . 7
2.2. Modelo OSI . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2.1. Capa 1: Fı́sica . . . . . . . . . . . . . . . . . . . . . . 8
2.2.2. Capa 2: Enlace . . . . . . . . . . . . . . . . . . . . . . 8
2.2.3. Capa 3: Red . . . . . . . . . . . . . . . . . . . . . . . 9
2.2.4. Capa 4: Transporte . . . . . . . . . . . . . . . . . . . 12
2.2.5. Capa 5: Sesión . . . . . . . . . . . . . . . . . . . . . . 14
2.2.6. Capa 6: Presentación . . . . . . . . . . . . . . . . . . 14
2.2.7. Capa 7: Aplicación . . . . . . . . . . . . . . . . . . . . 14
3. RAW SOCKET ?? 16
3.1. Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.2. Funciones importantes . . . . . . . . . . . . . . . . . . . . . . 17
3.2.1. socket . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.2.2. sendto . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.2.3. recvfrom . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.2.4. getsockopt && setsocketopt . . . . . . . . . . . . . . . 18
3.3. Algunas estrcuturas importantes . . . . . . . . . . . . . . . . 19
3.3.1. Estructura ifreq . . . . . . . . . . . . . . . . . . . . . . 19
3.4. Un ejemplo para empezar . . . . . . . . . . . . . . . . . . . . 21
4. Sniffer 28
4.1. SNIFFER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
4.1.1. PROMISC MODE ?? . . . . . . . . . . . . . . . . . . 28
2
ÍNDICE GENERAL 3
4.2. ksniffer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
4.2.1. Compilación y Ejecución . . . . . . . . . . . . . . . . 31
4.3. Sniffer mejorado. . . . . . . . . . . . . . . . . . . . . . . . . . 31
5. Implantar Funcionalidades 42
5.1. Modificaciones . . . . . . . . . . . . . . . . . . . . . . . . . . 42
5.1.1. Añadimos UDP . . . . . . . . . . . . . . . . . . . . . . 42
5.1.2. Añadimos ICMP . . . . . . . . . . . . . . . . . . . . . 43
5.1.3. Añadimos DHCP . . . . . . . . . . . . . . . . . . . . . 44
5.1.4. Añadimos ARP . . . . . . . . . . . . . . . . . . . . . . 51
6. Conclusión 54
6.1. Problemas principales . . . . . . . . . . . . . . . . . . . . . . 54
6.2. Tutoriales futuros . . . . . . . . . . . . . . . . . . . . . . . . 54
6.3. Ideas Finales . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
6.4. Agradecimientos . . . . . . . . . . . . . . . . . . . . . . . . . 55
Índice de figuras
4
Parte 1
Prefacio
5
PARTE 1. PREFACIO 6
Bueno espero el tutorial sea claro, conciso y les sirva para empezar a
entender un poco más acerca de la programación de sockets crudos, empeze-
mos.
Parte 2
Conocimientos básicos
1. GCC
7
PARTE 2. CONOCIMIENTOS BÁSICOS 8
ETHERNET
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 BÁSICOS 9
IP
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 <asm/ b y t e o r d e r . h>”
#e n d i f
u8 tos ;
u16 tot len ;
u16 id ;
PARTE 2. CONOCIMIENTOS BÁSICOS 10
ICMP
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 ;
};
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 BÁSICOS 13
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
/∗ s o c k o p t l e v e l f o r UDP ∗/
RAW SOCKET
3.1. Introducción
Cuando nosotros trabajamos con rawsocket, perdemos y ganamos difer-
entes caracterı́sticas, entre las más improtantes destacan:
1. Los sockets raw son un nivel abstracto sobre la trama de red, de he-
cho son más abstractos que los sockets que ya conocemos que son
SOCK STREAM y SOCK DGRAM, al ser estos últimos un caso es-
pecı́fico de los sockets crudos.
2. Al usar sockets crudos, tenemos una pérdida 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ón IP + un puerto, ahora desmentimos en parte
eso, ya que en los sockets crudos es el kernel el encargado de pasar
la información de un cierto protocolo a todos los sockets que estén
escuchando el mismo protocolo, no hay conexiones de red virtuales
como tal, es decir, no hay puertos.
4. Comunicaciones sin estándar, ya que uno lo debe de generar, al escribir
un servidor tendremos que escribir el cliente, ya que no es un estándar
y no cualquier programa entenderá 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ática-
mente.
16
PARTE 3. RAW SOCKET ?? 17
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>
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>
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>
Para el quinto parámetro se tiene una estrcutura de tipo sockaddr, que nos
permite tener acceso a la información de quien envio el paquete En el sexto
y ultimo parámetro se envia el tamaño de la estructura sockaddr
IPPROTO_IP - IP_OPTIONS
IPPROTO_IP - IP_HDRINCL
IPPROTO_TCP - TCP_MAXSEG
IPPROTO_TCP - TCP_NODELAY
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 ?? 20
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 ∗/
};
};
Figura 3.1: Ejecución captada por IPTraf del código bajado de internet y
como vemos no funciona
/∗ 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;
/∗ 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 á n l o s p a q u e t e s
∗/
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 ) ;
/∗−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−∗/
/∗ HEADER IP ∗/
iph−>i p h l = 5 ;
/∗ Se e s c o g e l a v e r s i ó 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
/∗−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−∗/
/∗ 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ú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úmero 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 ó n de una c o n e x i ó n ∗/
tcph−>t h f l a g s = TH SYN ;
/∗ Indicamos e l tamañ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 ó , por
PARTE 3. RAW SOCKET ?? 25
/∗ 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 ) ;
return 0 ;
}
Paquete enviado
Paquete enviado
Paquete enviado
Paquete enviado
Paquete enviado
root@koitoerdp:~/Tutorial raw-sockets#
4.1. SNIFFER
Primero que nada,¿qué es un sniffer?, bueno es un programa de captura
de tramas, que se usa con diversos fines, como pueden ser el análisis de
protocolos, la gestión de las redes, fines maliciosos XD, análisis de fallos,
detección de posibles ataques o intrusos, o como simple medidor de tráfico.
28
PARTE 4. SNIFFER 29
echarle un vistazo al código puede ser en este momento un tanto dı́ficil, pero
al final de este tutorial puede ser bastante didáctico, para ver y corroborar
lo aprendido.
4.2. ksniffer
Muy bien, es hora de programar un sniffer sencillo, que capture el tràfico
TCP que pasa por nuestra interfaz, entonces empecemos.
#include <s t d i o . h>
#include < f c n t l . h>
#include <s y s / s o c k e t . h>
#include <r e s o l v . h>
#include <netdb . h>
#include <n e t i n e t / i n . h>
#include <n e t i n e t / t c p . h>
#include <n e t i n e t / i p . h>
int main ( ) {
/∗ Creamos e l s o c k e t crudo , e l c u a l s ó l o va a
c a p t u r a r e l t r á f i c o de p a q u e t e s TCP, como l o
i n d i c a l a o p c i ó n IPPROTO TCP ∗/
int f d = s o c k e t ( PF INET , SOCK RAW, IPPROTO TCP) ;
/∗ Será 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 á 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ón , e s t o l o
hacemos s e ñ 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 ó n , l o c u a l
e x p l i c a r é un poco más 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” ) ;
}
Paquete capturado
Contenido :
Hexadecimal
450028ffffffb616400ffffff806ffffffc0ffffffddffffffc0
ffffffa8145ffffffc0ffffffa81468ffffffb3016ffffffc3d6
e2affffff831dffffffbbffffffa65010fffffffa4fffffffb8f
fffffe300
Entendible
[CARACTERES OMITIDOS]
Siguiente --------------------------------------
/∗ 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 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<s y s / s o c k e t . h>
#include<f e a t u r e s . h>
#include<l i n u x / i f p a c k e t . h>
#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<n e t / i f . h>
/∗ 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 n u x / i f e t h e r . h>
/∗ L i b r e rı́ a de l o s p a q u e t e s i p ∗/
#include<l i n u x / i p . h>
/∗ 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 n u x / t c p . 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 / i n . h>
/∗ 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<c t y p e . h>
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 ) ;
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 á 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 <i n t e r f a z > <n o p a q u t e 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áquina ∗/
s o c k e t i f ( argv [ 1 ] , r s o c k , ETH P IP ) ;
/∗ Decimos e l nú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ú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 é 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ás de su
i n f o r m a c i ó 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 f l a g s =0;
flags = ifr . ifr flags ;
PARTE 4. SNIFFER 37
/∗ Checamos s i l a i n t e r f a z e s t á 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 r r i b a \n ” ) ;
e x i t ( −1) ;
}
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 ó n IP ” ) ;
e x i t ( −1) ;
}
p r i n t f ( ”La D i r e c c i ó 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á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áscara de r e d ” ) ;
e x i t ( −1) ;
}
p r i n t f ( ”La Má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 ó 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 ó n de
broadcast ” ) ;
e x i t ( −1) ;
}
p r i n t f ( ”La d i r e c c i ó n de b r o a d c a s t de l a i n t e r f a z e s : ”
PARTE 4. SNIFFER 38
);
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 á 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á ∗/
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 ;
}
i f (num!=0)
printf (” . ”) ;
p++;
}
p r i n t f ( ” \n” ) ;
}
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
struct t c p h d r ∗ h t c p ;
unsigned char ∗ data ;
int d a t a l e n ;
Como vermos tenemos funciones llamada obtener que nos permiten sacar
la información de las diferentes capas, aunque todo esto se pudo haber hecho
en una sola función creo que está más claro al separarlo en varias. Aho-
ra 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á el tema de la siguiente parte.
Parte 5
Implantar Funcionalidades
5.1. Modificaciones
Como mencioné antes, ahora se le implementarán algunas funcionalidades
extras, para que quede más clara la forma de trabajo de un sniffer un poco
más completo; en este caso, debemos recordar que la documentación de cada
protocolo se haya en un RFC, el cual tendrémos que leer y entender si nece-
sitamos un análisis de un cierto protocolo especı́ficamente. En las siguientes
subsecciones sólo pongo la modificación del código que se hizo, no pongo to-
do el sniffer, ya que como tal ocupa muchas hojas, pero cada modificación
la pueden hallar en un programa sniffer#.c, que incluyo a descarga en mi
página.
42
PARTE 5. IMPLANTAR FUNCIONALIDADES 43
#define DHCP MAX OPTION LEN (DHCP MTU MAX − DHCP FIXED LEN)
#define DHCP MIN OPTION LEN (DHCP MTU MIN − DHCP FIXED LEN)
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ódigo f u e n t e de i m p l e m e n t a c i ó n de DHCP en n u e s t r o s n i f f e r ∗/
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 ;
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
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
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
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 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
/∗ 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 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ódigo f u e n t e de i m p l e m e n t a c i ó 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 ) ) ;
}
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 ---------
Parte 6
54
PARTE 6. CONCLUSIÓN 55
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