I don't want to confuse nor hijack his topic, so this reason I've created new one. Besides this more dedicated to conversions over from existing WinDivert sample applications sources .. like the one I'm posting today, netdump.
About WinDivert - http://reqrypt.org/windivert.html
“WinDivert is a user-mode capture/sniffing/modification/blocking/re-injection package for Windows Vista, Windows Server 2008, Windows 7, and Windows 8. WinDivert can be used to implement user-mode packet filters, packet sniffers, firewalls, NAT, VPNs, tunneling applications, etc., without the need to write kernel-mode code.
- The main features of the WinDivert are:
- User-mode packet capture, sniffing, dropping, filtering, modification, re-injection, etc.
- Simple, high-level, programming API.
- Fully documented with sample programs.
- Full IPv6 support.
- Full loopback (localhost) support.
- A modern WDF/WFP driver implementation.
- Open source; Licensed under GNU Lesser General Public License (LGPL) version 3. See the License for more information.
WinDivert provides similar functionality to divert sockets from FreeBSD/MacOS, NETLINK sockets from Linux, and some commercial packages such as WinPkFilter for Windows. WinDivert also supports passive packet sniffing similar to Winpcap. ”
My PureBasic WinDivert sample package is available HERE.. PBWinDivert_samples.zip
Example utility source code... Netdump
Code: Select all
; /*
; * DESCRIPTION:
; * This is a simple traffic monitor. It uses a WinDivert handle in SNIFF mode.
; * The SNIFF mode copies packets And does Not block the original.
; *
; * usage: netdump.exe windivert-filter [priority]
; netdump true ; < -- Diverts all traffic (w/WINDIVERT_FLAG_SNIFF flag.)
; */
IncludeFile "include\WinDivert_Header.pbi"
IncludeFile "include\WinDivert_Exit_Routine.pbi"
IncludeFile "include\Long2IP.pbi"
IncludeFile "include\IsPrint.pbi"
#MAXBUF = $FFFF
Procedure mainTask()
Protected.i Handle, Console
Protected.l I, packet_len
Protected.w Priority = 0
Protected.s tcpSrcPort, tcpDstPort, tcpSeqNum, tcpAckNum, tcpHdrLength, tcpRSRV, tcpNS
Protected.s tcpCWR, tcpECE, tcpURG, tcpACK, tcpPSH, tcpRST, tcpSYN, tcpFIN, tcpWin, tcpChksum, tcpUrgPtr
Protected.s udpSrcPort, udpDstPort, udpHdrLength, udpChksum, pData1.a
Protected.s IP_ver, IP_hdrlength, IP_tos, IP_length, IP_id, IP_fragResv, IP_fragsDF
Protected.s IP_fragsMF, IP_fragOffset, IP_TTL, IP_Protocol, IP_chksum
Protected.s IPv6_ver, IPv6_TrafficClass, IPv6_FlowLabel, IPv6_Length, IPv6_NextHdr.s, IPv6_HopLimit
Protected.u IPv6_SrcAddr, IPv6_dstAddr
Protected.s ICMP_Type, ICMP_Code, ICMP_Chksum, ICMP_Body
Protected.s ICMPv6_Type, ICMPv6_Code, ICMPv6_Chksum, ICMPv6_Body
*Packet = AllocateMemory(#MAXBUF)
SafeExit\Packet = *Packet
addr.WINDIVERT_ADDRESS
*ip_header.WINDIVERT_IPHDR
*ipv6_header.WINDIVERT_IPV6HDR
*icmp_header.WINDIVERT_ICMPHDR
*icmpv6_header.WINDIVERT_ICMPV6HDR
*tcp_header.WINDIVERT_TCPHDR
*udp_header.WINDIVERT_UDPHDR
If Not OpenConsole()
MessageRequester("netdump", "Unable to open Console, program will now close", #PB_MessageRequester_Ok)
End
EndIf
Select CountProgramParameters()
Case 1
filter$ + ProgramParameter(0)
Case 2
Priority = Val(ProgramParameter(1))
Default
PrintN("Usage: netdump windivert-filter [priority]"+#CRLF$+#CRLF$+
"Examples:"+#CRLF$+
" netdump true"+#CRLF$+
" netdump "+#DQUOTE$+"outbound and tcp.DstPort == 80"+#DQUOTE$+" 1000"+#CRLF$+
" netdump "+#DQUOTE$+"inbound and tcp.Syn"+#DQUOTE$+" -4000")
;filter$ = "outbound and tcp.DstPort == 80"
Exit()
EndSelect
; // Get console For pretty colors.
Console = GetStdHandle_(#STD_OUTPUT_HANDLE)
SafeExit\Console = Console
; // Divert traffic matching the filter:
handle = WinDivertOpen(filter$, #WINDIVERT_LAYER_NETWORK, priority, #WINDIVERT_FLAG_SNIFF)
SafeExit\hWndDivert = handle
If handle = #INVALID_HANDLE_VALUE
If GetLastError_() = #ERROR_INVALID_PARAMETER
PrintN("error: filter syntax error")
Exit()
Else
PrintN("error: failed To open the WinDivert device ("+Str(GetLastError_())+")")
Exit()
EndIf
EndIf
; // Max-out the packet queue:
If Not WinDivertSetParam(handle, #WINDIVERT_PARAM_QUEUE_LEN, 8192)
PrintN("error: failed to set packet queue length ("+Str(GetLastError_())+")")
Exit()
ElseIf Not WinDivertSetParam(handle, #WINDIVERT_PARAM_QUEUE_TIME, 2048)
PrintN("error: failed to set packet queue time ("+Str(GetLastError_())+")")
Exit()
EndIf
PrintN("Now waiting for network activity."+#CRLF$)
; Main Loop:
Repeat
; // Read a matching packet.
If Not WinDivertRecv(handle, *packet, MemorySize(*packet), @addr, @packet_len)
PrintN("warning: failed to read packet ("+Str(GetLastError_())+")")
Continue
EndIf
; // Print info about the matching packet.
WinDivertHelperParsePacket(*packet, packet_len, @*ip_header, @*ipv6_header, @*icmp_header, @*icmpv6_header, @*tcp_header, @*udp_header, #Null, #Null)
If Not *ip_header And Not *ipv6_header
PrintN("warning: junk packet")
EndIf
; // Dump packet info:
SetConsoleTextAttribute_(Console, #FOREGROUND_RED)
PrintN(#CRLF$+"Packet [Direction="+Str(addr\Direction)+" IfIdx="+Str(addr\IfIdx)+" SubIfIdx="+Str(addr\SubIfIdx))
If *ip_header
IP_ver = Str(GET_ipVERSION(*ip_header))
IP_hdrlength = Str(GET_ipHDRLENGTH(*ip_header))
IP_tos = Str(ntohs_(PeekA(@*ip_header\TOS)))
IP_length = Str(ntohs_(PeekU(@*ip_header\Length)))
IP_id = RSet(Hex(ntohs_(PeekU(@*ip_header\Id))), 4, "0")
IP_fragResv = Str(WINDIVERT_IPHDR_GET_RESERVED(*ip_header))
IP_fragsDF = Str(WINDIVERT_IPHDR_GET_DF(*ip_header))
IP_fragsMF = Str(WINDIVERT_IPHDR_GET_MF(*ip_header))
IP_fragOffset = Str(WINDIVERT_IPHDR_GET_FRAGOFF(*ip_header))
IP_TTL = Str(PeekA(@*ip_header\TTL))
IP_Protocol = Str(PeekA(@*ip_header\Protocol))
IP_chksum = Hex(ntohs_(PeekU(@*ip_header\Checksum)))
IP_srcAddr$ = Long2IP(ntohl_(PeekL(@*ip_header\SrcAddr)))
IP_dstAddr$ = Long2IP(ntohl_(PeekL(@*ip_header\DstAddr)))
SetConsoleTextAttribute_(Console, #FOREGROUND_GREEN | #FOREGROUND_RED)
PrintN("IPv4 [Version=" + IP_ver + " HdrLength=" + IP_hdrlength +
" TOS=" + IP_tos + " Length=" + IP_length + " Id=0x" + IP_id +
" Reserved=" + IP_fragResv + " DF=" + IP_fragsDF + " MF=" + IP_fragsMF +
" FragOff=" + IP_fragOffset + " TTL=" + IP_TTL + " Protocol=" + IP_Protocol +
" Checksum=0x" + IP_chksum +" SrcAddr="+IP_srcAddr$+" DstAddr="+IP_dstAddr$ + "]")
EndIf
If *ipv6_header
IPv6_ver = Str(GET_IPv6VERSION(*ipv6_header))
IPv6_TrafficClass = Str(WINDIVERT_IPV6HDR_GET_TRAFFICCLASS(*ipv6_header))
IPv6_FlowLabel = Str(WINDIVERT_IPV6HDR_GET_FLOWLABEL(*ipv6_header))
IPv6_Length = Str(ntohs_(PeekU(@*ipv6_header\Length)))
IPv6_NextHdr = Str(PeekA(@*ipv6_header\NextHdr))
IPv6_HopLimit = Str(PeekA(@*ipv6_header\HopLimit))
IPv6_srcAddr$ = "" : IPv6_dstAddr$ = ""
For k = 0 To 7
IPv6_srcAddr = PeekU(@*ipv6_header\SrcAddr[k])
IPv6_dstAddr = PeekU(@*ipv6_header\DstAddr[k])
If IPv6_srcAddr : IPv6_srcAddr$ + LCase(Hex(ntohs_(IPv6_srcAddr))) : EndIf
If IPv6_dstAddr : IPv6_dstAddr$ + LCase(Hex(ntohs_(IPv6_dstAddr))) : EndIf
If k = 0 : IPv6_srcAddr$ + "::" : IPv6_dstAddr$ + "::"
ElseIf k < 7
If IPv6_srcAddr : IPv6_srcAddr$ + ":" : EndIf
If IPv6_dstAddr : IPv6_dstAddr$ + ":" : EndIf
EndIf
Next
SetConsoleTextAttribute_(Console, #FOREGROUND_GREEN | #FOREGROUND_RED)
PrintN("IPv6 [Version=" + IPv6_ver + " TrafficClass=" + IPv6_TrafficClass + " FlowLabel=" + IPv6_FlowLabel +
" Length=" + IPv6_length + " NextHdr=" + IPv6_NextHdr + " HopLimit=" + IPv6_HopLimit + " SrcAddr=" + IPv6_srcAddr$ +
" DstAddr=" + IPv6_dstAddr$ + "]")
EndIf
If *icmp_header
ICMP_Type = Str(PeekA(@*icmp_header\Type))
ICMP_Code = Str(PeekA(@*icmp_header\Code))
ICMP_Chksum = Hex(ntohs_(PeekU(@*icmp_header\Checksum)))
ICMP_Body = Str(ntohl_(PeekL(@*icmp_header\Body)))
SetConsoleTextAttribute_(Console, #FOREGROUND_RED)
PrintN("ICMP [Type=" + ICMP_Type + " Code=" + ICMP_Code + " Checksum=0x" + ICMP_Chksum + " Body=0x" + ICMP_Body + "]")
EndIf
If *icmpv6_header
ICMPv6_Type = Str(PeekA(@*icmpv6_header\Type))
ICMPv6_Code = Str(PeekA(@*icmpv6_header\Code))
ICMPv6_Chksum = Hex(ntohs_(PeekU(@*icmpv6_header\Checksum)))
ICMPv6_Body = Str(ntohl_(PeekL(@*icmpv6_header\Body)))
SetConsoleTextAttribute_(Console, #FOREGROUND_RED)
PrintN("ICMPV6 [Type=" + ICMPv6_Type + " Code=" + ICMPv6_Code + " Checksum=0x" + ICMPv6_Chksum + " Body=0x" + ICMPv6_Body + "]")
EndIf
If *tcp_header
tcpSrcPort = Str(ntohs_(PeekU(@*tcp_header\SrcPort)))
tcpDstPort = Str(ntohs_(PeekU(@*tcp_header\DstPort)))
tcpSeqNum = Str(ntohl_(PeekL(@*tcp_header\SeqNum)) & $FFFFFFFF)
tcpAckNum = Str(ntohl_(PeekL(@*tcp_header\AckNum)) & $FFFFFFFF)
tcpHdrLength = Str(GET_tcpHDRLENGTH(*tcp_header))
tcpRSRV = Str(GET_tcpRESERVED(*tcp_header))
tcpNS = Str(GET_tcpNS(*tcp_header))
tcpCWR = Str(GET_tcpCWR(*tcp_header))
tcpECE = Str(GET_tcpECE(*tcp_header))
tcpURG = Str(GET_tcpURG(*tcp_header))
tcpACK = Str(GET_tcpACK(*tcp_header))
tcpPSH = Str(GET_tcpPSH(*tcp_header))
tcpRST = Str(GET_tcpRST(*tcp_header))
tcpSYN = Str(GET_tcpSYN(*tcp_header))
tcpFIN = Str(GET_tcpFIN(*tcp_header))
tcpWin = Str(ntohs_(PeekU(@*tcp_header\Window)))
tcpChksum = Hex(ntohs_(PeekU(@*tcp_header\Checksum)))
tcpUrgPtr = Str(ntohs_(PeekU(@*tcp_header\UrgPtr)))
SetConsoleTextAttribute_(Console, #FOREGROUND_GREEN)
PrintN("TCP [SrcPort=" + tcpSrcPort + " DstPort=" + tcpDstPort + " SeqNum=" + tcpSeqNum + " AckNum=" + tcpAckNum +
" HdrLength=" + tcpHdrLength + " Reserved=" + tcpRSRV + " Flags:[NS="+tcpNS + " CWR=" + tcpCWR + " ECE=" + tcpECE + " URG=" + tcpURG +
" ACK=" + tcpACK + " PSH=" + tcpPSH + " RST=" + tcpRST + " SYN=" + tcpSYN + " FIN=" + tcpFIN +
"] Window=" + tcpWin + " Checksum=0x" + tcpChksum + " UrgPtr=" + tcpUrgPtr + "]")
EndIf
If *udp_header
udpSrcPort = Str(ntohs_(PeekU(@*udp_header\SrcPort)))
udpDstPort = Str(ntohs_(PeekU(@*udp_header\DstPort)))
udpHdrLength = Str(ntohs_(PeekU(@*udp_header\Length)))
udpChksum = Hex(ntohs_(PeekU(@*udp_header\Checksum)))
SetConsoleTextAttribute_(Console, #FOREGROUND_GREEN)
PrintN("UDP [SrcPort=" + udpSrcPort + " DstPort=" + udpDstPort + " Length=" + udpHdrLength + " Checksum=0x" + udpChksum + "]")
EndIf
SetConsoleTextAttribute_(Console, #FOREGROUND_GREEN | #FOREGROUND_BLUE)
pData$ = ""
For i = 0 To packet_len-1
If (i % 20) = 0
pData$ + #CRLF$ + " "
EndIf
pData$ + RSet(Hex(PeekA(*Packet+i)), 2, "0")
Next
PrintN(pData$)
SetConsoleTextAttribute_(Console, #FOREGROUND_RED | #FOREGROUND_BLUE)
pData$ = "" : pData = 0
For i = 0 To packet_len-1
If (i % 40) = 0
pData$ + #CRLF$ + " "
EndIf
pData = PeekA(*Packet+i)
If IsPrint(pData) : pData$ + Chr(PeekA(*Packet+i))
Else
pData$ + "."
EndIf
Next
PrintN(pData$+#CRLF$)
ForEver
EndProcedure
mainTask()
Changelog
Code: Select all
Rev #5 (Updated on Tuesday Dec 2, 2014)
* Added netfilter.pb (Credits to the PureBasic community. Special thanks to infratec & JHPJHP for the aid.)
* Tweaks to existing projects.
-----------
Rev #4 (Updated on Sunday Nov 23, 2014)
* netdump.pb (location: parent)
- More code beautification.
* GetTCPFlags_.pbi (formely known as GetTCPFlags_STR.pbi, Location: \Include\)
- Revamped the old procedure.
-----------
Rev #3 (Updated on Friday Nov 21, 2014)
* Updated to WinDivert 1.1.7 Library and required driver files. (Enhancements to IPv6 support)
* WinDivert_Header.pbi (location: \Includes\)
- Updated existing PB-Specific Macros labelling.
- PureBasic - Specific Macros additions (e.g, .. GET_tcpSYN(), SET_tcpSYN, UNSET_tcpSYN.)
- Particular WINDIVERT_TCPHDR Structure Field names been changed.
* netdump.pb (location: parent)
- Match changes made in WinDivert_Header.pbi file.
- Beautified the code.
- TCP Header logging now defines three more tcp flags (NS, CWR, ECE)
-----------
Rev #2 (Updated on Wed Nov 19, 2014
* WinDivert_Header.pbi
- Added two additional PureBasic - Specific Macros.
..WINDIVERT_IPHDR_SET_VERSION(), INDIVERT_IPHDR_SET_HDRLENGTH()
* netdump.pb
- N/A
-----------
Rev #1 (Updated on Wed Nov 16, 2014)
* WinDivert_Header.pbi
- Updates to the Macros labelling. Couple still was using the old WinDivert Macro names.
- Added two additional PureBasic - Specific Macro.
..WINDIVERT_IPHDR_GET_VERSION(), WINDIVERT_IPHDR_GET_HDRLENGTH()
* netdump.pb
- Now using the two new WinDivert Header file Macros additions.
..WINDIVERT_IPHDR_GET_VERSION(), WINDIVERT_IPHDR_GET_HDRLENGTH()
- Adjustment to RSet() on IP Header ID retrieval, showing couple extra characters.