Nmap2PSObject.psm1

# Nmap2PSObject.psm1

# Function: Get-NmapRegularScan
function Get-NmapRegularScan {
    <#
    .SYNOPSIS
    Parses the results of a regular Nmap scan with no support for additional flags from an XML file.
 
    .DESCRIPTION
    This function reads an Nmap XML output file and converts it into PowerShell objects.
    It extracts host-level information such as IP addresses, MAC addresses, vendors,
    and status.
 
    .PARAMETER FilePath
    The full path to the Nmap XML file to parse.
 
    .EXAMPLE
    Get-NmapRegularScan -FilePath "C:\scans\scan.xml"
 
    .NOTES
    Author: Kalichuza
    #>


    param (
        [string]$FilePath
    )
    
    # Load the Nmap XML file
    $nmapXml = [xml](Get-Content -Path $FilePath)

    # Initialize an array to store PSCustomObjects
    $hosts = @()

    foreach ($currentHost in $nmapXml.nmaprun.hosthint) {
        $hostname = $currentHost.hostname
        $ipAddress = $currentHost.address.addr
        $macAddress = if ($currentHost.address.Count -ge 2) { $currentHost.address[1].addr } else { $null }
        $vendor = if ($currentHost.address.Count -ge 2) { $currentHost.address[1].vendor } else { $null }
        $status = $currentHost.status.state

        $hostObject = [PSCustomObject]@{
            Hostname   = $hostname
            IPAddress  = $ipAddress
            MACAddress = $macAddress
            Vendor     = $vendor
            Status     = $status
        }

        $hosts += $hostObject
    }

    return $hosts
}

# Function: Get-NmapVersionScan
function Get-NmapVersionScan {
    <#
    .SYNOPSIS
    Parses the results of a Nmap scan uding the -sV flag with version information from an XML file.
 
    .DESCRIPTION
    This function reads an Nmap XML output file and converts it into PowerShell objects.
    It extracts host-level information such as IP addresses, MAC addresses, vendors,
    and status.
 
    .PARAMETER FilePath
    The full path to the Nmap XML file to parse.
 
    .EXAMPLE
    Get-NmapVersionScan -FilePath "C:\scans\scan.xml"
 
    .NOTES
    Author: Kalichuza
    #>


    param (
        [string]$FilePath
    )

    # Load the Nmap XML file
    $nmapXml = [xml](Get-Content -Path $FilePath)

    # Initialize an array to store PSCustomObjects
    $hosts = @()

    foreach ($currentHost in $nmapXml.nmaprun.host) {
        $hostname = $currentHost.hostname
        $ipAddress = $currentHost.address.addr
        $macAddress = if ($currentHost.address.Count -ge 2) { $currentHost.address[1].addr } else { $null }
        $vendor = if ($currentHost.address.Count -ge 2) { $currentHost.address[1].vendor } else { $null }
        $status = $currentHost.status.state

        $ports = @()

        if ($currentHost.ports.port) {
            foreach ($port in $currentHost.ports.port) {
                $portNumber = $port.portid
                $protocol = $port.protocol
                $state = $port.state.state
                $serviceName = $port.service.name
                $serviceVersion = if ($port.service.version) { $port.service.version } else { "Unknown" }
                $product = if ($port.service.product) { $port.service.product } else { "Unknown" }

                $ports += [PSCustomObject]@{
                    PortNumber      = $portNumber
                    Protocol        = $protocol
                    State           = $state
                    ServiceName     = $serviceName
                    ServiceVersion  = $serviceVersion
                    Product         = $product
                }
            }
        }

        $hostObject = [PSCustomObject]@{
            Hostname   = $hostname
            IPAddress  = $ipAddress
            MACAddress = $macAddress
            Vendor     = $vendor
            Status     = $status
            OpenPorts  = $ports
        }

        $hosts += $hostObject
    }

    return $hosts
}

