检测端口是否打开有几种方式,比如
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 }