WinDivert is a powerful user-mode capture/sniffing/modification/blocking/re-injection package forWindows 10, Windows 11, and Windows Server.WinDivert can be used to implement user-mode packet filters, packet sniffers,firewalls, NAT, VPNs, tunneling applications, etc., without the need towrite kernel-mode code.
To uninstall, simply delete the WinDivert.dll,WinDivert32.sys, and WinDivert64.sys files.If already running, the WinDivert driver will be automaticallyuninstalled during the next machine reboot.The WinDivert driver can also be manually removed by (1) terminatingall processes that are using WinDivert, and (2) issuing the followingcommands at the command prompt
The WINDIVERT_LAYER_NETWORK andWINDIVERT_LAYER_NETWORK_FORWARDlayers allow the user application to capture/block/inject network packetspassing to/from (and through) the local machine.Due to technical limitations, process ID information is not availableat these layers.
The WINDIVERT_LAYER_FLOW layer captures information aboutnetwork flow establishment/deletion events.Here, a flow represents either (1) aTCP connection, or (2) an implicit flow created by the firstsent/received packet for non-TCP traffic, e.g., UDP.Old flows are deleted when the corresponding connection is closed (for TCP),or based on an activity timeout (non-TCP).Flow-related events can be captured, but not blocked nor injected.Process ID information is also available at this layer.Due to technical limitations, theWINDIVERT_LAYER_FLOW layer cannot capture flow events thatoccurred before the handle was opened.
The WINDIVERT_LAYER_SOCKET layer can capture or block eventscorresponding to socket operations, such as bind(),connect(), listen(), etc., or the terminationof socket operations, such as a TCP socket disconnection.Unlike the flow layer, most socket-related events can be blocked.However, it is not possible to inject new or modified socket events.Process ID information (of the process responsible for the socket operation)is available at this layer.Due to technical limitations, this layer cannot capture events thatoccurred before the handle was opened.
Finally, the WINDIVERT_LAYER_REFLECT layer can capture eventsrelating to WinDivert itself, such as when another process opens anew WinDivert handle, or closes an old WinDivert handle.WinDivert events can be captured but not injected nor blocked.Process ID information (of the process responsible for opening theWinDivert handle) is available at this layer.This layer also returns data in the form of an object representationof the filter string used to open the handle.The object representation can be converted back into a human-readablefilter string using theWinDivertHelperFormatFilter()function.This layer can also capture events that occurred before the handle was opened.This layer cannot capture events related to otherWINDIVERT_LAYER_REFLECT-layer handles.
Remarks
The WINDIVERT_ADDRESS structurerepresents the "address" of a captured or injected packet.The address includes the packet's timestamp, layer, event, flags, andlayer-specific data.All fields are set by WinDivertRecv()when the packet/event is captured.Only some fields are used byWinDivertSend() when a packetis injected.
The Loopback flag is set for loopback packets.Note that Windows considers any packet originating from, and destined to, thecurrent machine to be a loopback packet, so loopback packets are notlimited to localhost addresses.Note that WinDivert considers loopback packets to beoutbound only, and will not capture loopback packets on theinbound path.
The Impostor flag is set for impostor packets.An impostor packet is any packet injected by another driver rather thanoriginating from the network or Windows TCP/IP stack.Impostor packets are problematic since they can cause infinite loops,where a packet injected by WinDivertSend() is captured again by WinDivertRecv().For more information, see WinDivertSend().
The *Checksum flags indicate whether the packet has valid checksumsor not.When IP/TCP/UDP checksum offloading is enabled, it is possible thatcaptured packets do not have valid checksums.Invalid checksums may be arbitrary values.
The Network.* fields are only valid at theWINDIVERT_LAYER_NETWORK andWINDIVERT_LAYER_NETWORK_FORWARD layers.The Network.IfIdx/Network.SubIfIdx indicate the packet'snetwork adapter (a.k.a. interface) index.These values are ignored for outbound packets.
The Flow.* fields are only valid at theWINDIVERT_LAYER_FLOW layer.The Flow.ProcessId is the ID of the process thatcreated the flow (for outbound), or receives the flow (for inbound).The(Flow.LocalAddr, Flow.LocalPort, Flow.RemoteAddr, Flow.RemotePort, Flow.Protocol)fields form the network 5-tuple associated with the flow.For IPv4, the Flow.LocalAddr and Flow.RemoteAddrfields will be IPv4-mapped IPv6 addresses,e.g. the IPv4 address X.Y.Z.W will be represented by::ffff:X.Y.Z.W.
The Socket.* fields are only valid at theWINDIVERT_LAYER_SOCKET layer.The Socket.ProcessId is the ID of the process that executedthe socket operation.The(Socket.LocalAddr, Socket.LocalPort, Socket.RemoteAddr, Socket.RemotePort, Socket.Protocol)fields form the network 5-tuple associated with the operation.For IPv4, the Socket.LocalAddr and Socket.RemoteAddrfields will be IPv4-mapped IPv6 addresses.The WINDIVERT_EVENT_SOCKET_BIND andWINDIVERT_EVENT_SOCKET_LISTEN events can occur before aconnection attempt has been made, meaning that theSocket.RemoteAddr and Socket.RemotePort fieldsfor these events will be zero.
The Reflect.* fields are only valid at theWINDIVERT_LAYER_REFLECT layer.The Reflect.ProcessId is the ID of the process thatopened the WinDivert handle.The Reflect.Timestamp field is a timestamp indicating when thehandle was opened, usingthe same clock asQueryPerformanceCounter().The Reflect.Layer, Reflect.Flags, and Reflect.Priority fields correspond to theWinDivertOpen() parameters ofthe opened handle.
Remarks
Opens a WinDivert handle for the given filter.Unless otherwise specified by flags, any packet or event thatmatches the filter will be diverted to the handle.Diverted packets/events can be read by the application withWinDivertRecv().
A typical application is only interested in a subset of all network trafficor events.In this case the filter should match as closely as possible tothe subset of interest.This avoids unnecessary overheads introduced by diverting packets to theuser-mode application.See the filter language section for moreinformation.
Different WinDivert handles can be assigned different priorities by thepriority parameter.Packets are diverted to higher priority handles before lower priorityhandles.Packets injected by a handle are then diverted to the next priority handle,and so on, provided the packet matches the handle's filter.A packet is only diverted once per priority level, so handles should notshare priority levels unless they use mutually exclusive filters.Otherwise it is not defined which handle will receive the packet first.Higher priority values represent higher priorities, withWINDIVERT_PRIORITY_HIGHEST being the highest priority,0 the middle (and a good default) priority,and WINDIVERT_PRIORITY_LOWEST the lowest priority.
For layers that do support capturing, the captured packet/data will be writtento the pPacket buffer.If non-NULL, then the total number of byteswritten to pPacket will be written to pRecvLen.If the pPacket buffer is too small, the packet will betruncated and the operation will fail with theERROR_INSUFFICIENT_BUFFER error code.This error can be ignored if the application only intends to receive partof the packet, e.g., the IP headers only.For layers that do not capture packets/data, the pPacket parametershould be NULL and packetLen should be zero.
An application should call WinDivertRecv()as soon as possibleafter a successful call to WinDivertOpen().When a WinDivert handle is open, any packet/event that matches the filter willbe captured and queued until handled byWinDivertRecv().Packets/events are not queued indefinitely, and if not handled in a timelymanner, data may be lost.The amount of time a packet/event is queued can be controlled using theWinDivertSetParam() function.
Return Value
TRUE if a packet was successfully received, or FALSE otherwise.Use GetLastError() to get the reason.The error code ERROR_IO_PENDING indicates that the overlappedoperation has been successfully initiated and that completion will beindicated at a later time.All other codes indicate an error.
Batched I/O makes it possible to receive up to WINDIVERT_BATCH_MAXpackets at once using a single operation, reducing the number ofkernel/user-mode context switches and improving performance.To enable batched I/O:
Remarks
Injects a packet into the network stack.The injected packet may be one received fromWinDivertRecv(), or amodified version, or a completely new packet.Injected packets can be captured and diverted again by other WinDiverthandles with lower priorities.
For the WINDIVERT_LAYER_NETWORK layer thepAddr->Outbound value determines which direction the packetis injected.If the pAddr->Outbound field is 1,the packet will be injected into the outbound path(i.e. a packet leaving the local machine).Else, if pAddr->Outbound is 0,the packet is injected into the inbound path (i.e. a packet arrivingto the local machine).Note that only the Outbound field, and not the IP addresses in the injected packet, determines the packet's direction.
For packets injected into the inbound path, thepAddr->Network.IfIdx andpAddr->Network.SubIfIdx fields are assumed to contain validinterface numbers.These may be retrieved from WinDivertRecv()(for packet modification),or from the IP Helper API.
For outbound injected packets, the IfIdx and SubIfIdxfields are currently ignored and may be arbitrary values.Injecting an inbound packet on the outbound path may work (for sometypes of packets), however this should be considered "undocumented" behavior,and may be changed in the future.
c80f0f1006