Click here to Skip to main content
Click here to Skip to main content

How to write a simple but effective TCP/IP port scanner for Win32

, 27 Oct 2001
Rate this:
Please Sign up or sign in to vote.
An article on how to write a TCP/IP port scanner with a GUI, based on the MFC's property sheet paradigm

The TCP/IP port scanner

Introduction

Writing a TCP/IP port scanner, it's not so hard. This article shows you how to develop a simple but effective port scanner for Win32, using a self written socket classes (not the CSocket which comes with MFC) and a small framework based on the CPropertySheet/CPropertyPage classes.

The scanner also includes a module for testing connections (the Connect page) and allows the handling of the local database of services (the Services page).

What you should to know

The sample application presented here does not requires a deep knowledge of the TCP/IP protocol. If you have some notions about the MFC and the Winsock API, then you are on the right direction.

How a scanner works

Each time you send or receive data through the Internet, your mail (or web, chat, or whatever) program must connect to a remote port of a remote host. Some of the services which runs over the Internet are resumed into the following table:

service port description
echo 7 Echo
daytime 13 Daytime
ftp 21 File Transfer Protocol
ssh 22 SSH Remote Login Protocol
telnet 23 Telnet
smtp 25 Simple Mail Transfer
time 37 Time
nameserver 42 Host Name Server
nicname 43 Who Is
domain 53 Domain Name Server
gopher 70 Gopher
http 80 World Wide Web HTTP
kerberos 88 Kerberos
pop3 110 Post Office Protocol
netbios-ns 137 NETBIOS Name Service
netbios-dgm 138 NETBIOS Datagram Service
netbios-ssn 139 NETBIOS Session Service

In fact, the list of services/ports is greater than the above and includes three different port ranges:

port range utilization
0 - 1023 well known ports, which include the most common services, like SMTP, POP3, FTP, etc.
1024 - 49151 registered ports, which are assigned by the IANA organization
49152 - 65535 dynamic and/or private ports, which can be freely used

As the RFCs say (RFC793 for the TCP and RFC768 for the UDP protocol), the above ports can be used for TCP and UDP connections, so it's not unusual to see duplicated entries for the same service, like in:

service port/protocol description
echo 7/tcp Echo
echo 7/udp Echo

The TCP/IP protocol is based on the OSI (Open Systems Interconnection) model, developed between 1977 and 1984. That model uses a proposal of the ISO (International Organization for Standardization), so it is well known as the ISO/OSI model also. The ISO/OSI architecture divides the network into various layers (application, presentation, session, transport, network, data-link and physical).

Think to a layer like a plant of a building. At the lower level is your network card, used to exchange raw data between the computers, while at the higher level is your preferred client sending mail or browsing the web. In fact, the TCP/IP is not a protocol, but a suite of protocols, composed by:

protocol description
IP (Internet Protocol) the protocol used to exchange raw data between remote hosts
TCP (Transport Control Protocol) the protocol used to exchange data between applications
UDP (User Data Protocol) used as the TCP to exchange data between applications, but more simpler and less reliable than the TCP
ICMP (Internet Control Message Protocol) used at the network layer for error messaging

The correspondence between the ISO/OSI model and the suite of the TCP/IP protocols can be represented by the following table:

ISO/OSI model TCP/IP suite
application layer client program
presentation layer client program
session layer client program
transport layer TCP/UDP
network layer ICMP/IP/IGMP
data-link layer ARP/hardware/RARP
physical layer ARP/hardware/RARP

The IP and TCP protocols are the ground of data transfer. The IP protocol, which works at network layer, handles the transfer of raw data between computers. At this level, each packet contains the data which must be transferred and the IP address of the sender and the receiver. The TCP protocol works at the transport layer, but the principle is the same. TCP replaces the IP address concept with the port concept. Each transferred packet contains the data and the port number, where the port number is associated with a service instead of a computer.

In other words, the IP protocol moves the raw data from one computer to other, using the IP address to identify each computer of the network. Well, but when the data arrives to the destination computer, where must it be left? Are you browsing the WEB? If so, the TCP protocol redirects the incoming data through the port used by the HTTP service (80). Are you using an FTP client? The TCP protocol redirects the incoming data through the port used by the service (21), and so on.

As you can see, the port and service concepts are the basic principles used during data transfer through the Internet. Now you can understand which is the main purpose of a TCP/IP scanner. If you want to know what are the services currently running on a remote host, you must scan its ports.

Implementation

The sample code presented here is only an example of Winsock programming. Do not think it like the best approach to the scan topical. As you know, the Winsock API can be used with three different modes, blocking, non-blocking and asyncronous modes. Our scanner uses the third (asyncronous) mode.

Probably this is not the best mode which can be used with this topical (maybe using the blocking mode into a separate thread guarantees a better result), but this is not the point. Commercial scanners use a lot of threads to scan as fast as possible the mayor number of ports at the same time. This is not our purpose. Our scanner must scan one port at time, without blocking the UI until the work is done, and to do it in that way, the best approach is the asyncronous mode, used here to practice and exercise with the Winsock API. Of course, you are free to modify the proposed code to apply the Winsock mode you prefer.

