• C/C++ Select端口扫描 [转载]




    #define _CRT_SECURE_NO_DEPRECATE
    #define _CRT_NONSTDC_NO_DEPRECATE
    #define _WINSOCK_DEPRECATED_NO_WARNINGS
    #define _AFXDLL
    
    #include <afxext.h>
    #include <winsock.h>
    
    // 编译时需使用的库
    #pragma comment(lib,"wsock32.lib")
    
    // select()成员定义
    #define ZERO (fd_set *)0
    
    // 变量定义
    int maxth, scanok, scannum;
    int portip, hoststart, hoststop, startport, endport;
    //定义了开始I和结束P地址,开始和结束端口
    long searchnum, searched;
    void usage(char*);
    // 定义显示使用方法函数
    void playx(int);
    // 定义状态提示函数
    void setip2(char*);
    // 定义设置IP函数
    void customport(char*, char*, char*);
    // 定义自定义扫描端口函数
    void portscannow(int);
    // 定义端口扫描扫描
    
    // 主程序
    int main(int argc, char* argv[])
    {
        WSADATA wsadata;
        // 清屏
        system("cls.exe");
    
        // 检查输入
        if ((argc < 3) || (argc > 4))
        {
            // 显示帮助提示
            usage(argv[0]);
            return-1;
        }
    
        // 检测是否为port扫描
        if (!(stricmp(strlwr(argv[1]), "-p") == 0))
        {
            usage(argv[0]);
            return-1;
        }
    
        // 程序初始化
        //如果初始化错误
        if (WSAStartup(MAKEWORD(1, 1), &wsadata) != 0)
        {
            printf("
    Wsatartup error");
            //出错信息
            return-1;
        }
    
        // 端口扫描参数转换
        // 如果参数为三个
        if (argc == 3)
        {
            // 直接设置IP
            setip2(argv[2]);
        }
        // 如果参数为四个
        else
            if (argc == 4)
            {
                // 进入定制端口扫描处理
                customport(argv[0], argv[2], argv[3]);
            }
        // 参数过多显示帮助
            else
            {
                usage(argv[0]);
                return-1;
            }
    
        // 扫描端口开始
        portscannow(argc);
    
        WSACleanup();
        return 0;
    }
    
    // 帮助提示函数
    void usage(char* prog)
    {
        printf("Usage: %s <Option>", prog);
        printf("
    
     <Option>:");
        printf("
     -p [ Port|StartPort-EndPort ] < HostName|IP|StartIP-EndIP >");
        printf("
    
     Example: ");
        printf("
     %s -p 192.168.0.1", prog);
        printf("
     %s -p 192.168.0.1-192.168.0.254", prog);
        printf("
     %s -p 21-80 192.168.0.1", prog);
        printf("
     %s -p 21-80 192.168.0.1-192.168.0.254
    ", prog);
        return;
    }
    
    // 进度提示
    void playx(int play = 0)
    {
        // 进度条
        const char* plays[12] =
        {
            " | ",
            " / ",
            " - ",
            " // ",
            " | ",
            " / ",
            " - ",
            " // ",
            " | ",
            " / ",
            " - ",
            " // ",
        }
        ;
    
        if (searchnum != 0)
        {
            for (int i = 0; i <= 3; i++)
            {
                printf(" =%s= %d%s Completed.  
    ", plays[i], searched * 100 / (searchnum + 1), "%");
                Sleep(5);
            }
        }
        else
        {
            printf(" =%s=
    ", plays[play]);
            //显示进度
            Sleep(10);
        }
    }
    
    // 设置IP
    void setip2(char* cp)
    {
        int host;
        struct hostent* testhost;
        const char* startip = "", * endip = "";
    
        // 判断是否为 192.168.0.1-192.168.0.254 形式的输入
        if (strstr(cp, "-") && strlen(cp) > 15 && strlen(cp) < 32)
        {
            // 提取出结束IP
            endip = strchr(cp, '-') + 1;
            // 提取出开始IP
            strncpy((char *)startip, cp, strlen(cp) - strlen(strchr(cp, '-')));
    
            // 给控制要扫描IP段的变量赋值
            hoststart = ntohl(inet_addr(startip));
            hoststop = ntohl(inet_addr(endip));
        }
        else
        {
            // 取得输入的主机地址
            testhost = gethostbyname(startip);
    
            // 如果地址不存在
            if (!testhost)
            {
                WSACleanup();
                printf("
    Can't get ip of: %s", cp);
                exit(-1);
            }
            // 给控制要扫描IP段的变量赋值
            memcpy(&host, testhost->h_addr, 4);
            hoststop = hoststart = ntohl(host);
        }
    }
    
    // 测试线程是否已满
    void TestThread(int thread = 200)
    {
        for (;;)
        {
            playx();
    
            // 测试线程是否已满
            if (maxth > thread)
                Sleep(100);
            else break;
        }
        return;
    }
    
    // 等待线程结束函数
    void WaitThreadEnd()
    {
        // 延时
        Sleep(6000);
    
        // 显示等待提示
        printf("
         
    ");
        printf(" Wait ( %d )Thread end...
    ", maxth);
    
        for (;;)
        {
            // 判断所有线程是否已经结束
            if (maxth > 0)
            {
                // 延时等待线程序结束
                Sleep(100);
                playx();
                continue;
            }
            else break;
        }
        printf("
    ");
        return;
    }
    
    // 定制端口扫描参数定义
    void customport(char* cp, char* cp2, char* cp3)
    {
        int intport;
        char* checker;
    
        // 处理要扫描的端口
        // 扫描开始端口变量赋值
        startport = atoi(cp2);
        // 扫描结束端口变量赋值
        endport = atoi(cp2);
    
        // 判断是否 21-80 形式
        if (strstr(cp2, "-"))
        {
            intport = atoi(checker = strchr(cp2, '-') + 1);
            if (intport > 0 && intport < 65536)
                // 扫描结束端口变量赋值
                endport = intport;
        }
    
        // 端口大小判断
        if (startport < 0 || startport>65536 || endport < 0 || endport>65535)
        {
            usage(cp);
            exit(-1);
        }
        // 处理ip地址
        setip2(cp3);
    }
    
    // 端口扫描函数
    UINT portscan(LPVOID port)
    {
        int addr = portip;
        // 取得要扫描的地址
        int sock;
        struct fd_set mask;
        struct timeval timeout;
        struct sockaddr_in server;
        unsigned long flag = 1;
    
        // 创建一个sock
        sock = socket(AF_INET, SOCK_STREAM, 0);
    
        // 创建sock失败处理
        if (sock == INVALID_SOCKET)
        {
            printf("
    Sock Error:%s", WSAGetLastError());
            maxth--;
            return-1;
        }
    
        // 给sock成员赋值
        server.sin_family = AF_INET;
        server.sin_addr.s_addr = htonl(addr);
        // 要扫描的地址
        server.sin_port = htons(short(port));
        // 要扫描的端口
    
        // 显示进度
        playx();
    
        // 调用ioctlsocket()设置套接字为非阻塞模式
        if (ioctlsocket(sock, FIONBIO, &flag) != 0)
        {
            // 设置失败处理
            printf("
    Sock Error:%s", WSAGetLastError());
            closesocket(sock);
            maxth--;
            return-1;
        }
    
        // 调用connect()连接远程主机端口
        connect(sock, (struct sockaddr*)&server, sizeof(server));
    
        timeout.tv_sec = 18;
        // 超时限制为18秒
        timeout.tv_usec = 0;
        FD_ZERO(&mask);
        // 清空集合mask
        FD_SET(sock, &mask);
        // 将sock放入集合mask中
    
        // 用select() 处理扫描结果
        switch (select(sock + 1, ZERO, &mask, ZERO, &timeout))
        {
        case-1:
        {
            printf("
    Select() error");
            maxth--;
            return-1;
        }
    
        // sock超时处理
        case 0:
        {
            maxth--;
            closesocket(sock);
            return-1;
        }
    
        default:
            if (FD_ISSET(sock, &mask))
            {
                // 禁止sock发送和接受数据
                shutdown(sock, 0);
    
                // 设置输出结果格式
                printf(" [Found:] %s Port: %d open.
    ", inet_ntoa(server.sin_addr), ntohs(server.sin_port));
    
                // 关闭sock
                closesocket(sock);
                scanok++;
                maxth--;
                return 1;
            }
        }
        return 0;
    }
    
    // 扫描开始主函数
    void portscannow(int xp)
    {
        int sport;
        char* timenow, timebuf[32];
    
        // 定义默认扫描的端口
        const char* ports[32] = {"80","443","445"};
    
        // 显示扫描开始的时间
        timenow = _strtime(timebuf);
        printf("
    PortScan Start Time: %s
    
    ", timenow);
    
        // 计数器初始化.
        int i = 0;
        maxth = 0;
        scanok = 0;
        scannum = 0;
        searched = 0;
    
        // 计算要扫描的端口数量
        searchnum = hoststop - hoststart + 1;
        if (xp == 3)
            searchnum = searchnum * 32;
        if (xp == 4)
            searchnum = searchnum * (endport - startport + 1);
    
        // 端口扫描开始
        for (portip = hoststart; portip <= hoststop; portip++, scannum++)
        {
            // *.*.*.0和*.*.*.255 地址处理
            if ((portip % 256) == 0 || (portip % 256) == 255)
            {
                if (xp == 3)
                    searchnum = searchnum - 32;
                if (xp == 4)
                    searchnum = searchnum - (endport - startport + 1);
                scannum--;
                playx();
                continue;
            }
    
            if (i > 11)i = 0;
            // 默认端口扫描
            // scan 192.168.0.1
            // scan 192.168.0.1-192.168.0.254
            if (xp == 3)
            {
                for (sport = 0; sport < 32; sport++, maxth++, searched++)
                {
                    // 测试当前线程是否大于180
                    TestThread(180);
                    // 产生新的线程处理端口扫描
                    CWinThread* pthread = AfxBeginThread(portscan, LPVOID(atoi((char*)ports[sport])));
                    //延时
                    Sleep(120);
                }
            }
    
            // 自定义端口扫描
            // scan -p 21 192.168.0.1
            // scan -p 21-80 192.168.0.1-192.168.0.254
            if (xp == 4)
            {
                // 计算要扫描的端口
                sport = endport - startport;
                if (sport > 500)
                {
                    // 扫描自定义的端口
                    for (sport = startport; sport <= endport; sport++, maxth++, searched++)
                    {
                        TestThread(2000);
                        // 产生新的线程处理端口扫描
                        CWinThread* pthread = AfxBeginThread(portscan, LPVOID(sport));
                        // 延时
                        Sleep(10);
                    }
                }
                else
                {
                    // 扫描自定义的端口
                    for (sport = startport; sport <= endport; sport++, maxth++, searched++)
                    {
                        // 测试当前线程是否大于250
                        TestThread(250);
                        // 产生新的线程处理端口扫描
                        CWinThread* pthread = AfxBeginThread(portscan, LPVOID(sport));
                        // 延时
                        Sleep(100);
                        playx();
                    }
                }
            }
        }
    
        // 等待所有的线程结束
        WaitThreadEnd();
    
        // 显示端口扫描结束时间
        timenow = _strtime(timebuf);
        printf("
    PortScan End Time: %s", timenow);
        printf("
    Scan %d Hosts completed. Open %d Ports!
    ", scannum, scanok);
    }
    

    版权声明: 本博客,文章与代码均为学习时整理的笔记,博客中除去明确标注有参考文献的文章,其他文章【均为原创】作品,转载请务必【添加出处】,您添加出处是我创作的动力!

    警告:如果您恶意转载本人文章,则您的整站文章,将会变为我的原创作品,请相互尊重!
  • 相关阅读:
    苹果所有常用证书,appID,Provisioning Profiles配置说明及制作图文教程(精)
    使用tcpdump抓取HTTP包
    android保持在休眠时,后台程序继续运行(让程序获取设备电源锁)
    insert数据时,获取插入数据的id
    Android学习笔记(五五):通知Notification(下)
    apk反编译与android项目代码混淆
    android 解决横竖屏切换时重新载入的问题
    android中往字符串数组动态添加元素
    error 25015安装程序集“C:WindowsMicrosoft .NETFrameworkv2.0.50727xxx.dll”失败,原因是出现了系统错误:另一个程序正在使用此文件,进程无法访问
    win7 安装vs2013后无法连接远程数据库,出现如下提示的解决方法
  • 原文地址:https://www.cnblogs.com/LyShark/p/15087272.html
Copyright © 2020-2023  润新知