InfocyteNetworkTest.psm1
Write-Host "Importing Infocyte Network Test Module" $PS = $PSVersionTable.PSVersion.tostring() if ($PSVersionTable.PSVersion.Major -lt 3) { Write-Warning "Powershell Version not supported. Install version 3.x or higher" return } else { Write-Host "Checking PSVersion [Minimum Supported: 3.0]: PASSED [$PS]!`n" } <# .SYNOPSIS Test-ICNetworkAccess Tests remote administration protocols and configurations for agentless scanning with Infocyte .DESCRIPTION Tests Domain, System, and Credential configuration for use with Infocyte HUNT. Will attempt several tests of the credentials, permissions, remote connectivity, networking, and DNS Resolution. .PARAMETER Target (Mandantory) IP Address or FQDN of a remote system to test against .PARAMETER Credential (Mandatory) Network credentials to test (PSCredential Object) .PARAMETER ProxyAddress (Optional) Web Address of the proxy ie. http://192.168.1.2:8080 .PARAMETER ProxyCredential (Optional) Proxy credentials (PSCredential Object) .PARAMETER Out (Optional) Output folder. Defaults to $env:Temp\ic\ .EXAMPLE PS C:\> $Netcreds = Get-Credentials PS C:\> Test-ICNetworkAccess -Target 192.168.1.5 -Credential $Netcreds .EXAMPLE PS C:\> $Netcreds = Get-Credentials PS C:\> $Proxycreds = Get-Credentials PS C:\> Test-ICNetworkAccess -Target 192.168.1.5 -Credential $Netcreds -ProxyAddress "http://192.168.1.2:8080" -ProxyCredential $Proxycreds .NOTES Tests we will run: 1. Test DNS Resolution 2. Test DNS Reverse Lookup 3. Test Proxy 4. Test Internet Access a. http:\\www.google.com b. https:\\incyte.infocyte.com 5. Test Remote Connectivity (Ping) 6. Test Credentials (Username and Password Combo) 7. Test Active Directory Permissions 8. Gather Resultant Set of Policy (RSoP) 9. Test Remote File Transfer (SMB) a. C:\Windows\Temp b. C:\Users\<someoneelse>\Desktop 10. Test Remote Execution a. Test WMI b. Test Schedtasks c. Test Remote Registry d. Test PSRemoting 11. Test 443 Back to Infocyte from Remote Endpoint #> Function Test-ICNetworkAccess { [CmdletBinding()] Param( [Parameter(Position = 0, Mandatory = $True, HelpMessage = "The remote system to test connectivity to")] [ValidateNotNullOrEmpty()] [String] $Target, [Parameter(Position = 1, Mandatory = $True, HelpMessage = "Elevated account that will be used with HUNT")] [ValidateNotNullOrEmpty()] [System.Management.Automation.PSCredential] $Credential, [Parameter(Mandatory = $False, HelpMessage = "Address of proxy in the form of: http://<myproxy-ip>:8080")] [String] $ProxyAddress, [Parameter(Mandatory = $False, HelpMessage = "Proxy credentials for authenticated proxies")] [ValidateNotNullOrEmpty()] [System.Management.Automation.PSCredential] $ProxyCredential, [String] $ReturnAddress="https://incyte.infocyte.com", [String] $Out="$Env:Temp\ic" ) $Admin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator") If (-NOT $Admin) { Write-Verbose "NOTE: Your shell is not running as Administrator (But you shouldn't need it for this script)." } # MAIN $Creds = [System.Management.Automation.PSCredential]$Credential $Username = $Creds.GetNetworkCredential().UserName $Domain = $Creds.GetNetworkCredential().Domain if (($Domain -ne $null) -AND ($Domain -ne "")) { $FQUsername = "$Domain\$Username" } else { $FQUsername = $Username } $TestNum = 0 $TestResults = @{} if (-NOT $PSScriptRoot) { $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent } if (-NOT (Test-Path $out)) { mkdir $out } $OutputFileLocation = "$Out\InfocyteTest.log" $ports = 22,53,80,135,137,139,389,443,445,1024,1025,1026,3389,5985,5986,49152,49153,49154,65535 $ExternalIP = (Invoke-WebRequest ifconfig.me/ip -UseBasicParsing).Content.Trim() $IPAddress = Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object { $_.ipenabled -AND $_.Ipaddress.length -gt 0 -AND $_.DefaultIPGateway.length -gt 0 } If (-NOT $ReturnAddress) { $ReturnAddress = $IPAddress.ipaddress[0] } # Start transcript log of this script's output Start-Transcript -path $OutputFileLocation Write-Host "Running script with the following parameters:" Write-Host "Remote Test Target: $Target" Write-Host "Executed From: $ReturnAddress [ExtIP: $ExternalIP] by $(whoami)" Write-Host "Credential: $($Credential.Username)" Write-Host "ProxyAddress: $ProxyAddress" Write-Host "ProxyCredential: $($ProxyCredential.Username)" if ($ProxyAddress) { if ($ProxyAddress -match "http") { # "http://<myproxy-ip>:8012" } elseif ($ProxyAddress -like "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}") { $ProxyAddress = "http://$ProxyIP" } else { Write-Warning "ProxyAddress ($ProxyAddress) may be in the wrong format. Should be http://myproxyaddress.com or http://192.168.1.80:8080" } } $TestResults['Config'] = @{ Target = $target ReturnAddress = $ReturnAddress SourceAddress = $IPAddress.ipaddress[0] DNS = $IPAddress.DNSServerSearchOrder ExtIP = $ExternalIP Credential = $($Credential.Username) ProxyAddress = $ProxyAddress ProxyCredential = $($ProxyCredential.Username) } Write-Host -ForegroundColor Cyan "`n===========================================================================" Write-Host -ForegroundColor Cyan "===========================================================================" Write-Host -ForegroundColor Gray "This script will run several tests to test for remote connectivity, DNS, Internet Access, and permissions necessary to run Infocyte HUNT" Write-Host -ForegroundColor Gray "Any failed test or warning may be an issue that needs to be addressed before you use Infocyte HUNT" Write-Host -ForegroundColor Gray "Log File Location: $OutputFileLocation" Start-Sleep 3 Write-Host -ForegroundColor Cyan "`n=== BEGINING TESTS ===" # Flush Local DNS Cache for testing Write-Host "`nFlushing DNS" ipconfig /flushdns | out-null #region Internet Tests # Test DNS Resolution and connectivity to the internet $Testnum += 1 $InternetTestAddr = "www.google.com" Write-Host -ForegroundColor Cyan "`n[TEST $TestNum] Testing DNS resolution and connectivity to the internet (Optional)" $Result = @{ Name = "Internet Connectivity Test (Optional)" Test = $TestNum Description = "Testing DNS resolution and connectivity to the internet ($InternetTestAddr)" Success = $True } $DNSEntry = Get-DNSEntry $InternetTestAddr if ($DNSEntry) { Write-Host "SUCCESS: $($DNSEntry.Hostname) => $($DNSEntry.IP)" $Result['DNSResult'] = $True } else { Write-Warning "FAIL: DNS Resolution of $InternetTestAddr failed - Your internet may be down" $Result['DNSResult'] = $False $Result['Success'] = $False } try { $ICMP = Test-Connection -BufferSize 16 -Count 1 -ComputerName $InternetTestAddr -ea STOP Write-Host "SUCCESS: Ping (ICMP) to $InternetTestAddr ($($ICMP.IPV4Address)) in $($ICMP.ResponseTime) m/s" $Result['ICMPResult'] = $True } catch { $Message = $_.Exception.Message $ErrorType = $_.Exception.GetType().FullName Write-Warning "FAIL: Ping (ICMP) to $InternetTestAddr - Message: $Message" $Result['ICMPResult'] = $False } $TestResults["Test$TestNum"] = $Result # Test DNS Resolution and connectivity to Incyte $TestNum += 1 Write-Host -ForegroundColor Cyan "`n[TEST $TestNum] Testing DNS resolution and connectivity to Infocyte (Required)" $Result = @{ Name = "Infocyte Cloud Connectivity Test" Test = $TestNum Description = "Testing DNS resolution and connectivity to Infocyte (Required)" Success = $True } $DNSEntry = Get-DNSEntry "incyte.infocyte.com" if ($DNSEntry) { Write-Host "SUCCESS: $($DNSEntry.Hostname) => $($DNSEntry.IP)" $Result['DNSResult'] = $True } else { Write-Warning "FAIL: DNS Resolution of incyte.infocyte.com failed - Your internet may be down" $Result['DNSResult'] = $False $Result['Success'] = $False } try { $ICMP = Test-Connection -BufferSize 16 -Count 1 -ComputerName incyte.infocyte.com -ea STOP Write-Host "SUCCESS: Ping (ICMP) to incyte.infocyte.com ($($ICMP.IPV4Address)) in $($ICMP.ResponseTime) m/s" $Result['ICMPResult'] = $True } catch { $Message = $_.Exception.Message $ErrorType = $_.Exception.GetType().FullName Write-Warning "FAIL: Ping (ICMP) to incyte.infocyte.com (($($ICMP.IPV4Address)) - Message: $Message" $Result['ICMPResult'] = $False } $TestResults["Test$TestNum"] = $Result #endregion Internet Test #region Proxy Tests # $req = [system.Net.WebRequest]::Create($TestWebsite) # $res = $results.GetResponse() # $int = [int]$res.StatusCode # Write-Host $int $TestNum += 1 Write-Host -ForegroundColor Cyan "`n[TEST $TestNum] Testing web connectivity with direct access (No Proxy)" $TestWebsite = 'https://incyte.infocyte.com' $Result = @{ Name = "Proxy Test" Test = $TestNum Description = "Testing connectivity to Infocyte via various proxy configurations" Success = $True } #Configure Proxy if required $showcurrentproxy = netsh winhttp show proxy Write-Host "Current System Proxy Settings:`n" Write-Host "-------------------`n" $showcurrentproxy try { $wc = new-object net.webclient $results = $wc.DownloadString($TestWebsite) if ($results -match "All services are operational") { Write-Host "SUCCESS: Web (http) connectivity with direct access (No Proxy) succeeded to $TestWebsite" $Result['NoProxy'] = $True } else { Write-Warning "FAIL: Web (http) connectivity with direct access (No Proxy) failed to $TestWebsite" $Result['NoProxy'] = $False $Result['Success'] = $False } } catch { Write-Warning "FAIL: Web (http) connectivity with direct access (No Proxy) failed to $TestWebsite" $Message = $_.Exception.Message Write-Warning "Message: $Message" $Result['NoProxy'] = $False $Result['Success'] = $False } if ($ProxyAddress) { if ($ProxyCredential) { # Testing web client with authenticated Proxy $AuthType = "Negotiate" Write-Host "Testing proxied web client with $AuthType Proxy Auth" $wc = New-ProxyWebClient $ProxyAddress $ProxyCredential $AuthType } else { # Testing web client with unauthenticated Proxy Write-Host "Testing web client with unauthenticated proxy ($ProxyAddress)" $wc = New-ProxyWebClient $ProxyAddress } try { $results = $wc.DownloadString($TestWebsite) if ($results -match "All services are operational") { Write-Host "SUCCESS: Web (http) connectivity with unauthenticated Proxy succeeded to $TestWebsite" $Result['WithProxy'] = $True $Result['Success'] = $True } else { Write-Warning "FAIL: Web (http) connectivity with unauthenticated Proxy failed to $TestWebsite" $Result['WithProxy'] = $False $Result['Success'] = $False } } catch { Write-Warning "FAIL: Web (http) connectivity with unauthenticated Proxy failed to $TestWebsite" $Message = $_.Exception.Message Write-Warning "Message: $Message" $Result['WithProxy'] = $False $Result['Success'] = $False } } $TestResults["Test$TestNum"] = $Result #endregion #region Remote Target Connectivity Tests # Test DNS Resolution and connectivity to Target $TestNum += 1 Write-Host -ForegroundColor Cyan "`n[TEST $TestNum] Testing DNS resolution and connectivity to $target" $Result = @{ Name = "Target DNS Test" Test = $TestNum Description = "Testing DNS resolution and connectivity to $target" Success = $True } $DNSEntry = Get-DNSEntry $target if ($DNSEntry) { $IP = $DNSEntry.IP $Hostname = $DNSEntry.Hostname Write-Host "SUCCESS: DNS Resolved $target to $Hostname ($IP)" $Result['DNSResult'] = $True if ($Hostname -notlike "*.$Domain") { Write-Warning "This system seems to have resolved to a domain that is different from the provided credentials for $Domain." Write-Warning "You may need to provide the correct credentials for the resolved domain or check your DNS provider" Write-Warning "If this result is unexpected, ensure this system is pointed to the correct DNS server." $Result['DNSDomainAlignment'] = $False } else { $Result['DNSDomainAlignment'] = $True } } else { Write-Warning "FAIL: DNS Resolution to target failed" $Result['DNSResult'] = $False $Result['Success'] = $False } # Test Remote Connectivity (Ping) Write-Host "`nTesting Connectivity to $IP w/ ICMP" try { $ICMP = Test-Connection -BufferSize 16 -Count 1 -ComputerName $IP -ea STOP Write-Host "SUCCESS: Ping (ICMP) to $Hostname ($($ICMP.IPV4Address)) in $($ICMP.ResponseTime) m/s" $Result['ICMPResult'] = $True } catch { $Message = $_.Exception.Message $ErrorType = $_.Exception.GetType().FullName Write-Warning "FAIL: Ping (ICMP) to $Hostname (($($ICMP.IPV4Address)) - Message: $Message" $Result['ICMPResult'] = $False } $TestResults["Test$TestNum"] = $Result # Test Remote Connectivity (Ports) $TestNum += 1 Write-Host -ForegroundColor Cyan "`n[TEST $TestNum] Performing TCP port scan of the following ports:" Write-Host $ports $Result = @{ Name = "Port Scan" Test = $TestNum Description = "Performing TCP port scan of the following ports [$ports] to $target" Success = $True } $PortResults = $ports | Test-Connectivity -IP $IP $Result['Results'] = $PortResults Write-Host "===========================================================================" Write-Host -NoNewline ("{0,-8}`t{1,-35}`t{2}`n" -f "Port","Name","Access") $PortResults | ForEach-Object { if ($_.Access) { Write-Host -ForegroundColor Green -NoNewline ("{0,-8}`t{1,-35}`t{2}`n" -f $_.Port,$_.Name,$_.Access) } else { Write-Host -ForegroundColor Red -NoNewline ("{0,-8}`t{1,-35}`t{2}`n" -f $_.Port,$_.Name,$_.Access) } } Write-Host "" $opendynports = ($PortResults | Where-Object { $_.Port -ge 49152 -AND $_.Port -lt 65535 }).Access | where { $_.true } If ($opendynports) { $Result['DynamicPorts'] = $true } else { Write-Warning "FAIL: No Access to $($r.Name) on $IP - Will affect WMI & RPC Execution and Deployment against a Windows-based Hosts" $Result['DynamicPorts'] = $False } $Result['SSH'] = $True $Result['SMB'] = $True $Result['WMI/RPC'] = $False $Result['WinRM_HTTP'] = $True $Result['WinRM_HTTPS'] = $True $PortResults | ForEach-Object { $r = $_ if (-NOT $r.Access) { Switch ($_.Port){ 22 { Write-Warning "FAIL: No Access to $($r.Name) on $IP - Will affect SSH Execution and Deployment against a Unix-based Hosts" $Result['SSH'] = $False } 135 { Write-Warning "FAIL: No Access to $($r.Name) on $IP - Will affect WMI and RPC-based Execution and Deployment against a Windows-based Hosts" $Result['WMI/RPC'] = $False } 139 { If (-NOT ($PortResults | Where-Object { $_.Port -eq 445 }).Access) { Write-Warning "FAIL: No Access to $($r.Name) on $IP - May affect RPC Execution and Deployment against a Windows-based Hosts" $Result['SMB'] = $False } } 445 { If (-NOT ($PortResults | Where-Object { $_.Port -eq 139 }).Access) { Write-Warning "FAIL: No Access to $($r.Name) on $IP - May affect Deployment & File Recovery against a Windows-based Hosts" $Result['SMB'] = $False } } 5985 { Write-Warning "FAIL: No Access to $($r.Name) on $IP - May affect PSRemoting Execution and Deployment against a Windows-based Hosts" $Result['WinRM_HTTP'] = $False } 5986 { Write-Warning "FAIL: No Access to $($r.Name) on $IP - May affect PSRemoting via HTTPS Execution and Deployment against a Windows-based Hosts" $Result['WinRM_HTTPS'] = $False } default {} } } } $open = ($PortResults | where { $_.Access }).count if ($open -eq 0) { $Result['Success'] = $False } $TestResults["Test$TestNum"] = $Result #endregion Remote Target Connectivity Test #region Permissions Tests # Test Credentials against domain $TestNum += 1 Write-Host -ForegroundColor Cyan "`n[TEST $TestNum] Validating Credentials are valid..." $Result = @{ Name = "Credential Test" Test = $TestNum Description = "Validating Credentials are valid on $Domain" Success = $True } $TestCreds = Test-ADCredentials $Creds if ($TestCreds.isValid) { Write-Host "SUCCESS: Credentials for $Username are valid on $Domain" } else { Write-Warning "FAIL: Credentials for $Username are either not valid or you cannot connect to DirectoryServices on $Domain" $Result['Success'] = $False } $TestResults["Test$TestNum"] = $Result # Get RSOP permissions Write-Host "Getting Resultant Set of Policy (RSoP) for localhost - output to file $Out\InfocyteTest_RSoP_localhost.html" GPResult.exe /USER $Username /H "$Out\InfocyteTest_RSoP_localhost.html" /F GPResult.exe /USER $Username /v > "$Out\InfocyteTest_RSoP_localhost.txt" <# Write-Host "Getting Resultant Set of Policy (RSoP) for $Hostname - output to file $Out\InfocyteTest_RSoP_$Hostname.txt" Gpresult /S $Hostname /U $FQUsername /P ($Creds.GetNetworkCredential().Password) /USER $Username /v > "$Out\InfocyteTest_RSoP_$Hostname.txt" if ($res -match "does not have RSOP data") { Write-Warning "$res" Write-Warning "Fallback: Attempting to gather RSoP for current user" Gpresult /S $Hostname /U $FQUsername /P ($Creds.GetNetworkCredential().Password) /v > "$Out\InfocyteTest_RSoP_$Hostname.txt" } #> #endregion Permissions Test #region Remote Execution Protocol Tests # Test WMI Execution $TestNum += 1 $Result = @{ Name = "WMI Test" Test = $TestNum Description = " Testing WMI Execution Against $Hostname ($target)" Success = $True } Write-Host -ForegroundColor Cyan "`n[TEST $TestNum] Testing WMI Execution..." if (($PortResults | Where-Object { $_.Port -eq 135 }).Access -AND $opendynports) { $GetWmiObjectParams = @{ Class = "win32_OperatingSystem" Property = "Caption" ComputerName = $Hostname Credential = $Creds Impersonation = 'Impersonate' Authority = "ntlmdomain:$Domain" } Try { $OS = (Get-WmiObject @GetWmiObjectParams -ea Stop).Caption Write-Host "SUCCESS: WMI w/ NTLM succeeded. $Hostname ($IP) is a $OS System" $Result['NTLM'] = $True } Catch { Write-Warning "FAIL: WMI with NTLM failed to $Hostname ($IP)" $Result['NTLM'] = $False $Result['Success'] = $False } # Test Kerberos $GetWmiObjectParams = @{ Class = "win32_OperatingSystem" Property = "Caption" ComputerName = $Hostname Credential = $Creds Impersonation = 'Impersonate' Authority = "kerberos:"+$Domain+"\"+$Hostname.Split('.')[0]+'$' } #Write-Host "Testing WMI w/ explicit Kerberos authentication (Recommended)" Try { $OS = (Get-WmiObject @GetWmiObjectParams -ea Stop).Caption Write-Host "SUCCESS: WMI w/ Kerberos succeeded. $Hostname ($IP) is a $OS System" $Result['Kerberos'] = $True $Result['Success'] = $True } Catch { Write-Warning "FAIL: WMI with Kerberos failed to $Domain\$Hostname ($IP)" $Result['Kerberos'] = $False } } else { Write-Warning "No connectivity to RPC & Dynamic port - skipping WMI test" $Result['Success'] = $False } $TestResults["Test$TestNum"] = $Result # Test SMB Connectivity $TestNum += 1 $Result = @{ Name = "SMB Test" Test = $TestNum Description = "Testing Server Message Block (SMB) connectivity to $($IP)/C$ ($target)" Success = $True } Write-Host -ForegroundColor Cyan "`n[TEST $TestNum] Testing Server Message Block (SMB) connectivity to $($IP)/C$ ($target)" if (($PortResults | Where-Object { $_.Port -eq 139}).Access -OR ($PortResults | Where-Object { $_.Port -eq 445}).Access) { try { $mountdrive = New-PSDrive -Name test -PSProvider FileSystem -Root "\\$IP\C$" -Credential $Creds -ea STOP Write-Host "SUCCESS: Connected to $IP via SMB" } catch { $Message = $_.Exception.Message Write-Warning "FAIL: Could not connect to $IP via SMB - C$ administrative share may not be accessible - Message: $Message" $Result['Success'] = $False } } else { Write-Warning "No connectivity to NetBIOS and SMB ports - skipping SMB Transfer test" $Result['Success'] = $False } $TestResults["Test$TestNum"] = $Result # Test Remote Schtasks $TestNum += 1 $Result = @{ Name = "Remote SchTasks Test" Test = $TestNum Description = "Testing Remote Schtasks Execution to $IP ($target)" Success = $True } Write-Host -ForegroundColor Cyan "`n[TEST $TestNum] Testing Remote Schtasks (via RPC) Execution..." if (($PortResults | Where-Object { $_.Port -eq 135 }).Access -AND $opendynports) { $a = SCHTASKS /Create /S $IP /U $FQUsername /P ($Creds.GetNetworkCredential().Password) /TN test /TR 'c:\windows\system32\cmd.exe /c Net Time' /SC ONCE /ST 23:59 /RU SYSTEM /F if ($a -match "SUCCESS") { Write-Host "SUCCESS: Remote task (test) created on $IP" Start-Sleep 1 # Run the task $b = SCHTASKS /Run /S $IP /U $FQUsername /P ($Creds.GetNetworkCredential().Password) /TN test if ($b -match "SUCCESS") { Write-Host "SUCCESS: Remote task (test) was initiated on $IP" } else { Write-Warning "FAIL: Remote task (test) failed to initiate" Write-Warning "$b" $Result['Success'] = $False } } else { Write-Warning "FAIL: Remote task (test) failed on $IP" Write-Warning "$a" $Result['Success'] = $False } # Query Task status $a = SCHTASKS /query /S $IP /U $FQUsername /P ($Creds.GetNetworkCredential().Password) /TN test if (($a -match "Running") -OR ($a -match "Ready")) { Write-Host "SUCCESS: Remote task (test) ran successfully on $IP" } else { Write-Warning "FAIL: Remote task (test) ran into some issues on $IP" Write-Warning "$a" } #Delete the task (Cleanup) Start-Sleep 1 SCHTASKS /delete /S $IP /U $FQUsername /P ($Creds.GetNetworkCredential().Password) /TN test /F | Out-Null } else { Write-Warning "No connectivity to RPC and Dynamic ports - skipping Remote Schtasks test" $Result['Success'] = $False } $TestResults["Test$TestNum"] = $Result # Test PSRemoting $TestNum += 1 $Result = @{ Name = "WinRM Test" Test = $TestNum Description = "Testing Powershell Remoting (WinRM) Execution to $target" Success = $True } Write-Host -ForegroundColor Cyan "`n[TEST $TestNum] Testing Powershell Remoting Execution..." if (($PortResults | Where-Object { $_.Port -eq 5985}).Access -or ($PortResults | Where-Object { $_.Port -eq 5986}).Access) { try { $errorActionPreference = "Stop" $r = Invoke-Command -ComputerName $target -Credential $Creds -ea Stop { 1 } Write-Host "SUCCESS: Powershell Remoting Session established with $target" } catch { $Message = $_.Exception.Message Write-Warning "FAIL: PSRemoting to $target failed. Message: $Message" $Result['Success'] = $False } } else { Write-Warning "No connectivity to Powershell Remoting ports - skipping Powershell Remoting test" $Result['Success'] = $False } $TestResults["Test$TestNum"] = $Result #endregion Remote Execution Protocol Tests # Test Endpoint Return Path to HUNT Server $TestNum += 1 $Result = @{ Name = "Return Path Test" Test = $TestNum Description = "Testing remote endpoint TCP443 return path to $ReturnAddress" Success = $True } Write-Host -ForegroundColor Cyan "`n[TEST $TestNum] Testing remote endpoint TCP443 return path to $ReturnAddress..." $RemoteScript = ' #Infocyte Test function Test-Port ($target, $port=443) { $tcpclient = New-Object Net.Sockets.TcpClient try { $tcpclient.Connect($target,$port) } catch {} try { $tcpclient.Close() } catch {} if ($tcpclient.Connected) { $tcpclient.Close(); "Infocyte: SUCCESS" > C:\windows\temp\accesstest.txt } else { "Infocyte: FAIL" > C:\windows\temp\accesstest.txt } } Test-Port '+$ReturnAddress+'' $bytes = [System.Text.Encoding]::Unicode.GetBytes($RemoteScript) $encodedCommand = [Convert]::ToBase64String($bytes) $Result['Return443'] = $true if (($PortResults | Where-Object { $_.Port -eq 135 }).Access) { try { Invoke-WmiMethod -class Win32_process -name Create -ArgumentList "powershell.exe -Nop -NoLogo -Win Hidden -encodedCommand $encodedCommand" -ComputerName $Target | Out-Null if ($ReturnAddress -eq $IPAddress.ipaddress[0]) { $server = New-TcpListener -Port 443 $msg = Receive-TCPMessage } else { Start-Sleep 5 $msg = Get-Content test:\\result.txt -ea SilentlyContinue } if ($msg -notmatch "SUCCESS") { $Result['Return443'] = $false $Result['Success'] = $False } } catch { $Message = $_.Exception.Message Write-Warning "FAIL: Could not test return path - WMI Command Failed - Message: $Message" $Result['Success'] = $False } finally { Remove-PSDrive test -ea SilentlyContinue } } else { Write-Warning "No connectivity to WMI ports - skipping Remote Endpoint Return Path test" $Result['Success'] = $False } $TestResults["Test$TestNum"] = $Result <# if (($PortResults | Where-Object { $_.Port -eq 139}).Access -OR ($PortResults | Where-Object { $_.Port -eq 445}).Access) { try { $mountdrive = New-PSDrive -Name test -PSProvider FileSystem -Root "\\$IP\C$\Windows\Temp" -Credential $Creds -ea STOP Write-Host "SUCCESS: Connected to $IP via SMB" } catch { $Message = $_.Exception.Message $ErrorType = $_.Exception.GetType().FullName Write-Warning "FAIL: Could not test return path - C$ administrative share may not be accessible - Message: $Message" } $RemoteScript | Out-File -FilePath "test:\testaccess.ps1" -Width 4096 } else { Write-Warning "No connectivity to NetBIOS and SMB ports - skipping Remote Endpoint Return Path test" } $cmd = "powershell.exe -script testaccess.ps1" #> $TestResults | ConvertTo-Json | Out-File "$Out\InfocyteTest.json" Write-Host -ForegroundColor Cyan "All Tests Complete!" Write-Host "Results are found here:" Write-Host "$Out\InfocyteTest_RSoP_localhost.txt" Write-Host "$Out\InfocyteTest_RSoP_localhost.html" Write-Host "$Out\InfocyteTest.log" Write-Host "$Out\InfocyteTest.json" "$Out\InfocyteTest_RSoP_localhost.txt\n" | out-file "$env:temp\ictestoutputfolders" "$Out\InfocyteTest_RSoP_localhost.html" | out-file "$env:temp\ictestoutputfolders" -Append "$Out\InfocyteTest.log" | out-file "$env:temp\ictestoutputfolders" -Append "$Out\InfocyteTest.json" | out-file "$env:temp\ictestoutputfolders" -Append return $TestResults } # FUNCTIONS Function Get-DNSEntry ($target) { try { Write-Verbose "Resolving $target" $Temp = [System.Net.Dns]::GetHostEntry($target) } catch { $Message = $_.Exception.Message $ErrorType = $_.Exception.GetType().FullName Write-Warning "[ERROR] Failed DNS Lookup against $target - No such host/IP is known - Message: $Message" Write-Warning "Using DNS $(nslookup $target)" return } if ($target -match "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}") { $IPAddress = $target } else { if (($temp.AddressList | Where-Object { $_.AddressFamily -eq 'InterNetwork' }) -is [System.Net.IPAddress]) { $IPAddress = ($temp.AddressList | Where-Object { $_.AddressFamily -eq 'InterNetwork' }).IPAddressToString } else { $IPAddress = ($temp.AddressList | Where-Object { $_.AddressFamily -eq 'InterNetwork' })[0].IPAddressToString } } $Result = @{ IP = $IPAddress IPs = $temp.AddressList.IPAddressToString HostName = $Temp.HostName } New-Object PSObject -Property $Result } function Test-Port ($target, $port) { $tcpclient = New-Object Net.Sockets.TcpClient try { $tcpclient.Connect($target,$port) } catch {} if($tcpclient.Connected) { $tcpclient.Close() Write-Verbose "[SUCCESS] Port $port on $target is open" $True } else { Write-Warning "[FAILURE] Port $port on $target is closed" $False } } Function New-TCPListener { Param ( [Parameter(Mandatory=$true, Position=0)] [ValidateNotNullOrEmpty()] [int] $Port ) Try { # Set up endpoint and start listening $endpoint = new-object System.Net.IPEndPoint([ipaddress]::any,$port) Write-Host "TCP Listener being set up on $($endpoint.Address):$($port)" $listener = new-object System.Net.Sockets.TcpListener $EndPoint $listener.start() return $listener } Catch { Write-Error "$($Error[0])" } } Function Receive-TCPMessage { Param ( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [System.Net.Sockets.TcpListener]$Listener, [Parameter(Mandatory=$false)] [int]$timeout=15000 ) Try { # Wait for an incoming connection $timer = [system.diagnostics.stopwatch]::StartNew() while (-NOT $listener.Pending()) { if ($timer.Elapsed.TotalMilliseconds -gt $timeout) { # Close TCP connection and stop listening if hits timeout $listener.stop() # Timeout Write-Warning "No response from target before timeout!" return } Start-Sleep 1 } $data = $listener.AcceptTcpClient() Write-Host "Connection Established!" if ($data -AND -NOT $data.Available) { return "Success!" } # Read data from stream and write it to host $stream = $data.GetStream() if (-NOT $stream.DataAvailable) { $stream.close() return "Success!" } $bytes = New-Object System.Byte[] 1024 while (($i = $stream.Read($bytes,0,$bytes.Length)) -ne 0){ $EncodedText = New-Object System.Text.ASCIIEncoding $data = $EncodedText.GetString($bytes,0, $i) if ($data) { Write-Host "Got some data:" Write-Output $data } } $stream.close() } Catch { Write-Warning "ERROR: Listener failed with: $($Error[0])" } finally { # Close TCP connection and stop listening $listener.stop() } } function Test-Connectivity { [CmdletBinding()] Param( [Parameter(Position = 0, Mandatory = $True, ValueFromPipeline=$False)] [ValidatePattern("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}")] [String] $IP, [Parameter(Position = 1, Mandatory = $True, ValueFromPipeline=$True)] [ValidateRange(1,65535)] [Int32] $port, [Parameter(Position = 2, Mandatory = $False, ValueFromPipeline=$False)] [ValidateRange(1,128)] [Int32] $MaxThreads = 24 ) BEGIN { $portdict = @{ 22 = "SSH (TCP 22)" 53 = "DNS (TCP 53)" 80 = "HTTP (TCP 80)" 135 = "WMI/RPC (TCP 135)" 137 = "NetBIOS (TCP 137)" 139 = "NetBIOS (TCP 139)" 389 = "LDAP (TCP 389)" 443 = "HTTPS (TCP 443)" 445 = "SMB (TCP 445)" 1024 = "Dynamic-Legacy (TCP 1024)" 1025 = "Dynamic-Legacy (TCP 1025)" 1026 = "Dynamic-Legacy (TCP 1026)" 3389 = "Remote Desktop (TCP 3389)" 5985 = "PSRemoting-HTTP (TCP 5985)" 5986 = "PSRemoting-HTTPS (TCP 5986)" 49152 = "Dynamic (TCP 49152)" 49153 = "Dynamic (TCP 49153)" 49154 = "Dynamic (TCP 49154)" 65535 = "Dynamic (TCP 65535)" } $TestPort_Scriptblock = { Param($target, $port) $tcpclient = New-Object Net.Sockets.TcpClient try { $tcpclient.Connect($target,$port) } catch {} if($tcpclient.Connected) { $tcpclient.Close() Write-Verbose "[SUCCESS] Port $port on $target is open" $True } else { Write-Warning "[FAILURE] Port $port on $target is closed" $False } } $ports = @() } PROCESS { $ports += $_ } END { # Create Runspace for multi-threading $RunspacePool = [RunspaceFactory]::CreateRunspacePool(1, $MaxThreads) $RunspacePool.Open() $Jobs = @() $ports | ForEach-Object { $Job = [powershell]::Create().AddScript($TestPort_Scriptblock) $Job.AddArgument($IP) | Out-Null $Job.AddArgument($_) | Out-Null $Job.RunspacePool = $RunspacePool $Jobs += New-Object PSObject -Property @{ Port = $_ Pipe = $Job Result = $Job.BeginInvoke() } } # Track Progress of Port Scan $elapsedTime = [system.diagnostics.stopwatch]::StartNew() Do { Write-Progress -activity "Port Scanning" -Status "$([string]::Format("Waiting... Elapsed Time: {0:d2}:{1:d2}.{2:d3}", $elapsedTime.Elapsed.minutes, $elapsedTime.Elapsed.seconds, $elapsedTime.Elapsed.Milliseconds))" #Start-Sleep -Milliseconds 50 } While ( $Jobs.Result.IsCompleted -contains $false) Write-Progress -activity "Port Scanning" -Completed "Port scan completed!" $Results = @() ForEach ($Job in $Jobs ) { $Result = @{ "Port" = $Job.Port "Name" = $portdict[$Job.Port] "Access" = $Job.Pipe.EndInvoke($Job.Result)[0] } $Results += New-Object PSObject -Property $Result } # Cleanup $elapsedTime.stop() $RunspacePool.Close() $Results } } Function Test-ADCredentials { Param( [Parameter(Position = 0, Mandatory = $True)] [System.Management.Automation.PSCredential] $Credential ) Add-Type -AssemblyName System.DirectoryServices.AccountManagement -IgnoreWarnings $ct = [System.DirectoryServices.AccountManagement.ContextType]::Domain try { $pc = New-Object System.DirectoryServices.AccountManagement.PrincipalContext($ct, $Credential.GetNetworkCredential().Domain) } catch { $Message = $_.Exception.Message $ErrorType = $_.Exception.GetType().FullName Write-Warning "ERROR: Could not contact DirectoryServices on domain $($Credential.GetNetworkCredential().Domain) - Message: $Message" return } New-Object PSObject -Property @{ Username = $Credential.UserName isValid = $pc.ValidateCredentials($Credential.GetNetworkCredential().UserName, $Credential.GetNetworkCredential().Password) } } Function Test-RemoteWMI { Param($IP, $credential) $GetWmiObjectParams = @{ Class = "win32_OperatingSystem" Property = "Caption" ComputerName = $IP Credential = $credential } Try { $OS = (Get-WmiObject @GetWmiObjectParams).Caption } Catch { } $GetWmiObjectParams2 = @{ ClassName = "Win32_Process" Property = "Name,CommandLine,ExecutablePath" ComputerName = $IP Credential = $credential } $proc = (Get-CimInstance @GetWmiObjectParams) #(Get-CimInstance -ClassName Win32_Process -Property Name, CommandLine, ExecutablePath)[6] | select Name, CommandLine, ExecutablePath | fl } Function New-ProxyWebClient { # Test HTTP Proxy Authentication (Basic, NTLM, Digest, Negotiate/Kerberos) Param( [Parameter(Position = 0, Mandatory = $True)] [String] $ProxyAddress, [Parameter(Position = 1, Mandatory = $False)] [System.Management.Automation.PSCredential] $Credential, [Parameter(Position = 2, Mandatory = $False)] [String] $AuthType = "Negotiate" ) $BypassLocal = $True $BypassList = @() if ($AuthType -eq "") { # [ValidateSet("", "Basic", "NTLM", "Digest", "Kerberos", "Negotiate")] $AuthType = "Negotiate" } #$BypassList.Insert(";*.$Domain") try { $wc = new-object net.webclient $proxyUri = new-object system.uri($ProxyAddress) } catch { $Message = [String]$_.Exception.Message Write-Warning "ERROR: Could not set up proxy - Message: $Message" } if ($Credential) { # Configure Authenticated proxy Write-Verbose "Configuring Proxy ($ProxyAddress) using $AuthType authentication" try { $cachedCredentials = new-object system.net.CredentialCache $cachedCredentials.Add($proxyUri, $AuthType, $Credential.GetNetworkCredential()) $wc.Proxy = new-object system.net.WebProxy($proxyUri, $bypassLocal) $wc.Proxy.Credentials = $cachedCredentials.GetCredential($proxyUri, $AuthType, $Domain) } catch { $Message = [String]$_.Exception.Message Write-Warning "ERROR: Could not add credentials to proxy - Message: $Message" } return $wc } else { # Use Default System Proxy Settings (Internet Explorer Settings) Write-Verbose "Configuring Proxy ($ProxyAddress) using default (Internet Explorer) Proxy credentials" try { $wc.Proxy = new-object system.net.WebProxy($proxyUri, $bypassLocal) $wc.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials } catch { $Message = $_.Exception.Message $ErrorType = $_.Exception.GetType().FullName Write-Warning "ERROR: Error while setting system's default proxy credentials - Message: $Message" } $showcurrentproxy = netsh winhttp show proxy Write-Verbose $showcurrentproxy return $wc } } # SIG # Begin signature block # MIINOAYJKoZIhvcNAQcCoIINKTCCDSUCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUU6+F7KL1AWm+OL/ARtrD3Ag3 # l7Cgggp2MIIFHzCCBAegAwIBAgIQA7ShIT20JORyIag/jWOSyzANBgkqhkiG9w0B # AQsFADB2MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMTUwMwYDVQQDEyxEaWdpQ2VydCBTSEEyIEhp # Z2ggQXNzdXJhbmNlIENvZGUgU2lnbmluZyBDQTAeFw0xODA5MTIwMDAwMDBaFw0y # MDExMTgxMjAwMDBaMF4xCzAJBgNVBAYTAlVTMQ4wDAYDVQQIEwVUZXhhczEPMA0G # A1UEBxMGQXVzdGluMRYwFAYDVQQKEw1JbmZvY3l0ZSwgSW5jMRYwFAYDVQQDEw1J # bmZvY3l0ZSwgSW5jMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApzcR # GuszlupWLdmtti4glKsr6SS2sp370yioc2XyIwPzU/etsBQa41x6VO7HXjtSXSry # p3SYaoLPQmBiAzKjDP6dzu0l7cQFbwPMky3SGqrC3Wr+Kw/qoMgn3wKBxzPJ53Gj # s1oxNwyz2N7FwN977vErW9C/FgM/XuE7Zde/HGl3oxTJNtY++BG2Ri3rwi5hNbzV # 5+avrJFW1DzHVBXYxbrE9vNy4V6s7dlZT2xZoJ3AtHoBCUMgHRKii3wHgFRaxiuz # 6XzlvHzmnh02KUfoV6cX++bP4bRtsJjmvrfJV+Mhlh/MhUidhhQQx0spLIfxv+vZ # OACP5jLm0g2fj4G4VQIDAQABo4IBvzCCAbswHwYDVR0jBBgwFoAUZ50PIAkMzIo6 # 5YJGcmL88cyQ5UAwHQYDVR0OBBYEFBqi6MjBKip4kQYxVCjC7yOrUHWFMA4GA1Ud # DwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzBtBgNVHR8EZjBkMDCgLqAs # hipodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1oYS1jcy1nMS5jcmwwMKAu # oCyGKmh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWhhLWNzLWcxLmNybDBM # BgNVHSAERTBDMDcGCWCGSAGG/WwDATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3 # dy5kaWdpY2VydC5jb20vQ1BTMAgGBmeBDAEEATCBiAYIKwYBBQUHAQEEfDB6MCQG # CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wUgYIKwYBBQUHMAKG # Rmh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJIaWdoQXNz # dXJhbmNlQ29kZVNpZ25pbmdDQS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0B # AQsFAAOCAQEABnQP0mJYXNzfz4pMCc4FbQ9qe8NjloGuIlUgXaxlFAoMKZWMueXq # mciPWULaE+Wd5ChTuNsrWKG7bWYYWmmo7C1RWhdZhQT/C+k3lFcsSr6gdXAXiOmv # 3xv3d3oqfNe19G6jt6akQ6LjEauRw4xKinoK/S61Pw9c1KtEAGT8djgX74h433fy # FPiQd//ePnihKN+GXRCeLvSaDGuVrhHuI6UUhe3MK2/Nb8MzFddwkOOdpky1HBn4 # 8oFEAOzbrTVTTv4BWLNRvAiY8UO3D2Kt322UuAdXIKNxWB94UaFt2jg2QsRkTHGQ # MmbQ8OgMIWWNcE9RcVKuobYbzUAGPoMimTCCBU8wggQ3oAMCAQICEAt+EJA8OEkP # +i9nmoehp7kwDQYJKoZIhvcNAQELBQAwbDELMAkGA1UEBhMCVVMxFTATBgNVBAoT # DERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UE # AxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2UgRVYgUm9vdCBDQTAeFw0xMzEwMjIx # MjAwMDBaFw0yODEwMjIxMjAwMDBaMHYxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxE # aWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xNTAzBgNVBAMT # LERpZ2lDZXJ0IFNIQTIgSGlnaCBBc3N1cmFuY2UgQ29kZSBTaWduaW5nIENBMIIB # IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtEpefQcPQd7E9XYWNr1x/88/ # T3NLnNEN/krLV1hehRbdAhVUmfCPPC9NAngQaMjYNUs/wfdnzpgcrjO5LR2kClST # xIWi3zWx9fE8p7M0+11IyUbJYkS8SJnrKElTwz2PwA7eNZjpYlHfPWtAYe4EQdrP # p1xWltH5TLdEhIeYaeWCuRPmVb/IknCSCjFvf4syq89rWp9ixD7uvu1ZpFN/C/FS # iIp7Cmcky5DN7NJNNEyw4bWfnMb2byzN5spTdAGfZzXeOEktzu05RIIZeU4asrX7 # u3jwSWanz/pclnWSixpy2f9QklPMPsJDMgkahhNpPPuBMjMyZHVzKCYdCDA7BwID # AQABo4IB4TCCAd0wEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYw # EwYDVR0lBAwwCgYIKwYBBQUHAwMwfwYIKwYBBQUHAQEEczBxMCQGCCsGAQUFBzAB # hhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wSQYIKwYBBQUHMAKGPWh0dHA6Ly9j # YWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEhpZ2hBc3N1cmFuY2VFVlJvb3RD # QS5jcnQwgY8GA1UdHwSBhzCBhDBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQu # Y29tL0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDBAoD6gPIY6aHR0 # cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9v # dENBLmNybDBPBgNVHSAESDBGMDgGCmCGSAGG/WwAAgQwKjAoBggrBgEFBQcCARYc # aHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAKBghghkgBhv1sAzAdBgNVHQ4E # FgQUZ50PIAkMzIo65YJGcmL88cyQ5UAwHwYDVR0jBBgwFoAUsT7DaQP4v0cB1Jgm # GggC72NkK8MwDQYJKoZIhvcNAQELBQADggEBAGoO/34TfAalS8AujPlTZAniuliR # MFDszJ/h06gvSEY2GCnQeChfmFZADx66vbE7h1zcW9ggDe0aFk3VESQhS/EnaZAT # 6xGhAdr9tU55WXW9OCpqw/aOQSuKoovXLFFR2ZygyONOumyoR9JO0WgfjAJXO7Mp # ao5qICq58gBiZLrI6QD5zKTUupo12K8sZWwWfFgh3kow0PrrJF0GyZ0Wt61KRdMl # 4gzwQKpcTax+zQaCuXZGaQjYMraC/uOpWDRDG45nZ5c/aDEWNjiVPof3x8OvnXp3 # Gdnek7X9biv8lPk9t0wSNSwwvuiNngVwmkgT9IzW5x6sOOeo860Mt3rsZ+0xggIs # MIICKAIBATCBijB2MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5j # MRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTUwMwYDVQQDEyxEaWdpQ2VydCBT # SEEyIEhpZ2ggQXNzdXJhbmNlIENvZGUgU2lnbmluZyBDQQIQA7ShIT20JORyIag/ # jWOSyzAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkq # hkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGC # NwIBFTAjBgkqhkiG9w0BCQQxFgQUDLahFhcattWyxHYYeLrViWcLn9owDQYJKoZI # hvcNAQEBBQAEggEApeyLIF/Mhkd3IqDQMimuvIG7ygwXeDvq98NtBXf4SwWQ1BB7 # TvlNX3p3nz61xLphVO26AaF75X2f+u7XT6nuhbGiVGI3/iSJGG96QVjMNbt6YLO3 # jaGogcVzWMwarpWPc9frG9EFYiYNYvZNzi9aL7XI4cDne76bVAZhOwOeMUlHiUnG # t7rWapQFTdyyIXGd2ChSZ1cKPzXdDLxYiTq2Mxgnn9V9oUaLNB+kHistJRVKpI7N # t4t+OIRuIwHUO3kHfFAwV69HfEE7kRA656wb1mG8ySCcvqJRmgMPrIRjlL615Q3r # 4LAFOsxNNd7HCbguTvcKvIh6pKqD5I+JKP+DzA== # SIG # End signature block |