通行证│用户名: 密码: 验证码: 验证码,看不清楚?请点击刷新验证码 电信网通铁通移动   在线
文章搜索:
热门搜索:红客 黑鹰 红客技术 安全动画 红客培训
首页 文章 软件 动画 资源 励志 论坛 邮箱 会员 军事 科技 博客 爱心红客 最近更新 800g资源
 业内新闻 漏洞公告 病毒公告 电脑知识 网络知识 菜鸟入门 攻防教程 黑客攻防 安全编程 工具使用 综合安全 个人安全 安全相关 Q Q安全 原创精华 红客人物 站内事件
您现在的位置: 爱国者安全网 >> 文章类 >> 红客教程 >> 网络编程 >> 文章正文
BCB快速打造多线程端口扫描器
责任编辑:酷酷の鱼   更新日期:2007-12-13
 
文章作者:灰狐
原始出处:灰狐's Blog ( www.HuiHu32.cN )

很久没发些什么了,整天只来学习而不奉献总感觉有点什么,呵呵,就把这篇拙作发出来吧,通过本文您能学到的东西是理解BCB中对于多线程类的详细使用方法。最近已经陆续开始考试了,唉,一个比一个头大。

注:本文已发表在2007年《黑客防线》第12期,网络首发地址为作者灰狐's Blog(www.huihu32.cn),
    转载请注明出处!


        最近复习Winsocket编程,才发现自己以前很多东西都忘的差不多了,以前只是简单地看书,然后把书上那段TCP的代码抄下来运行一遍成功后就自认为已经理解了网络通信编程。现在才知道自己是多么可笑,唉,希望大家引以为戒喔。
    对于编程,根据个人的学习经验:多写是必须的,不管你看过多少代码。通常可以先定下一个难度不算太大(起码你知道大概可以怎样实现)的任务,然后就着手认真去做,遇到了问题就查资料,或参考别人的某个功能实现思路,坚持做完后你就会进步很多。
    今天我们就要做一个扫描TCP端口是否开放的程序,原理很简单,就是写一个TCP的客户端程序,然后connect某个端口,根据是否响应来确认是否开放。当然了,它很容易被误导(譬如有防火墙的因素),不过我们重在练习,先做出来再说。(其实,本文的重点在于后面的多线程类使用,千万别到这里就扔下了哦)
    首先用VC写一个演示的控制台程序,查看是否能达到目的,代码如下:(注:本文所有演示代码均有不同程度删减,完整版本请查看附带的源工程)
#include <stdio.h>
#include <winsock2.h>

#pragma comment(lib,"ws2_32")

#define START 80        //起始端口
#define END  1025    //终止端口

int main(int argc,char *argv[])
{
    int i;
    WSADATA ws;
    SOCKET sockfd;
    struct sockaddr_in their_addr;
//初始化加载库
    WSAStartup(MAKEWORD(2,2),&ws);
//设置连接信息
    their_addr.sin_family = AF_INET;
    their_addr.sin_addr.S_un.S_addr = inet_addr(argv[1]);    //根据命令行参数1确定扫描IP
    for(i=START;i<=END;i++)
    {    //循环建立socket后连接
        sockfd = socket(AF_INET,SOCK_STREAM,0);
        their_addr.sin_port = htons(i);
        printf("正在扫描端口:%d \n",i);
        if(connect(sockfd,(struct sockaddr*)&their_addr,sizeof(struct sockaddr)) == SOCKET_ERROR)
        {    //如果连接失败直接进行下个端口的扫描
            continue;
        }
//否则认为此端口开放
        printf("\n\t端口 %d 开放!\n\n",i);
    }
    closesocket(sockfd);
    WSACleanup();
    return 0;
}
整个代码的大体流程就是这样,非常简单,估计没人看不懂,先看一下效果,进入程序目录,拿www.sohu.com来测试吧,看我的截图图1:

    不过这个程序中存在着一些非常明显的问题:程序执行速度极慢(即使是在扫描本机的时候每个端口也需要将近1秒的时间);受网络影响明显,比如我在测试sohu的时候一次扫描的很正常,但另一次却卡在81端口了;界面不够美观,呵呵,总得考虑用户体验度吧。
