param( [Parameter(Mandatory=$true)] [string]$ScanDirectory, [Parameter(Mandatory=$true)] [string]$FingerprintsFile, [Parameter(Mandatory=$false)] [string]$OutputDirectory = ".\categorized_interfaces" ) # Function to test if a string matches any pattern in an array function Test-Patterns { param( [string]$Text, [array]$Patterns ) foreach ($pattern in $Patterns) { if ($Text -match [regex]::Escape($pattern)) { return $true } } return $false } # Function to convert PSObject to Hashtable function ConvertTo-Hashtable { param ( [Parameter(ValueFromPipeline)] $InputObject ) process { if ($null -eq $InputObject) { return $null } if ($InputObject -is [System.Collections.Hashtable]) { return $InputObject } $hash = @{} $InputObject.PSObject.Properties | ForEach-Object { $hash[$_.Name] = $_.Value } return $hash } } # Function to check if headers match the specified patterns function Test-Headers { param( [array]$Headers, $HeaderPatterns ) # Convert PSObject to Hashtable if needed $headerPatternsHash = $HeaderPatterns | ConvertTo-Hashtable foreach ($headerPattern in $headerPatternsHash.GetEnumerator()) { $headerFound = $false foreach ($header in $Headers) { if ($header.Key -eq $headerPattern.Key) { foreach ($value in $header.Value) { if (Test-Patterns -Text $value -Patterns $headerPattern.Value) { $headerFound = $true break } } } } if (-not $headerFound) { return $false } } return $true } # Function to categorize a single interface based on fingerprints function Get-InterfaceCategory { param( [PSCustomObject]$InterfaceData, [PSCustomObject]$Fingerprints ) foreach ($category in $Fingerprints.PSObject.Properties) { $fingerprint = $category.Value $matched = $true # Check URL patterns if ($fingerprint.urlPatterns) { $urlFound = $false foreach ($port in $InterfaceData.OpenPorts) { if ($port.WebRequest) { $requests = @($port.WebRequest) if ($requests[0] -isnot [array]) { $requests = @($requests) } foreach ($request in $requests) { if (Test-Patterns -Text $request.Url -Patterns $fingerprint.urlPatterns) { $urlFound = $true break } } } } if (-not $urlFound) { $matched = $false } } # Check content patterns if ($matched -and $fingerprint.contentPatterns) { $contentFound = $false foreach ($port in $InterfaceData.OpenPorts) { if ($port.WebRequest) { $requests = @($port.WebRequest) if ($requests[0] -isnot [array]) { $requests = @($requests) } foreach ($request in $requests) { if ($request.Content -and (Test-Patterns -Text $request.Content -Patterns $fingerprint.contentPatterns)) { $contentFound = $true break } } } } if (-not $contentFound) { $matched = $false } } # Check header patterns if ($matched -and $fingerprint.headerPatterns) { $headersFound = $false foreach ($port in $InterfaceData.OpenPorts) { if ($port.WebRequest) { $requests = @($port.WebRequest) if ($requests[0] -isnot [array]) { $requests = @($requests) } foreach ($request in $requests) { if ($request.Headers -and (Test-Headers -Headers $request.Headers -HeaderPatterns $fingerprint.headerPatterns)) { $headersFound = $true break } } } } if (-not $headersFound) { $matched = $false } } if ($matched) { return $category.Name } } return "Unknown" } # Function to generate HTML report function New-CategoryReport { param( [string]$OutputDirectory ) $reportPath = Join-Path $OutputDirectory "categorization_report.html" $categories = Get-ChildItem -Path $OutputDirectory -Directory $html = @"
Total Categories: $($categories.Count)
Generated: $(Get-Date)
| IP Address | Hostname | Ports | Links |
|---|---|---|---|
| $($interfaceData.IP) | $($interfaceData.Hostname) | $ports | $linksHtml |