Public/Network/Scan-NetworkforWebLogon.ps1

FUNCTION Scan-NetworkforWebLogon {

#### Tester Script
<#
 
$Protocol = "HTTPS"
$IP = "192.168.10.254"
$Port = 60443
 
$Page = (Invoke-WebRequest -Uri "$($Protocol)://$($IP):$Port" -UseBasicParsing -TimeoutSec 10 -ErrorAction SilentlyContinue -SkipCertificateCheck).RawContent
 
IF ($Page -match '(?i)content\s*=\s*["'']?\d+;\s*url\s*=\s*''([^"''>\s]+)') {
 
    $NewURL = $matches[1]
    IF ($NewURL.Substring(0,1) -eq "/") { $NewURL = $NewURL.Substring(1,$NewURL.Length-1) }
 
    $Page += (Invoke-WebRequest -Uri "$($Protocol)://$($IP):$Port/$NewURL" -UseBasicParsing -TimeoutSec 10 -ErrorAction SilentlyContinue -SkipCertificateCheck).RawContent
   
}
ELSEIF ($Page -match '(?i)content\s*=\s*["'']?\d+;\s*url\s*=\s*''([^"''>\s]+)') {
 
    $NewURL = $matches[1]
    IF ($NewURL.Substring(0,1) -eq "/") { $NewURL = $NewURL.Substring(1,$NewURL.Length-1) }
 
    $Page += (Invoke-WebRequest -Uri "$($Protocol)://$($IP):$Port/$NewURL" -UseBasicParsing -TimeoutSec 10 -ErrorAction SilentlyContinue -SkipCertificateCheck).RawContent
   
}
 
CLS
$Page
 
#>


    [CmdletBinding(DefaultParameterSetName='CIDR')]
    PARAM (
        [Parameter(ParameterSetName = 'CIDR')]
        [ValidatePattern(
            '^((?:(?:25[0-5]|2[0-4]\d|1?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|1?\d?\d)/(?:3[0-2]|[12]?\d))|' +
            '(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|' +
            '([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|' +
            '([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|' +
            '[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|' +
            '::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|' +
            '([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))' +
            '/(12[0-8]|1[01]\d|[1-9]?\d)$'
        )]
        [STRING]$CIDR = "$($(Get-NetIPAddress -AddressFamily IPv4 | Sort-Object ifIndex | Where-Object {$_.IPAddress -ne ""127.0.0.1""}).IPAddress | Select-Object -First 1)/$($(Get-NetIPAddress -AddressFamily IPv4 | Sort-Object ifIndex | Where-Object {$_.IPAddress -ne ""127.0.0.1""}).PrefixLength | Select-Object -First 1)",
        [Parameter(Mandatory, ParameterSetName = 'Range')]
        [System.Net.IPAddress]$StartIP = $null,
        [Parameter(Mandatory, ParameterSetName = 'Range')]
        [System.Net.IPAddress]$EndIP = $null,
        [Parameter(Mandatory, ParameterSetName = 'IPAddress')]
        [System.Net.IPAddress[]]$IPAddress = $null,
        [INT]$TimeountSeconds = 7,
        [INT]$MaxConcurrentJobs = 26
    )

    IF ($PSVersionTable.PSVersion.Major -lt 7) { Write-Warning "This PowerShell Command requires PowerShell 7 to run properly."; RETURN }
    
    FUNCTION Get-IPRangeFromCIDR {
    Param(
        [Parameter(Mandatory=$true, HelpMessage="Enter a subnet in the form a.b.c.d/m")]
        [string]$Cidr
    )
    
    # Split the CIDR notation into IP and prefix length
    $parts = $Cidr -split "/"
    $ipAddressString = $parts[0]
    [int]$prefixLength = $parts[1]
    
    # Convert the IP address to a 32-bit integer for bitwise operations
    $ip = [System.Net.IPAddress]::Parse($ipAddressString)
    [byte[]]$ipBytes = $ip.GetAddressBytes()
    [Array]::Reverse($ipBytes) # Reverse to match little-endian byte order
    [UInt32]$ipUint = [System.BitConverter]::ToUInt32($ipBytes, 0)
    
    # Calculate the network mask (e.g., /24 is 255.255.255.0)
    [UInt32]$maskUint = [UInt32]::MaxValue -shr (32 - $prefixLength) -shl (32 - $prefixLength)

    # Calculate the network ID (first IP) and broadcast address (last IP) using bitwise operations
    [UInt32]$networkIdUint = $ipUint -band $maskUint
    [UInt32]$broadcastUint = $ipUint -bor (-bnot $maskUint)

    # Convert the integer results back to IPAddress objects
    [byte[]]$networkBytes = [System.BitConverter]::GetBytes($networkIdUint)
    [Array]::Reverse($networkBytes)
    [System.Net.IPAddress]$firstIP = [System.Net.IPAddress]::New($networkBytes)

    [byte[]]$broadcastBytes = [System.BitConverter]::GetBytes($broadcastUint)
    [Array]::Reverse($broadcastBytes)
    [System.Net.IPAddress]$lastIP = [System.Net.IPAddress]::New($broadcastBytes)
    
    # Return a custom object with the results
    return [pscustomobject][ordered]@{
        CIDR        = $Cidr
        FirstIP     = $firstIP.IPAddressToString
        LastIP      = $lastIP.IPAddressToString
        NetworkID   = $firstIP.IPAddressToString # First IP is generally the network ID
        Broadcast   = $lastIP.IPAddressToString # Last IP is the broadcast address
    }
    }
    FUNCTION Convert-SubnetMaskToCIDR {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$SubnetMask
    )

    try {
        $ip = [IPAddress]$SubnetMask
        $bytes = $ip.GetAddressBytes()
        
        $bitCount = 0
        foreach ($byte in $bytes) {
            $bitString = [Convert]::ToString($byte, 2).PadLeft(8, '0')
            $bitCount += ($bitString.ToCharArray() | Where-Object { $_ -eq '1' }).Count
        }

        if ($bitCount -lt 0 -or $bitCount -gt 32) {
            throw "Invalid subnet mask"
        }

        return $bitCount
    }
    catch {
        Write-Error "Invalid subnet mask format: $_"
        return $null
    }
}
    FUNCTION Get-IPRange {
    param(
        [Parameter(Mandatory=$true)]
        [string]$StartIP,
        [Parameter(Mandatory=$true)]
        [string]$EndIP
    )
    
    # Convert the IP addresses to numerical values for iteration
    # The bytes need to be reversed due to Endianness differences between network order and system's UInt32 representation
    $start_bytes = ([System.Net.IPAddress]$StartIP).GetAddressBytes()
    [Array]::Reverse($start_bytes)
    $start_int = [System.BitConverter]::ToUInt32($start_bytes, 0)

    $end_bytes = ([System.Net.IPAddress]$EndIP).GetAddressBytes()
    [Array]::Reverse($end_bytes)
    $end_int = [System.BitConverter]::ToUInt32($end_bytes, 0)

    # Ensure start IP is not greater than end IP
    if ($start_int -gt $end_int) {
        Write-Error "Start IP address must be less than or equal to End IP address."
        return
    }

    $ip_range = @()
    for ($i = $start_int+1; $i -le $end_int-1; $i++) {
        # Convert the integer back to an IP address byte array, reverse it again, and join the octets
        $ip_bytes = [System.BitConverter]::GetBytes([UInt32]$i)
        [Array]::Reverse($ip_bytes)
        $ip_string = ($ip_bytes -join '.')
        $ip_range += $ip_string
    }
    
    return $ip_range
}
    FUNCTION Test-TCPPorts {
                                                                                
        <#
            .SYNOPSIS
            Tests TCP connectivity to a specified host on multiple ports asynchronously.
 
            .DESCRIPTION
            Tests TCP connectivity to a specified hostname or IP address on ports 1-1024, 4443, 4444, 8000, 8080, 8443, and 10443.
            Runs tests asynchronously with a maximum of 100 concurrent tests and displays a progress bar.
 
            .PARAMETER ComputerName
            The hostname or IP address to test connectivity against.
 
            .PARAMETER Timeout
            The timeout in milliseconds for each TCP connection attempt. Default is 2000ms.
 
            .EXAMPLE
            Test-TCPPorts -ComputerName "example.com"
            Tests TCP connectivity to example.com on specified ports.
 
            .EXAMPLE
            Test-TCPPorts -ComputerName "192.168.1.1" -Timeout 1000
            Tests TCP connectivity to 192.168.1.1 with a 1000ms timeout.
 
            .OUTPUTS
            PSCustomObject with properties: ComputerName, Port, IsOpen, Error (if any).
        #>

        [CmdletBinding()]
        param (
            [string]$ComputerName = $env:COMPUTERNAME,

            [Parameter()]
            [int]$Timeout = 1200
        )

        # Define the ports to test
        $ports = @()
        $ports = 80, 81, 443, 4433, 4443, 4444, 5000, 5001, 8000, 8080, 8081, 8443, 10443, 60443
        $ports = $ports | Sort-Object -Unique

        $totalPorts = $ports.Count
        $results = [System.Collections.ArrayList]::new()
        $completed = 0

        # Create a runspace pool
        $runspacePool = [RunspaceFactory]::CreateRunspacePool(1, 50)
        $runspacePool.Open()

        $tasks = [System.Collections.ArrayList]::new()

        # ScriptBlock for testing a single port
        $scriptBlock = {
        param ($ComputerName, $Port, $Timeout)
        $result = [PSCustomObject]@{
            ComputerName = $ComputerName
            Port         = $Port
            IsOpen       = $false
        }

        try {
            $tcpClient = New-Object System.Net.Sockets.TcpClient
            $connection = $tcpClient.BeginConnect($ComputerName, $Port, $null, $null)
            $success = $connection.AsyncWaitHandle.WaitOne($Timeout, $false)

            if ($success) {
                $tcpClient.EndConnect($connection)
                $result.IsOpen = $true
            }
            $tcpClient.Close()
        }
        catch {
            $result.Error = $_.Exception.Message
        }
        finally {
            if ($null -ne $tcpClient) {
                $tcpClient.Dispose()
            }
        }

        return $result | Where-Object { $_.IsOpen -eq $True }
    }

        # Create async tasks for each port
        foreach ($port in $ports) {
        $powershell = [PowerShell]::Create()
        $powershell.RunspacePool = $runspacePool
        [void]$powershell.AddScript($scriptBlock).AddArgument($ComputerName).AddArgument($port).AddArgument($Timeout)
        $handle = $powershell.BeginInvoke()
        $tasks.Add([PSCustomObject]@{
            PowerShell = $powershell
            Handle     = $handle
            Port       = $port
        }) | Out-Null
    }

        # Process tasks and update progress
        while ($tasks.Count -gt 0) {
        $completedTasks = $tasks | Where-Object { $_.Handle.IsCompleted }
        foreach ($task in $completedTasks) {
            $result = $task.PowerShell.EndInvoke($task.Handle)
            if ($result.IsOpen) {
                [void]$results.Add($result)
            }
            $task.PowerShell.Dispose()
            $tasks.Remove($task)
            $completed++

            # Update progress bar
            $percentComplete = [math]::Round(($completed / $totalPorts) * 100, 2)
            # Write-Progress -Activity "Testing TCP Ports on $ComputerName" -Status "Tested $completed of $totalPorts ports" -PercentComplete $percentComplete -Id 120932315
        }

        # Small sleep to prevent excessive CPU usage
        Start-Sleep -Milliseconds 100
    }

        # Clean up
        $runspacePool.Close()
        $runspacePool.Dispose()

        # Complete the progress bar
        Write-Progress -Id 120932315 -Activity "Testing TCP Ports on $ComputerName" -Completed

        # Return results sorted by port
        return $results | Sort-Object Port
    }
    FUNCTION ParseWebContentforDeviceInfo {

        [CmdletBinding()]
        PARAM (
            $Page
        )

        $Result = [PSCustomObject]@{            
            DeviceType = "Unknown"
            DeviceManufacturer = "Unknown"        
            LoginPage = "Unknown"
        }

        IF ($Page -like "* ARRIS *") { $Result.DeviceManufacturer = "ARRIS" ; $Result.DeviceType = "Modem\Router"; $Result.LoginPage = "True" }
        ELSEIF ($Page -like "* Datto*") { $Result.DeviceManufacturer = "Datto" ; $Result.DeviceType = "Backup"; $Result.LoginPage = "False" }
        ELSEIF ($Page -like "* Datto*" -and $Page -like "*Portal Login*") { $Result.LoginPage = "False" }
        ELSEIF ($Page -like "* WatchGuard *") { $Result.DeviceManufacturer = "WatchGuard" ; $Result.DeviceType = "Firewall"; $Result.LoginPage = "True" }
        ELSEIF ($Page -like "*form id=""login""*") { $Result.LoginPage = "True" }
        ELSEIF ($Page -like "*IIS Windows Server*") { $Result.DeviceManufacturer = "Unknown" ; $Result.DeviceType = "Windows Server (IIS)"; $Result.LoginPage = "False" }
        ELSEIF ($Page -like "*Unifi Network*") { $Result.DeviceManufacturer = "Ubiquiti" ; $Result.DeviceType = "Unifi Controller"; $Result.LoginPage = "True" }
        ELSEIF ($Page -like "*Yealink*Phone*") { $Result.DeviceManufacturer = "Yealink" ; $Result.DeviceType = "VoIP Phone"; $Result.LoginPage = "True" }
        ELSEIF ($Page -like "*Web Image Monitor*") { $Result.DeviceManufacturer = "Ricoh" ; $Result.DeviceType = "Printer"; $Result.LoginPage = "True" }
        ELSEIF ($Page -like "*iDrac*") { $Result.DeviceManufacturer = "Dell"; $Result.DeviceType = "iDrac"; $Result.LoginPage = "True" }
        ELSEIF ($Page -like "*Canon Inc*") { $Result.DeviceManufacturer = "Canon"; $Result.DeviceType = "Printer"; $Result.LoginPage = "True" }
        ELSEIF ($Page -like "*GWN Project*") { $Result.DeviceManufacturer = "Grandstream Networks"; $Result.DeviceType = "Wi-Fi AP?"; $Result.LoginPage = "True" }
        ELSEIF ($Page -like "*sonicwall*" -and ($Page -like "*sslvpnPortal*" -or $Page -like "*sslvpn-Portal*")) { $Result.DeviceManufacturer = "SonicWall"; $Result.DeviceType = "FireWall (VPN Portal)"; $Result.LoginPage = "True" }
        ELSEIF ($Page -like "*sonicwall*" -and $Page -like "*sonicui/7/login*") { $Result.DeviceManufacturer = "SonicWall"; $Result.DeviceType = "FireWall (MGMT Portal)"; $Result.LoginPage = "True" }
        ELSEIF ($Page -like "*sonicwall*") { $Result.DeviceManufacturer = "SonicWall"; $Result.DeviceType = "FireWall?"; $Result.LoginPage = "True" }
        ELSEIF ($Page -like "*.linkedin.com*") { $Result.DeviceManufacturer = "Unknown"; $Result.DeviceType = "Windows Server (IIS)"; $Result.LoginPage = "False" }
        ELSEIF (($Page -like "*CyberPower Systems*" -or $Page -like "*CyberPowerSystems*") -and $Page -like "*UPS*") { $Result.DeviceManufacturer = "CyberPower"; $Result.DeviceType = "UPS"; $Result.LoginPage = "True" }
        ELSEIF ($Page -like "*Windows&#169; Communication Foundation service*") { $Result.DeviceManufacturer = "Unknown"; $Result.DeviceType = "Windows Server? (WCF)"; $Result.LoginPage = "False" }
        ELSEIF ($Page -like "*ClickShare*") { $Result.DeviceManufacturer = "Barco"; $Result.DeviceType = "ClickShare"; $Result.LoginPage = "True" }


        ### Servers
        ELSEIF ($Page -like "*ESXi Host*") { $Result.DeviceManufacturer = "VMware"; $Result.DeviceType = "ESXi Host"; $Result.LoginPage = "True" }


        ### Firewalls
        ELSEIF ($Page -like "*FortiGate*") { $Result.DeviceManufacturer = "FortiGate"; $Result.DeviceType = "Firewall"; $Result.LoginPage = "True" }


        ### Switches
        ELSEIF ($Page -like "*tp-link*") { $Result.DeviceManufacturer = "TP Link"; $Result.DeviceType = "Switch?"; $Result.LoginPage = "True" }
        ELSEIF ($Page -like "*Cisco*Cisco*") { $Result.DeviceManufacturer = "Cisco"; $Result.DeviceType = "Switch"; $Result.LoginPage = "True" }


        ### NAS
        ELSEIF ($Page -like "*Synology*DiskStation*") { $Result.DeviceManufacturer = "Synology"; $Result.DeviceType = "NAS"; $Result.LoginPage = "True" }



        ### UPS
        ELSEIF ($Page -like "*apc.com*") { $Result.DeviceManufacturer = "APC"; $Result.DeviceType = "UPS"; $Result.LoginPage = "True" }



        ### Printers
        ELSEIF ($Page -like "*HP*PrintPages*") { $Result.DeviceManufacturer = "HP"; $Result.DeviceType = "Printer"; $Result.LoginPage = "True" }
        ELSEIF ($Page -like "*/hp/device/*") { $Result.DeviceManufacturer = "HP"; $Result.DeviceType = "Printer"; $Result.LoginPage = "True" }
        ELSEIF ($Page -like "*Kyocera*") { $Result.DeviceManufacturer = "Kyocera"; $Result.DeviceType = "Printer"; $Result.LoginPage = "True" }


        ### Conference Room Devices
        ELSEIF ($Page -like "*CollabOS*") { $Result.DeviceManufacturer = "Logitech"; $Result.DeviceType = "Conference Room Equipment"; $Result.LoginPage = "False" }


        ### Phones
        ELSEIF ($Page -like "*Poly Web Configuration Utility*") { $Result.DeviceManufacturer = "Polycom"; $Result.DeviceType = "VoIP Phone"; $Result.LoginPage = "True" }


        ### Guesses
        ELSEIF ($Page -like "*CyberPower*") { $Result.DeviceManufacturer = "CyberPower"; $Result.DeviceType = "UPS"; $Result.LoginPage = "True" }
        ELSEIF ($Page -like "*HP*Printer*") { $Result.DeviceManufacturer = "HP"; $Result.DeviceType = "Printer"; $Result.LoginPage = "True" }
        ELSEIF ($Page -like "*Canon*Printer*") { $Result.DeviceManufacturer = "Canon"; $Result.DeviceType = "Printer"; $Result.LoginPage = "True" }
        ELSEIF ($Page -like "*Brother*Printer*") { $Result.DeviceManufacturer = "Brother"; $Result.DeviceType = "Printer"; $Result.LoginPage = "True" }
        ELSEIF ($Page -like "*Printer*") { $Result.DeviceManufacturer = "Unknown"; $Result.DeviceType = "Printer?"; $Result.LoginPage = "Unknown" }
        ELSEIF ($Page -like "*Sharp Global*") { $Result.DeviceManufacturer = "Sharp"; $Result.DeviceType = "Printer"; $Result.LoginPage = "True" }
        # ELSEIF ($Page -like "*Phone*") { $Result.DeviceManufacturer = "Unknown"; $Result.DeviceType = "Phone?"; $Result.LoginPage = "True" }


        ### Catch Alls
        ELSEIF ($Page -like "*/framework/Unified.js*" -and $Page -like "*/framework/cookie/client/cookie.html*") { $Result.DeviceManufacturer = "HP"; $Result.DeviceType = "Printer?"; $Result.LoginPage = "True" }
        ELSEIF ($Page -like "*/cgi-bin/whome.cgi*") { $Result.DeviceManufacturer = "Unknown"; $Result.DeviceType = "Door Controller?"; $Result.LoginPage = "True" }
        ELSEIF ($Page -like "*Embedded Web Server*") { $Result.DeviceManufacturer = "HP?"; $Result.DeviceType = "Printer?"; $Result.LoginPage = "True?" }
        ELSEIF ($Page -like "*stackit_icon*") { $Result.DeviceManufacturer = "Optamate"; $Result.DeviceType = "StackIt"; $Result.LoginPage = "True" }


        ### End
        ELSE { }
        RETURN $Result
    }

    IF ($IPAddress) { $IPs = $IPAddress }
    ELSEIF ($StartIP -ne $null -and $EndIP -ne $null) { $IPs = Get-IPRange -StartIP $StartIP -EndIP $EndIP }
    ELSE { $IPs = Get-IPRange -StartIP (Get-IPRangeFromCIDR $CIDR).FirstIP -EndIP (Get-IPRangeFromCIDR $CIDR).LastIP }

    $Jobs = @()
    $ScanResults = @()
    $DeviceInfo = $Null
    $IPCount = $IPs.Count
    $IPCountCurrent = 0
    $Protocol = $null
  
    $Jobs = @()
    Get-Job | Remove-Job -Force
    FOREACH ($IP in $IPs) {

        $PercentProgress = [Math]::Round((((Get-Job -State "Completed").Count / $IPs.Count) * 100),0)

        Write-Progress -Id 120932315 -Activity "Scanning Ports" -Status "$PercentProgress% - $($(Get-Job -State "Completed").Count) of $($IPs.Count) Jobs Completed" -PercentComplete $PercentProgress 
            
        WHILE ((Get-Job -State 'Running').Count -ge $MaxConcurrentJobs) { Start-Sleep -Milliseconds 50 }
        
        $Job = Start-Job -ScriptBlock {
            ### Vars
            $JobResults = @()

            ### Includes
            ${function:Get-IPRangeFromCIDR} = ${Using:function:Get-IPRangeFromCIDR}
            ${function:Convert-SubnetMaskToCIDR} = ${Using:function:Convert-SubnetMaskToCIDR}
            ${function:Get-IPRange} = ${Using:function:Get-IPRange}
            ${function:Test-TCPPorts} = ${Using:function:Test-TCPPorts}
            ${function:ParseWebContentforDeviceInfo} = ${Using:function:ParseWebContentforDeviceInfo}
            
            $OpenPorts = (Test-TCPPorts $Using:IP).Port
  
            FOREACH ($OpenPort in $OpenPorts) {  
                $Protocol = $null    
                $Page = $null
                TRY {
                    IF ($OpenPort -eq 80) { 0/0 }

                        $Page = (Invoke-WebRequest -Uri "https://$($Using:IP):$OpenPort/" -UseBasicParsing -TimeoutSec $Using:TimeountSeconds -ErrorAction SilentlyContinue -SkipCertificateCheck).RawContent

                        ### First Regex Check
                        IF ($Page -match '(?i)content\s*=\s*["'']?\d+;\s*url\s*=\s*([^"''>\s]+)') {
                            $NewURL = $matches[1]
                            IF ($NewURL.Substring(0,1) -eq "/") { $NewURL = $NewURL.Substring(1,$NewURL.Length-1) }
                            
                            $CheckPage = $Page
                            $Page += (Invoke-WebRequest -Uri "https://$($Using:IP):$OpenPort/$NewURL" -UseBasicParsing -TimeoutSec $Using:TimeountSeconds -ErrorAction SilentlyContinue -SkipCertificateCheck).RawContent
                            IF ($CheckPage -eq $Page) { $Page = $null }
                        }
                        
                        ### Second Regex Check
                        IF ($Page -match '(?i)content\s*=\s*["'']?\d+;\s*url\s*=\s*''([^"''>\s]+)') {
                            $NewURL = $matches[1]
                            IF ($NewURL.Substring(0,1) -eq "/") { $NewURL = $NewURL.Substring(1,$NewURL.Length-1) }
                            
                            $CheckPage = $Page
                            $Page += (Invoke-WebRequest -Uri "https://$($Using:IP):$OpenPort/$NewURL" -UseBasicParsing -TimeoutSec $Using:TimeountSeconds -ErrorAction SilentlyContinue -SkipCertificateCheck).RawContent
                            IF ($CheckPage -eq $Page) { $Page = $null }
                        }
                        
                        $Protocol = "HTTPS"                
                }
                CATCH {
                    TRY {
                        IF ($OpenPort -eq 443) { 0/0 }
                            
                        $Page = (Invoke-WebRequest -Uri "http://$($Using:IP):$OpenPort/" -UseBasicParsing -TimeoutSec $Using:TimeountSeconds -ErrorAction SilentlyContinue -SkipCertificateCheck).RawContent
                            
                        IF ($Page -match '(?i)content\s*=\s*["'']?\d+;\s*url\s*=\s*([^"''>\s]+)') {
                            $NewURL = $matches[1]
                            IF ($NewURL.Substring(0,1) -eq "/") { $NewURL = $NewURL.Substring(1,$NewURL.Length-1) }
                                                               
                            $CheckPage = $Page
                            $Page += (Invoke-WebRequest -Uri "https://$($Using:IP):$OpenPort/$NewURL" -UseBasicParsing -TimeoutSec $Using:TimeountSeconds -ErrorAction SilentlyContinue -SkipCertificateCheck).RawContent
                            IF ($CheckPage -eq $Page) { $Page = $null }
                        }
                             
                        ### Second Regex Check
                        IF ($Page -match '(?i)content\s*=\s*["'']?\d+;\s*url\s*=\s*''([^"''>\s]+)') {
                            $NewURL = $matches[1]
                            IF ($NewURL.Substring(0,1) -eq "/") { $NewURL = $NewURL.Substring(1,$NewURL.Length-1) }
                            
                            $CheckPage = $Page
                            $Page += (Invoke-WebRequest -Uri "https://$($Using:IP):$OpenPort/$NewURL" -UseBasicParsing -TimeoutSec $Using:TimeountSeconds -ErrorAction SilentlyContinue -SkipCertificateCheck).RawContent
                            IF ($CheckPage -eq $Page) { $Page = $null }
                        }                                  
                                                        
                        $Protocol = "HTTP"
                    }
                    CATCH {
                        $Page = $null
                    }
                }

                IF ($Page -eq $null -or $Page -eq "") { }
                ELSE {
                    $DeviceInfo = ParseWebContentforDeviceInfo $Page

                    $JobResults += [PSCustomObject]@{    
                        PSTypeName = 'IntegrisPowerShell.NetworkforWebLogonPages'
                        IPAddress = $Using:IP
                        Port = $OpenPort
                        Protocol = $Protocol
                        Type = $DeviceInfo.DeviceType
                        Manufacturer = $DeviceInfo.DeviceManufacturer
                        LoginPage = $DeviceInfo.LoginPage
                    }
                }
            }

            RETURN $JobResults
        }

        $Jobs += $Job
    } 
    $Jobs | Wait-Job | Out-Null
    Write-Progress -Id 120932315 -Activity "Testing TCP Ports on $ComputerName" -Status "Tested $completed of $totalPorts ports" -PercentComplete 100 -Completed

    $Results = @()
    FOREACH ($Item in $Jobs) {

        $ReceivedJob = Receive-Job $Item -Keep
        IF ($ReceivedJob -eq $null) { CONTINUE }

        FOREACH ($Entry in $ReceivedJob) {

            IF ($Results[$Results.Count-1].IPAddress -eq $Entry.IPAddress) {

        
            #IF ($Results[$Results.Count-1].IPAddress -eq $Entry.IPAddress -and
            # $Results[$Results.Count-1].Type -eq $Entry.Type -and
            # $Results[$Results.Count-1].Manufacturer -eq $Entry.Manufacturer) {
                    
                [Array]$Results[$Results.Count-1].Port += $Entry.Port
                [Array]$Results[$Results.Count-1].Protocol += $Entry.Protocol
                [Array]$Results[$Results.Count-1].Protocol = $Results[$Results.Count-1].Protocol | Select-Object -Unique

                IF ($Results[$Results.Count-1].Type -eq $null) { $Results[$Results.Count-1].Type = $Entry.Type }
                IF ($Results[$Results.Count-1].Manufacturer -eq $null) { $Results[$Results.Count-1].Manufacturer = $Entry.Manufacturer }
                IF ($Results[$Results.Count-1].LoginPage -eq $null) { $Results[$Results.Count-1].LoginPage = $Entry.LoginPage }
            }
            ELSE {
                $Results += [PSCustomObject]@{    
                    PSTypeName = 'IntegrisPowerShell.NetworkforWebLogonPages'
                    IPAddress = $Entry.IPAddress
                    Port = $Entry.Port
                    Protocol = $Entry.Protocol
                    Type = $Entry.Type
                    Manufacturer = $Entry.Manufacturer
                    LoginPage = $Entry.LoginPage
                }
            }
        }
    }    

    RETURN $Results
}