作者:kf_701 寫(xiě)作時(shí)間:2005/4 Email:kf_701@21cn.com 原作者信息,謝謝,
hacker成長(zhǎng)的代碼之路:嗅探(1)Unix系統(tǒng)
。 要求的專(zhuān)業(yè)知識(shí): 一: 精通OSI參考模型,精通 網(wǎng)絡(luò) 五層:物理層,數(shù)據(jù)鏈路層,網(wǎng)絡(luò)層,傳 輸層,應(yīng)用層。精通每一層的協(xié)議,數(shù)據(jù)報(bào)格式。精通網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu), 第一層,第作者:kf_701 寫(xiě)作時(shí)間:2005/4 Email:kf_701@21cn.com原作者信息,謝謝。
要求的專(zhuān)業(yè)知識(shí):
一: 精通OSI參考模型,精通網(wǎng)絡(luò)五層:物理層,數(shù)據(jù)鏈路層,網(wǎng)絡(luò)層,傳
輸層,應(yīng)用層。精通每一層的協(xié)議,數(shù)據(jù)報(bào)格式。精通網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu),
第一層,第二層,第三層的網(wǎng)絡(luò)互聯(lián),數(shù)據(jù)的轉(zhuǎn)發(fā)和路由等。
二: 精通C語(yǔ)言程序設(shè)計(jì),UNIX/LINUX程序設(shè)計(jì),網(wǎng)絡(luò)程序設(shè)計(jì)。熟悉
UNIX/LINUX系統(tǒng)操作,熟悉著名服務(wù)的基本配置,特性及使用的端口
號(hào)。熟悉經(jīng)典網(wǎng)絡(luò)命令的使用,如:netstat,ping,traceroute,
netcat,arp等。
三: 精通標(biāo)準(zhǔn)SQL語(yǔ)言,熟悉流行的數(shù)據(jù)庫(kù)使用,如:Oracle,Mysql等。
掌握數(shù)據(jù)庫(kù)與WEB語(yǔ)言的結(jié)合使用。
sniffer,我想大家都聽(tīng)說(shuō)過(guò),不過(guò)是截獲數(shù)據(jù)報(bào)而已了。這樣的事情多是發(fā)生在局域
網(wǎng)內(nèi)。因此我們要完全明白內(nèi)網(wǎng)的工作原理。
由于寫(xiě)這個(gè)文章的時(shí)候,用的多的是以太網(wǎng),因此我們的實(shí)驗(yàn)也在以太網(wǎng)環(huán)境里完成。
首先要知道是的局域網(wǎng)的互聯(lián)方式,目前使用的有第一層(物理層)的互聯(lián),主要使用
轉(zhuǎn)發(fā)器,常用的轉(zhuǎn)發(fā)器就是集線器了,也就是我們常稱(chēng)的HUB,用HUB互聯(lián)的網(wǎng)絡(luò)是一個(gè)總
線結(jié)構(gòu)的網(wǎng)絡(luò),在總線結(jié)構(gòu)的網(wǎng)絡(luò)里,數(shù)據(jù)是廣播形式的傳送的。也就是兩臺(tái)主機(jī)間的通
信信息,其它的主機(jī)也可以收到,不過(guò)網(wǎng)絡(luò)設(shè)備檢查到目標(biāo)物理地址并非是自己,便丟掉
這個(gè)數(shù)據(jù)包。但必境是收到了。
我們用程序把這些數(shù)據(jù)報(bào)全部復(fù)制一份保存下來(lái),就是所謂的sniffer了。還要做的一
件事就是把網(wǎng)卡設(shè)為混雜模式(Linux里面可用命令#ifconfig ethx promisc),我們
將在程序里自己完成。
物理層互聯(lián)的局域網(wǎng)稱(chēng)為共享式局域網(wǎng)。
但現(xiàn)在不少的局域網(wǎng)是在第二層(數(shù)據(jù)鏈路層)互聯(lián)的,使用的網(wǎng)絡(luò)設(shè)備多是網(wǎng)橋,最
出名的網(wǎng)橋叫交換機(jī),想必你也聽(tīng)說(shuō)過(guò)了。這樣聯(lián)成的局域網(wǎng)叫交換式局域網(wǎng)。在這樣的
網(wǎng)內(nèi),數(shù)據(jù)不再是廣播了。
那我們?nèi)绾尾拍躶niffer呢?也就是如何讓別人的數(shù)據(jù)還能發(fā)到我們的機(jī)器上的網(wǎng)絡(luò)設(shè)
備上來(lái)呢?問(wèn)題出來(lái)了,答案是ARP欺騙。留作后續(xù)。
進(jìn)入我們的主題,如何寫(xiě)程序把數(shù)據(jù)報(bào)從數(shù)據(jù)鏈路層copy過(guò)來(lái)。
Unix里常用的方法是:BSD的BPF(分組過(guò)濾器),SVR的DLPI(數(shù)據(jù)鏈路提供者接口),
Linux的SOCK_PACKET接口。
如果你沒(méi)有聽(tīng)說(shuō)過(guò)開(kāi)放源代碼,那么你可能沒(méi)有必要再讀下去了。我可不想去重復(fù)已經(jīng)
完成的工作。
libpcap,一個(gè)公開(kāi)可得源碼的截獲函數(shù)庫(kù),它在三種接口上都可以使用。因此我們將
使用這個(gè)函數(shù)庫(kù)來(lái)完成我們的程序。
53行,打開(kāi)一個(gè)網(wǎng)絡(luò)設(shè)備用來(lái)嗅探。
59-64行,加入一條過(guò)濾規(guī)則,這里是只截UDP數(shù)據(jù)報(bào)。
74行,返回一個(gè)數(shù)據(jù)報(bào)。
我們用data_print函數(shù)分析打印出IP報(bào)頭的源IP和目的IP,UDP報(bào)頭中的源端口和目
標(biāo)端口。
1 /* author : kf_701
2 * mtime : 2005
3 * email : kf_701@21cn.com
4 * address : 合肥大學(xué)生公寓
5 * school : ahau.edu
6 */
7
8 /* The program is used to capture data from data
9 * link layer,It is simply,only output ip address
10 * and port,read this code,then you will understand
11 * how to use libpcap functions.
12 * ****Best wishes to you !****
13 *
14 * if you want to use it ,please compile like:
15 * $gcc -lpcap thisfile.c
16 */
17 #include
18 #include
19 #include
20 #include
21 #include
22
23 #include
24 #include
25 #include
26 #include
27 #include
28 #include
29 #include
30 #include
31
32 #define MAXLINE 255
33
34 static void data_print(char *,int);
35
36 int main(int argc,char **argv)
37 {
38 char *device;
39 pcap_t *pd;
40 int snlen=80,link_type;
41 uint32_t netip,netmask;
42 char errbuf[PCAP_ERRBUF_SIZE],cmd[MAXLINE];
43 int data_len; /* captured data length */
44 char *data_ptr; /* captured data ptr */
45 struct bpf_program fcode;
46 struct pcap_pkthdr pkthdr;
47 struct ether_header *eptr;
48
49 /* open device and init struct pcap */
50 if((device=pcap_lookupdev(errbuf)) == NULL)
51 printf("pcap_lookupdev: %s\n",errbuf),exit(1);
52
53 if((pd=pcap_open_live(device,snlen,1,500,errbuf)) == NULL)
54 printf("pcap_open_live: %s\n",errbuf),exit(1);
55
56 if(pcap_lookupnet(device,&netip,&netmask,errbuf)<0)
57 printf("pcap_lookupnet: %s\n",errbuf),exit(1);
58
59 strcpy(cmd,"udp");/* only capture UDP packet */
60 if(pcap_compile(pd,&fcode,cmd,0,netmask)<0)
61 printf("pcap_compile: %s\n",pcap_geterr(pd)),exit(1);
62
63 if(pcap_setfilter(pd,&fcode)<0)
64 pcap_perror(pd,"pcap_setfilter"),exit(1);
65
66 if((link_type=pcap_datalink(pd)) < 0)
67 pcap_perror(pd,"pcap_datalink"),exit(1);
68
69 printf("-----------------------------------\n\
70 kf_701 sniffer,listen on %s for udp packets...\n",
71 device);
72
73 while(1){ /* catpture data and print */
74 data_ptr=(char *)pcap_next(pd,&pkthdr);
75 if(data_ptr == NULL)
76 continue;
77 data_len = pkthdr.caplen;
78
79 switch(link_type){
80 case DLT_NULL: /* loopback header = 4 bytes */
81 data_print(data_ptr+4,data_len-4);
82 break;
83 case DLT_EN10MB: /* ether header = 14 bytes */
84 eptr = (struct ether_header *)data_ptr;
85 if(ntohs(eptr->ether_type) != ETHERTYPE_IP)
86 break;
87 data_print(data_ptr+14,data_len-14);
88 break;
89 case DLT_PPP: /* ppp header = 24 bytes */
90 data_print(data_ptr+24,data_len-24);
91 break;
92 default:
93 ;
94 }
95 }/* end while */
96 }
97
98 static void
99 data_print(char *ptr,int len)
100 {
101 int ip_hlen;
102 struct ip *ip;
103 struct udphdr *udp;
104 char *src,*dst;
105
106 printf("Captured a packet!----------------------------\n");
107
108 /* deal with part of ip head */
109 if(len < sizeof(struct ip)+sizeof(struct udphdr)){
110 printf("* error,data_len = %d\n",len);
111 return;
112 }
113 ip = (struct ip *)ptr;
114 if(ip->ip_v != 4){
115 printf("* error,not ipv4,dropped.\n");
116 return;
117 }
118 ip_hlen = ip->ip_hl << 2;
119 if(ip_hlen < sizeof(struct ip)){
120 printf("* error:ip_hl = %d\n",ip->ip_hl);
121 return;
122 }
123 src = malloc(sizeof(char)*20);
124 dst = malloc(sizeof(char)*20);
125 strncpy(src,inet_ntoa((struct in_addr)ip->ip_src),20);
126 strncpy(dst,inet_ntoa((struct in_addr)ip->ip_dst),20);
127 printf("* ip_src = %s,ip_dst = %s\n",src,dst);
128
129 /* deal with udp part of udp head */
130 if(len 131 printf("* error:data_len = %d,ip_hlen = %d\n",len,ip_hlen); 132 return; 133 } 134 udp = (struct udphdr *)(ptr+ip_hlen); 135 printf("* source(port) = %d,dest(port) = %d,length(ip+udp+data) = %d\n",\ 136 ntohs(udp->source),ntohs(udp->dest),ntohs(udp->len)+ip_hlen); 137 138 return; 139 } 關(guān)于libpcap函數(shù)庫(kù)的詳細(xì)使用,請(qǐng)自行查閱文章或手冊(cè),電腦資料
《hacker成長(zhǎng)的代碼之路:嗅探(1)Unix系統(tǒng)》(http://clearvueentertainment.com)。
有問(wèn)題請(qǐng)給我mail,謝謝。
*****待續(xù)*******
原文轉(zhuǎn)自:http://www.ltesting.net