Skip to content

Instantly share code, notes, and snippets.

@daniel0x00
Created April 27, 2020 16:01
Show Gist options
  • Save daniel0x00/129368961c2b194a12cf8213171ab684 to your computer and use it in GitHub Desktop.
Save daniel0x00/129368961c2b194a12cf8213171ab684 to your computer and use it in GitHub Desktop.
Converts PowerShell PoshNmap JSON output into a pipeline-enabled one with some other improvements
function ConvertTo-ScanResult {
# Parse an output of PoshNmap by @JustinGrote
# Author: Daniel Ferreira (@daniel0x00)
# License: BSD 3-Clause
<#
.SYNOPSIS
Parse and improve the JSON output of PoshNmap.
.EXAMPLE
Invoke-Nmap 40.100.12.0/24 -OutFormat JSON -ArgumentList '--top-ports=10' | ConvertFrom-Json | ConvertTo-ScanResult -ScannerLocation internet-australia | ConvertTo-Json -Depth 10
.PARAMETER ScannerLocation
String. Represents the location of the scanner. It will be included in the output JSON.
Default: internet
.PARAMETER ScannerHostname
String. Represents the name of the scanner. It will be included in the output JSON.
Default: $env:COMPUTERNAME
#>
[CmdletBinding()]
[OutputType([PSCustomObject])]
param(
[Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)]
[PSCustomObject] $InputObject,
[Parameter(Position=1, Mandatory=$false, ValueFromPipeline=$false)]
[string] $ScannerLocation='internet',
[Parameter(Position=2, Mandatory=$false, ValueFromPipeline=$false)]
[string] $ScannerHostname=$env:COMPUTERNAME
)
process {
# Prepare the array of results.
# Check if array is null, so there were no hosts up. Force results to output rest of metadata:
$ScanResults = $InputObject.nmaprun.host
$ScanResultsCount = $ScanResults.Length
if ($null -eq $ScanResults) { $ScanResults = 1 }
# Make global data of the scan request available 'per output record':
$ScanInfo = [PSCustomObject]@{
info = $InputObject.nmaprun.scaninfo
command = $InputObject.nmaprun.args
target = [string](([regex]::Match($InputObject.nmaprun.args,'\s(?<target>[\d\-\./]+).?$')).groups['target'].value)
results = $ScanResultsCount
scanner = [PSCustomObject]@{
hostname = $ScannerHostname
location = $ScannerLocation
}
}
# Output:
$ScanResults | ForEach-Object {
# Build summary:
$Summary = [PSCustomObject]@{
tcp = [PSCustomObject]@{
open = ($_.ports.port.foreach({$_.where({$_.protocol -eq 'tcp' -and $_.state.state -eq 'open'})})).portid -join '/'
closed = ($_.ports.port.foreach({$_.where({$_.protocol -eq 'tcp' -and $_.state.state -notmatch 'open'})})).portid -join '/'
}
udp = [PSCustomObject]@{
open = ($_.ports.port.foreach({$_.where({$_.protocol -eq 'udp' -and $_.state.state -eq 'open'})})).portid -join '/'
closed = ($_.ports.port.foreach({$_.where({$_.protocol -eq 'udp' -and $_.state.state -notmatch 'open'})})).portid -join '/'
}
}
# Output:
$_ | Select-Object *, @{n='scan';e={$ScanInfo}}, @{n='summary';e={$Summary}}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment