【问题标题】:Unix TCP port scannerUnix TCP 端口扫描器
【发布时间】:2023-03-16 00:19:01
【问题描述】:

我有一个 TCP 端口扫描器,它扫描给定 IP 上所有打开的端口,并只返回打开的端口和在其上运行的服务的名称。为此,我创建了一个套接字,将其设置为非阻塞模式,如果端口超时,则在端口上 select() 表示端口已关闭,否则为打开。问题是我的 select() 总是超时,即使我尝试扫描打开的端口。我希望有人指出我的错误,我的逻辑不好吗?

#include <stdlib.h>
#include <iostream>
#include <cstdio>
#include <string.h>
#include <netdb.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/time.h>
#include <errno.h>

using namespace std;
fd_set    working_set;
hostent *he;
char* protoc [2] = { "tcp","udpn" };
int port;
struct sockaddr_in servaddr;
int sendfd;
servent *srvport;
void set_nonblock(int socket) {
    int flags;
    flags = fcntl(socket,F_GETFL,0);
    assert(flags != -1);
    fcntl(socket, F_SETFL, flags | O_NONBLOCK);
}
void set_block(int socket) {
    int flags;
    flags = fcntl(socket,F_GETFL,0);
    assert(flags != -1);
    fcntl(socket, F_SETFL, flags | ~O_NONBLOCK);
}

int main( int argc, char* argv[] )
{

    struct timeval  timeout;
    timeout.tv_sec  = 1;
    timeout.tv_usec = 0;
    char* host = argv[1];
    char* pro = argv[2];
    int portlow  = atoi(argv[3]);
    int porthigh = atoi(argv[4]);

    fprintf(stderr, "n Scanning host=%s, protocol=%s, ports: %d -> %d   \n",
            host, pro, portlow, porthigh);

    if(strcmp(pro, protoc[0])==0)
        pro = protoc[0];
    else if (strcmp(pro, protoc[1])==0)
        pro = protoc[1];
    else
    {
        herror("n specify valid protocol - tcp or udpn");
        exit(-1);
    }


    if((he = gethostbyname(argv[1])) == NULL)
    {
        herror("n *** gethostbyname() failed ***n");
        exit(-1);
    }
    /*In case TCP protocol is selected for scan, app opens streaming socket

for every port to be scanned, tries to connect to it, and if successful

it displays information about service using struct servent.
*/

    if(strcmp(pro, protoc[0])==0) // tcp scan
    {
        for(port = portlow; port <= porthigh; port++)
        {
            // open stream socket
            if((sendfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
            {
                perror("*** socket(,SOCK_STREAM,) failed ***n");
                exit(-1);
            }
            set_nonblock(sendfd);
            bzero(&servaddr, sizeof(servaddr));

            servaddr.sin_family = AF_INET;
            servaddr.sin_port = htons(port);
            servaddr.sin_addr = *((struct in_addr *)he->h_addr);
            int res = connect(sendfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
int ser;
            if (res < 0) {
                 if (errno == EINPROGRESS) {
                    timeout.tv_sec = 0;
                    timeout.tv_usec = 10;
                    FD_SET(sendfd, &working_set);

                    if ((ser=select(sendfd+1, NULL, &working_set, NULL, &timeout)) > 0) {
                          srvport = getservbyport(htons(port), protoc[0]);

                    }
                    else {
                       fprintf(stderr, "Timeout or error() %d\n",ser);
                       perror("select(): ");

                    }
                 }
                 else {
                    fprintf(stderr, "Error connecting %d - %s\n", errno, strerror(errno));
                 }
                 if(srvport != NULL)
                     printf("tport %d: %sn   \n ", port, srvport->s_name);
                 else if (ser=0)
                   close(sendfd);
                 fflush(stdout);
              }

            //set_block(sendfd);
        }//end of for()
    }
}

【问题讨论】:

    标签: c unix tcp port-scanning


    【解决方案1】:

    这是相当多的代码。我没有运行它。但是,这个:

    if (ser=(select(sendfd, NULL, &working_set, NULL, &timeout)) > 0) {
    

    错了。 select() 的第一个参数是“三个集合中任何一个中编号最高的文件描述符,加 1”(参见 man page)。

    另外,你应该像这样加括号:

    if ((ser = select(...)) > 0) {
    

    因为现在您将&gt; 运算符的结果分配给ser 变量,这可能不是您所期望的。

    【讨论】:

    • 我修复了这个错误,但现在我得到了所有端口的列表,我关闭套接字的方式是否也不好?我还更新了帖子中的代码。
    【解决方案2】:

    在使用 I/O 描述符集 working_set 之前,您需要确保清除它:

    FD_ZERO(&working_set);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-24
      • 1970-01-01
      • 1970-01-01
      • 2022-01-19
      • 1970-01-01
      • 1970-01-01
      • 2020-05-21
      相关资源
      最近更新 更多