basil00 / divert Goto Github PK
View Code? Open in Web Editor NEWWinDivert: Windows Packet Divert
Home Page: https://reqrypt.org/windivert.html
License: Other
WinDivert: Windows Packet Divert
Home Page: https://reqrypt.org/windivert.html
License: Other
WinDivert 2.2: Windows Packet Divert ==================================== 1. Introduction --------------- Windows Packet Divert (WinDivert) is a user-mode packet interception library for Windows 7, Windows 8 and Windows 10. WinDivert enables user-mode capturing/modifying/dropping of network packets sent to/from the Windows network stack. In summary, WinDivert can: - capture network packets - filter/drop network packets - sniff network packets - (re)inject network packets - modify network packets WinDivert can be used to implement user-mode packet filters, sniffers, firewalls, NATs, VPNs, IDSs, tunneling applications, etc.. WinDivert supports the following features: - packet interception, sniffing, or dropping modes - support for loopback (localhost) traffic - full IPv6 support - network layer - simple yet powerful API - high-level filtering language - filter priorities - freely available under the terms of the GNU Lesser General Public License (LGPLv3) For more information see doc/windivert.html 2. Architecture --------------- The basic architecture of WinDivert is as follows: +-----------------+ | | +------->| PROGRAM |--------+ | | (WinDivert.dll) | | | +-----------------+ | | | (3) re-injected | (2a) matching packet | packet | | | | [user mode] | | ....................|...................................|................... [kernel mode] | | | | | | +---------------+ +-----------------> (1) packet | | (2b) non-matching packet ------------>| WinDivert.sys |--------------------------------------------> | | +---------------+ The WinDivert.sys driver is installed below the Windows network stack. The following actions occur: (1) A new packet enters the network stack and is intercepted by WinDivert.sys (2a) If the packet matches the PROGRAM-defined filter, it is diverted. The PROGRAM can then read the packet using a call to WinDivertRecv(). (2b) If the packet does not match the filter, the packet continues as normal. (3) PROGRAM either drops, modifies, or re-injects the packet. PROGRAM can re-inject the (modified) using a call to WinDivertSend(). 3. License ---------- WinDivert is dual-licensed under your choice of the GNU Lesser General Public License (LGPL) Version 3 or the GNU General Public License (GPL) Version 2. See the LICENSE file for more information. 4. About -------- WinDivert was written by basil. For further information, or bug reports, please contact: [email protected] The homepage for WinDivert is: https://reqrypt.org/windivert.html The source code for WinDivert is hosted by GitHub at: https://github.com/basil00/Divert
I am looking for a new sponsor for driver signing. The high-level requirements are:
WinDivert32.sys
and WinDivert64.sys
driver (probably about 1-2 releases per year).Note that there is no immediate problem as the current release is already signed. This is for anticipated future releases or bug fixes.
If you can help then please contact basil at reqrypt.org.
hi there.
was hoping on getting a hand. I'd like to modify the Web filter project to instead redirect DNS requests in blacklist to 127.0.0.1 (to blacklist ssl sites)
was unsure how to proceed. great product though!
Hi, basio00. I've added your product into my open source project.
[source code]
https://github.com/gilgil1973/snoop90/blob/master/include/capture/snoopwindivert.h
https://github.com/gilgil1973/snoop90/blob/master/include/capture/snoopwindivert.cpp
[sample demo video]
http://www.snoopspy.com/743
Thank you, again.
Is there a way to use the WinDivertRecv API function in a non-blocking way, synchronously?
I need not to use any threads or IOCP methods, but want the flow to continue also if there's nothing to receive.
I tried to use the standard select() method to determine if there's something to read from the handle before using the receive function, but it seems to work only with regular sockets.
WinDivertOpen("false", 0, 1000, 0);
GetLastError() returns 317 on Windows 7 32bit
according to MSDN, it is
https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382%28v=vs.85%29.aspx
ERROR_MR_MID_NOT_FOUND
317 (0x13D)
The system cannot find message text for message number 0x%1 in the message file for %2.
I searched WinDivert sources for ERROR_MR_MID_NOT_FOUND but found nothing
Do you have any idea what could be the reason of this error?
[Compile Envoronment]
VS2012 Debug Mode
[Source code]
netdump.c(line 230)
"if (isprint(packet[i]))"
It occurs "Expression: c >= -1 && c <= 255" debug assertion failed error.
In type castring variable from char into int, number of under -1 may be passed through stack.
I suggest you to modify your code as follows.
"if (isprint((unsigned char)packet[i]))"
Thank you in advance.
If any application of Win Divert other than Promiscus mode based application is running , then Internet Explorer Based Page loading is very Slow. All other Browasers , it is OK. Any idea on this?
In document(WinDiver.html) > Samples,
if (handle == INVALID_HANDLE_VALUE);
if (handle == INVALID_HANDLE_VALUE)
semicolon shoud be removed. :)
Hi there, just wan't to begin and say great project. I am sorry to post this into your issue tracker, but I wasn't sure where else to post it. How can I modify a packets sender information, such as mac and Ip address?
I want to listen for a certain outbound packet my application sends and then intercept the packet before it is sent out and change the source ip and mac and reinject it. I havent seen any details on how to modify a packet like this. Can you help me out with that?
(bug report received via email):
WinDivert does not appear to work on Windows 2008 Server (non-r2), both x86 and AMD64. DivertOpen() always returns a (110) error.
Test Environment: Windows 7 X86
Result:
Note:
WinDivert does not seem to capture traffic inbound on port 80 when the destination address is not that of the capturing/sniffing computer.
I'm trying to capture all incoming packets and redirect/filter them with the ultimate goal of making a software only router that can be run on a laptop or pc. For example, we have a computer sharing its internet via a hosted (wireless) network with a laptop. The computer is connected with the internet through a router.
The problem arises when the laptop requests a website. I want the computer to capture that packet and do stuff with it but WinDivert does not see the http request coming from the laptop. I've WireShark running along side and that captures the packets just fine. When running a default hosted network (Windows DHCP, NAT, etc) I'm able to capture the returning response with WinDivert from the router but also not the initial request (so the packet seems to be passed along on the lower level just fine).
It seems that due to the different IP address the packets are ignored (similar to ) and in the case of the response the router does set the IP of the computer so the packet is captured. As I can not alter the destination IP address on the (client) laptop, is there a way to capture inbound traffic other then directly addressed packets or broadcasted ones?
Edit: Using Windows 7 x64 on both laptop and computer.
build.exe is not found in latest WDK kit. I'm new to this.
I'm building a simple app using your awesome library. Can you guide how to build driver?
DLL I able to build easily. Facing problem is in sys.
Using a different working directory causing a invalid install path for the DivertService.
Instead of using GetCurrentDirectory
(which gets the current working directory) you should use GetModuleFileName
and get the directory from there.
Example of Problem:
Files in c:\test\
:
WinDivert32.sys
WinDivert64.sys
WinDivert.dll
test.exe <-- calls WinDivert.dll
running test.exe
in c:\test
-> everything ok
running test.exe
in c:\
-> cannot install service, because working path is c:\
Eventlog shows install path: c:\WinDivert64.sys
Hi!
I was testing the webfilter sample changing the filter from "outbound && ip && tcp.DstPort == 80 && tcp.PayloadLength > 0" to "outbound && ipv6 && tcp.DstPort == 80 && tcp.PayloadLength > 0" and IPv6 packets were dropped in some specific cases.
Steps to reproduce this behaviour:
In additional, I noticed that in some cases the recalculation of checksum is required even with non-changed packets otherwise the packets will be dropped... I don't know the reason.
My impression is that there is some problem inside the driver code. Can you try to reproduce it inside your environment and give me some feedback?
Thanks in advance!
Is it possible using WinDivert to inject a modified packet by changing the destination IP to a valid local interface address? My goal is to intercept packets arriving from another PC and divert them to a local proxy server application. I can capture the packets from PC A, destined for PC C, on PC B, in the middle, and modify the packet accordingly. WinDivertSendEx(), return successfully, and the completion function does not indicate any errors. This is using a handle with WINDIVERT_LAYER_NETWORK_FORWARD specified. However, I see not indication that the packet ever makes it anywhere.
According to the MSFT 's "Packet Injection Functions" documentation, at https://msdn.microsoft.com/en-us/library/windows/hardware/ff569975(v=vs.85).aspx, "Cross-layer injection is enabled if the callout can supply all needed information that is required by the injection function, and the net buffer list has the format expected by the injection function. For example, a callout can capture a packet at the forward path, modify its destination address to that of the local computer, and call FwpsInjectTransportReceiveAsync0 to redirect the packet into the local computer's TCP/IP stack."
This makes me believe it is possible. I notice the WinDivert driver uses "FwpsInjectForwardAsync0" in the windivert_write() function, I did attempt to change that to use "FwpsInjectTransportReceiveAsync0" as an experiment (with the same results as the unmodified function). In both cases, I have tried WINDIVERT_DIRECTION_INBOUND and outbound, and uses the IfIdx and IfSubIdx of the adapter with the IP address I have modified the packet's destination address too. To verify that packet modification was working as planned, I modified the source address of the packet instead to that of the local NIC and it injected and sent successfully. By successfully I mean I could view it using Wireshark and verify the checksums.
Based on the quote from the documentation, maybe I am missing something regarding this part: " if the callout can supply all needed information that is required by the injection function, and the net buffer list has the format expected by the injection function".
Does anyone know if this can be done and if so, how? Thanks in advance
There are any restriccions using windivert (v1.1.7) connected to a switch with port mirroring? because i'm using an app with windivert and dont receive any package. I'm also using a app with winpcap and with this application the packets are received.
So, I haven't quite narrowed down if this is indeed a WinDivert on Win 10 issue or not, but my transparent proxy driven by WinDivert is completely non-functional on Windows 10. Functional before upgrade, no changes to app code. All outbound connections just spin and timeout. Will report back when I get to the actual root of the issue.
The WinDivert FORWARD layer was never properly tested. We have found the following bugs:
Both of these are bugs in the WinDivert driver. The non-FORWARD layer is not affected.
i will use it in my server for filter stream udp packet.
at this server,normal 1gbps/s data traffic
so,how to use kernel-mode filter?
maybe it is high-performance?
is right?
and how to?
When it's a loopback packet, e.g. from 127.0.0.1 (Mac 0x2) to 127.0.0.1(Mac 0x1) ,it's inbound, but addr.Direction is always outbound. That's why I wanna to check the Dst and Src MAC.
I can see the mac via Commview.
It's useful when using client and server on the same machine.
Hi
Is WinDivert well-suited for this use case?
For example, there are two open handles, one in sniffing mode for incoming DNS replies and second for HTTP packets. Userspace application analyzes DNS packets and decides to update HTTP filter rule (whitelisting/blacklisting, etc). Can I expect that closing existing HTTP filter handle and opening new one with updated filter expression will be completed before the browser starts connection to the IP received in DNS reply? So application can capture SYN packet from the new TCP connection to HTTP server using new filter?
Hi!
I'm testing the passthru example with "true" and "8" as parameters (also tried 1) and it works fine. However, copying a file over the network that usually runs at about 90 MB/s slows down to 25 MB/s. CPU load of the passthru program is between 20 and 25%.
Does WinDivert really slow down network traffic that much? Can this be improved? Other solutions, like WinpkFilter, have a much smaller impact (e.g. just 5% CPU load, just 10% drop in transfer rate).
Thanks!
I'm having a issue when I try to use passthru with the AVG Internet Security and Avast.
Calling the passtrhu with the line:
passthru.exe "outbound and (ip || ipv6) and tcp and tcp.PayloadLength > 0" 1
with AVG installed and updated, I can't access any site anymore.
And with Avast, I can't access my e-mails through Thunderbird.
Analysing the windivert.c, I've notice that the callback for the function FwpsInjectNetworkSendAsync0 is getting a C000021B error on status.
I think that's everything ok with WinDivert, but I can't reproduce the same behaviour with WFPSampler from Microsoft.
I've alread contacted the AVG and Avast support for this problem.
The people in Avast is now analysing the problem, but didn't found any problems yet.
Is anybody having this problem too?
Thanks.
in windows 2012 64bit system:
if (!WinDivertSend(handle, (PVOID)dnr, icmp_length, &send_addr,
NULL))
{
fprintf(stderr, "warning: failed to send ICMP message "
"(%d)\n", GetLastError());
}
in newfilter demo。
here always get 592 errors。
and in win7 64bit system
// Re-inject the matching packet.
if (!WinDivertSend(handle, packet, packet_len, &addr, NULL))
{
fprintf(stderr, "warning: failed to reinject packet (%d)\n",
GetLastError());
}
warning: failed to reinject packet (592)
always get 592 errors,why?
Hi,
Using the following code I cannot even log the HTTPS requests:
handle = WinDivertOpen(
"outbound and "
"(tcp.DstPort == 80 or tcp.DstPort == 443)",
0, 0, 0
);
Is this maybe unsupported or I am missing something?
(This is with webfilter example)
Is there any way to force the WinDivertSend function to inject an outbound packet on a specific interface? On the documentation page it states For outbound injected packets, the IfIdx and SubIfIdx fields are currently ignored and may be arbitrary values.
Is there any workaround for this, or that it is actually accepting the IfIdx and SubIfIdx fields as stated? We need to send packets on a specific interface, the default is of no use as there are multiple networks and it's always sending the packages to the wrong interface.
Hi, basil. I am gilgil. ;)
While making use of WinDivert dll, I met something unknown. Here is a test.
[Test Case 1]
While calling netdump command, I can see SYN/RST packets when I try to connect to 127.0.0.1:23.
netdump "tcp.SrcPort==23 tcp.DstPort==23"
While calling passthru command, I can not see any packets.
passthru "tcp.SrcPort==23 tcp.DstPort==23"
[Test Case 2]
Firefox application communicates with loopback(127.0.0.1) interface while application launches.
I can see the packets with netdump command.
netdump true
But I can not see any packets with passthru command.
passthru true 1
[Test Enviromnent]
Windows 7 Ultimate K
RAM 8G
Both WinDivert 1.1.2-rc and 1.1.1 has been tested.
passthru.c 111 line
[from]
if (!WinDivertSend(handle, packet, packet_len, &addr, NULL))
[to]
if (!WinDivertSend(handle, packet, packet_len, NULL, NULL))
When WinDivertSend is called, system crashes(blue screen).
Hi ,
Previously i was using windivert 1.0 in my application for filtering packets in forward layer.When i changed to 1.1.2 i am unable to filter packets in forward layer.Previously i set priority as -31768 and layer as forward for getting packets from forward layer but now i am unable to divert open with that priority.Even if i set the -1000 priority and layer as forward still i am unable to get data from forward layer.Hope for your help and advice..
Thanks,
If yes, is it checked deeply?
(bug report submitted via email):
DivertParseIPv6Address() does not parse some valid IPv6 addresses.
Unloading the driver can lead to a BSOD. This appears to only affect the 32-bit version of the driver. The Minidump reveals that the driver crashes in the windivert_unload() function during the NdisFreeNetBufferPool() call.
https://github.com/basil00/Divert/blob/master/include/windivert_device.h#L118
value 128 is too small, I propose to support arbitrary length filter strings or at least make this limit configurable in runtime
Hi,
I want to get the PID of a packet, "FWPS_INCOMING_METADATA_VALUES0_" is useful, according to DDK document:
typedef struct FWPS_INCOMING_METADATA_VALUES0_ {
...
FWP_BYTE_BLOB *processPath;
UINT64 token;
UINT64 processId;
...
} FWPS_INCOMING_METADATA_VALUES0;
could Divert provide with related interface? Thanks~
this is a great project!i like it very much.
but it diffculty to upgrade vs2013+wdk8.1
please give some version for vs2012+wdk8.1?
thanks
(reported via email).
WinDivert seems to lose some outbound TCP packets. This shows up as "TCP previous segment not captured" errors in wireshark, and can cause TCP re-transmission (& slowing down the connection, sometimes significantly).
Preliminary investigation indicates that the missing packets are not even sent to WinDiverts WFP callout function. Investigation continues...
Hi,
Is it possible with WinDivert to receive packets with source ip A and destination B, while I'm C but the packet was in the NIC?
I don't want to configure Windows as a router, and open an NETWORK _FORWARD layer handle.
Thanks!
Basil, I know there is an issue (#28) already opened regarding IPv6 and CheckSum calculations, but as you discuss driver code in that issue I decided to open a new one so we don't mix subjects.
I was porting the Webfilter sample to use IPv6, and noticed that, when I call the function "WinDivertHelperCalcChecksums()", even for unchanged packets, the packet checksum is invalid.
I verified that the DLL function "WinDivertHelperCalcChecksums()" uses Its own checksum calculation function, "WinDivertHelperCalcChecksum()", that is implemented also in the DLL source, independent from the Driver checksum functions.
Debugging the checksum calculation, I realized that the struct "WINDIVERT_PSEUDOV6HDR" has the two last members (Zero and NextHdr) with swapped positions. According to TCP documentation, regarding IPv6 pseudoheader and checksum calculation, Zeros must come before Next Header. As Zeros are 24 bit and Next Header 8 bit, and calculation takes in account 16-bit numbers, if not correctly aligned the result checksum is wrong.
I tested my theory just swapping the order in the structure, with positive results. I just changed in DLL source "windivert.c" from:
typedef struct { UINT32 SrcAddr[4]; UINT32 DstAddr[4]; UINT32 Length; UINT32 NextHdr:8; UINT32 Zero:24; } WINDIVERT_PSEUDOV6HDR, *PWINDIVERT_PSEUDOV6HDR;
to
typedef struct { UINT32 SrcAddr[4]; UINT32 DstAddr[4]; UINT32 Length; UINT32 Zero:24; UINT32 NextHdr:8; } WINDIVERT_PSEUDOV6HDR, *PWINDIVERT_PSEUDOV6HDR;
and checksum calculation went fine, with packets properly injected, without touching driver code.
Thanks again for such a useful library, and I hope this can help to improve It.
Hi,
I'm trying to write a simple program that receives all UDP packets and send them out without changing (passthru-like).
Also, I don't want the driver to touch/modify the checksums so I put the NO_CHECKSUM flag.
Now, I tried to send an outbound datagram with regular UDP socket. However, the target machine received the packet with invalid UDP checksum (Not zero. and IP checksum was right) and the listener didn't accept it!
Without WinDivert, or without the flag - the checksum is correct and the transfer works.
I'm using Windows 7, and the code I've used:
int main(){
HANDLE h = WinDivertOpen("ip && udp", WINDIVERT_LAYER_NETWORK, 0, WINDIVERT_FLAG_NO_CHECKSUM);
WINDIVERT_ADDRESS addr;
UINT len;
CHAR buff[10000];
while (1) {
WinDivertRecv(h, buff, sizeof(buff), &addr, &len);
WinDivertSend(h, buff, len, &addr, NULL);
}
}
Am I missing something?
With the MSVC build (same problem with WDDK):
HANDLE handle = WinDivertOpen("ipv6", WINDIVERT_LAYER_NETWORK, 0 ,0L);
This freezes with an x64 build (in fact, Visual Studio sometimes crashes with this command), whereas it does work with an x86 build? I used the proper files for the x64 build, running under Visual Studio 2012 and 2013. I also tried older versions of WinDivert (1.1.4 and 1.1.5) and they have the same problem.
Tried both Windows 7 and 8 (x64).
One interesting feature would be to expose the process id in userland. This is useful in Windows when you want to block traffic coming from one specific application.
Here are some ideas for WinDivert1.2 in 2015:
Comments? Any other proposals?
Hi
When I run netdump true or net filter in cmd, I get "not a Valid Win32 Application".
- this is the cmd typing in netdump true
- this is the result of typing in netdump true. a window pops up and I click Run(R) == "실행"
- the result "Not a Valid Win32 Application" == 올바른 Win32 응용프로그램이 아닙니다.
Furthermore, if I use WinDivert 32bit via SnoopSpy, but I get result of
WinDivert unknown error 127.
I read http://reqrypt.org/windivert-faq.html#q1 but there is no document
about DivertOpen error code 127.
Could I get some help for this matter.
Thank you.
ps
I am using Win32 Vista Notebook.
I only tested the WinDivertSendEx method.
I'm trying to get these functions to work in C# and I'm having trouble with them. When I add the overlapped parameter (with the event set), I never have to wait (e.g., with WaitForSingleObject, or with the ManualResetEvent as the C# equivalent) as the event always seems signaled immediately after I call the method.
I expected this behavior:
Functions such as ReadFile and WriteFile set this handle to the nonsignaled state before they begin an I/O operation. When the operation has completed, the handle is set to the signaled state.
Do these methods work differently or is there a bug somewhere? If not, how is this supposed to work in WinDivert? I tried all possible variants to get the Overlapped to work in C# and I never get a callback or the wait to work.
How to get which application is requesting tcp connection i.e. sending/receiving packets.
If we can get like
tcpConnected( APPINFO)
tcpClosed( APPINFO)
That will awesome. Or If possible please give me few ideas/code to implement this.
I've a problem as I'm currently writing a firewall for a certain piece of software that's vulnerable to UDP attacks.
My fix for the exploit involved sending cached UDP packets using WinDivert, however WinDivertSend seems to cause quite a lot of performance drag.
I found that using WinDivertSend to reinject original UDP packets isn't slow, however sending packets with modified source & destination IP and Ports seems to be quite slow indeed.
My program currently can read all 5000 packets per second that I'm testing it with, however when I respond to those packets, the packets I read goes down to about 700/s since as my program is single-threaded.
Any idea why creating & sending new packets is relatively slow?
Here's the code I'm using to respond to send new UDP packets: http://pastebin.com/x0Q3kMQW
First of all thank you for this very useful lilbrary.
I am using WinDivert along with ICS (Internet Connection Sharing) to capture forwarded packets. i was having problem getting it work but after going through the issues posted here i got it to work somehow.
I opened a first handle to capture forward packets like this:
HANDLE forward_handle = WinDivertOpen("tcp.DstPort==80", WINDIVERT_LAYER_NETWORK_FORWARD, -1000, 0);
Then i open a second handle to inject the modified packet captured from the forward_handle like this:
HANDLE handle = WinDivertOpen("false", WINDIVERT_LAYER_NETWORK, 0, 0);
This works but at times the program crashes or sometimes the forwarded packets are not modified but am not really bothered by this i believe it might be a bug in my code. My real problem is, i am trying to add up the packetLen to get bandwith usage but the bandwith is always incorrect. After using the passthrue program provided with WinDivert i figured that the response packets are on the outbound path of the ICS machine. So i created a new thread where i open another handle to capture this packet and add up packetLen, this works for like a minute then calculation get wrong. Do you have any idea why this happens? i tried changing the priorities so many times but i still can't get it working properly. Would be glad if you can give me some insight on what to do. Thanks
(reported via email)
Networking sometimes disappears when using WinDivert-1.1.2-rc. It appears that WinDivert-1.1.1 is unaffected. Investigation continues...
Hello,
Thank you for the awesome software!
I've tried to re-sign drivers with own certificate. We are using both SHA-1 and SHA-256 signatures at the same time in the single file.
This type of signature works fine on Windows 8 and Windows 7. But on Windows 10 (10162) we see 577 error on Windivert Open.
What it could be?
Thank you.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.