📄 1110.html
字号:
<br>
1. 把网卡置于混杂模式。 2. 捕获数据包。 3. 分析数据包。 <br>
<br>
注:下面的源代码取至Chad Renfro的<< Basic Packet-Sniffer Construction from the Ground Up>> <br>
一文中 <br>
/************************Tcp_sniff_2.c********************/ <br>
1.#include <br>
2.#include <br>
3.#include <br>
4.#include <br>
5.#include <br>
6.#include <br>
7.#include <br>
8.#include <br>
9.#include "headers.h" <br>
<br>
#define INTERFACE "eth0" <br>
<br>
/*Prototype area*/ <br>
<br>
10.int Open_Raw_Socket(void); <br>
11.int Set_Promisc(char *interface, int sock); <br>
12.int main() { <br>
13.int sock, bytes_recieved, fromlen; <br>
14.char buffer[65535]; <br>
15.struct sockaddr_in from; <br>
16.struct ip *ip; <br>
17.struct tcp *tcp; <br>
18.sock = Open_Raw_Socket(); <br>
19. Set_Promisc(INTERFACE, sock); <br>
<br>
20. while(1) <br>
22. { <br>
23. fromlen = sizeof from; <br>
24. bytes_recieved = recvfrom(sock, buffer, sizeof buffer, 0, (struct sockaddr *)&from, &fromlen); <br>
25. printf("Bytes received ::: %5d",bytes_recieved); <br>
26. printf("Source address ::: %s",inet_ntoa(from.sin_addr)); <br>
27. ip = (struct ip *)buffer; <br>
/*See if this is a TCP packet*/ <br>
28. if(ip->ip_protocol == 6) { <br>
29. printf("IP header length ::: %d",ip->ip_length); <br>
30. printf("Protocol ::: %d",ip->ip_protocol); <br>
31. tcp = (struct tcp *)(buffer + (4*ip->ip_length)); <br>
32. printf("Source port ::: %d",ntohs(tcp->tcp_source_port)); <br>
33. printf("Dest port ::: %d",ntohs(tcp->tcp_dest_port)); <br>
34. } <br>
<br>
35. } <br>
36.} <br>
37.int Open_Raw_Socket() { <br>
38. int sock; <br>
39. if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) { <br>
/*Then the socket was not created properly and must die*/ <br>
40. perror("The raw socket was not created"); <br>
41. exit(0); <br>
42. }; <br>
43. return(sock); <br>
44. } <br>
<br>
45.int Set_Promisc(char *interface, int sock { <br>
46. struct ifreq ifr; <br>
47. strncpy(ifr.ifr_name, interface,strnlen(interface)+1); <br>
48. if((ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)) { <br>
/*Could not retrieve flags for the interface*/ <br>
49. perror("Could not retrive flags for the interface"); <br>
50. exit(0); <br>
51. } <br>
52. printf("The interface is ::: %s", interface); <br>
53. perror("Retrieved flags from interface successfully"); <br>
54. ifr.ifr_flags |= IFF_PROMISC; <br>
55. if (ioctl (sock, SIOCSIFFLAGS, &ifr) == -1 { <br>
/*Could not set the flags on the interface */ <br>
56. perror("Could not set the PROMISC flag:"); <br>
57. exit(0); <br>
58. } <br>
59. printf("Setting interface ::: %s ::: to promisc", interface); <br>
60. return(0); <br>
61. } <br>
<br>
/***********************EOF**********************************/ <br>
<br>
<br>
<br>
上面这段程序中有很详细的注解,不过我想还是有必要说一说,首先 <br>
第10行--int Open_Raw_Socket(void); 是我们的自定义函数,具体内容如下: <br>
<br>
<br>
37.int Open_Raw_Socket() { <br>
38. int sock; <br>
39. if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) { <br>
/*Then the socket was not created properly and must die*/ <br>
40. perror("The raw socket was not created"); <br>
41. exit(0); <br>
42. }; <br>
43. return(sock); <br>
44. } <br>
<br>
<br>
<br>
<br>
第39行 if((sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) { <br>
<br>
这里我们调用了socket函数,使创建了了一个原始套接口,使之收到TCP/IP信息包。 <br>
<br>
接下来第11行-int Set_Promisc(char *interface, int sock),这也是我们的自定义函数, <br>
目的是把网卡置于混杂模式,具体内容如下: <br>
45.int Set_Promisc(char *interface, int sock { <br>
46. struct ifreq ifr; <br>
47. strncpy(ifr.ifr_name, interface,strnlen(interface)+1); <br>
48. if((ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)) { <br>
/*Could not retrieve flags for the interface*/ <br>
49. perror("Could not retrive flags for the interface"); <br>
50. exit(0); <br>
51. } <br>
52. printf("The interface is ::: %s", interface); <br>
53. perror("Retrieved flags from interface successfully"); <br>
54. ifr.ifr_flags |= IFF_PROMISC; <br>
55. if (ioctl (sock, SIOCSIFFLAGS, &ifr) == -1 { <br>
/*Could not set the flags on the interface */ <br>
56. perror("Could not set the PROMISC flag:"); <br>
57. exit(0); <br>
58. } <br>
59. printf("Setting interface ::: %s ::: to promisc", interface); <br>
60. return(0); <br>
61. } <br>
<br>
首先 struct ifreq ifr; 定一了一个ifrreg的结构ifr,接下来 <br>
strncpy(ifr.ifr_name, interface,strnlen(interface)+1);,就是把我们网络设备的名字填 <br>
充到ifr结构中,在这里 #define INTERFACE "eth0" ,让我们再往下看, <br>
ioctl(sock, SIOCGIFFLAGS, &ifr),SIOCGIFFLAGS请求表示需要获取接口标志,现在到了 <br>
第54行,在我们成功的获取接口标志后把他设置成混杂模式, <br>
ifr.ifr_flags |= IFF_PROMISC;ioctl (sock, SIOCSIFFLAGS, &ifr)。OK,现在我们所说的 <br>
第一步已经完成--------把网卡置于混杂模式。 <br>
<br>
现在进入第二步,捕获数据包。从第20行开始,我们进入了一个死循环,while(1),在 <br>
第24行,recvfrom(sock, buffer, sizeof buffer, 0, (struct sockaddr *)&from, &fromlen), <br>
这个函数要做的就是接收数据,冰把接收到的数据放入buffer中。就是这么简单,已经完成了我 <br>
们要捕获数据包的任务。 <br>
<br>
到了第三步,分析数据包。27行,ip = (struct ip *)buffer,使我们在头文件中的IP结 <br>
构对应于所接收到的数据,接下来判断在网络层中是否使用的是TCP协议, <br>
if(ip->ip_protocol == 6) ,如果答案是,tcp信息包从整个IP/TCP包 buffer + (4*ip->ip_length) <br>
地址处开始,所以31行 tcp = (struct tcp *)(buffer + (4*ip->ip_length)),然后对应 <br>
结构把你所需要的信息输出。 <br>
/*************************headers.h**************************/ <br>
/*structure of an ip header*/ <br>
struct ip { <br>
unsigned int ip_length:4; /*little-endian*/ <br>
unsigned int ip_version:4; <br>
unsigned char ip_tos; <br>
unsigned short ip_total_length; <br>
unsigned short ip_id; <br>
unsigned short ip_flags; <br>
unsigned char ip_ttl; <br>
unsigned char ip_protocol; <br>
unsigned short ip_cksum; <br>
unsigned int ip_source; unsigned int ip_dest; <br>
}; <br>
<br>
/* Structure of a TCP header */ <br>
struct tcp { <br>
unsigned short tcp_source_port; <br>
unsigned short tcp_dest_port; <br>
unsigned int tcp_seqno; <br>
unsigned int tcp_ackno; <br>
unsigned int tcp_res1:4, /*little-endian*/ <br>
tcp_hlen:4, <br>
tcp_fin:1, <br>
tcp_syn:1, <br>
tcp_rst:1, <br>
tcp_psh:1, <br>
tcp_ack:1, <br>
tcp_urg:1, <br>
tcp_res2:2; <br>
unsigned short tcp_winsize; <br>
unsigned short tcp_cksum; <br>
unsigned short tcp_urgent; <br>
}; <br>
/*********************EOF***********************************/ <br>
<br>
<br>
<br>
从上面的分析我们可以清楚的认识到,认识一个SNIFF需要对TCP/IP协议有着详细的了解, <br>
否则你根本无法找到你需要的信息。有了上面的基础,你可以自己来做一个你需要的SNIFF了。 <br>
<br>
<br>
五 常用的SNIFF <br>
<br>
很少有原因会让你自己亲自动手来做一个自己的SNIFF,除非你是想了解他的原理,或者是 <br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -