Packet Monitor (PktMon.exe
) is a built-in network traffic analyzer (sniffer) that was introduced in Windows 10 1809 and Windows Server 2019. In the Windows 10 May 2020 Update (version 2004), many new features of the Packet Monitor were implemented (real-time packet capture is now supported, PCAPNG format support to easily import to Wireshark traffic analyzer). Thus, Windows has got a feature to capture network packets similar to that of tcpdump
, and system or network administrators can use it to diagnose network operation and performance.
Packet Monitor allows you to get all network activity passing through the computer’s network interface on the network packet level.
netsh trace
command was used to capture network traffic and inspect packets in Windows.You can get help on pktmon.exe
options and syntax by running the tool in the command prompt.
Here are the basic Packet Monitor commands:
- filter —manage packet filters
- comp –manage registered components
- reset —reset packet counters
- start –start packet monitoring
- stop —stop packet monitoring
- format –convert the traffic log file to a text format
- pcapng –convert to the pcapng format
- unload –unload the PktMon driver
To get help on a subcommand, enter its name:
pktmon filter
Let’s try to collect a dump of the traffic coming to some running services on a Windows 10 device. Suppose, we want to analyze the FTP (TCP ports 20, 21) and HTTP (Ports 80 and 443) traffic.
Create a packet filter for TCP ports (also, you can track UDP and ICMP traffic):
pktmon filter add -p 20 21
pktmon filter add HTTPFilter –p 80 443
Display the list of active filters:
pktmon filter list
To run background traffic capture, run this command:
pktmon start –etw
Log file name: C:\Windows\System32\PktMon.etl Logging mode: Circular Maximum file size: 512 MB Active measurement started.
pktmon start --etw -p 0 -c 9
where c value is the ID of the network interface you can get using this command:
pktmon comp list
The packet filter will write all traffic matching to the filters you have set to C:\Windows\System32\PktMon.etl
(its maximum file size is 512 MB). To stop dump recording, run the following command:
pktmon stop
Also, network packets stop being collected after a Windows reboot.
Then you can convert the traffic dump file from ETL to the plain text format:
pktmon format PktMon.etl -o c:\ps\packetsniffer.txt
or
pktmon PCAPNG PktMon.etl -o c:\ps\packetsniffer.pcapng
You can analyze the traffic dump in the text format or import the ETL file to the Microsoft Network Monitor or WireShark (in the PCAPNG format) installed on the administrator’s computer.
To remove all Packet Monitor filters you have created, run this command:
pktmon filter remove
You can use PktMon to track network traffic in the real time. To do it, use the -l real-time
parameter. In this mode, the captured packets are displayed in the console and are not written to the log file in the background.
pktmon start --etw -p 0 -l real-time
Ctrl+C
.If you see a packet loss (drop) in your network interface, PacketMon can show you the reason (for example, incorrect MTU or VLAN).
You can also use PktMon in Windows Admin Center using the extensions. The data you collect from computers or servers when diagnosing network issues may be used in more powerful software analyzing network traffic, like Microsoft Network Monitor or Wireshark.
7 comments
If you need to get NIC IDs as object, you can use:
function _getNICId {
pktmon comp list | Select-String “Id:” -AllMatches -Context 1 | % {
$values = $_ -split “`n” -replace “^>?\s+(Id:\s*)?” | select -First 2
[PSCustomObject]@{
NIC = $values[0]
ID = $values[1]
}
}
}
And powershell proxy function 🙂
function Invoke-NetworkCapturePktMon {
[CmdletBinding()]
param (
[int[]] $port
,
[int[]] $NICId
,
[switch] $dropOnly
,
[switch] $captureWholePacket
,
[int] $captureSizeMB = 512
,
[ValidateScript( { $_ -match “\.etl$” })]
[string] $captureName = “PktMon.etl”
,
[ValidateSet(‘real-time’, ‘multi-file’, ‘circular’, ‘memory’)]
[string] $logMode = “real-time”
,
[switch] $formatAsText
,
[switch] $formatAsPCAPNG
)
#region checks
if (! ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] “Administrator”)) {
throw “You don’t have administrator rights”
}
if ($formatAsText -or $formatAsPCAPNG -and $logMode -eq “real-time”) { Write-Warning “You are not capturing to file, specifying format is useless” }
if ($captureName -ne “PktMon.etl” -and $logMode -eq “real-time”) { Write-Warning “You are not capturing to file, specifying captureName is useless” }
if ($captureSizeMB -ne 512 -and $logMode -eq “real-time”) { Write-Warning “You are not capturing to file, specifying captureSizeMB is useless” }
#endregion checks
$existingFilter = pktmon filter list
if ($existingFilter -and $existingFilter -notmatch “There are no packet filters”) {
Write-Warning “### Existing pktmon filters:”
# output existing filters
$existingFilter
Write-Warning “### Deleting filters”
# delete existing filters
pktmon filter remove
}
#region prepare arguments
if (!$NICId) {
$choice = “”
while ($choice -notmatch “^[1|2]$”) {
$choice = Read-Host “Youd didn’t specified any NIC ID. Please select one of the options:`n1) Capture traffic from all NICs`n2) Show list of available NIC to make some selection`n”
}
if ($choice -eq “1”) {
(Get-Variable NICId).Attributes.Clear()
[string] $NICId = “all”
} else {
function _getNICId {
pktmon comp list | Select-String “Id:” -AllMatches -Context 1 | % {
$values = $_ -split “`n” -replace “^>?\s+(Id:\s*)?” | select -First 2
[PSCustomObject]@{
NIC = $values[0]
ID = $values[1]
}
}
}
$NICId = _getNICId | Out-GridView -Title “Select NIC(s) for traffic capture” -OutputMode Multiple | select -exp ID
}
}
$argument = “start –etw”
if ($captureWholePacket) { $argument += ” –packet-size 0″ }
if ($NICId) { $argument += ” –components $($NICId -join ” “)” }
if ($dropOnly) { $argument += ” –drop-only” }
$argument += ” –log-mode $logMode”
if ($logMode -ne “real-time”) {
$argument += ” –file-name $captureName”
$argument += ” –file-size $captureSizeMB”
}
#endregion prepare arguments
# set filters
if ($port) {
“### Setting port filter”
Write-Verbose “Arguments are: filter add –port $($port -join ‘ ‘)”
Start-Process “pktmon.exe” -arg “filter add –port $($port -join ‘ ‘)”
}
if ($logMode -eq “real-time”) {
Write-Warning “To stop capture press CTRL + C”
}
# start capture
“### Starting capture”
Write-Verbose “Arguments are: $argument”
Invoke-Expression “pktmon.exe $argument” # start-process neslo pouzit protoze nefungovalo CTRL+C pro preruseni
if ($logMode -ne “real-time”) {
Write-Warning “To stop capture run: pktmon.exe stop”
}
if ($logMode -ne “real-time” -and $formatAsText) {
“`n`nTo transform captured etl to txt run: pktmon.exe format pathToCapture.etl –out C:\temp\packetsniffer.txt”
}
if ($logMode -ne “real-time” -and $formatAsPCAPNG) {
“`n`nTo transform captured etl to pcapng run: pktmon.exe PCAPNG pathToCapture.etl –out C:\temp\packetsniffer.pcapng”
}
}
[…] https://woshub.com/network-sniffer-packet-monitor-pktmon/ […]
pktmon start –etw -p 0 -l real-time
Error: ‘0’ is not a valid event provider Id.
pktmon start –etw -p 0 -l real-time is all over the internet but it does not work.
Error: ‘0’ is not a valid event provider Id.
Error: ‘0’ is not a valid event provider Id.
seems like nobody cares about that error 😀
MSFT changed start command switches. Try ‘pktmon start -c -m real-time’