|
| 1 | +title: Port Probing Via PowerShell Network Cmdlets Or .NET Sockets |
| 2 | +id: 0f0a89f7-0fae-48f6-bb47-26c7b9e3c5bd |
| 3 | +related: |
| 4 | + - id: adf876b3-f1f8-4aa9-a4e4-a64106feec06 |
| 5 | + type: obsolete |
| 6 | +status: experimental |
| 7 | +description: | |
| 8 | + Detects the use of built-in PowerShell network diagnostic cmdlets or .NET socket classes to probe a specific TCP port on a local or remote host. |
| 9 | + Adversaries may use "Test-NetConnection" or "Test-Connection" with an explicit port, or directly instantiate .NET "Net.Sockets.Socket"/"Net.Sockets.TcpClient" objects and call their connect methods, to enumerate reachable network services as a precursor to lateral movement. |
| 10 | +references: |
| 11 | + - https://learn.microsoft.com/en-us/powershell/module/nettcpip/test-netconnection?view=windowsserver2022-ps |
| 12 | + - https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/test-connection?view=powershell-7.4 |
| 13 | + - https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.tcpclient.connect |
| 14 | + - https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.socket.connect |
| 15 | + - https://github.com/redcanaryco/atomic-red-team/blob/f339e7da7d05f6057fdfcdd3742bfcf365fee2a9/atomics/T1571/T1571.md#atomic-test-1---testing-usage-of-uncommonly-used-port-with-powershell |
| 16 | +author: Norbert Jaśniewicz (AlphaSOC) |
| 17 | +date: 2026-08-10 |
| 18 | +tags: |
| 19 | + - attack.discovery |
| 20 | + - attack.t1046 |
| 21 | +logsource: |
| 22 | + product: windows |
| 23 | + category: ps_script |
| 24 | + definition: 'Requirements: Script Block Logging must be enabled' |
| 25 | +detection: |
| 26 | + selection_tnc: |
| 27 | + # Match Test-NetConnection or tnc with port flag. Flags in PowerShell may be abbreviated to the shortest unambiguous prefix. |
| 28 | + ScriptBlockText|re|i: '(Test-NetConnection|tnc)[^\r\n]*[ \t]-(((Remote)?(P|Po|Por|Port))|Comm|Commo|Common|CommonT|CommonTC|CommonTCP|CommonTCPP|CommonTCPPo|CommonTCPPor|CommonTCPPort)[: \t]' |
| 29 | + selection_tc: |
| 30 | + ScriptBlockText|re|i: '(Test-Connection)[^\r\n]*[ \t]-(Tc|Tcp|TcpP|TcpPo|TcpPor|TcpPort)[: \t]' |
| 31 | + selection_dotnet_class: |
| 32 | + ScriptBlockText|contains: |
| 33 | + - 'Net.Sockets.Socket' |
| 34 | + - 'Net.Sockets.TcpClient' |
| 35 | + selection_dotnet_method: |
| 36 | + ScriptBlockText|contains: |
| 37 | + - '.Connect(' |
| 38 | + - '.ConnectAsync(' |
| 39 | + - '.BeginConnect(' |
| 40 | + selection_tcpclient_ctor: |
| 41 | + # The "TcpClient(host, port)" constructor connects immediately, so no separate connect call is made. |
| 42 | + # An argument separator is required before the closing parenthesis, so the non-connecting default constructor is not matched. |
| 43 | + # Line breaks are allowed inside the argument list, since PowerShell does not require a continuation character within parentheses. |
| 44 | + ScriptBlockText|re|i: |
| 45 | + # New-Object Net.Sockets.TcpClient("host", port) |
| 46 | + - 'Net\.Sockets\.TcpClient\([^)]*,' |
| 47 | + # [Net.Sockets.TcpClient]::new("host", port) |
| 48 | + - 'Net\.Sockets\.TcpClient\]::new\([^)]*,' |
| 49 | + condition: selection_tnc or selection_tc or all of selection_dotnet_* or selection_tcpclient_ctor |
| 50 | +falsepositives: |
| 51 | + - Infrastructure monitoring and health-check scripts |
| 52 | + - Administrators troubleshooting network connectivity or firewall rules |
| 53 | +level: low |
0 commit comments