Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WinDivertSend is slow #31

Closed
oubliette32 opened this issue Nov 14, 2014 · 7 comments
Closed

WinDivertSend is slow #31

oubliette32 opened this issue Nov 14, 2014 · 7 comments

Comments

@oubliette32
Copy link

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

@basil00
Copy link
Owner

basil00 commented Nov 14, 2014

The first thing to verify is that you are constructing well-formed packets. Try running WireShark to sniff your injected packets and check for errors.

@oubliette32
Copy link
Author

I'm 100% sure the packets are well formed as I've tested with a simple client, the client would read the original response perfectly fine, then the second cached response (a clone of the original) again, perfectly fine.

I looked in wireshark for anything abormal, but it seems all fine to me. The only thing that really changes is the destination port and ID (which are meant to change).

Is there anything else I should look for?

@dfct
Copy link

dfct commented Nov 14, 2014

Which function[s] is that class spending the most time in when sending packets?

I had a similar problem and resolved it by reducing the number of variables I created for each send packet call & instead modifying the existing pData packet directly.

@oubliette32
Copy link
Author

WinDivertSend is the function that's causing me problems. Calling it in my program is almost 10 times as expensive as my entire listening and caching code.

This was actually my second attempt, at first I had tried reversing the incoming packet so that it would send back out with a modified payload, but that had performance issues upon calling WinDivertSend too, so I had tried what I had mentioned originally.

It's not really necessarily that bad of performance if WinDivert can send 700/pps, however since as I could send plenty more with sendto and other winsock functions, I doubt this is expected behavior.

@basil00
Copy link
Owner

basil00 commented Nov 15, 2014

You say that "using WinDivertSend to reinject original UDP packets isn't slow". This is strange since WinDivertSend does not distinguish between modified, unmodified, or new packets -- i.e. they are all treated the same internally.

You can also try using WinDivertSendEx where the "overlapped" parameter is non-NULL. The default WinDivertSend waits to see if the injection was successful, and if not, returns an error code. The WinDivertSendEx function sends the packet and returns immediately, i.e. does not wait for the result, so can be faster. Maybe this is worth trying.

There may be more subtle problems. For example, using WinDivert may reorder packets. This should not matter to a well-written UDP application, but not everything is well-written.

Otherwise I cannot think of an obvious cause for the problem.

@oubliette32
Copy link
Author

I did some more tests using asynchronous IO and it still has the same problems, they're just less visible. The function does return instantly as expected, however wireshark reports that I send a single packet for every 10 or so that I receive.

I'm not sure if this is my problem or not. However, I've rewrote my application using a multi-threaded model and this is handling 70k/pps using 30% of the CPU (not too shabby!!), this will work perfectly for my needs.

I apologize if this issue was too subjective. However without multithreading, my server handled 3k out of 70k, so I presume there's still an issue somewhere?

@basil00
Copy link
Owner

basil00 commented Nov 17, 2014

70k/pps is probably quite a lot for WinDivert, so certainly multi-threading helps.

General performance tips:

  • Use multi-threading
  • Use WinDivertSendEx() and don't wait for the result. Most programs don't care if send fails because there is nothing that can be done about it anyway.
  • Pass WINDIVERT_FLAG_NO_CHECKSUM to WinDivertOpen() if you plan to recalculate the checksums anyway.
  • Max out WINDIVERT_PARAM_QUEUE_LEN and WINDIVERT_PARAM_QUEUE_TIME with WinDivertSetParam(), otherwise WinDivert may start dropping packets if the user-mode program is too slow.

As for your specific problem, the exact cause remains unclear. But since it appears solved I guess we can close the issue.

@basil00 basil00 closed this as completed Nov 17, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants