2.5.1. netstat command

Systems implementing the TCP/IP protocol typically include the netstat utility, which can be used, among other things, to list opened sockets.

The netstat command of Windows systems is known to be buggy:

The second bug can lead to suprising netstat outputs on Windows NT 4.0 systems. One particularly odd result is that TCP port 135 (used by the rpcss service, as explained later) is displayed twice in netstat outputs:

C:\WINNT>netstat -anp tcp | find ":135 "
  TCP    0.0.0.0:135            0.0.0.0:0              LISTENING
  TCP    0.0.0.0:135            0.0.0.0:0              LISTENING
  UDP    0.0.0.0:135            *:*                    

This is because the rpcss service opens both ports 135/tcp and 135/udp. But, with the bug aforementionned, 135/tcp is displayed a second time. This explains why 135/tcp appears twice.

Another serious bug exists in all versions of Windows NT systems before Windows Server 2003 and Windows XP SP2: for each outgoing TCP connection established from a Windows system, the local source port is displayed as LISTENING [7].

In the following example, a TCP connection was established to port 22 of a remote server. The TCP/IP driver allocated port 1367 as source port for the connection. In the netstat output, the port appears in the LISTENING state:

C:\WINDOWS>netstat -anp tcp | find ":1367"
  TCP    0.0.0.0:1367           0.0.0.0:0              LISTENING
  TCP    192.70.106.142:1367    192.70.106.76:22       ESTABLISHED

However, this port is not really in the LISTENING state, i.e, it is not possible to establish a new TCP connection on port 1367. Using hping [8] to send a TCP segment with the SYN flag set, a TCP segment with the RST-ACK flags set is returned:

jbm@garbarek ~> sudo hping -S -c 1 192.70.106.142 -p 1367
HPING 192.70.106.142 (ep1 192.70.106.142): S set, 40 headers + 0 data bytes
len=46 ip=192.70.106.142 flags=RA seq=0 ttl=127 id=47511 win=0 rtt=3.7 ms

--- 192.70.106.142 hping statistic ---
1 packets tramitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 3.7/3.7/3.7 ms

It turns out that this bug comes from an incorrect mapping between TDI objects and TCP sockets.

The Winsock API (implementation of BSD sockets API on Windows systems) is implemented on TCP/IP using the Afd driver, which uses the TDI (Transport Driver Interface) API to communicate with the TCP/IP driver.

To implement an outgoing TCP connection, the Afd driver creates two TDI objets:

Using a simple TCP client (nc.exe, [9]) to establish a TCP connection to port 22 of a remote server:

C:\WINNT>nc -z 192.168.1.254 22
the implementation at the TDI level can be monitored, using the TDIMon tool [10]:
1  8246D3F0 IRP_MJ_CREATE	     TCP:0.0.0.0:0	SUCCESS	Address Open	
2  8246D3F0 TDI_SET_EVENT_HANDLER    TCP:0.0.0.0:1038	SUCCESS	Error Event	
3  8246D3F0 TDI_SET_EVENT_HANDLER    TCP:0.0.0.0:1038	SUCCESS	Disconnect Event	
4  8246D3F0 TDI_SET_EVENT_HANDLER    TCP:0.0.0.0:1038	SUCCESS	Receive Event	
5  8246D3F0 TDI_SET_EVENT_HANDLER    TCP:0.0.0.0:1038	SUCCESS	Expedited Receive Event	
6  8246D3F0 TDI_SET_EVENT_HANDLER    TCP:0.0.0.0:1038	SUCCESS	Chained Receive Event	
7  8246D3F0 TDI_QUERY_INFORMATION    TCP:0.0.0.0:1038	SUCCESS	Query Address	
8  824C1AE0 IRP_MJ_CREATE	     TCP:Connection obj	SUCCESS	Context:0x822CF9B8	
9  824C1AE0 TDI_ASSOCIATE_ADDRES     TCP:Connection obj	SUCCESS	TCP:0.0.0.0:1038	
10 824C1AE0 TDI_CONNECT		     TCP:0.0.0.0:1038	192.168.1.254:22 SUCCESS		
The output can be interpreted as follow:
Thus, it appears that at the TDI level, a TCP connection is implemented using two TDI objects:
The problem is that the GetTcpTable() API retrieving the content of the current TCP connections table incorrectly translates the second TDI object as a TCP listening socket. As a consequence, the port is displayed as LISTENING by the netstat command. Note that any tools using this API will report incorrect results. Thus, results of such tools must be analyzed carefully, to filter ports reported as LISTENING. This bug has been fixed in Windows Server 2003 and in Windows XP SP2.