Private/Export/Format-SignalContent.ps1
|
# PSGuerrilla - Jim Tyler, Microsoft MVP - CC BY 4.0 # https://github.com/jimrtyler/PSGuerrilla | https://creativecommons.org/licenses/by/4.0/ # AI/LLM use: see AI-USAGE.md for required attribution function Format-SignalContent { [CmdletBinding()] param( [Parameter(Mandatory)] [PSCustomObject]$ScanResult, [Parameter(Mandatory)] [ValidateSet('Html', 'Text', 'Sms')] [string]$Format, [PSCustomObject[]]$Threats ) if (-not $Threats) { $Threats = $ScanResult.NewThreats } if (-not $Threats -or $Threats.Count -eq 0) { return $null } $critCount = @($Threats | Where-Object ThreatLevel -eq 'CRITICAL').Count $highCount = @($Threats | Where-Object ThreatLevel -eq 'HIGH').Count $medCount = @($Threats | Where-Object ThreatLevel -eq 'MEDIUM').Count switch ($Format) { 'Sms' { if ($Threats.Count -eq 1) { $t = $Threats[0] $topInd = if ($t.Indicators.Count -gt 0) { $t.Indicators[0] } else { 'Suspicious activity' } # Truncate indicator for SMS if ($topInd.Length -gt 100) { $topInd = $topInd.Substring(0, 97) + '...' } return "PSGuerrilla SIGNAL: NEW COMPROMISE - $($t.Email) (Score:$($t.ThreatScore.ToString('N0')), $($t.ThreatLevel)). $topInd. Details emailed." } else { $parts = @("PSGuerrilla SIGNAL: $($Threats.Count) new threats detected.") if ($critCount -gt 0) { $parts += "$critCount CRITICAL" } if ($highCount -gt 0) { $parts += "$highCount HIGH" } if ($medCount -gt 0) { $parts += "$medCount MEDIUM" } $top = $Threats | Sort-Object -Property ThreatScore -Descending | Select-Object -First 1 $parts += "Top: $($top.Email) (Score:$($top.ThreatScore.ToString('N0')))" $parts += "Details emailed." return $parts -join ' ' } } 'Text' { $lines = @() $lines += 'PSGuerrilla Field Report Alert' $lines += '=' * 50 $lines += "Scan Time: $($ScanResult.Timestamp.ToString('yyyy-MM-dd HH:mm:ss')) UTC" $lines += "Users Scanned: $($ScanResult.TotalUsersScanned)" $lines += "New Threats: $($Threats.Count)" if ($critCount) { $lines += "CRITICAL: $critCount" } if ($highCount) { $lines += "HIGH: $highCount" } if ($medCount) { $lines += "MEDIUM: $medCount" } $lines += '' $lines += 'FLAGGED USERS:' $lines += '-' * 50 foreach ($t in $Threats) { $lines += "$($t.ThreatLevel) (Score: $($t.ThreatScore.ToString('N0'))) - $($t.Email)" foreach ($ind in $t.Indicators) { $lines += " - $ind" } $lines += '' } return $lines -join "`n" } 'Html' { $esc = { param([string]$s) [System.Web.HttpUtility]::HtmlEncode($s) } $sb = [System.Text.StringBuilder]::new(4096) [void]$sb.Append(@" <div style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, sans-serif; max-width: 700px; margin: 0 auto; background: #0d1117; color: #e6edf3; padding: 24px; border-radius: 8px;"> <h2 style="margin: 0 0 8px; color: #e6edf3;">PSGuerrilla Field Report Alert</h2> <p style="color: #8b949e; margin: 0 0 16px;">Scan: $($ScanResult.Timestamp.ToString('yyyy-MM-dd HH:mm:ss')) UTC | $($ScanResult.TotalUsersScanned) users scanned | $($ScanResult.TotalEventsAnalyzed) events analyzed</p> <table style="width: 100%; border-collapse: collapse; margin-bottom: 16px;"> <tr> "@) if ($critCount -gt 0) { [void]$sb.Append("<td style=`"text-align: center; padding: 12px; background: rgba(248,81,73,0.15); border-radius: 6px;`"><div style=`"font-size: 2em; font-weight: 700; color: #f85149;`">$critCount</div><div style=`"color: #8b949e; font-size: 0.85em;`">CRITICAL</div></td>") } if ($highCount -gt 0) { [void]$sb.Append("<td style=`"text-align: center; padding: 12px; background: rgba(219,109,40,0.15); border-radius: 6px;`"><div style=`"font-size: 2em; font-weight: 700; color: #db6d28;`">$highCount</div><div style=`"color: #8b949e; font-size: 0.85em;`">HIGH</div></td>") } if ($medCount -gt 0) { [void]$sb.Append("<td style=`"text-align: center; padding: 12px; background: rgba(210,153,34,0.15); border-radius: 6px;`"><div style=`"font-size: 2em; font-weight: 700; color: #d29922;`">$medCount</div><div style=`"color: #8b949e; font-size: 0.85em;`">MEDIUM</div></td>") } [void]$sb.Append('</tr></table>') foreach ($t in ($Threats | Sort-Object -Property ThreatScore -Descending)) { $levelColor = switch ($t.ThreatLevel) { 'CRITICAL' { '#f85149' } 'HIGH' { '#db6d28' } 'MEDIUM' { '#d29922' } default { '#58a6ff' } } [void]$sb.Append(@" <div style="background: #161b22; border: 1px solid #30363d; border-radius: 8px; padding: 12px; margin-bottom: 12px;"> <h3 style="margin: 0 0 8px;">$(& $esc $t.Email) <span style="background: $levelColor; color: #fff; padding: 2px 8px; border-radius: 10px; font-size: 0.75em;">$($t.ThreatLevel) ($($t.ThreatScore.ToString('N0')))</span></h3> <ul style="margin: 0; padding-left: 20px; font-size: 0.9em;"> "@) foreach ($ind in $t.Indicators) { [void]$sb.Append("<li style=`"margin-bottom: 4px;`">$(& $esc $ind)</li>") } [void]$sb.Append('</ul></div>') } [void]$sb.Append('</div>') return $sb.ToString() } } } |