简单的端口扫描器(TCP connect)

时间:2024-03-09 12:18:56

端口扫描器原理相对简单,采用的是TCP connect状态判断。具体来说:TCP connect方式使用系统网络API connect向目标主机的端口发起连接,如果无法连接,说明该端口关闭。该方式扫描速度比较慢,而且由于建立完整的TCP连接会在目标机上留下记录信息,不够隐蔽。所以,TCP connect是TCP SYN无法使用才考虑选择的方式。

在编写过程中,采用多线程时遇到共享变量访问的同步问题,经过试验,这里仅仅简单采用Sleep()函数进行等待就能拥有不错的效果。

代码及部分说明如下:

 

#include <stdio.h>

#include <WinSock2.h>

#include <time.h>

#pragma comment(lib,"ws2_32.lib")

 

int gNumThread = 0;

 

void usage()

{

   printf("Usage: <TCPScanner> [IP] [StartPort]-[EndPort]\n");

   printf("Example: TCPScanner 192.168.1.1 80-100\n");

   ExitProcess(1);

}

 

DWORD WINAPI ThreadProc(LPVOID pPara);

 

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

{

   WSADATA wsad;

   SOCKADDR_IN target;

   char *IP,*p;

   USHORT PortEnd,PortStart,i;

   clock_t TimeStart,TimeEnd;

   HANDLE    hThread;

    DWORD    dwThreadId;

 

   //参数处理

   if(argc!=3) usage();

   IP = argv[1];  //第一个参数是IP

   PortStart = atoi(argv[2]);  //第二个参数是端口范围,分别得到首尾端口

   for(p = argv[2];*(p++)!=\'-\';);  //指向结束端口的起始位置

   PortEnd = atoi(p);

 

   printf("Scanner will work on %s %d-%d now..\n",IP,PortStart,PortEnd);

   TimeStart = clock();

 

   //加载,创建套接字,填写目标主机地址,按端口扫描

   WSAStartup(MAKEWORD(2,2),&wsad);

   target.sin_family = AF_INET;

   target.sin_addr.s_addr = inet_addr(IP);

   for(i=PortStart;i<=PortEnd;++i){

        target.sin_port = htons(i);

        //创建进程接收数据

        hThread = CreateThread(NULL,0,ThreadProc,(LPVOID)&target,0,&dwThreadId);

        Sleep(10);  //主进程先等待一段时间,使得子进程能够有时间来读取端口信息,不致跳过、错开某些端口

        if (hThread == NULL){

            printf("CreateThread() failed: %d\n", GetLastError());

            break;

        }

        CloseHandle(hThread); //不再需要这个句柄,关掉它,但并非是关掉对应线程

   }

 

   Sleep(50);  //等待上一段时间,等待所有子进程结束任务

   TimeEnd = clock();

   printf("Time cost:%.3fs\n",(float)(TimeEnd-TimeStart)/CLOCKS_PER_SEC);

 

   WSACleanup();

   return 0;

}

 

DWORD WINAPI ThreadProc(LPVOID pParam)

{

   SOCKADDR_IN target = *(SOCKADDR_IN*) pParam;

   SOCKET sConn;

 

   printf("%s %d\n",inet_ntoa(target.sin_addr),ntohs(target.sin_port));

   sConn = socket(AF_INET,SOCK_STREAM,IPPROTO_IP);

   if(connect(sConn,(const SOCKADDR*) &target,sizeof(target)) == SOCKET_ERROR) return 0;

   printf("Port %d is open\n",ntohs(target.sin_port));

             

   closesocket(sConn);

   return 0;

}