Here are my updates.
Code: Select all
;Activate 'threadsafe executable' and 'Request Administrator' in PB Compiler Options, and deactivate 'unicode executable' for this version.
Structure DIVERT_ADDRESS
IfIdx.l
SubIfIdx.l
Direction.a
EndStructure
Structure DIVERT_IPHDR
StructureUnion
HdrLength.a
Version.a
EndStructureUnion
TOS.a
Length.u
Id.u
FragOff0.u
TTL.a
Protocol.a
Checksum.u
SrcAddr.l
DstAddr.l
EndStructure
Structure DIVERT_IPV6HDR
StructureUnion
TrafficClass0.a
Version.a
FlowLabel0.a
TrafficClass1.a
EndStructureUnion
FlowLabel1.u
Length.u
NextHdr.a
HopLimit.a
SrcAddr.l[4]
DstAddr.l[4]
EndStructure
Structure DIVERT_ICMPHDR
Type.a
Code.a
Checksum.u
Body.l
EndStructure
Structure DIVERT_ICMPV6HDR
Type.a
Code.a
Checksum.u
Body.l
EndStructure
Structure DIVERT_TCPHDR
SrcPort.u
DstPort.u
SeqNum.l
AckNum.l
StructureUnion
Reserved1.a
HdrLength.a
;;;;HdrLength.u
;;;;Reserved1.u
EndStructureUnion
StructureUnion
Fin.a
Syn.a
Rst.a
Psh.a
Ack.a
Urg.a
Reserved2.a
;;;;Fin.u
;;;;Syn.u
;;;;Rst.u
;;;;Psh.u
;;;;Ack.u
;;;;Urg.u
EndStructureUnion
;;;;StructureUnion
;;;; Reserved2.u
;;;;EndStructureUnion
Window.u
Checksum.u
UrgPtr.u
EndStructure
Structure DIVERT_UDPHDR
SrcPort.u
DstPort.u
Length.u
Checksum.u
EndStructure
#MAXBUF = $FFFF
#DIVERT_DIRECTION_OUTBOUND = 0
#DIVERT_DIRECTION_INBOUND = 1
#ERROR_INVALID_PARAMETER = 87 ;This indicates an invalid packet filter string, layer, priority, Or flags.
#ERROR_FILE_NOT_FOUND = 2 ;One Or more of the WinDivert.sys, WinDivert.inf, And WdfCoInstaller*.dll files were Not found.
#ERROR_ACCESS_DENIED = 5 ;The calling application does Not have Administrator privileges.
#ERROR_INVALID_IMAGE_HASH = 577 ;The WinDivert.sys driver does Not have a valid digital signature (see the driver signing requirements above), Or
; / *
#DIVERT_FLAG_SNIFF = 1 ;
;This flag opens the WinDivert handle in packet sniffing mode. In packet sniffing mode the original packet is
; Not dropped-And-diverted (the Default) but copied-And-diverted. This mode is useful For implementing packet
; sniffing tools similar To those applications that currently use Winpcap.
#DIVERT_FLAG_DROP = 2
;This flag indicates that the user application does not intend to read matching packets with DivertRecv(), instead the
; packets should be silently dropped. This is useful For implementing simple packet filters using the WinDivert filter language.
;If both DIVERT_FLAG_SNIFF and DIVERT_FLAG_DROP flags are set, the WinDivert handle will be in "passthru" mode that neither captures
;nor drops any packet. Such a handle is useful For applications that only require packet injection
; * \
; #DIVERT_PARAM_QUEUE_LEN = 0, ; /* Packet queue length. */
;Sets the maximum length of the packet queue for DivertRecv(). Currently the default value is 512, the minimum is 1, and the maximum is 8192.
; #DIVERT_PARAM_QUEUE_TIME = 1 ; /* Packet queue time. */
;Sets the minimum time, in milliseconds, a packet can be queued before it is automatically dropped. Packets cannot be queued indefinitely,
; And ideally, packets should be processed by the application As soon As is possible. Note that this sets the minimum time a packet can be
; queued before it can be dropped. The actual time may be exceed this value.
; Currently the Default value is 256, the minimum is 32, And the maximum is 1024.
#IP_CE = $8000 ; Congestion Experienced
#IP_DF = $000 ; Don't Fragment
#IP_MF = $2000 ; More Fragments
#IP_OFFMASK = $1FFF ; Offset mask value
#tcp_FlagFIN = $0001
#tcp_FlagSYN = $0002
#tcp_FlagRST = $0004
#tcp_FlagPUSH = $0008
#tcp_FlagACK = $0010
#tcp_FlagURG = $0020
#tcp_FlagECN = $0040 ; ECN-Echo
#tcp_FlagCWR = $0080 ; Congestion Window reduced
#tcp_FlagNS = $0100
#tcp_FlagRS = $0E00
#tcp_FlagMASK = $003F ; All Flags considered.
#tcp_FlagDO = $F000
#tcp_flagsAll = #tcp_FlagFIN | #tcp_FlagSYN | #tcp_FlagRST | #tcp_FlagPUSH | #tcp_FlagACK | #tcp_FlagURG ; #tcp_FlagECN | #tcp_FlagCWR | ; #tcp_FlagNS | #tcp_FlagRS
#DIVERT_HELPER_NO_IP_CHECKSUM = 1
#DIVERT_HELPER_NO_ICMP_CHECKSUM = 2
#DIVERT_HELPER_NO_ICMPV6_CHECKSUM = 4
#DIVERT_HELPER_NO_TCP_CHECKSUM = 8
#DIVERT_HELPER_NO_UDP_CHECKSUM = 16
Prototype protoDivertOpen(filter.s, layer, priority.u, flags.q)
Global DivertOpen.protoDivertOpen
Prototype.b protoDivertGetParam(handle, param, pValue.q)
Global DivertGetParam.protoDivertGetParam
Prototype.b protoDivertSetParam(handle, param, value.q)
Global DivertSetParam.protoDivertSetParam
Prototype.b protoDivertRecv(handle, *pPacket, packetLen, pAddr, recvLen)
Global DivertRecv.protoDivertRecv
Prototype.b protoDivertSend(handle, *pPacket, packetLen, pAddr, sendLen)
Global DivertSend.protoDivertSend
Prototype.b protoDivertHelperParsePacket(*pPacket, packetLen, *ppIpHdr, *ppIpv6Hdr, *ppIcmpHdr, *ppIcmpv6Hdr, *ppTcpHdr, *ppUdpHdr, *ppData, pDataLen)
Global DivertHelperParsePacket.protoDivertHelperParsePacket
Prototype.b protoDivertHelperParseIPv4Address(addrStr.s, *pAddr)
Global DivertHelperParseIPv4Address.protoDivertHelperParseIPv4Address
Prototype.b protoDivertHelperParseIPv6Address(addrStr.s, *pAddr)
Global DivertHelperParseIPv6Address.protoDivertHelperParseIPv6Address
Prototype protoDivertHelperCalcChecksums(*pPacket, packetLen, flags.q)
Global DivertHelperCalcChecksums.protoDivertHelperCalcChecksums
Prototype.b protoDivertClose(handle)
Global DivertClose.protoDivertClose
Procedure.s MatchFlags(tp.s)
tcpFlags.s = "RS NS CWR ECE URG ACK PSH RST SYN FIN"
len = Len(tp) : If len > 13 : len = 13 : EndIf : tcpMultiFlags.s = ""
While len > 0 ;And len < 12
If 0 < len :
If Mid(tp, len, 1) <> "1" : len-1 : Continue : EndIf
tcpMultiFlags + ", " + StringField(tcpFlags,len-3, " ") :
EndIf
len-1
Wend
If Mid(tcpMultiFlags, 1, 2) = ", " : tcpMultiFlags = "("+Mid(tcpMultiFlags,2)+")" : EndIf
ProcedureReturn tcpMultiFlags
EndProcedure
Procedure.s TestForError()
Result.s = ""
dwMessageId = GetLastError_()
*lpBuffer = AllocateMemory(255)
FormatMessage_(#FORMAT_MESSAGE_FROM_SYSTEM, #Null, dwMessageId, #Null, *lpBuffer, MemorySize(*lpBuffer), #Null)
dwDescription.s = PeekS(*lpBuffer)
Result = "Error: " + Str(dwMessageId) + " - " + Left(dwDescription, Len(dwDescription) - 1)
FreeMemory(*lpBuffer)
ProcedureReturn Result
EndProcedure
WinDivert = OpenLibrary(#PB_Any, "WinDivert.dll")
If IsLibrary(WinDivert)
DivertOpen = GetFunction(WinDivert, "DivertOpen")
; filter.s = "true" ;true - Divert all traffic, false - Diverts no traffic
filter.s = "outbound && ip && (tcp.DstPort == 80 && tcp.PayloadLength > 0)"
#DIVERT_LAYER_NETWORK = 0 ; /* The network layer. 0 is the default. */
#DIVERT_LAYER_NETWORK_FORWARD = 1 ; /* The network layer (forwarded packets). */
#DIVERT_PRIORITY_DEFAULT = -1000
hWndDivert = DivertOpen(filter, #DIVERT_LAYER_NETWORK, #DIVERT_PRIORITY_DEFAULT, #DIVERT_FLAG_SNIFF)
If hWndDivert <> #INVALID_HANDLE_VALUE
Debug "---------------"
Debug "DivertOpen"
Debug "---------------"
Debug "hWndDivert: " + Str(hWndDivert)
Debug " filter: " + filter
#DIVERT_PARAM_QUEUE_LEN = 0
#DIVERT_PARAM_QUEUE_TIME = 1
DivertSetParam = GetFunction(WinDivert, "DivertSetParam")
DivertSetParam(hWndDivert, #DIVERT_PARAM_QUEUE_LEN, 8192)
DivertSetParam(hWndDivert, #DIVERT_PARAM_QUEUE_TIME, 1024)
*pPacket = AllocateMemory(#MAXBUF)
pAddr.DIVERT_ADDRESS
DivertRecv = GetFunction(WinDivert, "DivertRecv")
If DivertRecv(hWndDivert, *pPacket, MemorySize(*pPacket), @pAddr, @recvLen)
Debug "---------------"
Debug "DivertRecv"
Debug "---------------"
Debug "pAddr\IfIdx: " + PeekL(@pAddr\IfIdx)
Debug "pAddr\SubIfIdx: " + PeekL(@pAddr\SubIfIdx)
If PeekA(@pAddr\Direction) : pDirection.s = "1 for Inbound" : Else : pDirection.s = "0 for Outbound" : EndIf
Debug "pAddr\Direction: " + pDirection : Debug ""
*ppIpHdr.DIVERT_IPHDR : *ppIpv6Hdr.DIVERT_IPV6HDR : *ppIcmpHdr.DIVERT_ICMPHDR
*ppIcmpv6Hdr.DIVERT_ICMPV6HDR : *ppTcpHdr.DIVERT_TCPHDR : *ppUdpHdr.DIVERT_UDPHDR
DivertHelperParsePacket = GetFunction(WinDivert, "DivertHelperParsePacket")
DivertHelperParsePacket(*pPacket, recvLen, @*ppIpHdr, @*ppIpv6Hdr, @*ppIcmpHdr, @*ppIcmpv6Hdr, @*ppTcpHdr, @*ppUdpHdr, @*ppData, @pDataLen)
If *ppIpHdr
Debug "ppIpHdr\Version: " + Str(PeekA(@*ppIpHdr\Version) >> 4 & %1111)
Debug "ppIpHdr\HdrLength: " + Str((PeekA(@*ppIpHdr\HdrLength) & %1111) * 4) + " bytes"
Debug "ppIpHdr\TOS: " + ntohs_(PeekA(@*ppIpHdr\TOS))
Debug "ppIpHdr\Length: " + ntohs_(PeekU(@*ppIpHdr\Length))
ipHdrId.u = ntohs_(PeekU(@*ppIpHdr\Id))
Debug "ppIpHdr\Id: 0x"+RSet (Hex(ipHdrId), 4, "0") + " (" + ipHdrId + ")"
;;;;Debug "ppIpHdr\Id: " + ntohs_(PeekU(@*ppIpHdr\Id))
FragOff0.u = PeekU(@*ppIpHdr\FragOff0)
FragCalc1.l = (FragOff0 & $0080) >> 7 : FragCalc2.l = (FragOff0 & $0040) >> 6
FragCalc3.l = (FragOff0 & $0020) >> 5 : FragCalc4.l = ntohs_(FragOff0 & $FF1F) * 8
FragOff_Str.s = "0x0"
If FragCalc1 : FragOff_Str + "3 (Reserved)"
ElseIf FragCalc2 : FragOff_Str + "2 (Don't Fragment)"
ElseIf FragCalc3 : FragOff_Str + "1 (More Fragment)"
Else : FragOff_Str + "0 (Fragment Offset)"
EndIf
Debug "ppIpHdr\FragOff0"
Debug "_Flags: "+FragOff_Str
Debug " --Bit 0 (Reseverd): " + Str(FragCalc1)
Debug " --Bit 1 (May Fragment = 0 / Don't Fragment = 1): " + Str(FragCalc2)
Debug " --Bit 2 (Last Fragment = 0 / More Fragments = 1): " + Str(FragCalc3)
Debug " --Fragment Offset: " + Str(FragCalc4)
Debug ""
Debug "ppIpHdr\TTL: " + PeekA(@*ppIpHdr\TTL)
IpHdrProtocol.a = PeekA(@*ppIpHdr\Protocol) : IpProtocol.s
Select IpHdrProtocol
Case 1 : IpProtocol = "ICMP"
Case 2 : IpProtocol = "IGMP"
Case 6 : IpProtocol = "TCP"
Case 17 : IpProtocol = "UDP"
Case 47 : IpProtocol = "GRE"
Default : IpProtocol = "Other"
EndSelect
Debug "ppIpHdr\Protocol: " + IpProtocol + " ("+IpHdrProtocol+")"
ipHdrChksum.u = ntohs_(PeekU(@*ppIpHdr\Checksum))
Debug "ppIpHdr\Checksum: 0x" + RSet (Hex(ipHdrChksum), 4, "0") + " (" + ipHdrChksum + ")"
;;;;;;;;Debug "ppIpHdr\Checksum: " + ntohs_(PeekU(@*ppIpHdr\Checksum))
Debug "ppIpHdr\SrcAddr: " + IPString(PeekL(@*ppIpHdr\SrcAddr))
Debug "ppIpHdr\DstAddr: " + IPString(PeekL(@*ppIpHdr\DstAddr))
EndIf
If *ppIpv6Hdr
Debug "---------------"
Debug "ppIpv6Hdr\TrafficClass0: " + PeekA(@*ppIpv6Hdr\TrafficClass0)
Debug "ppIpv6Hdr\Version: " + PeekA(@*ppIpv6Hdr\Version)
Debug "ppIpv6Hdr\FlowLabel0: " + PeekA(@*ppIpv6Hdr\FlowLabel0)
Debug "ppIpv6Hdr\TrafficClass1: " + PeekA(@*ppIpv6Hdr\TrafficClass1)
Debug "ppIpv6Hdr\FlowLabel1: " + ntohs_(PeekU(@*ppIpv6Hdr\FlowLabel1))
Debug "ppIpv6Hdr\Length: " + ntohs_(PeekU(@*ppIpv6Hdr\Length))
Debug "ppIpv6Hdr\NextHdr: " + PeekA(@*ppIpv6Hdr\NextHdr)
Debug "ppIpv6Hdr\HopLimit: " + PeekA(@*ppIpv6Hdr\HopLimit)
Debug "ppIpv6Hdr\SrcAddr[1]: " + IPString(PeekL(@*ppIpv6Hdr\SrcAddr[0]))
Debug "ppIpv6Hdr\SrcAddr[2]: " + IPString(PeekL(@*ppIpv6Hdr\SrcAddr[1]))
Debug "ppIpv6Hdr\SrcAddr[3]: " + IPString(PeekL(@*ppIpv6Hdr\SrcAddr[2]))
Debug "ppIpv6Hdr\SrcAddr[4]: " + IPString(PeekL(@*ppIpv6Hdr\SrcAddr[3]))
Debug "ppIpv6Hdr\DstAddr[1]: " + IPString(PeekL(@*ppIpv6Hdr\DstAddr[0]))
Debug "ppIpv6Hdr\DstAddr[2]: " + IPString(PeekL(@*ppIpv6Hdr\DstAddr[1]))
Debug "ppIpv6Hdr\DstAddr[3]: " + IPString(PeekL(@*ppIpv6Hdr\DstAddr[2]))
Debug "ppIpv6Hdr\DstAddr[4]: " + IPString(PeekL(@*ppIpv6Hdr\DstAddr[3]))
EndIf
If *ppIcmpHdr
Debug "---------------"
Debug "ppIcmpHdr\Type: " + PeekA(@*ppIcmpHdr\Type)
Debug "ppIcmpHdr\Code: " + PeekA(@*ppIcmpHdr\Code)
icmpHdrChksum.u = ntohs_(PeekU(@*ppIcmpHdr\Checksum))
Debug "ppIcmpHdr\Checksum: 0x" + RSet (Hex(icmpHdrChksum), 4, "0") + " ("+ icmpHdrChksum+")"
;;;;;;;;Debug "ppIcmpHdr\Checksum: " + ntohs_(PeekU(ppIcmpHdr\Checksum))
Debug "ppIcmpHdr\Body: " + ntohl_(PeekL(@*ppIcmpHdr\Body))
EndIf
If *ppIcmpv6Hdr
Debug "---------------"
Debug "ppIcmpv6Hdr\Type: " + PeekA(@*ppIcmpv6Hdr\Type)
Debug "ppIcmpv6Hdr\Code: " + PeekA(@*ppIcmpv6Hdr\Code)
Debug "ppIcmpv6Hdr\Checksum: " + ntohs_(PeekU(@*ppIcmpv6Hdr\Checksum))
Debug "ppIcmpv6Hdr\Body: " + ntohl_(PeekL(@*ppIcmpv6Hdr\Body))
EndIf
If *ppTcpHdr
Debug "---------------"
Debug "ppTcpHdr\SrcPort: " + ntohs_(PeekU(@*ppTcpHdr\SrcPort))
Debug "ppTcpHdr\DstPort: " + ntohs_(PeekU(@*ppTcpHdr\DstPort))
Debug "ppTcpHdr\SeqNum: " + ntohl_(PeekL(@*ppTcpHdr\SeqNum))
Debug "ppTcpHdr\AckNum: " + ntohl_(PeekL(@*ppTcpHdr\AckNum))
Debug "ppTcpHdr\HdrLength: " + Str((PeekB(@*ppTcpHdr\HdrLength) >> 4 & %1111) * 4) + " bytes"
Debug "ppTcpHdr\Reserved1: " + Str(PeekB(@*ppTcpHdr\Reserved1) & %1111)
; Debug "ppTcpHdr\Reserved1: " + PeekU(@*ppTcpHdr\Reserved1)
; Debug "ppTcpHdr\HdrLength: " + PeekU(@*ppTcpHdr\HdrLength)
Debug "ppTcpHdr\[Reserved2, Urg, Ack, Psh, Rst, Syn, Fin]" : tcpFlags.b = PeekB(@*ppTcpHdr\Urg)
Debug "_TCP Flags: (0x"+ Hex(tcpFlags) +") "+MatchFlags(RSet(Bin(tcpFlags),10,"0"))
;;;;;;;;Debug "ppTcpHdr\Fin: " + PeekU(@*ppTcpHdr\Fin)
;;;;;;;;Debug "ppTcpHdr\Syn: " + PeekU(@*ppTcpHdr\Syn)
;;;;;;;;Debug "ppTcpHdr\Rst: " + PeekU(@*ppTcpHdr\Rst)
;;;;;;;;Debug "ppTcpHdr\Psh: " + PeekU(@*ppTcpHdr\Psh)
;;;;;;;;Debug "ppTcpHdr\Ack: " + PeekU(@*ppTcpHdr\Ack)
;;;;;;;;Debug "ppTcpHdr\Urg: " + PeekU(@*ppTcpHdr\Urg)
;;;;;;;;Debug "ppTcpHdr\Reserved2: " + PeekU(@*ppTcpHdr\Reserved2)
Debug "ppTcpHdr\Window: " + ntohs_(PeekU(@*ppTcpHdr\Window))
tcpHdrChksum.u = ntohs_(PeekU(@*ppTcpHdr\Checksum))
Debug "ppTcpHdr\Checksum: 0x" + RSet (Hex(tcpHdrChksum), 4, "0") + " ("+ tcpHdrChksum+")"
;;;;;;;;Debug "ppTcpHdr\Checksum: " + ntohs_(PeekU(@*ppTcpHdr\Checksum))
Debug "ppTcpHdr\UrgPtr: " + ntohs_(PeekU(@*ppTcpHdr\UrgPtr))
EndIf
If *ppUdpHdr
Debug "---------------"
Debug "ppUdpHdr\SrcPort: " + ntohs_(PeekU(@*ppUdpHdr\SrcPort))
Debug "ppUdpHdr\DstPort: " + ntohs_(PeekU(@*ppUdpHdr\DstPort))
Debug "ppUdpHdr\Length: " + ntohs_(PeekU(@*ppUdpHdr\Length))
udpHdrChksum.u = ntohs_(PeekU(@*ppUdpHdr\Checksum))
Debug "ppUcpHdr\Checksum: 0x" + RSet (Hex(udpHdrChksum), 4, "0") + " ("+ udpHdrChksum+")"
;;;;;;;;Debug "ppUdpHdr\Checksum: " + ntohs_(PeekU(@*ppUdpHdr\Checksum))
EndIf
Debug "---------------"
Debug "*ppData"
Debug "---------------"
Debug PeekS(ppData, pDataLen) ; Show Packet's data/payload.
Else
Debug "---------------"
Debug "DivertRecv"
Debug TestForError()
Debug "---------------"
EndIf
FreeMemory(*pPacket)
DivertClose = GetFunction(WinDivert, "DivertClose")
DivertClose(hWndDivert)
Else
Debug "---------------"
Debug "DivertOpen"
GetErrorCode = GetLastError_()
If GetErrorCode = #ERROR_INVALID_PARAMETER
Debug "Error Code: 87, This indicates an invalid packet filter string, layer, priority, Or flags. "
ElseIf GetErrorCode =#ERROR_FILE_NOT_FOUND
Debug "Error Code: 2 , One Or more of the WinDivert.sys, WinDivert.inf, And WdfCoInstaller*.dll files were Not found. "
ElseIf GetErrorCode =#ERROR_ACCESS_DENIED
Debug "Error Code: 5, The calling application does Not have Administrator privileges."
ElseIf GetErrorCode = #ERROR_INVALID_IMAGE_HASH
Debug "Error Code: 577, The WinDivert.sys driver does Not have a valid digital signature (see the driver signing requirements above), Or"
Debug "WinDivert.sys is the wrong version, i.e. 32-bit on 64-bit Windows Or vice versa"
Else
Debug "Error Code: "+Str(GetErrorCode)+" unknown."
If GetLastError_() > 0 : Debug TestForError() : EndIf
EndIf
Debug "WinDivert error: failed to open Divert device."
Debug "---------------"
;;;;;;;;Debug "---------------"
;;;;;;;;Debug "DivertOpen"
;;;;;;;;Debug TestForError()
;;;;;;;;Debug "---------------"
EndIf
CloseLibrary(WinDivert)
RunProgram("sc", "stop WinDivert1.0", "")
RunProgram("sc", "delete WinDivert1.0", "")
Else : Debug "WinDivert - 'WinDivert.dll' file might not have been found."
EndIf
: Updated, Rev6 (28/09/2013).
Rev 5 (28/09/2013) - Altered a little the appearance of the logging little more.
Rev 4 (28/09/2013) - Made several corrections and adjustments mainly to the TCP Header related stuff.
Rev 2 - Change: styled the most of the checksums.