I covered a post for packet capture without Wireshark in the post here
This is using "netsh" as Windows ships with an inbox packet capture component called "ndiscap," which is implemented as an ETW trace provider, this mean no Wireshark installs and native Windows commands.
Packet Capture with netsh
If you wish to capture all traffic then the command is very simple, this is that command, if you do not specify the path the etl trace will be created in the folder where the command is run:
netsh trace start capture=yes tracefile=AllTraffic.etl report=disabled
Packet Capture that remains valid after reboot
If you wish to capture traffic after a reboot then you need to enable persistent mode like this:
netsh trace start capture=yes tracefile=AllTraffic.etl persistent=yes report=disabled
LDAP Traffic Only
However lets say we wish to capture all the LDAP traffic for unsigned connections, which will use TCP:389 the command would be:
netsh trace start capture=yes tracefile=c:\temp\LDAP_Trace.etl persistent=yes overwrite=yes keywords=TCP.Port=389 report=disabled
We have added more parameters to the command in that example so lets go over these parameters:
capture=yes: Enables packet capture.
tracefile=LDAP_Trace.etl: Specifies the output trace file.
persistent=yes: Keeps the trace running across reboots (optional).
overwrite=yes: Overwrites the trace file if it already exists.
keywords=TCP.Port=389: Captures only traffic on TCP port 389.
report=disabled= Does not save the CAB file with diagnostic data outside of packet capture.
Stopping the trace
When you have reproduced the problem you are looking to analyse then you can stop the trace with this command:
netsh trace stop
Other Packet Capture Examples
If you wish to capture different types of data in your packet capture then there are some sample commands below that go though some examples:
Specific IP Trace (to and from)
netsh trace start capture=yes IPv4.Address=10.11.70.266 tracefile=AllTraffic.etl report=disabled
DNS Trace
netsh trace start capture=yes keywords=DNS tracefile=DNS_Trace.etl report=disabled
HTTPS and TCP:443 Trace
netsh trace start capture=yes keywords=TCP tracefile=HTTPS_Trace.etl persistent=yes report=disabled
HTTP/HTTPS Trace
netsh trace start capture=yes keywords=HTTP tracefile=WebTraffic.etl report=disabled
SMB Trace
netsh trace start capture=yes keywords=SMB tracefile=SMB_Trace.etl report=disabled
Convert the ETW traces
We now need convert the ETW traces to PCAPNG files using an application called "etl2pcapng" you can obtain the Windows executable from the link below:
https://github.com/microsoft/etl2pcapng/releases
The file generated by ndiscap is an etl file, which can be opened by ETW-centric tools like Microsoft Message Analyzer, but cannot be opened by Wireshark, which is the preferred tool for many engineers. Etl2pcapng.exe can convert the etl file to a pcapng file for opening with Wireshark.
The command is then:
etl2pcapng <etw-file> <output-file>
This as an example command woudl be:
etl2pcapng LDAP_Trace.etl ldap.pcapng
This will then output a file called ldap.pcapng which can be used in Wireshark as you can see below:
You can open this file in Wireshark and manually filter for events you are interested in, however as we are looking in this trace for "simple binds" (which is the bind that uses clear text passwords) we can get as script to analyse that file.
Analyse Wireshark file for LDAP
First, we need to analyse the Wireshark files for all LDAP requests which will include all the LDAP requests binding to TCP:389 this will give us a CSV file:
Script : Analyse-pcapng.ps1
Note : This will require WireShark with “tshark” installed, if you have not installed this script, will give you details of how to install it when you run the Powershell.
# Requires tshark to be installed
# Analyzes .pcapng files for LDAP traffic and exports to CSV
# Function to check if tshark is installed
function Test-TsharkInstalled {
try {
$null = Get-Command tshark -ErrorAction Stop
return $true
}
catch {
Write-Host @"
Error: tshark is not installed or not in PATH. Here's how to fix this:
1. Install Wireshark:
- Go to https://www.wireshark.org/download.html
- Download the Windows Installer (.exe)
- During installation, CHECK THE BOX for 'Install TShark'
2. Add tshark to your system PATH:
- Press Win + S and type 'environment'
- Click 'Edit the system environment variables'
- Click 'Environment Variables' button
- Under 'System Variables', find and select 'Path'
- Click 'Edit'
- Click 'New'
- Add: C:\Program Files\Wireshark (or your Wireshark installation path)
- Click 'OK' on all windows
3. Verify installation:
- Open a NEW PowerShell window
- Type: tshark --version
After completing these steps, run this script again.
"@ -ForegroundColor Yellow
return $false
}
}
function Analyze-PcapFile {
param (
[Parameter(Mandatory=$true)]
[string]$FilePath
)
try {
# Create CSV output filename
$csvOutput = $FilePath -replace '\.pcapng$', '_ldap_analysis.csv'
# Command for CSV output
$csvCommand = 'tshark -r "' + $FilePath + '" -Y "tcp.dstport==389" -T fields ' + `
'-e frame.number -e frame.time -e ip.src -e tcp.srcport -e ip.dst -e tcp.dstport -e tcp.len -e _ws.col.Info ' + `
'-E header=y -E separator=","'
Write-Host "Analyzing: $FilePath" -ForegroundColor Cyan
# Create CSV export
$csvResults = Invoke-Expression $csvCommand
if ($csvResults) {
$csvResults | Out-File $csvOutput -Encoding UTF8
Write-Host "Data exported to: $csvOutput" -ForegroundColor Green
}
else {
Write-Host "No matching packets found in $FilePath" -ForegroundColor Yellow
}
}
catch {
Write-Host "Error analyzing file: $($_.Exception.Message)" -ForegroundColor Red
}
}
# Main script execution
if (-not (Test-TsharkInstalled)) {
exit 1
}
# Get all .pcapng files
$pcapFiles = Get-ChildItem -Filter "*.pcapng"
if ($pcapFiles.Count -eq 0) {
Write-Host "No .pcapng files found in current directory." -ForegroundColor Yellow
exit
}
foreach ($file in $pcapFiles) {
Analyze-PcapFile -FilePath $file.FullName
}
Parse CSV file for "simple binds"
Now we need to parse this file for binds that have no authentication attached that will send the password in "clear text" this will use this logic:
# Import CSV and search for Simple Bind requests
$data = Import-Csv $FilePath
# Looking for entries that indicate simple authentication
$simpleBinds = $data | Where-Object {
$_.'_ws.col.Info' -like '*SimpleAuth*' -or
$_.'_ws.col.Info' -like '*simple bind*' -or
$_.'_ws.col.Info' -like '*SIMPLE_BIND*'
If any are found the script will let you know on the screen which saves you manually searching though the file yourself, unless you would rather manually go though all those packets - one by one.
Script : SimpleBindChecker.ps1
# Script to search LDAP analysis CSV files for Simple Bind requests with clear text
function Search-SimpleBinds {
param (
[Parameter(Mandatory=$true)]
[string]$FilePath
)
try {
Write-Host "Analyzing: $FilePath" -ForegroundColor Cyan
# Check if file exists
if (-not (Test-Path $FilePath)) {
Write-Host "File not found: $FilePath" -ForegroundColor Red
return
}
# Import CSV and search for Simple Bind requests
$data = Import-Csv $FilePath
# Looking for entries that indicate simple authentication
$simpleBinds = $data | Where-Object {
$_.'_ws.col.Info' -like '*SimpleAuth*' -or
$_.'_ws.col.Info' -like '*simple bind*' -or
$_.'_ws.col.Info' -like '*SIMPLE_BIND*'
}
if ($simpleBinds) {
Write-Host "`nFound Simple Bind requests:" -ForegroundColor Green
$simpleBinds | Format-Table -AutoSize
# Count the number of simple binds found
Write-Host "`nTotal Simple Bind requests found: $($simpleBinds.Count)" -ForegroundColor Yellow
}
else {
Write-Host "No Simple Bind requests found in $FilePath" -ForegroundColor Yellow
}
}
catch {
Write-Host "Error processing file: $($_.Exception.Message)" -ForegroundColor Red
}
}
# Get all CSV files in current directory
$csvFiles = Get-ChildItem -Filter "*_ldap_analysis.csv"
if ($csvFiles.Count -eq 0) {
Write-Host "No LDAP analysis CSV files found in current directory." -ForegroundColor Yellow
exit
}
foreach ($file in $csvFiles) {
Search-SimpleBinds -FilePath $file.FullName
}
You will then get a report of how many simple binds have been found, which should be "zero" and in this case that is true: