PowerShell to detect USB events and execute actions

Last update: 27/08/2025
Author Isaac
  • PowerShell allows you to detect connections and disconnections USB in real time and send them to a central server via an API.
  • Enabling event channels and using WEF brings enterprise scale and forensic context alongside SIEM.
  • Production deployment combines Task Scheduler, endpoint security, and backend hardening.

Monitor USB events with PowerShell

Connecting memory cards, disks and peripherals via USB can open more doors than it seems: from data leaks to infections by malware without anyone noticing. Monitor and log USB devices entering and leaving the teams is therefore a key measure of ciberseguridad that many organizations already consider basic.

The good news is that the ecosystem Windows offers several approaches, from commercial tools to native methods such as PowerShell and Windows Event Forwarding (WEF). With a well thought out design, USB events can be detected in real time, recorded, sent to a central server and correlated. with other safety signals, all without friction for the user.

Overview and tools for tracking USB devices

In regulated companies (finance, health, etc.), control and traceability are required. The goal is to quickly identify unauthorized devices, prevent exfiltrations and detect attempts to introduce malware from removable media.

If you're looking for something ready-made, there are specific utilities. USB Device Tracker facilitates continuous inventory and auditing, saving identifiers, device type and connection/disconnection times, as well as useful reports to identify patterns or threats.

There are also lightweight utilities. USBDeview (NirSoft) shows present and past USB devices; doesn't send data to a server on its own, but integrates well with scripts to automate exports or notifications in your infrastructure.

In large-scale scenarios, endpoint suites help consolidate. Microsoft Endpoint Manager, ManageEngine Endpoint Central or Ivanti They allow USB device policies and logs at the corporate level, with reports or sending to centralized repositories.

For correlation and alerts, a SIEM like Splunk or Elastic Stack It can ingest USB events and trigger detections in real time. These platforms identify suspicious behavior (connections outside of business hours, unauthorized devices, etc.) and They fit perfectly with a pipeline that feeds data from PowerShell or WEF..

Solutions for auditing USB

Detection and Response with PowerShell: USB Events and Sending to Server

If you prefer flexibility, a script own in PowerShell is very powerful. You can detect connections and disconnections in real time, enrich with metadata and publish to a REST API for your backend.

First, list USB devices connected at a given time. The Win32_DiskDrive class with InterfaceType USB is a good starting point, although it is advisable to supplement with PnP data for the serial number when available:

# Enumerar almacenamiento USB actual
$usb = Get-CimInstance Win32_DiskDrive | Where-Object { $_.InterfaceType -eq 'USB' }
$enriquecido = foreach ($d in $usb) {
  $serial = (Get-CimInstance Win32_PhysicalMedia | Where-Object { $_.Tag -eq $d.DeviceID }).SerialNumber
  [PSCustomObject]@{
    DeviceID   = $d.DeviceID
    Model      = $d.Model
    Interface  = $d.InterfaceType
    Serial     = ($serial -replace '\s+', '').Trim()
  }
}
$enriquecido | Format-Table -AutoSize

In addition to inventory, the key is There real. PowerShell can subscribe to system events to react instantly when connecting or removing a device:

# Monitorizar llegada y retirada de volúmenes (EventType 2=arrive, 3=remove)
Unregister-Event -SourceIdentifier USBMonitor -ErrorAction SilentlyContinue
$null = Register-WmiEvent -Class Win32_VolumeChangeEvent -Action {
  $e = $Event.SourceEventArgs.NewEvent
  $tipo = if ($e.EventType -eq 2) { 'Insert' } elseif ($e.EventType -eq 3) { 'Remove' } else { 'Other' }
  $payload = [PSCustomObject]@{
    Hostname = $env:COMPUTERNAME
    TimeUtc  = (Get-Date).ToUniversalTime().ToString('o')
    Action   = $tipo
    Drive    = $e.DriveName
  }
  try {
    $json = $payload | ConvertTo-Json -Depth 5
    Invoke-RestMethod -Uri 'http://SERVIDOR_CENTRAL/api/usblog' -Method Post -Body $json -ContentType 'application/json'
  } catch {
    Write-Warning ("Error enviando evento USB: {0}" -f $_.Exception.Message)
  }
} -SourceIdentifier USBMonitor

If you also want to capture details of the hardware from the newly inserted USB disk, combines Win32_VolumeChangeEvent with a refresh of Win32_DiskDrive and cross-reference by volume/mounted letter as appropriate. You can also monitor Win32_DeviceChangeEvent for generic device events:

# Alternativa: evento genérico de dispositivo
Unregister-Event -SourceIdentifier USBGeneric -ErrorAction SilentlyContinue
$null = Register-WmiEvent -Class Win32_DeviceChangeEvent -Action {
  $e = $Event.SourceEventArgs.NewEvent
  $payload = [PSCustomObject]@{
    Hostname = $env:COMPUTERNAME
    TimeUtc  = (Get-Date).ToUniversalTime().ToString('o')
    EventType= $e.EventType  # 2 insert, 3 remove
  }
  try {
    Invoke-RestMethod -Uri 'http://SERVIDOR_CENTRAL/api/usblog' -Method Post -Body ($payload|ConvertTo-Json) -ContentType 'application/json'
  } catch {}
} -SourceIdentifier USBGeneric

For a one-time dump and immediate JSON delivery to your server, the pipeline is direct. The following pattern collects current USB drives, transforms them to JSON and publishes them in an API:

Get-CimInstance Win32_DiskDrive | Where-Object { $_.InterfaceType -eq 'USB' } |
  ForEach-Object {
    $serial = (Get-CimInstance Win32_PhysicalMedia | Where-Object { $_.Tag -eq $_.DeviceID }).SerialNumber
    [PSCustomObject]@{ DeviceID = $_.DeviceID; Model = $_.Model; Serial = ($serial -replace '\s+', '').Trim() }
  } |
  ConvertTo-Json |
  Invoke-RestMethod -Uri 'http://SERVIDOR_CENTRAL/api/usblog' -Method Post -ContentType 'application/json'

Beyond inventory and insertions/removals, Windows logs user driver activity related to USB. Enable the Microsoft-Windows-DriverFrameworks-UserMode/Operational channel and reviews key events: connection (e.g., 2003, 2004, 2006, 2010) and disconnection (2102, 2105, 2106), with useful metadata such as manufacturer, model, or instance paths.

  Example: Step-by-step instructions to enable or disable the Samsung proximity sensor

Real-time USB detection with PowerShell

REST API in Flask to centralize logs

You need a simple receiver to store and exploit the data. With Flask you can launch an /api/usblog endpoint. to validate, save and prepare the material for subsequent analysis or sending to SIEM:

from flask import Flask, request, jsonify
from datetime import datetime

app = Flask(__name__)
API_TOKEN = 'cambia-este-token-seguro'

@app.route('/api/usblog', methods=['POST'])
def log_usb():
    if request.headers.get('X-Api-Token') != API_TOKEN:
        return jsonify({'error': 'Unauthorized'}), 401
    data = request.get_json(silent=True)
    if not data:
        return jsonify({'error': 'No payload'}), 400
    line = f"{datetime.utcnow().isoformat()}Z\t{data}\n"
    with open('usb_log.txt', 'a', encoding='utf-8') as f:
        f.write(line)
    return jsonify({'status': 'ok'}), 200

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

To get it started, Install Flask with pip, save the script (e.g., server.py) and run it. From there, your PowerShell script can send events to http://SERVER_IP:5000/api/usblog by adding an X-Api-Token header if you have enabled it.

Although here we write in a file for simplicity, You can send to a database or to your SIEM, or even fork: to a SIEM for online analytics and a data lake (Hadoop/HDInsight) for long-term retention and high-volume forensics.

REST API for USB events

Going live: Autostart, Security, WEF, and Analytics

So that you don't depend on anyone's hand after a restart, automates the Boot from the PowerShell script with Task Scheduler or the Startup folder, and protect the deployment with good security practices.

Automatic startup in Windows

With Task Scheduler: Create a task with maximum privileges and trigger at login or system startup. As an action, run powershell.exe with NoProfile and ExecutionPolicy Bypass pointing to your .ps1.

If you prefer the Home folder: Create a .bat file that launches the script and place it in %APPDATA%\Microsoft\Windows\Start Menu\Programs\StartupIt's simple and works well on user workstations.

Example of .bat: powershell.exe -NoProfile -ExecutionPolicy Bypass -File «C:\path\script.ps1», adjusting the path to your environment and ensuring the script is signed or comes from a trusted source.

Safety recommendations

Protect the API: Firewall filtering, require token or mTLS, and apply rate limitsAvoid exposing the endpoint beyond the necessary network and record the minimum amount of personal data required in detail.

  How to Dub TikTok Videos - Lip Sync

Hardens the client: use service accounts with minimum privilegesRotate the token, validate TLS where applicable, and control the ExecutionPolicy with GPOs if applicable; if possible, sign the script and validate integrity.

Conduct regular audits: check the server and client logs, compares unusual patterns and cross-references with device control policies to detect unauthorized access or deviation.

Windows Event Forwarding (WEF) for corporate coverage

When you want scale and resilience in Windows, WEF forwards events to a Windows Event Collector (WEC) server without installing additional agents. It's passive with respect to logging: it doesn't enable channels or change audits; these settings must be applied via GPO.

Double subscription model: baseline (for all computers) and suspect (for a subset after an alert)The suspects list collects more signals for forensic context and can be updated without affecting the rest.

Recommended data destination: Baseline to SEM/SIEM or SQL; suspect to MapReduce/HDInsight/Data Lake due to its volume and lower signal-to-noise ratio. The SIEM correlates and alerts at machine speed; the data retains data for years and allows for complex analysis.

Indicative scalability: Up to 5.000 events/s in SQL/SEM; 5.000-50.000 in SEM; above that, data lakeOn standard WEC servers, the practical figure is around 3.000 events/s in total depending on hardware and disks.

Push vs Pull: The most flexible is subscription initiated by the origin (push) configured by GPO. Pull requires predefining clients in WEC and remote event reading permissions (adding the credential to the Event Log Readers group).

Encryption and authentication: In domain, Kerberos encryption by default (NTLM optional); HTTPS is used with certificate authentication when Kerberos is not available. Authentication is mutual in both cases.

Format and frequency: Default “Rendered Text”; alternative “Events” (XML binary) is more compactDelivery modes: Normal, Minimize bandwidth (push, batches every ~6h), Minimize latency (push, batches ~30s), or custom via WECUTIL with DeliveryMaxItems and DeliveryMaxLatencyTime.

Practical limits of WEC: EVTX log disk (I/O), simultaneous TCP connections and log size (persistent keys per source). For large volumes, wecutil.exe is preferable to the Event Viewer console.

Enable key channels and size logs: DriverFrameworks-UserMode/Operational (enable and expand to ~50 MB), CAPI2/Operational (100 MB and permissions for Event Log Readers), AppLocker (EXE/DLL and MSI/Script, ~100 MB). Use GPO with wevtutil for scripting:

