检测端口是否打开有几种方式,比如

TCP connect扫描:(优点:不需要权限、可以同时扫描多个端口。缺点:容易被察觉)。

SYN扫描:(半开放扫描,利用TCP三次握手,发送SYN标志,端口开放,则会返回正常的SYN+ACK标志的TCP报文,否则反馈RST标志报文)。

ACK扫描(构造含有ACK标志的TCP报文到主机,不能确定端口关闭或者开放,因为主机收到ACK报文,不管端口是否开放,都会返回RST标志报文,但是可以用来检测防火墙配置,看防火墙是否过滤了这个端口)。

FIN扫描等(构造含有FIN标志的TCP报文到主机,返回RST标志报文,则端口关闭,无反应,则表示端口打开)。

以下用connect方式检测,速度快。

  1 // MultiThreadScan.cpp : 定义控制台应用程序的入口点。
  2 //
  3 
  4 #include "stdafx.h"
  5 #include <WinSock2.h>
  6 #include <windows.h>
  7 #include <filesystem>
  8 
  9 #pragma comment(lib,"ws2_32.lib");//system32/ws2_32.dll
 10 
 11 #define OK 0
 12 #define ERR -1
 13 
 14 #define SCAN_IP "192.168.1.109"
 15 #define SCAN_START_PORT 80
 16 #define SCAN_END_PORT 91
 17 #define THREAD_MAX 10
 18 
 19 #define  IPADDR_LEN 16
 20 
 21 unsigned short g_ausThreadState[THREAD_MAX] = { 0 };
 22 
 23 typedef struct tagScanInfo
 24 {
 25     char szIpAddr[IPADDR_LEN];
 26     unsigned short usPort;
 27     unsigned short usThreadIdx;
 28 }SCAN_INFO_S;
 29 
 30 #define TEST_PTR 0//不建议用指针,因为传入参数可能会因为线程启动问题导致错误
 31 //线程函数,共同使用变量导致的冲突
 32 DWORD WINAPI ScanPort(LPVOID lpParam)
 33 {
 34     SOCKET iFd;
 35     SOCKADDR_IN stTarget = { 0 };
 36     int iConnRet;
 37     SCAN_INFO_S stScan = { 0 };
 38     SCAN_INFO_S *pstScan;
 39 
 40     if (TEST_PTR)
 41     {
 42         pstScan = (SCAN_INFO_S *)lpParam;//这也是一种强制转换方法,结果和下面mencpy()结果一样,
 43 
 44         printf("\n[Thread:%d] Scan:%s:%u", pstScan->usThreadIdx, pstScan->szIpAddr, pstScan->usPort);
 45 
 46         stTarget.sin_family = AF_INET;
 47         stTarget.sin_addr.s_addr = inet_addr(pstScan->szIpAddr);
 48         stTarget.sin_port = htons(pstScan->usPort);//h:host to n:net s:short
 49 
 50         //TCP连接申请套接字,发送时候,向socket里面写数据,接收时取数据
 51         iFd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 52         if (iFd < 0)
 53         {
 54             return OK;
 55         }
 56 
 57         //发起连接,通过ifd进行通许
 58         iConnRet = connect(iFd, (SOCKADDR*)&stTarget, sizeof(SOCKADDR));
 59         if (iConnRet == OK)
 60         {
 61             printf("\n[Thread:%d] %s:PORT:%u is open", pstScan->usThreadIdx, pstScan->szIpAddr, pstScan->usPort);
 62         }
 63         else
 64         {
 65             printf("\n[Thread:%d] %s:PORT:%u is close", pstScan->usThreadIdx, pstScan->szIpAddr, pstScan->usPort);
 66         }
 67     }
 68     else
 69     {
 70         memcpy(&stScan, lpParam, sizeof(SCAN_INFO_S));//相当于把参数做了一次强制转换,注意和strcpy区别
 71         printf("\n[Thread:%d] Scan:%s:%u", stScan.usThreadIdx, stScan.szIpAddr, stScan.usPort);
 72 
 73         stTarget.sin_family = AF_INET;
 74         stTarget.sin_addr.s_addr = inet_addr(stScan.szIpAddr);
 75         stTarget.sin_port = htons(stScan.usPort);//h:host to n:net s:short
 76 
 77         //TCP连接申请套接字,发送时候,向socket里面写数据,接收时取数据
 78         iFd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 79         if (iFd < 0)
 80         {
 81             return OK;
 82         }
 83 
 84         //发起连接,通过ifd进行通许
 85         iConnRet = connect(iFd, (SOCKADDR*)&stTarget, sizeof(SOCKADDR));
 86         if (iConnRet == OK)
 87         {
 88             printf("\n[Thread:%d] %s:PORT:%u is open", stScan.usThreadIdx, stScan.szIpAddr, stScan.usPort);
 89         }
 90         else
 91         {
 92             printf("\n[Thread:%d] %s:PORT:%u is close", stScan.usThreadIdx, stScan.szIpAddr, stScan.usPort);
 93         }
 94     }
 95     
 96     closesocket(iFd);
 97     g_ausThreadState[stScan.usThreadIdx] = 0;//标记线程结束
 98     return OK;
 99 }
100 
101 //单线程扫描
102 //int ScanPort1(char szIpAddr[], unsigned short usPort)
103 //{
104 //    SOCKET iFd;
105 //    SOCKADDR_IN stTarget = { 0 };
106 //    int iConnRet;
107 //
108 //    stTarget.sin_family = AF_INET;
109 //    stTarget.sin_addr.s_addr = inet_addr(szIpAddr);
110 //    stTarget.sin_port = htons(usPort);//h:host to n:net s:short
111 //
112 //    //TCP连接申请套接字,发送时候,向socket里面写数据,接收时取数据
113 //    iFd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
114 //    if (iFd < 0)
115 //    {
116 //        return OK;
117 //    }
118 //
119 //    //发起连接,通过ifd进行通许
120 //    iConnRet = connect(iFd, (SOCKADDR*)&stTarget, sizeof(SOCKADDR));
121 //    if (iConnRet==OK)
122 //    {
123 //        printf("\n%s:PORT:%u is open",szIpAddr,usPort);
124 //    }
125 //    else
126 //    {
127 //        printf("\n%s:PORT:%u is close", szIpAddr, usPort);
128 //    }
129 //
130 //    closesocket(iFd);
131 //    return OK;
132 //}
133 
134 int StartScan()
135 {
136     WSADATA stWsa;
137     HANDLE hThread[THREAD_MAX] = { 0 };
138     unsigned short usPort = SCAN_START_PORT;
139     SCAN_INFO_S stScan = { 0 };
140 
141     memcpy(stScan.szIpAddr, SCAN_IP, IPADDR_LEN);
142 
143     if (WSAStartup(0x0202, &stWsa) != OK)
144     {
145         return ERR;
146     }
147 
148     //循环扫描某个ip的某个端口
149     while (usPort <= SCAN_END_PORT)
150     {
151         for (int i = 0; i < THREAD_MAX; ++i)
152         {
153             if (0 == g_ausThreadState[i])
154             {
155                 if (hThread[i] != 0)
156                 {
157                     CloseHandle(hThread[i]);
158                 }
159                 stScan.usPort = usPort;
160                 stScan.usThreadIdx = i;
161                 g_ausThreadState[i] = 1;
162                 hThread[i] = CreateThread(NULL, 0, ScanPort, &stScan, 0, NULL);
163                 usPort++;
164                 if (usPort>=SCAN_END_PORT)
165                 {
166                     break;
167                 }
168                 Sleep(100);//不sleep也会导致结构体资源冲突
169             }
170         }
171         //ScanPort1(SCAN_IP, usPort);
172     }
173 
174     WSACleanup();
175     return OK;
176 }
177 
178 int _tmain(int argc, _TCHAR* argv[])
179 {
180     StartScan();
181     system("pause");
182     return 0;
183 }

 

posted on 2015-10-20 14:43  俗剑仙·情如梦  阅读(761)  评论(0编辑  收藏  举报