linux下端口扫描程序(C)

来源:互联网 发布:ubuntu 服务管理 编辑:程序博客网 时间:2024/05/11 15:09

网络攻击第一步是扫描目标机的开放端口,其原理是(摘自http://www.pconline.com.cn/pcjob/nettech/safe/others/0502/557020_1.html):

根据TCP协议规范,当一台计算机收到一个TCP连接建立请求报文(TCP SYN)的时候,做这样的处理:

  1、 如果请求的TCP端口是开放的,则回应一个TCP ACK报文,并建立TCP连接控制结构(TCB);
  2、 如果请求的TCP端口没有开放,则回应一个TCP RST(TCP头部中的RST标志设为1)报文,告诉发起计算机,该端口没有开放。

  相应地,如果IP协议栈收到一个UDP报文,做如下处理:

  1、 如果该报文的目标端口开放,则把该UDP报文送上层协议(UDP)处理,不回应任何报文(上层协议根据处理结果而回应的报文例外);
  2、 如果该报文的目标端口没有开放,则向发起者回应一个ICMP不可达报文,告诉发起者计算机该UDP报文的端口不可达。

  利用这个原理,攻击者计算机便可以通过发送合适的报文,判断目标计算机哪些TCP或UDP端口是开放的,过程如下:

  1、 发出端口号从0开始依次递增的TCP SYN或UDP报文(端口号是一个16比特的数字,这样最大为65535,数量很有限);
  2、 如果收到了针对这个TCP报文的RST报文,或针对这个UDP报文的ICMP不可达报文,则说明这个端口没有开放;
  3、 相反,如果收到了针对这个TCP SYN报文的ACK报文,或者没有接收到任何针对该UDP报文的ICMP报文,则说明该TCP端口是开放的,UDP端口可能开放(因为有的实现中可能不回应ICMP不可达报文,即使该UDP端口没有开放)。

  这样继续下去,便可以很容易的判断出目标计算机开放了哪些TCP或UDP端口,然后针对端口的具体数字,进行下一步攻击,这就是所谓的端口扫描攻击。

   根据以上原理,我编写了以下代码(只进行了TCP扫描):

#include<stdlib.h>#include<stdio.h>#include<sys/socket.h>#include<netdb.h>#include<string.h>#include<unistd.h>#include<netinet/in.h>#include<arpa/inet.h>#include<fcntl.h>#include<time.h>#include<sys/types.h>#define TIMEOUT 5 //由于把socket设置为非阻塞,使用select函数,观察其                //5秒后的是否连接成功,连接不成功则认为其端口没有开放struct servenet{    char * s_name;char** s_aliases;int    s_port;char*  s_proto;};//参数是目标机的IPint main(int argc,char** argv){struct sockaddr_in server;int ret;int len;int scanport;    int start_port=0;    int end_port=1024;int sockfd;fd_set rset;fd_set wset;         struct servenet *sp;           for(scanport=start_port;scanport<end_port;scanport++)    {    if (-1==(sockfd=socket(AF_INET,SOCK_STREAM,0))){perror("can not create socket\n");exit(1);}memset(&server,0,sizeof(struct sockaddr_in));server.sin_family = AF_INET;server.sin_addr.s_addr = inet_addr(argv[1]);server.sin_port = htons(scanport);                 int flag = fcntl(sockfd, F_GETFL,0);fcntl(sockfd,F_SETFL, flag|O_NONBLOCK);struct timeval tm;tm.tv_sec = TIMEOUT;tm.tv_usec = 0;        //connect为非阻塞,连接不成功立即返回-1if (!connect(sockfd,(struct sockaddr*)&server,sizeof(struct sockaddr))){ sp=getservbyport(htons(scanport),"tcp");         printf("tcp port %d open:%s\n ",scanport,sp->s_name);                }//假如连接不成功,则运行select,直到超时else {FD_ZERO(&rset);FD_ZERO(&wset);FD_SET(sockfd, &rset);FD_SET(sockfd, &wset);int error; //错误代码int len = sizeof(error); //5秒后查看socket的状态变化 if (select(sockfd+1,&rset,&wset,NULL,&tm)>0){getsockopt(sockfd, SOL_SOCKET, SO_ERROR,&error, &len );if(error == 0)printf("Port %d is opened\n", scanport);}}close(sockfd);}return 0;}


原创粉丝点击