一、TCP扫描技术
常用的端口扫描技术有很多种,如 TCP connect() 扫描 、TCP SYN 扫描、TCP FIN 扫描 等,网络上也有很多文章专门介绍,比如 :http://www.antai-genecon.com/suml/zhishiyy/jingong/duankougj.htm 上就介绍了很多我的程序 所使用的最基本的扫描技术:TCP 扫描。
操作系统提供的 connect() 系统调用,用来与每一个感兴趣的目标计算机的端口进行连接。如果端口处于侦听状态,那么connect()就能成功。否则,这个端口是不能用的,即没有提供服务。这个技术的一个最大的优点是,你不需要任何权限。系统中的任何用户都有权利使用这个调用。另一个好处就是速度。如果对每个目标端口以线性的方式,使用单独的connect()调用,那么将会花费相当长的时间,你可以通过同时打开多个套接字,从而加速扫描。使用非阻塞 I/O 允许你设置一个低的时间用尽周期,同时观察多个套接字。但这种方法的缺点是很容易被发觉,并且被过滤掉。目标计算机的logs文件会显示一连串的连接和连接是出错的服务消息,并且能很快的使它关闭。
作者提示:未经许可扫描他人的计算机端口属非法行为。本程序只是展示一种端口扫描技术,请不得将其用于非法目的,否则后果自负。
二、程序简介
为了提高扫描速度,本程序采用了多线程技术和非阻塞I/O的技术。程序的主界面是一个对话框,下面是程序框架示意图:
1、全局变量:
以下是所有全局变量的定义:HWND g_hWnd = NULL; //处理消息的窗口句柄
2、StartScan 线程:
unsigned long g_ulAddr = INADDR_NONE; //扫描的主机地址
DWORD g_dwTimeOut = 1000; //连接超时时间,以ms计
bool g_bTerminate = false; //是否用户发出结束扫描的标志
short g_nMaxThread = 200; //最大允许的扫描线程数,经试验不宜大于200
short g_nThreadCount = 0; //当前正在扫描的进程数
这个线程完成的任务是启动具体的扫描DoScanPort线程,对某一个端口进行扫描。该进程启动的DoScanPort线程的最大数量在设定的值范围内,如果线程数已达最大,则会等待某些线程结束后再启动新的线程。如果用户发出结束扫描信息,则不再启动新的线程,而等待已启动的线程结束后返回。下面是这线程的执行体代码:DWORD WINAPI StartScan(LPVOID lpParam)
{
tag_PORTS* pScanParam = (tag_PORTS*)lpParam;
DWORD dwThreadId;
unsigned short i;
if (pScanParam->bSepecifiedPort)
{
for(i=0; i<=pScanParam->nCount; i++)
{
if (g_bTerminate)
{
break; //用户已发出结束扫描命令
}
while(g_nThreadCount >= g_nMaxThread)
{
Sleep(10);
}
if (CreateThread(NULL,
0,
DoScanPort,
(LPVOID)new short(pScanParam->nArrOfPorts[i]),
0,
&dwThreadId) != NULL)
{
g_nThreadCount ++;
}
}
}
else
{
for(i=pScanParam->iStartPort; i<=pScanParam->iEndPort; i++)
{
if (g_bTerminate)
{
break; //用户已发出结束扫描命令
}
while(g_nThreadCount >= g_nMaxThread)
{
Sleep(10);
}
if (CreateThread(NULL, 0, DoScanPort, (LPVOID)new short(i), 0, &dwThreadId) != NULL)
{
g_nThreadCount ++;
}
}
}
//等待各端口扫描线程结束
while (g_nThreadCount > 0)
{
Sleep(50);
}
::SendMessage(g_hWnd, SCAN_THREAD, STARTSCAN_COMPLETE, 0);
delete pScanParam;
return ERROR_SUCCESS;
}