Judging by Web search results, Windows 10 has included a new network traffic capturing mechanism since October 2018; however, two and a half years later, it still seems to be largely unknown (I only discovered it a few days ago).
Microsoft
provides and supports a “classic” NDIS Filter traffic capturing mechanism
(NdisCap, its associated Microsoft-Windows-NDIS-PacketCapture ETW provider and
a PowerShell cmdlet Add-NetEventPacketCaptureProvider) and previously also
supported a Windows Filtering Platform capture mechanism (WFPCapture, its
associated Microsoft-Pef-WFP-MessageProvider ETW provider and a PowerShell cmdlet
Add-NetEventWFPCaptureProvider). The new mechanism (PktMon and its associated
Microsoft-Windows-PktMon ETW provider) does not yet have a PowerShell cmdlet to
add it to ETW tracing sessions.
According
to the PktMon
home page, “[PktMon] is especially helpful in virtualization scenarios,
like container networking and SDN, because it provides visibility within the
networking stack”. The mechanism that allows PktMon to intercept a packet at
various points in its transition through the network stack are additional “hooks”
introduced into NDIS.sys. Some typical stack traces of the points at which
PktMon is invoked are:
PktMon!PktMonPacketLogCallback+0x19
ndis!PktMonClientNblLog+0xbd
ndis!PktMonClientNblLogNdis+0x2b
ndis!ndisCallSendHandler+0x3ca4b
ndis!ndisInvokeNextSendHandler+0x10e
ndis!NdisSendNetBufferLists+0x17d
PktMon!PktMonPacketLogCallback+0x19
ndis!PktMonClientNblLog+0xbd
ndis!PktMonClientNblLogNdis+0x2b
ndis!ndisMIndicateNetBufferListsToOpen+0x3e95c
ndis!ndisMTopReceiveNetBufferLists+0x1bd
ndis!ndisCallReceiveHandler+0x61
ndis!ndisInvokeNextReceiveHandler+0x1df
ndis!ndisFilterIndicateReceiveNetBufferLists+0x3be91
ndis!NdisFIndicateReceiveNetBufferLists+0x6e
PktMon can be seen as an improvement on NdisCap. The main
advantage (in my opinion) is that PktMon can be loaded and started without
requiring rebinding of the network stack. As I have mentioned in other
articles, rebinding the network stack can, under unfortunate circumstances, be
a risky undertaking. The new ability to intercept packets at various points in
the network stack is something that I have never personally had a need to use
but is probably welcomed by those who have had difficulty in diagnosing network
problems in “virtualization scenarios”.
One thing that PktMon cannot do is to trace loopback
traffic, since the Windows loopback implementation does not use NDIS (WFP
mechanisms and raw sockets can capture such traffic).
There are 3 main components of PktMon: the driver (PktMon.sys),
a DLL (PktMonApi.dll) and an executable (PktMon.exe).
PktMon.sys
PktMon.sys is the core component. It is controlled via a small
set of IOCTLs (to start, stop and query a capture; add, remove and list packet
filters; list traceable components; reset trace counters) and the keywords used
in the ETWENABLECALLBACK (Config, Rundown, NblParsed, NblInfo and Payload).
The information in the list of traceable components will
seem familiar to anyone who has used the kernel debugger extensions “!ndiskd.miniports”,
“!ndiskd.protocols” and “!ndiskd.filters”. The list of components is not only
available via the IOCTL but is also included (in a different form) at the end
of an ETW trace if the “Rundown” keyword is enabled.
The packet filtering possibilities are of the
address/protocol-type/port type rather than what Microsoft sometimes calls OLP
(Offset value, bit Length, and value Pattern).
The output of the command “pktmon filter add help” accurately reflects the
filtering possibilities. The filtering mechanism does not allow “negative” conditions to be expressed – for example, one can’t specify “ignore RDP” (as one might wish to do if one is logged onto a system via RDP).
Similar to both NdisCap and WFPCapture, PktMon must be
explicitly loaded and/or started before it can generate any events; just
starting an ETW trace session containing Microsoft-Windows-PktMon is not enough to capture trace data.
PktMonApi.dll
PktMonApi.dll
currently has 9 exports, which are mostly just simple wrappings around IOCTLs
to PktMon.sys:
PktmonAddFilter
PktmonGetComponentList
PktmonGetFilterList
PktmonGetStatus
PktmonRemoveAllFilters
PktmonResetCounters
PktmonStart
PktmonStop
PktmonUnload
PktMonApi.dll
is not used by PktMon.exe (which contains its own simple wrappings around the
IOCTLs).
PktMon.exe
PktMon.exe
has several facets: it can configure and control PktMon.sys via its IOCTLs, it
can manage ETW trace sessions, it can extract information from the Microsoft-Windows-PktMon
ETL and save it in various formats (including “pcapng”), and it can perform “tcpdump”
style simple formatting of packets captured and display in real-time.
As
mentioned, PktMon.sys must be explicitly managed in order for Microsoft-Windows-PktMon
to capture data. It would be ideal (for me) if Microsoft-Windows-PktMon could
just be included in a Windows Performance Recorder (WPR) Profile along with
other providers and use of advanced ETW features (such as stack traces, SID information,
etc.). Since that is not possible, one must be content with the limited ETW
configuration options of PktMon.exe (provider, keywords and level) – a similar
situation to that with NdisCap and “netsh trace”.
The PktMon
home page currently says “Packet drops from Windows Firewall are not visible
through Packet Monitor yet” (my
emphasis of “yet”). I would not expect Windows Firewall drop detection to be
included in PktMon.sys, since they deal with different technologies. By
including both Microsoft-Windows-PktMon and Microsoft-Windows-WFP in ETW trace
sessions, one can see both the drops types detected by PktMon and the drops
caused by Windows Firewall. Perhaps the “yet” is just a nod to future improvements
in the PktMon.exe user interface to present a unified view of the output of the
two providers.
The
configuration defaults of PktMon.exe cause packets to be logged at all
interception points (--comp all); if the intent of a capture is just to analyse
the traffic in a tool like Wireshark, this can cause each packet to be repeated
twenty or more times in the network trace. One can tackle this by selecting
specific components when exporting captured data to the pcapng format, but I
prefer to use “PktMon start” with the “--comp nics” qualifier.
Microsoft Message Analyzer
Microsoft
Message Analyzer (MMA) was discontinued more-or-less contemporaneously with the
introduction of PktMon and the PktMon team provides no support for MMA. The OPN
(Open Protocol Notation) below allows the ETL output of PktMon to be viewed
comfortably in MMA (if one still has a copy installed).
The OPN is
short and it works (for me), but it includes some “design” decisions and is incomplete
(no support for the MBB (Mobile BroadBand) NDIS medium type, for example, and
probably in many unknown/unanticipated ways).
module PktMon;
using
Microsoft_Windows_PktMon;
using Standard;
using Ethernet;
using WiFi;
autostart
actor PktMonPayload(ep_Microsoft_Windows_PktMon e)
{
process e accepts m:Event_160 where m.PacketType == 1
{
dispatch endpoint Ethernet.Node accepts BinaryDecoder<Ethernet.Frame[m.LoggedPayloadSize < m.OriginalPayloadSize]>(m.Payload) as Ethernet.Frame;
}
process e accepts m:Event_160 where m.PacketType == 2
{
DecodeWiFiMessageAndDispatch(m.Payload);
}
}
Saving this
OPN in a file named %LOCALAPPDATA%\Microsoft\MessageAnalyzer\OPNAndConfiguration\OPNForEtw\CoreNetworking\PktMon.opn
(for example) and restarting MMA should enable the functionality (MMA may take some
time to completely start while it recompiles various OPN files).
Microsoft_Windows_PktMon
The Microsoft_Windows_PktMon
ETW provider defines 5 keywords:
1. Config: PktMon.exe help says “Internal
Packet Monitor errors”; I have never observed any.
2. Rundown: this causes the list of
components to be logged to the ETL when PktMon is stopped.
3. NblParsed: this causes address,
protocol type, port, etc. information for each packet to be logged. The same
information could be extracted from
the binary payload (if present), but it is not trivial to do this because of
various options at each layer (data link, network, transport).
4. NblInfo: this seems to be a superset
of the information logged as TcpipNlbOob by the Microsoft-Windows-TCPIP
provider at level 17 (uninteresting for most people).
5. Payload: this causes the raw data of
the packet to be logged. The data can be truncated, if desired (truncation
length information is included in the start IOCTL to PktMon.sys).
pktmon etl2pcap
Converting pktmon
packet events to PCAPNG format is, in principle, relatively straightforward.
There is a GitHub Microsoft repository with the code of a utility that performs
the slightly more difficult task of converting “netsh trace” packet data to
PCAPNG format (https://github.com/microsoft/etl2pcapng).
Perhaps surprisingly,
the “pktmon etl2pcap” command (“Convert pktmon log file to pcapng format”) only
produces a useful PCAPNG file if the packets were captured on an Ethernet/802.3
link. If packets were captured on a WiFi/802.11 link, the resulting PCAPNG
packet is recorded as having been captured on an Ethernet link; since the datalink
headers are different in content and length, a tool like Wireshark “decodes”
the packet data incorrectly.
Apart from correctly
identifying 802.11 frames as such (LINKTYPE_IEEE802_11), there is one other
addition step needed when saving 802.11 packets to PCAPNG format: the “protected”
flag in the 802.11 frame control field needs to be cleared. The “protected”
flag indicates whether the frame was encrypted; packets carrying network layer
data are protected/encrypted but, by the time received packets have reached the
packet capture hooks, the protected/encrypted content has been decrypted –
however the captured 802.11 packet header (frame control, etc.) is not updated.
If the protected bit is not cleared when saving the capture then, when the
capture is loaded into Wireshark, the packet is assumed to still be protected
and is displayed as such (no attempt is made to decode the “encrypted” portion
of the packet).
pktmon start --trace
Although the
help/documentation (“pktmon start help”) mentions this, I have been caught out
more than once puzzling over why certain expected events were missing from a
trace.
No comments:
Post a Comment