通行证│用户名: 密码: 验证码: 验证码,看不清楚?请点击刷新验证码 电信网通铁通移动   在线
文章搜索:
热门搜索:红客 黑鹰 红客技术 安全动画 红客培训
首页 文章 软件 动画 资源 励志 论坛 邮箱 会员 军事 科技 博客 爱心红客 最近更新 800g资源
 业内新闻 漏洞公告 病毒公告 电脑知识 网络知识 菜鸟入门 攻防教程 黑客攻防 安全编程 工具使用 综合安全 个人安全 安全相关 Q Q安全 原创精华 红客人物 站内事件
您现在的位置: 爱国者安全网 >> 文章类 >> 红客教程 >> 网络编程 >> 文章正文
一个简单的端口扫描编程序题
责任编辑:酷酷の鱼   更新日期:2008-1-21
 
一、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; //处理消息的窗口句柄
unsigned long g_ulAddr = INADDR_NONE; //扫描的主机地址
DWORD g_dwTimeOut = 1000; //连接超时时间,以ms计
bool g_bTerminate = false; //是否用户发出结束扫描的标志
short g_nMaxThread = 200; //最大允许的扫描线程数,经试验不宜大于200
short g_nThreadCount = 0; //当前正在扫描的进程数
2、StartScan 线程:
  这个线程完成的任务是启动具体的扫描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;
}      
3、DoScanPort 线程:
  这个线程负责具体扫描指定的端口,并将结果SendMessage给主对话框。下面是其代码: 
DWORD WINAPI DoScanPort(LPVOID lpParam)
{
 DWORD dwRet;
 short nPort = *(short*) lpParam;
 delete lpParam;
 
 SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
 if(sock == INVALID_SOCKET)
 {
  AfxMessageBox("创建套接字失败!");
  dwRet = ERROR_CREATE_SOCKET;
 }
 else
 {  
  unsigned long flag = 1;  
  if ((ioctlsocket(sock, FIONBIO, &flag) != 0))
  {
   AfxMessageBox("未能改为非阻塞模式!");
   dwRet = ERROR_MODIFY_FIONBIO;
  }
  else
  {
   sockaddr_in severAddr;
   severAddr.sin_family = AF_INET;
   severAddr.sin_port = htons(nPort);   
   severAddr.sin_addr.S_un.S_addr = g_ulAddr;
   connect(sock, (sockaddr*)&severAddr, sizeof(severAddr));
   
   struct fd_set mask;   
   FD_ZERO(&mask);
   FD_SET(sock, &mask);
   
   struct timeval timeout;
   timeout.tv_sec = g_dwTimeOut / 1000;
   timeout.tv_usec = g_dwTimeOut % 1000;
   
   switch(select(0, NULL, &mask, NULL, &timeout))
   {
   case -1:
    dwRet = ERROR_SELECT;
    break;
    
   case 0:
    dwRet = ERROR_SELECT_TIMEOUT;
    break;
    
   default:  
    dwRet = ERROR_SUCCESS;
   };
  }  
  closesocket(sock);
 }
 g_nThreadCount --;
 if (dwRet == ERROR_SUCCESS)
 {
  ::SendMessage(g_hWnd, SCAN_THREAD, DOSCAN_FIND_PORT, nPort);
 }
 else
 {
  ::SendMessage(g_hWnd, SCAN_THREAD, DOSCAN_END_PORT, nPort);
 }
 return dwRet;
}      
 三、运行结果
  本程序在VC6+WinXp下编写调试运行正确,在Win98下运行正确。
在我的计算机扫描本机1-5000号端口,超时设置1000ms,200个最大线程数,约需要45秒。当超时设置再短一些时速度可达每秒150个端口的速度。
 四、结束语
  事实上,速度要想再提高,可能需要其它方法了。如果线程数开得过多,则由于线程的调度开销过大,速度反而会降低。如果超时设置过短,可能引起扫描的结果不正确(这须视网络情况决定),并且由于是多线程,超时等待的时间也可能小于因线程调度而等待的时间,则也不能提高速度。
  另外我还发现了一个问题,就是扫描本机时,如果以IP地址127.0.0.1时,则139#端口没有开放;如果设置为本机的实际IP时则139#端口是开放的,这不知是何原因,还望高手指点。
  本程序还有一个需要改进的地方,就是不象大多数端口扫描器可扫描指定的IP段,而只设计成扫描指定的某一台主机。
  • 上一篇文章:
  • 下一篇文章: 没有了
  • 最近更新
    推荐文章 瑞星公司01月21日发布 每日计算机病毒及木马播报
    普通文章 网络上最流行的“杀毒常识”
    普通文章 一个简单的端口扫描编程序题
    普通文章 一个截获用户输入的编程例子
    推荐文章 推荐:防火墙的分类及优缺点综述
    普通文章 Thinstall2.517 Unpackme 脱壳
    普通文章 强大的HA1过微软签名
    普通文章 巧用EasyShare突破限制实现宽带共享主义
    普通文章 做好预防 春节前后最易爆发的三类病毒
    普通文章 “VB邮件蠕虫变种EA”通过MSN发送带毒链接
    热门文章
    普通文章2007年新增电脑病毒36.3万种
    普通文章微软本月安全公告 两个紧急补丁
    普通文章损失过亿 全球十大计算机病毒排名
    普通文章Windows Vista 本月无安全补丁
    普通文章美媒:中国网络战攻防战力世界第一
    普通文章麦咖啡误报:错将合法网站当贼抓
    普通文章截获MSN Photo木马新变种“小欧”
    普通文章微软:我们的代码比赛门铁克更安全
    普通文章Dvbbs8.1 0DAY(通杀Access和mssql版本)
    普通文章浅谈国内的渗透评估过程
    精彩专题