为了解决以上问题,今天我完全使用BCB 6.0来做这个程序,开发平台是Win XP SP2,采用多线程技术。(程序完整源工程已经打包附上,附有详细注释,可直接编译运行)
    在附带的源程序中我做了详细的注释,本文中着重要讲的地方是怎样利用BCB中提供的多线程功能来使我们的程序执行速度得到大幅度提高。
    直接使用API进行多线程编程通常来说要考虑的东西比较多,幸运的是BCB提供了一个功能强大的多线程类,但我们不能直接使用它,需要先派生出一个子类,然后在这个子类中完成具体的功能。派生子类的方法是使用向导:File|New|Thread Object,在Class Name中输入TScanThread后直接确定,进入代码编辑,这时可以看到向导生成的类中包含了两个方法:TScanThread和Execute,分别用来进行初始化和执行具体代码。下面我详细讲一下怎样使用它,因为这个类并不能直接使用主窗体中的控件,但很显然我们通常都需要与窗体中的各种控件进行联系。
    假如在线程类中你要向主窗体的ScanResultMemo控件中添加扫描结果,可以这样做:首先在线程类的头文件中声明一个局部变量TMemo *AMemo;然后修改TScanThread这个构造函数,给添加一个形参改成如下:__fastcall TScanThread(bool CreateSuspended,TMemo *ResultMemo),并在实现过程中加入代码AMemo = ResultMemo;将构造函数的参数传递给局部变量AMemo,而在此类中是可以不受限制地使用AMemo这个变量的;在主窗体代码中创建线程的时候把实参传递给线程类的构造函数如下:
TScanThread test=new TScanThread(false,ScanResultMemo);
这样就完成了主窗体与线程类的联系。
    从上面的过程中可以看出是比较麻烦的,所以我们通常需要实现做好规划,尽量减少需要传递的参数数量,否则如果线程类比较多的话最后它们之间错综复杂的交错关系一定会让你大脑崩溃的。
    另外,通常不要把需要完成的功能代码直接写在线程类的Execute方法中,比较好的做法是先写一个成员函数,然后在Execute方法中调用这个函数;比如本程序中就是先声明了函数void __fastcall ScanPort();完成扫描功能,然后在Execute方法中调用它。在线程类的函数中除了构造函数外其他函数尽量不要带参数,否则很容易出错,需要使用参数的地方就使用成员局部变量解决。
    汗,上面说的似乎比较混乱(什么似乎,本来就乱,该打~~),不过大家一定要理顺关系哦,不然就麻烦了,连它是怎么运作的都不懂怎么控制它呢?这种机制初学起来似乎很是让人迷茫,但只要搞懂了它运行的流程就一点难度都没有了,真正的RAD啊。

[1] [2] 下一页

  • 上一篇文章:
  • 下一篇文章:
  • 最近更新
    固顶文章 爱国者安全网2007年度优秀版主评选
    普通文章 瑞星公司01月11日发布 每日计算机病毒及木马播报
    普通文章 破解博彩神助(专注彩票) V2.8.01
    推荐文章 推荐:跨站脚本执行漏洞代码的六点思路
    普通文章 Windows系统下的远程堆栈溢出 实战篇
    普通文章 Windows系统下的远程堆栈溢出 原理篇
    普通文章 MsSQLServer是如何加密口令的
    普通文章 浅谈国内的渗透评估过程
    普通文章 Dvbbs8.1 0DAY(通杀Access和mssql版本)
    普通文章 微软:我们的代码比赛门铁克更安全
    热门文章
    普通文章REAL蛀虫利用播放器漏洞下载恶意程序
    普通文章李彦宏:中国要在互联网领域逐渐超越美国
    普通文章马云:阿里巴巴的成功是一个生态链的成功
    普通文章Ingres用户认证非授权访问漏洞
    普通文章TCPreen FD_SET()函数远程栈溢出漏洞
    普通文章Winace UUE文件解压堆溢出漏洞
    普通文章Pclxav木马猎手第一代特征码引擎源代码
    普通文章IE收藏夹管理小精灵算法分析
    普通文章Extra Drive Pro算法分析历程
    普通文章雨过天晴自我注册
    精彩专题