All the code contained into the sample project can be divided into two sections, the simple framework used to build a CPropertySheet based MFC application and the classes used for the Winsock interface.

The CPropertySheetDialog.cpp/.h and CPropertyPageDialog.cpp/.h files contain all the classes required to use the property sheet paradigm as a base for our MFC application.

TcpPropertySheet.cpp/.h files contain the code for the main app, while all the Tcp[...]Page.cpp/.h files contain the code for the pages of the sheet.

All the code used to interface the Winsock API is contained into the CWinsock.cpp/.h and CSock.cpp/.h files. CAsyncSock.cpp/.h file contains the classes used to access the Winsock API in asyncronous mode, while the rest of the code is used internally to handle the list control (CListCtrlEx.cpp/.h), the program's configuration, etc.

Note that the base class for the Winsock interface is the CWinsock class, not the CSock. As you can see looking into the code, the CWinsock class is used to map all the Winsock services to the real library or to a dummy implementation, depending on the _DEBUGSOCKET macro definition. This is because the CWinsock class contains the code to handle locally a minimal SMTP/POP3 server, which you can use to exercise the SMTP/POP3 protocols without using an active Internet connection.

As usual for an MFC app, you must derive you own class (in this case, the CTcpScanApp class) from the CWinApp. Our scanner is not dialog, but property sheet-based, so you must override the default InitInstance() implementation for creating the property sheet and all the related pages:

BOOL CTcpScanApp::InitInstance(void)
{
    CScanPage ScanPage;
    CConnectPage ConnectPage;
    CServicesPage ServicesPage;
    CPropertyPageList* pPropertyPageList = new CPropertyPageList();

    if(pPropertyPageList)
    {
        PROPERTYPAGE* p;

        p = new PROPERTYPAGE(IDD_PAGE_SCAN,&ScanPage,RUNTIME_CLASS(CScanPage));
        pPropertyPageList->Add(p);

        p = new PROPERTYPAGE(IDD_PAGE_CONNECT,
              &ConnectPage,RUNTIME_CLASS(CConnectPage));
        pPropertyPageList->Add(p);
        
        p = new PROPERTYPAGE(IDD_PAGE_SERVICES,
              &ServicesPage,RUNTIME_CLASS(CServicesPage));
        pPropertyPageList->Add(p);

        CTcpScanPropertySheet* pPropertySheetDialog
              = new CTcpScanPropertySheet(NULL,pPropertyPageList);
        if(pPropertySheetDialog)
        {
            if(pPropertySheetDialog->Create())
            {
                m_pMainWnd = pPropertySheetDialog;
                pPropertySheetDialog->DoModal();
            }

            delete pPropertySheetDialog;
        }

        delete pPropertyPageList;
    }

    return(FALSE);
}

The property sheet dialog is based on the CPropertySheetDialog/CPropertyPageDialog classes, which handles all the required stuff. The Apply and the Help buttons are removed by the framework, so each page of the property sheet has only the OK and the Cancel buttons. Each page of the sheet modifies the text of the OK button, according to its needs.

As you can see, each class used as a page of the sheet defines the following handlers:

BOOL    OnInitDialog(void);
BOOL    OnSetActive(void);
BOOL    OnKillActive(void);
void    OnKillSheet(void);
void    OnOk(void);
void    OnCancel(void);

If you decide to use the CPropertySheetDialog/CPropertyPageDialog classes into your own code, do not miss to do the same.

About the features of our scanner, consider that the Connect page allows you to test only the connections which use the same channel for commands and data. This means you can use that page to send and receive data with protocols like SMTP, POP3, HTTP, etc., but not with protocols like FTP, which uses two different channels (one for the commands and other for the data).

When using the Connect page, remember that you are entering raw data, so if you want to get some HTML page through the HTTP protocol, you must specify the HTTP request as the standard say (in this case, specifying the pair of CR/LF chars at the end of the request).

Any kind of ideas, suggestions or enhancements are always welcome.

Luca Piergentili

lpiergentili@yahoo.com

http://www.geocities.com/lpiergentili/

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Luca Piergentili
Web Developer
Italy Italy
I like C and C++, Acid Jazz, James Brown, gli Spaghetti Aglio e Olio, alla Bolognesa, alla Puttanesca e le Fettuccine alla Matriciana ('Maccaroni' over the world). Of course I like beautiful big tits girls too, my little car, Frank Zappa, the art of Zen, italian coffee and much more...

Comments and Discussions

 
QuestionHow do you close an open port? PinmemberPélège2-Nov-01 14:22 
AnswerRe: How do you close an open port? PinmemberNish [BusterBoy]19-Feb-02 8:56 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141223.1 | Last Updated 28 Oct 2001
Article Copyright 2001 by Luca Piergentili
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid