nmap / npcap

Nmap Project's Windows packet capture and transmission library
https://npcap.com
Other
2.97k stars 514 forks source link

Npcap version 1.10 collects duplicate frames - only on out going frames #285

Open IbTornoe opened 3 years ago

IbTornoe commented 3 years ago

We have a third party tool installed called Performance Guard (PG). This tool has it own version of winpcap imbedded. They have renamed the driver to pgnpf.sys so that it does not conflict with winpcap driver coming with Wireshark. PG could in this way live side by side with Wireshark without any conflict. We could uninstall PG and that would live winpcap untouched and Wireshark would still work, or we could uninstall Wireshark and that would leave pgnpf.sys and PG would still work. Using Wireshark and npcap.sys then Wireshark gets duplicates of all frames sent out of the machine. Received frames are OK. Removing the pgnpf.sys driver, then it all works fine.

pstavirs commented 3 years ago

I've seen a similar behaviour when both winpcap and npcap are installed and their services running in parallel.

dmiller-nmap commented 3 years ago

Yes, this is because of the different ways WinPcap and Npcap work. Npcap exists in the network stack as a filter driver above the miniport driver and below all protocol drivers. It sees all packets going up (inbound) and down (outbound). WinPcap is a protocol driver instead, which means that by ordinary design it can only see inbound traffic. In order to see outbound traffic, it instructs the stack to reflect (loop back) all outbound packets at the miniport so that they travel back up the stack as well. This is inefficient because all outbound traffic traverses the stack twice, and the special loopback pathway is intended for debugging and therefore not optimized in Windows.

Npcap, when WinPcap is installed and being used by a program, will see the traffic on the stack in both directions, capturing it each time. This is why you are seeing duplicate packets. In most cases, installing Npcap in WinPcap API Compatibility Mode will cause the other program to use it instead, resolving the issue. In this particular case, PG might not choose to use Npcap regardless, so you will have to make the decision to either remove it or put up with the duplicate packets for now.

It is possible that there may be a way for Npcap to mark packets it has seen and captured, in order to avoid capturing them again. I am only speculating because I haven't tried this yet, but I'll keep this issue open until I've done a feasibility study.

pstavirs commented 3 years ago

@dmiller-nmap Thanks for the technical explanation! Could #289 also be related to this?

IbTornoe commented 3 years ago

Hi, thanks for the very useful description, appreciated ;-) And sorry for the late answer, I did not get any notification on your answer . . . Regarding our Performance Guard (PG), they have included their own copy of the driver and also given it a new name so it does not conflict with the driver that came with Wireshark. Would be nice if there were a configuration in npcap so that it could detect that winpcap is also loaded and then through away at least IP packets with same Identification number.

dmiller-nmap commented 3 years ago

I have an idea of how to address this, and I need to experiment a bit to determine if it will work: We already check for whether a packet is a loopback packet here: https://github.com/nmap/npcap/blob/9ba2e23bd7a345efcd4f19ef7537b7b2e9fbfc00/packetWin7/npf/npf/Read.c#L572-L574

We could add an additional check: if the HigherPacketFilter includes NDIS_PACKET_TYPE_ALL_LOCAL, then we should expect that we will see all packets twice. This is how WinPcap accomplishes capturing outgoing traffic, after all. If that is the case and a packet has the loopback flag, then we will choose not to show it. I'd have to determine whether this ought to be affected by PacketSetLoopbackBehavior.

IbTornoe commented 3 years ago

Sounds promising. Would be great to have a solution for this ;-)

pstavirs commented 2 years ago

Any update on this?

finert commented 2 years ago

As also mentioned in https://github.com/nmap/npcap/issues/58 I just tested with 1,60 but still seeing every sent packet twice. Out of ideas in my side, tried every permutation of install options (Winpcap compatible yada yada and so on). Never happened with WinPCAP back in the days, so I assume it's still something maybe related to other products being installed? Running VMWare Workstation on all of my machines if that helps

finert commented 1 year ago

I've figured a solution AND a workaround which at leasted fixed my problem. Things I observed: After booting my machine I have the issue with those duplicate sent packets. --> If I go to the Interface Settings and disable and re-enable the interface the problem is gone --> rebooting brings back the issue

So I've came across that there is some issue probably with driver LoadOrder etc. and while searching for drivers with the LoadOrd Tool from Winternals I spotted that there is my PacketCache installation from Netresec (https://www.netresec.com/?page=PacketCache)

That being obvious because it also reads my packets I removed the service and now the issue disappeared.

I've already emailed Netresec about that so they're aware -> it's rarely possible that everyone having this issue also has PacketCache running, but maybe another long forgotten piece of software or maybe the disable/enable workaround might help.

erik4711 commented 1 year ago

I've already emailed Netresec about that so they're aware -> it's rarely possible that everyone having this issue also has PacketCache running, but maybe another long forgotten piece of software or maybe the disable/enable workaround might help.

This issue doesn't seem to be limited to only when running PacketCache, but to raw sockets in general. Creating a raw socket with IOControl ReceiveAll will effectively cause NPcap to receive duplicate packets.

Here's a proof of concept PowerShell code that triggers this bug in NPcap:

#Proof-of-Concept for NPcap bug #285 and #58
#Run the following powershell commands as Aministrator to establish a raw socket with ReceiveAll IOControl
#Replace the IP address below with the IP of your network interface
$ip = [Net.IPAddress]::Parse("192.168.1.2")
$endPoint = New-Object System.Net.IPEndPoint($ip, 0)
$socket = New-Object System.Net.Sockets.Socket([Net.Sockets.AddressFamily]::InterNetwork,[Net.Sockets.SocketType]::Raw, [Net.Sockets.ProtocolType]::IP)
$socket.Bind($endPoint)
$_ = $socket.IOControl([Net.Sockets.IOControlCode]::ReceiveAll, [BitConverter]::GetBytes(1), $null)  
Write-Host "Press any key to release the raw socket for $ip"
$_ = $Host.UI.RawUI.ReadKey()
$socket.Close()