实现一个简单的sniffer

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
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
#include<stdio.h>
#include<pcap.h>
#include<unistd.h>
#include<stdlib.h>
//#include<pcap/bpf.h>
#include<netinet/ip.h>
#include<netinet/ip_icmp.h>
#include<netinet/tcp.h>
#include<netinet/udp.h>
#include<netinet/ether.h>
#include<arpa/inet.h>
#define ETHER_SIZE 14
 
///get_packet()回调函数
///header:收到的数据包的pcap_pkthdr类型的指针
///packet:收到的数据包数据
void get_packet(u_char*args, const struct pcap_pkthdr *header,const u_char *packet){
     
    static int count = 1;
    const char * payload;
    printf("==================================packet number: %d=============================\n",count++);
     
    ///ETHER_SIZE:以太帧首部长度14个字节
    ///IP包头(tcp包头(数据))
    ///IP包头(udp包头(数据))
    ///IP包头(icmp包头(数据))
    struct ip * ip = (struct ip *)(packet + ETHER_SIZE);
    printf("IP header length: %d\n",ip->ip_hl<<2);
    printf("From %s\n",inet_ntoa(ip->ip_src));
    printf("To %s\n",inet_ntoa(ip->ip_dst));
    int ip_hl = ip->ip_hl<<2;
 
    ///对报文类型进行了扩展
    ///可以分析IP包、ICMP包、TCP包、UDP包
    switch(ip->ip_p){
 
        case IPPROTO_TCP:
        {
            printf("----Protocol TCP----\n");
            struct tcphdr *tcp = (struct tcphdr *)(packet + 14 + ip_hl);           
            printf("tcp -> source:%d\n",ntohs(tcp -> source));
            printf("tcp -> dest:%d\n",ntohs(tcp -> dest));
            printf("tcp -> seq:%d\n",ntohs(tcp -> seq));
            printf("tcp -> ack_seq:%d\n",ntohs(tcp -> ack_seq));     
            printf("tcp -> headerLenth:%d\n",tcp -> doff << 2);
            printf("tcp -> fin:%d\n",tcp -> fin);
            printf("tcp -> syn:%d\n",tcp -> syn);
            printf("tcp -> rst:%d\n",tcp -> rst);
            printf("tcp -> psh:%d\n",tcp -> psh);
            printf("tcp -> ack:%d\n",tcp -> ack);
            printf("tcp -> urg:%d\n",tcp -> urg);
            printf("tcp -> window:%d\n",ntohs(tcp -> window));
            printf("tcp -> check:%d\n",ntohs(tcp -> check)); 
            //printf("tcp -> urg_ptr:%d\n",tcp -> urg_ptr);
             
            int h_size = tcp->doff<< 2;
            int payload_size = ntohs(ip->ip_len) - ip_hl - h_size;
             
            int i = payload_size;
            printf("payload is:%d\n",i);
             
            while(i > 0)
            {
                printf("%02x  ", packet[i]);
                if( i % 16 == 0 )
                    printf("\n");
                i--;
            }
            printf("\n");
            break;
        }
        case IPPROTO_UDP:
        {
            printf("----Protocol UDP----\n");
            struct udphdr *udp = (struct udphdr *)(packet + 14 + ip_hl);           
            printf("udp -> source:%d\n",ntohs(udp -> source));
            printf("udp -> dest:%d\n",ntohs(udp -> dest));
            printf("udp -> length:%d\n",ntohs(udp -> len));
            printf("udp -> check:%d\n",ntohs(udp -> check));
            int payload_size = ntohs(ip->ip_len) - ip_hl - 8;
            int i = payload_size;
            printf("payload is:%d\n",i);
             
            while(i > 0)
            {
                printf("%02x  ", packet[i]);
                if( i % 16 == 0 )
                    printf("\n");
                i--;
            }
            printf("\n");
            break;
        }
        case IPPROTO_ICMP:
        {
            printf("----Protocol ICMP----\n");
            struct icmphdr *icmp = (struct icmphdr *)(packet + 14 + ip_hl);
 
            if(icmp -> type == 8)
            {
                printf("--icmp_echo request--\n");
                printf("icmp -> type:%d\n",icmp -> type);
                printf("icmp -> code:%d\n",icmp -> code);
                printf("icmp -> checksum:%d\n",icmp -> checksum);
     
                printf("icmp -> id:%d\n",icmp -> un.echo.id);
                printf("icmp -> sequence:%d\n",icmp -> un.echo.sequence);
                int payload_size = ntohs(ip->ip_len) - ip_hl - 8;
                int i = payload_size;
                printf("payload is:%d\n",i);
             
                while(i > 0)
                {
                    printf("%02x  ", packet[i]);
                    if( i % 16 == 0 )
                        printf("\n");
                    i--;
                }
                printf("\n");
            }
            else if(icmp -> type == 0)
            {
                printf("--icmp_echo reply--\n");
                printf("icmp -> type:%d\n",icmp -> type);
                printf("icmp -> code:%d\n",icmp -> code);
                printf("icmp -> checksum:%d\n",icmp -> checksum);            
 
                printf("icmp -> id:%d\n",icmp -> un.echo.id);
                printf("icmp -> sequence:%d\n",icmp -> un.echo.sequence);
                int payload_size = ntohs(ip->ip_len) - ip_hl - 8;
                int i = payload_size;
                printf("payload is:%d\n",i);
             
                while(i > 0)
                {
                    printf("%02x  ", packet[i]);
                    if( i % 16 == 0 )
                        printf("\n");
                    i--;
                }
                printf("\n");
            }
            else
            {
                printf("icmp -> type:%d\n",icmp -> type);
                printf("icmp -> code:%d\n",icmp -> code);
                printf("icmp -> checksum:%d\n",icmp -> checksum);
                int payload_size = ntohs(ip->ip_len) - ip_hl - 8;
                int i = payload_size;
                printf("payload is:%d\n",i);
             
                while(i > 0)
                {
                    printf("%02x  ", packet[i]);
                    if( i % 16 == 0 )
                        printf("\n");
                    i--;
                }
                printf("\n");      
            }
            break;     
        }
        case IPPROTO_IP:
        {
            printf("----Protocol IP----\n");
            //printf("IP header length: %d\n",ip -> ip_hl<<2);
            printf("IP version: %d\n",ip -> ip_v);
            printf("IP type of service: %d\n",ip -> ip_tos);
            printf("IP total length: %d\n",ip -> ip_len);
            printf("IP identification: %d\n",ip -> ip_id);
            printf("IP fragment offset field: %d\n",ip -> ip_off);
            printf("IP time to live: %d\n",ip -> ip_ttl);
            printf("IP protocol: %d\n",ip -> ip_p);
            printf("IP checksum: %d\n",ip -> ip_sum);
            int payload_size = ntohs(ip->ip_len) - ip_hl;
            int i = payload_size;
            printf("payload is:%d\n",i);           
            while(i > 0)
            {
                printf("%02x  ", packet[i]);
                if( i % 16 == 0 )
                    printf("\n");
                i--;
            }
            printf("\n");
            break;         
        }          
        default:printf("Protocol unknown\n");
        return;
     
 
    }
}
         
 
 
int main(int argc,char*argv[]){
 
    char *dev, errbuf[PCAP_ERRBUF_SIZE];
    struct bpf_program fp;
    char filter_exp[] = "port 23";
    bpf_u_int32 mask;
    bpf_u_int32 net;
    struct pcap_pkthdr header;
    const u_char *packet;  
    int num_packets = 10;
     
    ///pcap_lookupdev()自动获取网络接口,返回一个网络接口的字符串指针
    ///如果出错,errbuf存放出错信息
    ///若想手动指定,则跳过此步,将要监听的网络字符串硬编码到pcap_open_live中
    dev = pcap_lookupdev(errbuf);
    if(dev==NULL){
        printf("ERROR:%s\n",errbuf);
        exit(2);
    }
    printf("The sniff interface is:%s\n",dev);
 
    ///pcap_lookupnet()获得设备的IP地址,子网掩码等信息
    ///net:网络接口的IP地址
    ///mask:网络接口的子网掩码
    if(pcap_lookupnet(dev,&net,&mask,errbuf)==-1){
        printf("ERROR:%s\n",errbuf);
        net = 0;
        mask = 0;
    }  
 
    ///pcap_open_live()打开网络接口
    ///BUFSIZ:抓包长度
    ///第三个参数:0代表非混杂模式,1代表混杂模式
    ///第四个参数:等待的毫秒数,超过这个值,获取数据包的函数会立即返回,0表示一直等待直到有数据包到来
    pcap_t * handle = pcap_open_live(dev,BUFSIZ,1,0,errbuf);
    if(handle == NULL){
        printf("ERROR:%s\n",errbuf);
        exit(2);
    }
/*这里我们测试发现不能过滤,注释掉这部分代码,程序可以正常运行了。
    ///pcap_compile()编译过滤表达式
    ///fp指向编译后的filter_exp
    ///filter_exp过滤表达式
    ///参数四:是否需要优化过滤表达式
    if(pcap_compile(handle,&fp,filter_exp,0,net)==-1){
        printf("Can't parse filter %s:%s\n",filter_exp,pcap_geterr(handle));
        return(2);
    }
     
    ///pcap_setfilter()应用这个过滤表达式
    ///完成过滤表达式后,我们可以使用pcap_loop()或pcap_next()登抓包函数抓包了
    if(pcap_setfilter(handle,&fp)==-1){
        printf("cant' install filter %s:%s\n",filter_exp,pcap_geterr(handle));
        return(2);
    }  
*/
    printf("Hello\n"); 
 
//  packet = pcap_next(handle,&header);
//  printf("Get a packet with length %d.\n",header.len);
 
    ///
    ///num_packets:需要抓的数据包的个数,一旦抓到了num_packets个数据包,pcap_loop立即返回。负数表示永远循环抓包,直到出错
    ///get_packet:回调函数指针
    //pcap_loop(handle,num_packets,get_packet,NULL);
    pcap_loop(handle,-1,get_packet,NULL);
     
    pcap_freecode(&fp);
     
    ///pcap_close()释放网络接口
    ///关闭pcap_open_live()获取的pcap_t的网络接口对象并释放相关资源
    pcap_close(handle);
    return(0);
}

  

posted @   ailx10  阅读(247)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示