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

Click here for larger image

Environment: Windows 2000/SP2, VC++ 6.0/SP3


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 ports ranges:

port range utilization
0 – 1023 well known ports, which includes 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 says (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 phisical).

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 Layer) 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
phisical 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
. 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, wher must be leaved ? 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.


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 tree different modes, blocking, non-blocking and asyncronous mode. 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 uses a lot of threads to scans as fast as possible the mayor number of ports at the same time. This is not our purpose. Our scanner must scans 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 exercize 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 contains all the classes required to use the property sheet paradigm as a base for our MFC application.
TcpPropertySheet.cpp/.h files contains the code for the main app, while all the Tcp[…]Page.cpp/.h files contains 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 because the CWinsock class contains the code to handle locally a minimal SMTP/POP3 server, which you can use to exercize 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

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





CTcpScanPropertySheet* pPropertySheetDialog =
new CTcpScanPropertySheet(NULL,
m_pMainWnd = pPropertySheetDialog;

delete pPropertySheetDialog;

delete pPropertyPageList;


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 uses 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 row 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
[email protected]


Download source – 130 Kb

More by Author

Must Read