// OVERVIEW
PortMon is a serial and parallel port monitor — it captures all I/O requests sent to serial (COM) and parallel (LPT) ports in real time. Originally designed for debugging hardware peripherals and printer drivers, it has significant relevance in security contexts for detecting rogue hardware implants, BadUSB devices presenting as COM ports, and keyloggers communicating over serial.
Note: PortMon is an older Sysinternals tool and may have driver compatibility issues on Windows 10/11 with Secure Boot or Driver Signature Enforcement enabled. Running on a test system without DSE enforcement, or in a VM, is recommended for forensic use.
Note: PortMon is an older Sysinternals tool and may have driver compatibility issues on Windows 10/11 with Secure Boot or Driver Signature Enforcement enabled. Running on a test system without DSE enforcement, or in a VM, is recommended for forensic use.
// HYLAS SECURITY NOTE — PortMon is uniquely relevant to hardware-based security testing. BadUSB devices (Rubber Ducky, O.MG Cable, DIY ESP32/Pico payloads) that present as HID + CDC Serial will appear as a COM port. PortMon can capture the serial data stream from such a device, exposing the C2 channel or exfiltration path.
// GUI OPERATION
PortMon is GUI-only (no CLI mode). Key operations:
| Action | Menu / Method | Description |
|---|---|---|
| Connect to local ports | Computer → Connect Local | Monitor all COM/LPT ports on the current machine |
| Connect to remote ports | Computer → Connect Remote → [hostname] | Monitor ports on a remote machine (requires portmon driver on remote) |
| Start / stop capture | Capture menu → Capture Events | Toggle real-time capture on/off |
| Filter by port | Filter → Filter... | Focus on specific COM port — useful to isolate one device |
| Filter by IRP type | Filter → Highlight... | Show only READ, WRITE, or specific IOCTL requests |
| Save log | File → Save | Export captured events to file for analysis |
| Clear display | Edit → Clear | Reset the event list to start a fresh capture |
// OUTPUT FIELDS
| Field | Description |
|---|---|
| Time | Timestamp of the I/O request (microsecond precision) |
| Process | Process making the request — KEY for identifying which process communicates with the device |
| Request | IRP (I/O Request Packet) type: IRP_MJ_READ, IRP_MJ_WRITE, IRP_MJ_DEVICE_CONTROL, etc. |
| Port | COM or LPT port identifier (e.g. \Device\Serial0 = COM1) |
| Length | Number of bytes in the request |
| Data | Hex dump + ASCII of the actual bytes sent or received |
| Other | IOCTL codes, baud rate changes, flow control, line state changes |
// SERIAL IOCTL REFERENCEIRP TYPES
| IRP / IOCTL | Meaning | Security relevance |
|---|---|---|
| IRP_MJ_CREATE | Port opened by a process | Identifies when a process connects to the COM device |
| IRP_MJ_READ | Data read from port (incoming from device) | See what the implant is sending to the host |
| IRP_MJ_WRITE | Data written to port (outgoing to device) | See what the host is sending to the implant (commands) |
| IRP_MJ_CLOSE | Port closed | Connection lifecycle tracking |
| IOCTL_SERIAL_SET_BAUD_RATE | Baud rate configuration | BadUSB/implants typically use 115200 baud |
| IOCTL_SERIAL_SET_LINE_CONTROL | Data bits, stop bits, parity | Standard: 8N1 (8 data, no parity, 1 stop) |
| IOCTL_SERIAL_SET_TIMEOUTS | Read/write timeout configuration | Very short timeouts suggest polling behaviour (beacon) |
| IOCTL_SERIAL_WAIT_ON_MASK | Waiting for specific events (data arrival) | Common in drivers that poll for incoming data |
// BADUSB & HARDWARE IMPLANT DETECTIONSECURITY
BadUSB devices (ESP32, Raspberry Pi Pico, Rubber Ducky, O.MG Cable) that present as both HID keyboard and USB CDC serial (composite USB device) will show up as:
Device Manager:
Human Interface Devices → USB Input Device (HID keyboard)
Ports (COM & LPT) → USB Serial Device (COMx) ← PortMon captures this
Registry location:
HKLM\SYSTEM\CurrentControlSet\Enum\USB\
HKLM\SYSTEM\CurrentControlSet\Services\usbser\Enum\
What PortMon reveals about a BadUSB serial channel:
1. IRP_MJ_CREATE from a process (which process opened the COM port?)
- Legitimate: Arduino IDE, PuTTY, device driver host
- Suspicious: cmd.exe, powershell.exe, python.exe, unknown binary
2. IRP_MJ_WRITE data — commands sent to the device
- Check the Data column for ASCII commands
- Base64 encoded strings suggest obfuscated C2 commands
3. IRP_MJ_READ data — data sent FROM the device to the host
- Keylog data, exfiltrated files, beaconing responses
4. IOCTL_SERIAL_SET_BAUD_RATE
- BadUSB typically: 9600, 115200, or 1000000 baud
- USB CDC virtual COM ignores actual baud — the rate is cosmetic
Rogue COM port audit via PowerShell (no PortMon needed):
Get-WMIObject Win32_SerialPort | Select Name, DeviceID, PNPDeviceID, Description
Get-PnpDevice | Where-Object{$_.Class -eq "Ports"} | Format-List
; Cross-reference VID/PID of found COM devices against known-good hardware inventory
; Suspicious VID:PID combinations:
; VID_2341 (Arduino), VID_2E8A (Raspberry Pi), VID_10C4 (Silicon Labs CP2102)
; VID_1A86 (CH340 — common in cheap clones)
// RED TEAMATTACKER
Use HID-only — avoid CDC serial channel if stealth is required. HID-only devices don't appear in COM ports and won't be captured by PortMon.
Spoof VID/PID — configure USB device to present as known-good hardware (e.g. Dell keyboard VID) to evade hardware inventory checks.
Encrypt serial channel — base64 + XOR minimum; ensure PortMon data capture reveals nothing useful in plaintext.
Use short burst comms — open COM port, send/receive, close immediately. Minimises the window for process-to-port association.
// BLUE TEAMDEFENDER
USB device whitelisting — use Windows Defender Device Control or a MDM policy to whitelist approved USB VID/PID combinations. Block unknown COM devices.
Audit COM port processes — periodic check: which processes have COM ports open?
handle64.exe \Device\SerialPhysical USB port control — epoxy unused USB ports, enforce port-locking hardware in high-security environments.
PortMon remote monitoring — deploy as part of a hardware implant detection sweep when a new USB device is found connected to an asset.