%SystemRoot%\System32\wevtutil.exe sl Microsoft-Windows-DriverFrameworks-UserMode/Operational /e:true
%SystemRoot%\System32\wevtutil.exe sl "Microsoft-Windows-DriverFrameworks-UserMode/Operational" /ms:52432896
%SystemRoot%\System32\wevtutil.exe sl Microsoft-Windows-CAPI2/Operational /e:true
%SystemRoot%\System32\wevtutil.exe sl Microsoft-Windows-CAPI2/Operational /ms:102432768
%SystemRoot%\System32\wevtutil.exe sl Microsoft-Windows-CAPI2/Operational /ca:"O:BAG:SYD:(A;;0x7;;;BA)(A;;0x2;;;AU)(A;;0x1;;;S-1-5-32-573)"
%SystemRoot%\System32\wevtutil.exe sl "Microsoft-Windows-AppLocker/EXE and DLL" /ms:102432768

USB and Device Activity Relevant Events: DriverFrameworks-UserMode: 2003, 2004, 2006, 2010, 2100, 2101, 2105, 2106, and 2102 (disconnected). In the Security and System channel, expand auditing for process creation (4688), registry changes (4657), RDP sessions (4778/4779), shared resources (5140, 5142, 5144), system time (4616), starts/stops (12/13/1074), and others collected in baseline and suspicious subscriptions.

  Find out how to offload unused apps on iPhone to reclaim storage space

Predefined WEF Subscriptions: “baseline” with security events, AppLocker, Sysmon/Operational (if applicable), SMBClient/Operational, Error Reporting, TaskScheduler/Operational, etc.; and “suspicious” with network (logon type 3), DNS Client/Operational (3008, filtering gaps), CAPI2 (11/70/90), PowerShell/Operational (4103-4106), DriverFrameworks-UserMode/Operational (2004) and more. Set “read existing events” to true on the suspects to scan history.

Advanced Options: force “Events” format with WECUTIL To double capacity and customize latency/batch size:

wecutil ss "NombreSuscripcion" /cf:Events
wecutil ss "NombreSuscripcion" /cm:Custom
wecutil ss "NombreSuscripcion" /dmi:1
wecutil ss "NombreSuscripcion" /dmlt:10

PowerShell Logging and Forensics

PowerShell since v5.0 enables the script block log (4104) by default, with fragmentation into multiple events when the content is large. This allows for the reconstruction of executed scripts, which is key in incident response.

For reconstructions, Filter by ScriptBlock ID and sort by sequence to concatenate the original content, even if you only recover part of it by log rotation:

# Extraer eventos 4104 con un ScriptBlockID concreto
$evts = Get-WinEvent -FilterHashtable @{ Path='C:\Ruta\Microsoft-Windows-PowerShell%4Operational.evtx'; ProviderName='Microsoft-Windows-PowerShell'; Id=4104 } |
        Where-Object { $_.Message -like '*51baf005-40a5-4878-ab90-5ecc51cab9af*' }
$sorted = $evts | Sort-Object { $_.Properties[0].Value }
$sorted | Select-Object TimeCreated, ActivityId, Id, Message
# Unir el contenido del script si tuvieras todos los segmentos
# ($sorted | ForEach-Object { $_.Properties[2].Value }) -join '' | Out-File script_reconstruido.ps1 -Encoding UTF8

Golden Rule: Increases log sizes and enables channels that are not active. to avoid losing artifacts due to rotation. In modern environments, increasing channel and EVTX sizes typically doesn't significantly impact performance.

ADAudit Plus and other integrations

For a file server-centric view, ADAudit Plus includes USB Storage Auditing reports with details of “file read,” “file modified,” “copy/paste,” and “removable device plug-in.” It also offers searching by server, path, author of the change, and message.

In broader ecosystems, Microsoft Endpoint Manager, ManageEngine Endpoint Central and Ivanti set policies and consolidate removable device signals, and a SIEM (Splunk/Elastic) collects events and alerts based on rules and machine learning. This framework covers both compliance and early detection.

Production start-up and safety

With all the above, you have a complete route: Real-time inventory and events with PowerShell, central API with Flask, startup automation, end-to-end security, and WEF for scalingIf you also power a SIEM and strengthen security auditing (baseline + suspect), you'll gain granular visibility, forensic context, and the ability to react to unauthorized access or USB infection attempts.