077b12f1039dceb830c2b83be8dcbd1b

An example of sniffer that use raw socket. Comments are in italian.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
/*
 * Sniffer base
 * by Gnix <gnixmail@gmail.com>
 * http://gnix.netsons.org
 */


#include <stdio.h>            // Standard I/O
#include <stdlib.h>           // Standard Library
#include <string.h>           // String functions
#include <unistd.h>           // Standard Unix
#include <errno.h>            // Gestione errori
#include <net/if.h>           // Contiene la struttura ifreq e la costante simbolica IF_NAMESIZE
#include <sys/ioctl.h>        // ioctl
#include <sys/socket.h>       // Socket functions
#include <linux/if_packet.h>  // Contiene la struttura sockaddr_ll
#include <linux/if_ether.h>   // Contiene la costante simbolica ETH_P_IP
#include <linux/ip.h>         // Contiene la struttura iphdr
#include <linux/tcp.h>        // Contiene la struttura tcphdr
#include <linux/udp.h>        // Contiene la struttura udphdr
#include <netinet/in.h>       // Contiene la costante simbolica IPPROTO_TCP
#define STAT(x) ((x)) ? 1 : 0
#define BUFFER_SIZE 2048



// Crea un raw socket
int raw_socket(int protocol)
{
        int rawsock;

        if((rawsock = socket(PF_PACKET, SOCK_RAW, htons(protocol)))== -1)       {
                perror("Error creating raw socket: ");
                exit(-1);
        }

        return rawsock;
}



// Collega il raw socket a una data interfaccia. L'interfaccia e' gestita
// come un semplice numero dal Kernel. Questo numero viene ricavato con la
// chiamata a ioctl.
int raw_bind(char *device, int rawsock, int protocol)
{
        struct sockaddr_ll sll;
        struct ifreq ifr;

        bzero(&sll, sizeof(sll));
        bzero(&ifr, sizeof(ifr));

        // Ricava l'interface index
        strncpy((char *)ifr.ifr_name, device, IFNAMSIZ);
        if((ioctl(rawsock, SIOCGIFINDEX, &ifr)) == -1) {
                printf("Error getting Interface index !\n");
                exit(-1);
        }

        // Popola struttura sll e fai bind
        sll.sll_family = AF_PACKET;
        sll.sll_ifindex = ifr.ifr_ifindex;
        sll.sll_protocol = htons(protocol);

        if((bind(rawsock, (struct sockaddr *)&sll, sizeof(sll)))== -1) {
                perror("Error binding raw socket to interface\n");
                exit(-1);
        }

        return 0;
}



// Stampa in esadecimale
void printHex(char *mesg, unsigned char *p, int len)
{
        printf("%s", mesg);

        while(len--) {
                printf("%.2X ", *p);
                p++;
        }

        printf("\n");
}



// Stampa il pachetto
void printPacket(unsigned char *packet, int len)
{
        // Variabili
        struct ethhdr *ethernet_header;
        struct iphdr  *ip_header;
        struct tcphdr *tcp_header;
        struct udphdr *udp_header;
        unsigned char *data;
        int data_len = 0;


        // Stampa messaggio iniziale
        printf("\n\n################[ Packet Starts ]################");

        // Controlla che la dimensione del pacchetto sia maggiore degli header ethernet e ip sommati.
        if(len >= (sizeof(struct ethhdr) + sizeof(struct iphdr))) {

                // Casting in ethhdr
                ethernet_header = (struct ethhdr*)packet;

                // Stampa header ethernet
                printf("\n----- Ethernet Header -----\n");
                printHex("ETH: Dest MAC   : ", ethernet_header->h_dest, 6);
                printHex("ETH: Source MAC : ", ethernet_header->h_source, 6);
                printHex("ETH: Protocol   : ", (void*)&ethernet_header->h_proto, 2);

                // Controlla che il protocollo sia IP
                if(ntohs(ethernet_header->h_proto) == ETH_P_IP) {

                        // Casting in iphdr
                        ip_header = (struct iphdr*)(packet + sizeof(struct ethhdr));

                        printf("\n----- IP Header -----\n");
                        printf("IP: Header length    : %d bytes\n", ip_header->ihl*4);
                        printf("IP: Version          : %d  \n", ip_header->version);
                        printf("IP: Type of Service  : %d  \n", ip_header->tos);
                        printf("IP: Total length     : %d \n", ntohs(ip_header->tot_len));
                        printf("IP: Identification   : %d \n", ntohs(ip_header->id));
                        printf("IP: Flags            : %.2x\n", (unsigned char)((ip_header->frag_off)>>12));
                        printf("IP: Fragment offset  : %d  \n", ntohs(ip_header->frag_off) & 0x0FFF);
                        printf("IP: Time to live     : %d  \n", ip_header->ttl);
                        printf("IP: Protocol         : %d  \n", ip_header->protocol);
                        printf("IP: Header checksum  : %d  \n", ntohs(ip_header->check));
                        printf("IP: Source IP Address: %s  \n", inet_ntoa(ip_header->saddr));
                        printf("IP: Dest IP Address  : %s  \n", inet_ntoa(ip_header->daddr));

                        // Controlla che il protocollo sia tcp e che la dimensione del pacchetto sia almeno la somma di header eth,ip e tcp
                        if((ip_header->protocol == IPPROTO_TCP) && (len >= (sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct tcphdr)))) {

                                // Casting in tcphdr
                                tcp_header = (struct tcphdr*)(packet + sizeof(struct ethhdr) + ip_header->ihl*4);

                                printf("\n----- TCP Header -----\n");
                                printf("TCP: Source port          : %d\n", ntohs(tcp_header->source));
                                printf("TCP: Dest port            : %d\n", ntohs(tcp_header->dest));
                                printf("TCP: Sequence number      : %u\n", ntohl(tcp_header->seq));
                                printf("TCP: Acknowledgment number: %u\n", ntohl(tcp_header->ack_seq));
                                printf("TCP: Reserved             : %d\n", tcp_header->res1);
                                printf("TCP: Data offset          : %d\n", tcp_header->doff*4);
                                printf("TCP: Flags\n");
                                printf("TCP:      FIN             : %d\n", STAT(tcp_header->fin));
                                printf("TCP:      SYN             : %d\n", STAT(tcp_header->syn));
                                printf("TCP:      RST             : %d\n", STAT(tcp_header->rst));
                                printf("TCP:      PSH             : %d\n", STAT(tcp_header->psh));
                                printf("TCP:      ACK             : %d\n", STAT(tcp_header->ack));
                                printf("TCP:      URG             : %d\n", STAT(tcp_header->urg));
                                printf("TCP:      ECE             : %d\n", STAT(tcp_header->ece));
                                printf("TCP:      CWR             : %d\n", STAT(tcp_header->cwr));
                                printf("TCP: Window               : %d\n", ntohs(tcp_header->window));
                                printf("TCP: Checksum             : %d\n", ntohs(tcp_header->check));

                                // Ricava posizione dei dati e stampa
                                data = (packet + sizeof(struct ethhdr) + ip_header->ihl*4 + sizeof(struct tcphdr));
                                data_len = ntohs(ip_header->tot_len) - ip_header->ihl*4 - sizeof(struct tcphdr);
                                printHex("DATA: ", data, data_len);
                        }
                        // Controlla che il protocollo sia udp e che la dimensione del pacchetto sia almeno la somma di header eth, ip e udp
                        else if((ip_header->protocol == IPPROTO_UDP) && (len >= (sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr)))) {

                                // Casting in udphdr
                                udp_header = (struct udphdr*)(packet + sizeof(struct ethhdr) + ip_header->ihl*4);

                                printf("\n----- UDP Header -----\n");
                                printf("UDP: Source port: %d\n", htons(udp_header->source));
                                printf("UDP: Dest port  : %d\n", htons(udp_header->dest));
                                printf("UDP: Length     : %d\n", htons(udp_header->len));
                                printf("UDP: Checksum   : %d\n", htons(udp_header->check));

                                // Ricava posizione dei dati e stampa
                                data = (packet + sizeof(struct ethhdr) + ip_header->ihl*4 + sizeof(struct udphdr));
                                data_len = ntohs(ip_header->tot_len) - ip_header->ihl*4 - sizeof(struct udphdr);
                                printHex("DATA: ", data, data_len);
                        }
                        else {
                                printf("Not a TCP or UDP packet.\n");

                        }
                }
        }
        else {
                printf("Packet size too small!\n");
        }

        // Stampa messaggio finale
        printf("################[ Packet Ends ]################\n\n");

}



// Programma principale
int main(int argc, char **argv)
{
        // Variabili
        int raw;                           // raw socket descriptor
        unsigned char buffer[BUFFER_SIZE]; // buffer per i dati
        int len;                           // lunghezza buffer di dati ricevuto
        int n_packets;                     // numero pacchetti da sniffare
        struct sockaddr_ll info;           // struttura utilizzata in recvfrom
        int info_size = sizeof(info);      // dimensione struttura sockaddr_ll


        // crea raw socket
        raw = raw_socket(ETH_P_IP);

        // Bind socket all'interface
        raw_bind(argv[1], raw, ETH_P_IP);

        // Numero pacchetti da sniffare
        n_packets = atoi(argv[2]);

        // Inizia sniffing
        while(n_packets--) {
                if((len = recvfrom(raw, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&info, &info_size)) == -1) {
                        perror("Recv from returned -1: ");
                        exit(-1);
                }
                else {
                        // Pacchetto ricevuto.
                        printPacket(buffer, len);
                }
        }

        return 0;
}

Refactorings

No refactoring yet !

Your refactoring





Format Copy from initial code

or Cancel