C++网络安全工具编程(一)connect端口扫描器

端口扫描的种类有很多,其中最简单的即为基于TCP三次握手协议的connect扫描器。其原理为与服务端口建立一个socket连接,当连接上时即可判断端口打开,之后断开连接,进行下一端口的试探。

首先来看一个最简的c++客户端与目标服务器建立socket连接的基础代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include "stdafx.h"
#include <string.h>
#include <WinSock.h>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
    //初始化Windows Sockets 动态库

    WSADATA wsaData;
    if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
    {
        cout<<"找不到可使用的WinSock dll!"<<endl;
        return 1;
    }

    //创建套接字
    SOCKET sClient=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    if(sClient==INVALID_SOCKET)
    {
        cout<<"创建客户端socket失败!"<<endl;
        return 1;
    }
    //连接服务器
    SOCKADDR_IN addrServ;
    addrServ.sin_family=AF_INET;
    addrServ.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
    addrServ.sin_port=htons(10046);

    if(connect(sClient,(sockaddr *)&addrServ,sizeof(sockaddr))==SOCKET_ERROR)
    {
        cout<<"连接服务器失败!"<<endl;
        closesocket(sClient);
        return 1;
    }
    else
        cout<<"连接服务器成功!"<<endl;
   
    //关闭套接字,释放资源
    closesocket(sClient);
    WSACleanup();

    return 0;


这里注意一下,如遇到 error LNK2019: 无法解析的外部符号 _WSACleanup@0,该符号在函数 _wmain 此类错误,如上代码添加#pragma comment(lib,”ws2_32.lib”)即可。

由于功能需求的关系,这里就不讲解发送与接收消息的方法了,后续会陆续开篇。
在window下建立socket连接,通常需要使用winSock这个库,初始化动态库并创建套接字后,使用connect方法对目标IP(127.0.0.1)及端口(10046)尝试连接。
以上即为一个标准的windows平台下C++使用socket连接目标服务器的过程。

利用上面的代码,我们即可开始自己的端口扫描器的制作,原理非常简单,即将单一的对目标服务器端口的连接尝试,放置到一个for循环中批量操作,并根据结果显示不同的打印内容。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include "stdafx.h"
#include <string.h>
#include <WinSock.h>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
    //初始化Windows Sockets 动态库
    WSADATA wsaData;
    if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
    {
        cout<<"找不到可使用的WinSock dll!"<<endl;
        return 1;
    }
    SOCKET sClient = NULL;
    SOCKADDR_IN addrServ;
    addrServ.sin_family=AF_INET;
    addrServ.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
    for (int _port = 0;_port<100;_port++){
        if (sClient == NULL)
        {
            //创建套接字
            sClient=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
            if(sClient==INVALID_SOCKET)
            {
                cout<<"创建客户端socket失败!"<<endl;
                return 1;
            }
        }
    addrServ.sin_port=htons(_port);
    //连接服务器
    if(connect(sClient,(sockaddr *)&addrServ,sizeof(sockaddr))==SOCKET_ERROR)
    {
        cout<<"port "<<_port<<" is not open!"<<endl;
        //closesocket(sClient);
        //return 1;
    }
    else{
        cout<<"port "<<_port<<" open on host!!!!!!!!!!!!"<<endl;
        closesocket(sClient);
        sClient = NULL;
    }
}
    //关闭套接字,释放资源
    getchar();
    WSACleanup();
    return 0;

以上代码即可简单的实现0-100号端口的tcp扫描。不过运行速度较慢,连接超时的时限也没有加入。但对于入门学习来说已经基本满足了初学者对概念的熟悉。后续我们将针对此扫描做更多的拓展,例如,多线程端口扫描等等。
同时,需要注意的是,基于connect的端口扫描,是不隐蔽扫描,通过tcp服务器与目标端口建立3次握手的过程会被服务器记录下来,因此,只需要在服务器上稍加防护即可屏蔽此类扫描。
后续我将介绍其他类型的扫描方式。

最后发个运行效果:

谢谢关注。

BeiTown
2013.04.28

本文链接:C++网络安全工具编程(一)connect端口扫描器

转载声明:BeiTown原创,转载请注明来源:BeiTown's Coder 编码之源,谢谢


Tags: , ,