Open TechnikEmpire opened 5 years ago
Trying this new code in the sandbox, getting error 87 every time...
public static void ReadThread()
{
var packet = new WinDivertBuffer();
WinDivertAddress addr = new WinDivertAddress();
uint readLen = 0;
WinDivertParseResult result;
Span<byte> packetData = null;
NativeOverlapped recvOverlapped;
IntPtr recvEvent = IntPtr.Zero;
uint recvAsyncIoLen = 0;
recvOverlapped = new NativeOverlapped();
recvEvent = Kernel32.CreateEvent(IntPtr.Zero, false, false, IntPtr.Zero);
recvOverlapped.EventHandle = recvEvent;
try
{
while (!Disposed)
{
packetData = null;
readLen = 0;
recvAsyncIoLen = 0;
addr.Reset();
Console.WriteLine("Read");
if (!WinDivert.WinDivertRecvEx(winDivertHandle, packet, 0, ref addr, ref readLen, ref recvOverlapped))
{
var error = Marshal.GetLastWin32Error();
// 997 == ERROR_IO_PENDING
if (error != 997)
{
Console.WriteLine(string.Format("Unknown IO error ID {0} while awaiting overlapped result.", error));
continue;
}
while (Kernel32.WaitForSingleObject(recvEvent, 1000) == (uint)WaitForSingleObjectResult.WaitTimeout)
{
}
if (!Kernel32.GetOverlappedResult(winDivertHandle, ref recvOverlapped, ref recvAsyncIoLen, false))
{
Console.WriteLine("Failed to get overlapped result.");
continue;
}
readLen = recvAsyncIoLen;
}
Console.WriteLine("Read packet {0}", readLen);
result = WinDivert.WinDivertHelperParsePacket(packet, readLen);
if (addr.Direction == WinDivertDirection.Inbound)
{
Console.WriteLine("inbound!");
}
if (result.IPv4Header != null && result.TcpHeader != null)
{
Console.WriteLine($"V4 TCP packet {addr.Direction} from {result.IPv4Header->SrcAddr}:{result.TcpHeader->SrcPort} to {result.IPv4Header->DstAddr}:{result.TcpHeader->DstPort}");
}
else if (result.IPv6Header != null && result.TcpHeader != null)
{
Console.WriteLine($"V4 TCP packet {addr.Direction} from {result.IPv6Header->SrcAddr}:{result.TcpHeader->SrcPort} to {result.IPv6Header->DstAddr}:{result.TcpHeader->DstPort}");
}
if (packetData != null)
{
Console.WriteLine("Packet has {0} byte payload.", packetData.Length);
}
Console.WriteLine($"{nameof(addr.Direction)} - {addr.Direction}");
Console.WriteLine($"{nameof(addr.Impostor)} - {addr.Impostor}");
Console.WriteLine($"{nameof(addr.Loopback)} - {addr.Loopback}");
Console.WriteLine($"{nameof(addr.IfIdx)} - {addr.IfIdx}");
Console.WriteLine($"{nameof(addr.SubIfIdx)} - {addr.SubIfIdx}");
Console.WriteLine($"{nameof(addr.Timestamp)} - {addr.Timestamp}");
Console.WriteLine($"{nameof(addr.PseudoIPChecksum)} - {addr.PseudoIPChecksum}");
Console.WriteLine($"{nameof(addr.PseudoTCPChecksum)} - {addr.PseudoTCPChecksum}");
Console.WriteLine($"{nameof(addr.PseudoUDPChecksum)} - {addr.PseudoUDPChecksum}");
// Console.WriteLine(WinDivert.WinDivertHelperCalcChecksums(packet, ref addr, WinDivertChecksumHelperParam.All));
if (!WinDivert.WinDivertSendEx(winDivertHandle, packet, readLen, 0, ref addr))
{
Console.WriteLine("Write Err: {0}", Marshal.GetLastWin32Error());
}
}
}
catch (Exception ex)
{
Console.WriteLine("Fatal error in read thread: {0}", ex);
}
finally
{
WinDivert.WinDivertClose(winDivertHandle);
Kernel32.CloseHandle(recvEvent);
}
}
public static void RunSandbox()
{
winDivertHandle = WinDivert.WinDivertOpen("inbound and tcp", WinDivertLayer.Network, 0,
WinDivertOpenFlags.None);
WinDivert.WinDivertSetParam(winDivertHandle, WinDivertParam.QueueLen, 16384);
WinDivert.WinDivertSetParam(winDivertHandle, WinDivertParam.QueueTime, 8000);
WinDivert.WinDivertSetParam(winDivertHandle, WinDivertParam.QueueSize, 33554432);
Task.Run(FirewallThread);
}
87 on which line?
87 is invalid param. Right off the bat I don't see you resetting your overlapped event. Error codes are standard win api errors fyi to help you debug.
Never mind I am binding against windivert 2.0, I am guessing the params are not an exact match.
Windivert doesn't use semver even between minor versions the api is generally not backward compatible. 2.0 might as well be version 9000. A 2.0 update is in progress but the struct are now really ugly and hard to emulate.
I tried using the pinvoke binder application on the 2.0 windivert.h file but it crashed, do you know of any other tools that auto-generate the pinvoke?
I have 2.0 recv ex working in a fork, will post example code in a bit
Well I am having trouble getting send ex working. It gets 997 io pending error but then attempting to read the overlapped data after the send event has signalled always gives error 87...
I have recv ex working. Care to compare code and see if we can figure it out? My branch is here: https://github.com/DigitalRuby/WinDivertSharp/tree/2.0
I've got 2.0 working with receive and send with batching now, see the latest commits on my fork.
Yeah I already have all that working but I want to have accurate structs that are modifiable.
Yeah I already have all that working but I want to have accurate structs that are modifiable.
Sorry for bumping an old issue, did not want to create a new. I've seen some comments about you making your own driver, is it Open source? Thanks.
@Lemorz56 No problem. My driver is not open source. It doesn't even work like WinDivert anyway, as in, it's not a general purpose driver.
How would we modify a packet's payload content?
How would we modify a packet's payload content?
I ended up using the original C++ but im guessing you will need skip sending the one you want to change and then making your own using the old one, and sending that instead.
I'm probably going to archive this repo.
I'm probably going to archive this repo.
Yeah that's probably for the best
Sandbox code is out of sync with the latest version.