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 = @" Interface Categorization Report

Interface Categorization Report

Total Categories: $($categories.Count)

Generated: $(Get-Date)

"@ foreach ($category in $categories) { $files = Get-ChildItem -Path $category.FullName -Filter "*.json" $html += @"

$($category.Name)

"@ foreach ($file in $files) { $interfaceData = Get-Content $file.FullName | ConvertFrom-Json $ports = ($interfaceData.OpenPorts | ForEach-Object { $_.PortNumber }) -join ", " $links = @() foreach ($port in $interfaceData.OpenPorts) { if ($port.WebRequest) { $requests = @($port.WebRequest) if ($requests[0] -isnot [array]) { $requests = @($requests) } foreach ($request in $requests) { if ($request.Url) { $links += $request.Url } } } } $linksHtml = ($links | Select-Object -Unique | ForEach-Object { "$_" }) -join "
" $html += @" "@ } $html += @"
IP Address Hostname Ports Links
$($interfaceData.IP) $($interfaceData.Hostname) $ports $linksHtml
"@ } $html += @" "@ $html | Out-File -FilePath $reportPath -Encoding UTF8 return $reportPath } # Main script execution try { # Create output directory if it doesn't exist if (-not (Test-Path $OutputDirectory)) { New-Item -ItemType Directory -Path $OutputDirectory | Out-Null } # Load fingerprints file $fingerprints = Get-Content $FingerprintsFile | ConvertFrom-Json # Track categorization results $results = @{} # Process each JSON file in the scan directory Get-ChildItem -Path $ScanDirectory -Filter "*.json" | ForEach-Object { Write-Host "Processing $($_.Name)..." try { # Read and parse JSON file $interfaceData = Get-Content $_.FullName | ConvertFrom-Json # Get category $category = Get-InterfaceCategory -InterfaceData $interfaceData -Fingerprints $fingerprints # Create category directory if it doesn't exist $categoryDir = Join-Path $OutputDirectory $category if (-not (Test-Path $categoryDir)) { New-Item -ItemType Directory -Path $categoryDir | Out-Null } # Move file to appropriate category directory Move-Item $_.FullName -Destination $categoryDir -Force # Track result if (-not $results.ContainsKey($category)) { $results[$category] = 0 } $results[$category]++ Write-Host "Categorized as: $category" } catch { Write-Warning "Error processing $($_.Name): $_" } } # Generate HTML report $reportPath = New-CategoryReport -OutputDirectory $OutputDirectory # Display summary Write-Host "`nCategorization Summary:" $results.GetEnumerator() | Sort-Object Name | ForEach-Object { Write-Host "$($_.Key): $($_.Value) interfaces" } Write-Host "`nReport generated at: $reportPath" } catch { Write-Error "Script execution failed: $_" }