Enumerating available Transport Protocol Providers
Posted: Mon Aug 29, 2011 7:30 pm
Finished with the test bed code, thought it might help someone. for x 86, preferably Windows 7 but modify to use. Enjoy 

Code: Select all
; NOTE: This is intended for use on Windows 7 systems and not for below Windows Vista - with Winsock version 2.2 or greater
; test bed code works windows 2K and greater - may need to change WSAStartup($0202,@wsaData.WSADATA) to WSAStartup($0101,@wsaData.WSADATA) for below Windows Vista
; "test bed" code : may contain bugs or errors which will be corrected in the final version
#XP1_CONNECTIONLESS = $00000001
#XP1_GUARANTEED_DELIVERY = $00000002
#XP1_GUARANTEED_ORDER = $00000004
#XP1_MESSAGE_ORIENTED = $00000008
#XP1_PSEUDO_STREAM = $00000010
#XP1_GRACEFUL_CLOSE = $00000020
#XP1_EXPEDITED_DATA = $00000040
#XP1_CONNECT_DATA = $00000080
#XP1_DISCONNECT_DATA = $00000100
#XP1_SUPPORT_BROADCAST = $00000200
#XP1_SUPPORT_MULTIPOINT = $00000400
#XP1_MULTIPOINT_CONTROL_PLANE = $00000800
#XP1_MULTIPOINT_DATA_PLANE = $00001000
#XP1_QOS_SUPPORTED = $00002000
#XP1_INTERRUPT = $00004000 ; this bit is reserved
#XP1_UNI_SEND = $00008000
#XP1_UNI_RECV = $00010000
#XP1_IFS_HANDLES = $00020000
#XP1_PARTIAL_MESSAGE = $00040000
#XP1_SAN_SUPPORT_SDP = $00080000
#IPPROTO_ICMP = 1
#IPPROTO_IGMP = 2
#BTHPROTO_RFCOMM = 3
#IPPROTO_TCP = 6
#IPPROTO_UDP = 17
#IPPROTO_ICMPV6 = 58
#IPPROTO_RM = 113
#PFL_MULTIPLE_PROTO_ENTRIES = $00000001
#PFL_RECOMMENDED_PROTO_ENTRY = $00000002
#PFL_HIDDEN = $00000004
#PFL_MATCHES_PROTOCOL_ZERO = $00000008
#PFL_NETWORKDIRECT_PROVIDER = $00000010
#MAX_PROTOCOL_CHAIN = 7
#WSAPROTOCOL_LEN = 255
#AF_IPX = 6 ; = #AF_NS ; IPX protocols: IPX, SPX, etc.
#AF_INET6 = 23
#AF_NETBIOS = 17
#AF_IRDA = 26
#AF_BTH = 32
Structure WSAPROTOCOLCHAIN
ChainLen.i
ChainEntries.i[#MAX_PROTOCOL_CHAIN]
EndStructure
Structure WSAPROTOCOL_INFOW
dwServiceFlags1.l
dwServiceFlags2.l
dwServiceFlags3.l
dwServiceFlags4.l
dwProviderFlags.l
ProviderId.b[16]
dwCatalogEntryId.l
ProtocolChain.WSAPROTOCOLCHAIN
iVersion.i
iAddressFamily.i
iMaxSockAddr.i
iMinSockAddr.i
iSocketType.i
iProtocol.i
iProtocolMaxOffset.i
iNetworkByteOrder.i
iSecurityScheme.i
dwMessageSize.l
dwProviderReserved.l
szProtocol.w[#WSAPROTOCOL_LEN+1]
EndStructure
Structure WSABUFFERPROTOCOL
buf.WSAPROTOCOL_INFOW[0]
EndStructure
Prototype PWSAStartup(wVersionRequested, lpWSAData)
Prototype PStringFromGUID2(rguid, lpsz, cchMax)
Prototype PWSACleanup()
Prototype PWSCEnumProtocols(lpiProtocols, lpProtocolBuffer, lpdwBufferLength, lpErrno)
Prototype PWSCGetProviderPath(lpProviderId, lpszProviderDllPath, lpProviderDllPathLen, lpErrno) ; returns a wide character string
Global WSAStartup.PWSAStartup
Global StringFromGUID2.PStringFromGUID2
Global WSACleanup.PWSACleanup
Global WSCEnumProtocols.PWSCEnumProtocols
Global WSCGetProviderPath.PWSCGetProviderPath
Procedure LoadLibraries()
Global Lib_Winsock.i, Lib_Ole32.i
Lib_Winsock = OpenLibrary(#PB_Any,"ws2_32.dll")
If Lib_Winsock
WSAStartup.PWSAStartup=GetFunction(Lib_Winsock,"WSAStartup")
WSACleanup.PWSACleanup=GetFunction(Lib_Winsock,"WSACleanup")
WSCEnumProtocols.PWSCEnumProtocols=GetFunction(Lib_Winsock,"WSCEnumProtocols")
WSCGetProviderPath.PWSCGetProviderPath=GetFunction(Lib_Winsock,"WSCGetProviderPath")
EndIf
Lib_Ole32 = OpenLibrary(#PB_Any,"Ole32.dll")
If Lib_Ole32
StringFromGUID2.PStringFromGUID2=GetFunction(Lib_Ole32,"StringFromGUID2")
EndIf
If Lib_Winsock <> 0 And Lib_Ole32 <> 0
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndProcedure
LoadLibraries()
;Declare And initialize variables
iResult.i = 0
iNuminfo.i = 0
i.i
dwBufferLen.i = 16384
*buffproto.WSABUFFERPROTOCOL = #Null
*lpProtoInfo.WSAPROTOCOL_INFOW = #Null
iErrno.i = 0
lpErrno.i
lpProviderDllPathLen = #MAX_PATH
iRet = 0
;Initialize Winsock
If WSAStartup($0202,@wsaData.WSADATA) <> 0 ; windows Vista and up
Debug "WSAStartup failed"
End
EndIf
; WSAStartup($0101,@wsaData.WSADATA) ; below windows Vista
*buffproto = AllocateMemory(dwBufferLen)
If *buffproto = #Null
Debug "Memory allocation for providers buffer failed"
WSACleanup()
End
EndIf
iNuminfo = WSCEnumProtocols(#Null, #Null, @dwBufferLen, @iErrno) ; call it the first time for the size
If iNuminfo = #SOCKET_ERROR
If iErrno <> #WSAENOBUFS
Debug "WSCEnumProtocols failed with error : " +Str(iErrno)
If *buffproto
FreeMemory(*buffproto)
*buffproto = #Null
WSACleanup()
End
Else
Debug "WSCEnumProtocols failed with error : WSAENOBUFS " + Str(iErrno)
Debug "Increasing buffer size to " +Str(dwBufferLen)
If *buffproto
FreeMemory(*buffproto)
*buffproto = #Null
*buffproto = AllocateMemory(dwBufferLen)
If *buffproto = #Null
Debug "Memory allocation increase for buffer failed"
WSACleanup()
End
EndIf
EndIf
EndIf
EndIf
EndIf
*lpProtoInfo = *buffproto
iNuminfo = WSCEnumProtocols(#Null, *lpProtoInfo, @dwBufferLen, @iErrno); call it the second time for the info
If iNuminfo = #SOCKET_ERROR
Debug "WSCEnumProtocols failed with error : " + Str(iErrno)
If *lpProtoInfo
FreeMemory(*lpProtoInfo)
*lpProtoInfo = #Null
WSACleanup()
End
EndIf
EndIf
;When providers are installed, a dummy provider is installed/created to aid in installation/implementation of the provider. An application that calls WSAEnumProtocols will not see any entry
;with a chain length of zero or if it is a dummy provider; only WSCEnumProtocols will return these chain length zero and dummy provider entries, along with all other entries.
;When trying to see these entries you need to use WSCEnumProtocols or you'll never see the provider dummy or chain length zero entries and only see the base and layered chain
;non-zero and non-dummy entries. With increasing sophistication of malicious items such as virus, trojam, worm, root kit, and other malicious applications, its become possible for a
;malicious item to subvert these dummy and zero length, or non-zero length and non-dummy, entries for their own purpose such as installing communications 'back doors' into a system
;and not detectable by the common protection packages which rely on actual direct activity of the malicious file, or signatures, for detection but do nothing to detect activity for
;things which are normally on a system such as these zero length, non-zero length, dummy, and non-dummy, items. There is only one package on the market, a specialized forensic package
;costing over $3000.00 per license, which will explore this area in a comprehensive manner (actually more deeply than what is shown here), so its possible for malicious activity here to remain
;undetected for a long time until something happens which points to this area (rare) or someone actually checks or the user thinks something is wrong by indicators such as abnormal data
;usage or things simply not acting correctly communications wise but there are no indicators from normal AV/anti-malware packages. Some of the more recent hijacking activity techniques also
;seems to favor attacking this area.
;
;Additionally, finding a problem here can also be the cause of things, such as abnormally high ping in on-line games, or slow, or no, loading of, or access to, network resources such as shares.
;It is also possible for a poorly designed and implemented provider for an application to have corrupted an existing entry and cause problems.
;
;Being able to see all the available transport protocol's basic information, including the dummy or chain length zero entries, allows us a chance to detect malicious, or other, activity and/or problems
;in this area when compared against the norm.
;
;We load all the functions from the proper .dll's in this example and do not use the 'function_(etc....)' use of PureBasic implementation of these API functions. We do this to make sure PB
;is not interactive in the API function implementation and to help ensure that malicious activity detection (implemented later) for winsock is isolated from PB to avoid any possibility of false detection.
Debug "Winsock Catalog Available Transport Protocol Provider Entry (number available = " + Str(iNuminfo) + ")"
For i = 0 To iNuminfo - 1
Debug "----------------------------------------------------------"
If *buffproto\buf[i]\ProtocolChain\ChainLen = 1
entrytype$ = "Base Service Provider"
ElseIf *buffproto\buf[i]\ProtocolChain\ChainLen = 0
entrytype$ = "Layered Chain Entry"
Else
If *buffproto\buf[i]\ProtocolChain\ChainLen > 1
entrytype$ = "A protocol chain consisting of one or more layered protocols on top of a base protocol."
EndIf
EndIf
Debug "Entry type : " + entrytype$
If entrytype$ = "Layered Chain Entry"
Debug "(Note: A layered protocol is one that implements only higher level communications functions while relying on an underlying transport stack for actual data exchange with a remote endpoint.)"
EndIf
Debug "Description : " + PeekS(@*buffproto\buf[i]\szProtocol, -1, #PB_Unicode)
*BufGuid = AllocateMemory(80)
iRet = StringFromGUID2(@*buffproto\buf[i]\ProviderId, *BufGuid, 79)
guid$ = PeekS(*BufGuid, -1, #PB_Unicode)
FreeMemory(*BufGuid)
Debug "Provider ID : " + guid$
*lpszProviderDllPath = AllocateMemory(#MAX_PATH)
wscerr.i = WSCGetProviderPath(@*buffproto\buf[i]\ProviderId, *lpszProviderDllPath, @lpProviderDllPathLen, @lpErrno)
provpath$ = PeekS(*lpszProviderDllPath, -1, #PB_Unicode)
FreeMemory(*lpszProviderDllPath)
If provpath$ = ""
*lpszProviderDllPath = #Null
*lpszProviderDllPath = AllocateMemory(#MAX_PATH)
wscerr.i = WSCGetProviderPath(@*buffproto\buf[i]\ProviderId, *lpszProviderDllPath, @lpProviderDllPathLen, @lpErrno)
provpath$ = PeekS(*lpszProviderDllPath, -1, #PB_Unicode)
FreeMemory(*lpszProviderDllPath)
EndIf
Debug "Provider Path : " + provpath$
Debug "Catalog Entry ID : " + Str(*buffproto\buf[i]\dwCatalogEntryId)
Debug "Version : " + Str(*buffproto\buf[i]\iVersion)
Select *buffproto\buf[i]\iAddressFamily
Case #AF_INET
family$ = "The Internet Protocol version 4 (IPv4) address family."
Case #AF_IPX
family$ = "The IPX/SPX address family. Only supported if NWLink IPX/SPX NetBIOS Compatible Transport installed. Not supported on Windows Vista and later."
Case #AF_APPLETALK
family$ = "The AppleTalk address family. This address family is only supported if AppleTalk protocol is installed. Not supported on Windows Vista and later."
Case #AF_NETBIOS
family$ = "The NetBIOS address family. Only supported if the Windows Sockets provider for NetBIOS is installed."
Case #AF_INET6
family$ = "The Internet Protocol version 6 (IPv6) address family."
Case #AF_IRDA
family$ = "The Infrared Data Association (IrDA) address family. Only supported if computer has an infrared port and driver installed."
Case #AF_BTH
family$ = "The Bluetooth address family. Computer must have Bluetooth adapter and driver installed."
Default
family$ = "Unknown or undefined family type."
EndSelect
Debug "Address Family : " + family$ + " (" + Str(*buffproto\buf[i]\iAddressFamily) + ")"
Debug "Maximum Address length : " + Str(*buffproto\buf[i]\iMaxSockAddr)
Debug "Minimum Address length : " + Str(*buffproto\buf[i]\iMinSockAddr)
Select *buffproto\buf[i]\iSocketType
Case #SOCK_STREAM
socktype$ = "Provides sequenced, reliable, two-way, connection-based byte streams with OOB Data transmission mechanism. Uses Transmission Control Protocol (TCP) for Internet address familys IPv4 and IPv6."
Case #SOCK_DGRAM
socktype$ = "Supports datagrams, which are connectionless, unreliable buffers of a fixed (typically small) maximum length. Uses User Datagram Protocol (UDP) for Internet address familys IPv4 and IPv6."
Case #SOCK_RAW
socktype$ = "Provides raw socket allowing an application to manipulate next upper-layer protocol header. To manipulate the IPv4 header, the IP_HDRINCL option must be set on socket. To manipulate IPv6 header IPV6_HDRINCL option must be set on the socket."
Case #SOCK_RDM
socktype$ = "Provides a reliable message datagram. Only supported If the Reliable Multicast Protocol is installed."
Case #SOCK_SEQPACKET
socktype$ = "Provides a pseudo-stream packet based on datagrams."
Default
socktype$ = "Unknown or undefined socket type"
EndSelect
Debug "Socket Type : " + socktype$ + " (" + Str(*buffproto\buf[i]\iSocketType) + ")"
Select *buffproto\buf[i]\iProtocol
Case #IPPROTO_ICMP
ipproto$ = "Internet Control Message Protocol (ICMP)."
Case #IPPROTO_IGMP
ipproto$ = "Internet Group Management Protocol (IGMP)."
Case #BTHPROTO_RFCOMM
ipproto$ = "Bluetooth Radio Frequency Communications (Bluetooth RFCOMM) protocol."
Case #IPPROTO_TCP
ipproto$ = "Transmission Control Protocol (TCP)."
Case #IPPROTO_UDP
ipproto$ = "User Datagram Protocol (UDP)."
Case #IPPROTO_ICMPV6
ipproto$ = "Internet Control Message Protocol Version 6 (ICMPv6)."
Case #IPPROTO_RM
ipproto$ = "PGM protocol For reliable multicast. Only supported if the Reliable Multicast Protocol is installed."
Default
ipproto$ = "Unknown, undefined, not configured. disabled, requires other components. or not applicapable for this entry. Note: Only one protocol needs to be set per Provider ID catalog entry ID."
EndSelect
Debug "Protocol : " + ipproto$ + " (" + Str(*buffproto\buf[i]\iProtocol) + ")"
Select *buffproto\buf[i]\dwProviderFlags
Case #PFL_MULTIPLE_PROTO_ENTRIES
pfl$ = "This is one of two or more entries for a single protocol (from a given provider) capable of implementing multiple behaviors."
Case #PFL_RECOMMENDED_PROTO_ENTRY
pfl$ = "This is the recommended or most frequently used entry for a protocol that is capable of implementing multiple behaviors."
Case #PFL_HIDDEN
pfl$ = "Set by a provider indicating to Ws2_32.dll this protocol should not be returned in buffer generated by WSCEnumProtocols. Obviously, a Windows Sockets 2 application should never see an entry with this bit set."
Case #PFL_MATCHES_PROTOCOL_ZERO
pfl$ = "A value of zero in the protocol parameter of socket or WSASocket matches this protocol entry."
Case #PFL_NETWORKDIRECT_PROVIDER
pfl$ = "Set by a provider indicating support for network direct access (supported Windows 7 and Windows Server 2008 R2 only)."
Default
pfl$ = "Unknown or provider flags not set (most likely)"
EndSelect
If *buffproto\buf[i]\dwProviderFlags = #PFL_HIDDEN
Debug "Warning !!!!! Provider bit set to hide entry from protocol enumeration."
Debug pfl$
Debug "Warning !!!!! Provider bit set to hide entry from protocol enumeration."
Else
Debug "ProviderFlags : " + pfl$
EndIf
Debug "Protocol Chain Length : " + Str(*buffproto\buf[i]\ProtocolChain\ChainLen)
Debug "Service Flags : " + "0x" +Hex(*buffproto\buf[i]\dwServiceFlags1) + "(below flags are set by provider vendor and do not indicate how the protocol functions or operates.)"
;// Check which bit flags are set.
If (*buffproto\buf[i]\dwServiceFlags1 & #XP1_CONNECTIONLESS)
Debug " Protocol provides connectionless (datagram) service. If not set, the protocol supports connection-oriented data transfer."
EndIf
If (*buffproto\buf[i]\dwServiceFlags1 & #XP1_GUARANTEED_DELIVERY)
Debug " Protocol guarantees that all data sent will reach the intended destination."
EndIf
If (*buffproto\buf[i]\dwServiceFlags1 & #XP1_GUARANTEED_ORDER)
Debug " Protocol guarantees that data arrives in order sent and is not duplicated. This does not necessarily mean data is always delivered, but that any data delivered is delivered in the order sent."
EndIf
If (*buffproto\buf[i]\dwServiceFlags1 & #XP1_MESSAGE_ORIENTED)
Debug " Protocol honors message boundaries as opposed to a stream-oriented protocol where there is no concept of message boundaries."
EndIf
If (*buffproto\buf[i]\dwServiceFlags1 & #XP1_PSEUDO_STREAM)
Debug " Protocol is message-oriented protocol, but message boundaries are ignored for receipts. Convenient when application does not desire message framing done by protocol."
EndIf
If (*buffproto\buf[i]\dwServiceFlags1 & #XP1_GRACEFUL_CLOSE)
Debug " Protocol supports two-phase (graceful) close. If not set, only abortive closes performed."
EndIf
If (*buffproto\buf[i]\dwServiceFlags1 & #XP1_EXPEDITED_DATA)
Debug " Protocol supports expedited (urgent) data."
EndIf
If (*buffproto\buf[i]\dwServiceFlags1 & #XP1_CONNECT_DATA)
Debug " Protocol supports connect data."
EndIf
If (*buffproto\buf[i]\dwServiceFlags1 & #XP1_DISCONNECT_DATA)
Debug " Protocol supports disconnect data."
EndIf
If (*buffproto\buf[i]\dwServiceFlags1 & #XP1_SUPPORT_BROADCAST)
Debug " Protocol supports a broadcast mechanism."
EndIf
If (*buffproto\buf[i]\dwServiceFlags1 & #XP1_SUPPORT_MULTIPOINT)
Debug " Protocol supports a multipoint or multicast mechanism. Control and data plane attributes are indicated below :"
EndIf
If (*buffproto\buf[i]\dwServiceFlags1 & #XP1_SUPPORT_MULTIPOINT)
If (*buffproto\buf[i]\dwServiceFlags1 & #XP1_MULTIPOINT_CONTROL_PLANE) ;= 1
Debug " Protocol control plane is rooted (value = 1)."
Else
Debug " Protocol control plane is nonrooted (value = 0)."
EndIf
If (*buffproto\buf[i]\dwServiceFlags1 & #XP1_MULTIPOINT_DATA_PLANE) ;= 1
Debug " Protocol data plane is rooted (value = 1)."
Else
Debug " Protocol data plane is nonrooted (value = 0)."
EndIf
EndIf
If (*buffproto\buf[i]\dwServiceFlags1 & #XP1_QOS_SUPPORTED)
Debug " Protocol supports quality of service requests."
EndIf
If (*buffproto\buf[i]\dwServiceFlags1 & #XP1_INTERRUPT)
Debug " This bit is reserved."
EndIf
If (*buffproto\buf[i]\dwServiceFlags1 & #XP1_UNI_SEND)
Debug " Protocol is unidirectional in the send direction."
EndIf
If (*buffproto\buf[i]\dwServiceFlags1 & #XP1_UNI_RECV)
Debug " Protocol is unidirectional in the recv direction"
EndIf
If (*buffproto\buf[i]\dwServiceFlags1 & #XP1_UNI_SEND) = 0 And (*buffproto\buf[i]\dwServiceFlags1 & #XP1_UNI_RECV) = 0
Debug " Protocol is considered to be bidirectional."
EndIf
If (*buffproto\buf[i]\dwServiceFlags1 & #XP1_IFS_HANDLES)
Debug " Protocol socket descriptors returned by provider are operating system Installable File System (IFS) handles."
EndIf
If (*buffproto\buf[i]\dwServiceFlags1 & #XP1_PARTIAL_MESSAGE)
Debug " Protocol MSG_PARTIAL flag is supported in WSASend and WSASendTo."
EndIf
If (*buffproto\buf[i]\dwServiceFlags1 & #XP1_SAN_SUPPORT_SDP)
Debug " Protocol provides support for SAN. Supported on Windows 7 And Windows Server 2008 R2."
EndIf
Next
If *lpProtoInfo
FreeMemory(*lpProtoInfo)
*lpProtoInfo = #Null
EndIf
WSACleanup()
CloseLibrary(Lib_Winsock)
CloseLibrary(Lib_Ole32)