歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> 用C實現截獲網絡數據包

用C實現截獲網絡數據包

日期:2017/3/1 9:51:30   编辑:Linux編程

1. 把網卡置於混雜模式。

2. 捕獲數據包。

3. 分析數據包。

注:下面的源代碼取至Chad Renfro的 < < Basic Packet-Sniffer Construction from the Ground Up> > 一文中
/************************Tcp_sniff_2.c********************/
1.#include  
2.#include  
3.#include
4.#include
5.#include
6.#include
7.#include  
8.#include
9.#include "headers.h "

#define INTERFACE "eth0 "

 /*Prototype area*/

10.int Open_Raw_Socket(void); 
11.int Set_Promisc(char *interface, int sock); 
12.int main() {  
13.int sock, bytes_recieved, fromlen;  
14.char buffer[65535];
15.struct sockaddr_in from; 
16.struct ip *ip;
17.struct tcp *tcp;  
18.sock = Open_Raw_Socket();
19. Set_Promisc(INTERFACE, sock);

20. while(1)
22. {
23. fromlen = sizeof from;
24. bytes_recieved = recvfrom(sock, buffer, sizeof buffer, 0, (struct sockaddr *)&from, &fromlen);
25. printf( "\nBytes received ::: %5d\n ",bytes_recieved);
26. printf( "Source address ::: %s\n ",inet_ntoa(from.sin_addr));
27. ip = (struct ip *)buffer;
/*See if this is a TCP packet*/
28. if(ip-> ip_protocol == 6) {
29. printf( "IP header length ::: %d\n ",ip-> ip_length);
30. printf( "Protocol ::: %d\n ",ip-> ip_protocol);
31. tcp = (struct tcp *)(buffer + (4*ip-> ip_length));
32. printf( "Source port ::: %d\n ",ntohs(tcp-> tcp_source_port));
33. printf( "Dest port ::: %d\n ",ntohs(tcp-> tcp_dest_port));
34. }

35. }
36.}
37.int Open_Raw_Socket() {    
38. int sock;
39. if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) {
/*Then the socket was not created properly and must die*/
40. perror( "The raw socket was not created ");
41. exit(0);
42. };  
43. return(sock);  
44. }

45.int Set_Promisc(char *interface, int sock ) {  
46. struct ifreq ifr;      
47. strncpy(ifr.ifr_name, interface,strnlen(interface)+1);
48. if((ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)) {  
/*Could not retrieve flags for the interface*/
49. perror( "Could not retrive flags for the interface ");
50. exit(0);
51. } 
52. printf( "The interface is ::: %s\n ", interface);  
53. perror( "Retrieved flags from interface successfully ");
54. ifr.ifr_flags |= IFF_PROMISC;  
55. if (ioctl (sock, SIOCSIFFLAGS, &ifr) == -1 ) {  
/*Could not set the flags on the interface */  
56. perror( "Could not set the PROMISC flag: ");
57. exit(0);    
58. }
59. printf( "Setting interface ::: %s ::: to promisc ", interface);
60. return(0);
61. }

/***********************EOF**********************************/

上面這段程序中有很詳細的注解,不過我想還是有必要說一說,首先第10行--int Open_Raw_Socket(void); 是我們的自定義函數,具體內容如下:

37.int Open_Raw_Socket() {    
38. int sock;
39. if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) {
/*Then the socket was not created properly and must die*/
40. perror( "The raw socket was not created ");
41. exit(0);
42. };  
43. return(sock);  
44. }

               

第39行 if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) {

這裡我們調用了socket函數,使創建了了一個原始套接口,使之收到TCP/IP信息包。

  接下來第11行-int Set_Promisc(char *interface, int sock),這也是我們的自定義函數,目的是把網卡置於混雜模式,具體內容如下:
45.int Set_Promisc(char *interface, int sock ) {  
46. struct ifreq ifr;      
47. strncpy(ifr.ifr_name, interface,strnlen(interface)+1);
48. if((ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)) {  
/*Could not retrieve flags for the interface*/
49. perror( "Could not retrive flags for the interface ");
50. exit(0);
51. } 
52. printf( "The interface is ::: %s\n ", interface);  
53. perror( "Retrieved flags from interface successfully ");
54. ifr.ifr_flags |= IFF_PROMISC;  
55. if (ioctl (sock, SIOCSIFFLAGS, &ifr) == -1 ) {  
/*Could not set the flags on the interface */  
56. perror( "Could not set the PROMISC flag: ");
57. exit(0);    
58. }
59. printf( "Setting interface ::: %s ::: to promisc ", interface);
60. return(0);
61. }

  首先 struct ifreq ifr; 定一了一個ifrreg的結構ifr,接下來 strncpy(ifr.ifr_name, interface,strnlen(interface)+1);,就是把我們網絡設備的名字填充到ifr結構中,在這裡 #define INTERFACE "eth0 " ,讓我們再往下看,ioctl(sock, SIOCGIFFLAGS, &ifr),SIOCGIFFLAGS請求表示需要獲取接口標志,現在到了第54行,在我們成功的獲取接口標志後把他設置成混雜模式,ifr.ifr_flags |= IFF_PROMISC;ioctl (sock, SIOCSIFFLAGS, &ifr)。OK,現在我們所說的第一步已經完成--------把網卡置於混雜模式。

更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2013-11/92548p2.htm

Copyright © Linux教程網 All Rights Reserved