# Function: Get-NmapVulnScan
function Get-NmapVulnScan {
    <#
    .SYNOPSIS
    Parses the results of a Nmap scan using the --script flag with vulnerability information from an XML file.
 
    .DESCRIPTION
    This function reads an Nmap XML output file and converts it into PowerShell objects.
    It extracts host-level information such as IP addresses, MAC addresses, vendors,
    and status.
 
    .PARAMETER FilePath
    The full path to the Nmap XML file to parse.
 
    .EXAMPLE
    Get-NmapVulnScan -FilePath "C:\scans\scan.xml"
 
    .NOTES
    Author: Kalichuza
    #>

    param (
        [string]$FilePath
    )

    # Load the Nmap XML file
    $nmapXml = [xml](Get-Content -Path $FilePath)

    # Initialize an array to store PSCustomObjects
    $hosts = @()

    foreach ($currentHost in $nmapXml.nmaprun.host) {
        $hostname = $currentHost.hostname
        $ipAddress = $currentHost.address.addr
        $macAddress = if ($currentHost.address.Count -ge 2) { $currentHost.address[1].addr } else { $null }
        $vendor = if ($currentHost.address.Count -ge 2) { $currentHost.address[1].vendor } else { $null }
        $status = $currentHost.status.state
        $scripts = $currentHost.hostscript.script

        $ports = @()

        if ($currentHost.ports.port) {
            foreach ($port in $currentHost.ports.port) {
                $portNumber = $port.portid
                $protocol = $port.protocol
                $state = $port.state.state
                $serviceName = $port.service.name
                $serviceVersion = if ($port.service.version) { $port.service.version } else { "Unknown" }
                $product = if ($port.service.product) { $port.service.product } else { "Unknown" }

                $ports += [PSCustomObject]@{
                    PortNumber      = $portNumber
                    Protocol        = $protocol
                    State           = $state
                    ServiceName     = $serviceName
                    ServiceVersion  = $serviceVersion
                    Product         = $product
                }
            }
        }

        $scripts = @()

        if ($currentHost.hostscript.script) {
            foreach ($script in $currentHost.hostscript.script) {
                $scriptName = $script.id
                $scriptOutput = $script.output 
        }

        $scripts += [PSCustomObject]@{
            ScriptName = $scriptName
            ScriptOutput = $scriptOutput 
        }
    }

        $hostObject = [PSCustomObject]@{
            Hostname   = $hostname
            IPAddress  = $ipAddress
            MACAddress = $macAddress
            Vendor     = $vendor
            Status     = $status
            OpenPorts  = $ports
            Scripts    = $scripts
        }

        $hosts += $hostObject
    }

    return $hosts
}

function Format-NmapResults {
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]$InputObject,

        [Parameter(Mandatory = $true)]
        [string]$ScriptFunction
    )

    # Process the input object through the specified function
    $full = & $ScriptFunction -FilePath $InputObject

    foreach ($pc in $full) {
        # Combine IPv4 and IPv6 addresses with a pipe separator
        $ipAddress = if ($pc.IPAddress -is [array]) {
            $pc.IPAddress -join " | "
        } else {
            $pc.IPAddress
        }

        # Display top-level information for each IP address
        Write-Host "IPAddress: $ipAddress" -ForegroundColor Cyan
        if ($pc.Hostname) { Write-Host "Hostname: $($pc.Hostname)" }
        if ($pc.Vendor) { Write-Host "Vendor: $($pc.Vendor)" }
        if ($pc.Status) { Write-Host "Status: $($pc.Status)" }

        # Expand and display OpenPorts
        if ($pc.OpenPorts) {
            Write-Host "Open Ports:" -ForegroundColor Green
            foreach ($port in $pc.OpenPorts) {
                Write-Host " PortNumber : $($port.PortNumber)"
                Write-Host " Protocol : $($port.Protocol)"
                Write-Host " State : $($port.State)"
                Write-Host " ServiceName : $($port.ServiceName)"
                Write-Host " ServiceVersion : $($port.ServiceVersion)"
                Write-Host " Product : $($port.Product)"
                Write-Host ""
            }
        }

        # Expand and display Scripts
        if ($pc.Scripts) {
            Write-Host "Scripts:" -ForegroundColor Yellow
            foreach ($script in $pc.Scripts) {
                Write-Host " ScriptName : $($script.ScriptName)"
                Write-Host " ScriptOutput : $($script.ScriptOutput)"
                Write-Host ""
            }
        }

        # Add a separator for readability
        Write-Host ("-" * 50) -ForegroundColor DarkGray
    }
}