SEO Checker Tool

<#
.SYNOPSIS
SEO Checker Tool

.DESCRIPTION
This script analyzes a webpage for various SEO elements and provides a report.

.NOTES
File Name      : SEOChecker.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later, Internet connectivity
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\SEOChecker.ps1
#>

# Import required modules
Add-Type -AssemblyName System.Web

# Global variables
$script:reportPath = "$env:USERPROFILE\Desktop\SEO_Analysis_Report_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"

function Show-Menu {
    Clear-Host
    Write-Host "=== SEO Checker Tool ===" -ForegroundColor Cyan
    Write-Host "1. Analyze Website"
    Write-Host "2. View Last Report"
    Write-Host "3. Exit"
}

function Analyze-Website {
    $url = Read-Host "Enter the website URL to analyze (include http:// or https://)"
    
    if (-not ($url -match "^https?://")) {
        Write-Host "Invalid URL. Please include http:// or https://" -ForegroundColor Red
        return
    }

    Write-Host "`nAnalyzing $url..." -ForegroundColor Yellow

    try {
        $response = Invoke-WebRequest -Uri $url -UseBasicParsing
        $content = $response.Content
        $statusCode = $response.StatusCode

        $results = @{
            URL = $url
            StatusCode = $statusCode
            Title = Get-Title $content
            MetaDescription = Get-MetaDescription $content
            HeaderTags = Get-HeaderTags $content
            ImageAltTags = Get-ImageAltTags $content
            WordCount = Get-WordCount $content
            LoadTime = Measure-LoadTime $url
            MobileFriendly = Test-MobileFriendly $url
            SSL = Test-SSL $url
        }

        Generate-Report $results
    }
    catch {
        Write-Host "Error analyzing website: $_" -ForegroundColor Red
    }
}

function Get-Title($content) {
    if ($content -match "<title>(.*?)</title>") {
        return $matches[1]
    }
    return "No title found"
}

function Get-MetaDescription($content) {
    if ($content -match '<meta name="description" content="(.*?)"') {
        return $matches[1]
    }
    return "No meta description found"
}

function Get-HeaderTags($content) {
    $headers = @{}
    for ($i = 1; $i -le 6; $i++) {
        $count = ([regex]::Matches($content, "<h$i")).Count
        if ($count -gt 0) {
            $headers["H$i"] = $count
        }
    }
    return $headers
}

function Get-ImageAltTags($content) {
    $images = [regex]::Matches($content, '<img [^>]*alt="([^"]*)"')
    return @{
        TotalImages = $images.Count
        ImagesWithAlt = ($images | Where-Object { $_.Groups[1].Value -ne "" }).Count
    }
}

function Get-WordCount($content) {
    $text = $content -replace '<[^>]+>', '' -replace '&nbsp;', ' '
    $words = $text -split '\s+' | Where-Object { $_ -ne '' }
    return $words.Count
}

function Measure-LoadTime($url) {
    $stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
    Invoke-WebRequest -Uri $url -UseBasicParsing | Out-Null
    $stopwatch.Stop()
    return [math]::Round($stopwatch.Elapsed.TotalSeconds, 2)
}

function Test-MobileFriendly($url) {
    # This is a basic check. For a more accurate test, you'd need to use Google's Mobile-Friendly Test API
    $userAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1"
    $response = Invoke-WebRequest -Uri $url -UserAgent $userAgent -UseBasicParsing
    return $response.StatusCode -eq 200
}

function Test-SSL($url) {
    return $url.StartsWith("https://")
}

function Generate-Report($results) {
    $reportContent = @"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SEO Analysis Report</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 800px; margin: 0 auto; padding: 20px; }
        h1, h2 { color: #0078D4; }
        table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
        .good { color: green; }
        .warning { color: orange; }
        .bad { color: red; }
    </style>
</head>
<body>
    <h1>SEO Analysis Report</h1>
    <p>Generated on: $(Get-Date)</p>
    <p>URL: $($results.URL)</p>

    <h2>General Information</h2>
    <table>
        <tr><th>Status Code</th><td>$($results.StatusCode)</td></tr>
        <tr><th>Title</th><td>$($results.Title)</td></tr>
        <tr><th>Meta Description</th><td>$($results.MetaDescription)</td></tr>
        <tr><th>Word Count</th><td>$($results.WordCount)</td></tr>
        <tr><th>Load Time</th><td>$($results.LoadTime) seconds</td></tr>
        <tr><th>Mobile Friendly</th><td>$(if ($results.MobileFriendly) { "Yes" } else { "No" })</td></tr>
        <tr><th>SSL</th><td>$(if ($results.SSL) { "Yes" } else { "No" })</td></tr>
    </table>

    <h2>Header Tags</h2>
    <table>
        $(foreach ($header in $results.HeaderTags.GetEnumerator()) {
            "<tr><th>$($header.Key)</th><td>$($header.Value)</td></tr>"
        })
    </table>

    <h2>Images</h2>
    <table>
        <tr><th>Total Images</th><td>$($results.ImageAltTags.TotalImages)</td></tr>
        <tr><th>Images with Alt Text</th><td>$($results.ImageAltTags.ImagesWithAlt)</td></tr>
    </table>

    <h2>Recommendations</h2>
    <ul>
        $(if ($results.Title.Length -gt 60) { "<li class='warning'>Title is too long ($(($results.Title).Length) characters). Keep it under 60 characters.</li>" })
        $(if ($results.Title.Length -lt 30) { "<li class='warning'>Title is too short ($(($results.Title).Length) characters). Aim for 30-60 characters.</li>" })
        $(if ($results.MetaDescription.Length -gt 160) { "<li class='warning'>Meta description is too long ($(($results.MetaDescription).Length) characters). Keep it under 160 characters.</li>" })
        $(if ($results.MetaDescription.Length -lt 50) { "<li class='warning'>Meta description is too short ($(($results.MetaDescription).Length) characters). Aim for 50-160 characters.</li>" })
        $(if ($results.WordCount -lt 300) { "<li class='warning'>Content might be too short ($($results.WordCount) words). Aim for at least 300 words.</li>" })
        $(if ($results.LoadTime -gt 3) { "<li class='warning'>Page load time is slow ($($results.LoadTime) seconds). Aim for under 3 seconds.</li>" })
        $(if (-not $results.MobileFriendly) { "<li class='bad'>Page may not be mobile-friendly. Consider optimizing for mobile devices.</li>" })
        $(if (-not $results.SSL) { "<li class='bad'>Site is not using SSL. Consider switching to HTTPS for better security and SEO.</li>" })
        $(if ($results.ImageAltTags.ImagesWithAlt -lt $results.ImageAltTags.TotalImages) { "<li class='warning'>Not all images have alt text. Add alt text to improve accessibility and SEO.</li>" })
    </ul>
</body>
</html>
"@

    $reportContent | Out-File -FilePath $script:reportPath
    Write-Host "Report generated and saved to: $script:reportPath" -ForegroundColor Green
}

function View-LastReport {
    if (Test-Path $script:reportPath) {
        Start-Process $script:reportPath
    } else {
        Write-Host "No report found. Please analyze a website first." -ForegroundColor Yellow
    }
}

# Main program loop
do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-3)"

    switch ($choice) {
        "1" { Analyze-Website }
        "2" { View-LastReport }
        "3" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "3") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "3")

This SEO Checker Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to analyze various SEO elements of a webpage:
    • Page title
    • Meta description
    • Header tags (H1 to H6)
    • Image alt tags
    • Word count
    • Page load time
    • Mobile-friendliness (basic check)
    • SSL implementation
  3. A report generation function that creates an HTML report with the analysis results and recommendations.
  4. Option to view the last generated report.

Key features:

  • Analyzes important on-page SEO elements
  • Provides a visual HTML report with color-coded recommendations
  • Checks for mobile-friendliness and SSL implementation
  • Measures page load time
  • Offers suggestions for improvement based on common SEO best practices

This tool is particularly useful for:

  • Website owners who want to perform a basic SEO check
  • Digital marketers analyzing website SEO elements
  • Web developers ensuring they’ve implemented basic SEO best practices
  • Anyone learning about SEO and wanting to analyze real websites

To use this script effectively:

  1. Run the script in PowerShell
  2. Choose to analyze a website by entering its URL
  3. Review the generated HTML report
  4. Use the recommendations to improve the website’s SEO

Please note that this is a basic SEO checker and doesn’t cover all aspects of SEO. For a comprehensive SEO analysis, you would need to consider many more factors and potentially use more advanced APIs and tools. However, this script provides a good starting point for basic on-page SEO analysis.

Certificate Request Toolkit

<#
.SYNOPSIS
Certificate Request Toolkit

.DESCRIPTION
This script provides a comprehensive set of tools for creating, managing, and analyzing
certificate requests (CSRs) and certificates. It includes features for generating CSRs,
analyzing existing CSRs and certificates, and performing related tasks.

.NOTES
File Name      : CertRequestToolkit.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later, OpenSSL (optional for some features)
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\CertRequestToolkit.ps1
#>

# Check if OpenSSL is available
$openSSLAvailable = $null -ne (Get-Command openssl -ErrorAction SilentlyContinue)

function Show-Menu {
    Clear-Host
    Write-Host "=== Certificate Request Toolkit ===" -ForegroundColor Cyan
    Write-Host "1. Generate CSR"
    Write-Host "2. Analyze CSR"
    Write-Host "3. Analyze Certificate"
    Write-Host "4. Generate Self-Signed Certificate"
    Write-Host "5. Convert Certificate Format"
    Write-Host "6. Check Certificate Expiration"
    Write-Host "7. Verify Certificate Chain"
    Write-Host "8. Extract Public Key from Certificate"
    Write-Host "9. Exit"
}

function Generate-CSR {
    $subject = Read-Host "Enter the subject (e.g., CN=example.com,O=MyOrg,C=US)"
    $keySize = Read-Host "Enter key size (2048 or 4096, default is 2048)"
    if ([string]::IsNullOrWhiteSpace($keySize)) { $keySize = 2048 }

    $sanNames = @()
    do {
        $san = Read-Host "Enter Subject Alternative Name (or press Enter to finish)"
        if (-not [string]::IsNullOrWhiteSpace($san)) {
            $sanNames += $san
        }
    } while (-not [string]::IsNullOrWhiteSpace($san))

    $outputPath = Join-Path -Path $env:USERPROFILE -ChildPath "Desktop\certificate_request.csr"

    if ($openSSLAvailable) {
        $configPath = Join-Path -Path $env:TEMP -ChildPath "openssl_config.cnf"
        $config = @"
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no

[req_distinguished_name]
$subject

[v3_req]
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = @alt_names

[alt_names]
"@
        for ($i = 0; $i -lt $sanNames.Count; $i++) {
            $config += "DNS.$($i+1) = $($sanNames[$i])`n"
        }

        $config | Out-File -FilePath $configPath -Encoding ASCII

        $keyPath = Join-Path -Path $env:USERPROFILE -ChildPath "Desktop\private_key.pem"
        
        & openssl req -new -newkey rsa:$keySize -nodes -keyout $keyPath -out $outputPath -config $configPath

        Remove-Item -Path $configPath

        Write-Host "CSR generated and saved to: $outputPath" -ForegroundColor Green
        Write-Host "Private key saved to: $keyPath" -ForegroundColor Green
    }
    else {
        Write-Host "OpenSSL is not available. Using .NET to generate CSR (limited functionality)." -ForegroundColor Yellow
        
        $rsa = [System.Security.Cryptography.RSA]::Create($keySize)
        $req = New-Object -TypeName System.Security.Cryptography.X509Certificates.CertificateRequest(
            $subject, $rsa, [System.Security.Cryptography.HashAlgorithmName]::SHA256, 
            [System.Security.Cryptography.RSASignaturePadding]::Pkcs1)

        foreach ($san in $sanNames) {
            $req.CertificateExtensions.Add(
                [System.Security.Cryptography.X509Certificates.X509SubjectAlternativeNameExtension]::new(
                    $san, $false))
        }

        $csr = $req.CreateSigningRequest()
        [System.IO.File]::WriteAllBytes($outputPath, $csr)

        Write-Host "CSR generated and saved to: $outputPath" -ForegroundColor Green
        Write-Host "Note: Private key is not saved separately when using .NET method." -ForegroundColor Yellow
    }
}

function Analyze-CSR {
    $csrPath = Read-Host "Enter the path to the CSR file"
    if (-not (Test-Path $csrPath)) {
        Write-Host "CSR file not found." -ForegroundColor Red
        return
    }

    if ($openSSLAvailable) {
        Write-Host "`nCSR Analysis:" -ForegroundColor Yellow
        & openssl req -in $csrPath -noout -text
    }
    else {
        Write-Host "OpenSSL is not available. Limited analysis will be performed." -ForegroundColor Yellow
        $csrContent = Get-Content $csrPath -Raw
        $csrBytes = [System.Convert]::FromBase64String(($csrContent -replace "-----BEGIN CERTIFICATE REQUEST-----", "" -replace "-----END CERTIFICATE REQUEST-----", "").Trim())
        $csr = New-Object System.Security.Cryptography.X509Certificates.X509CertificateRequest(,$csrBytes)
        
        Write-Host "`nCSR Subject: $($csr.Subject)" -ForegroundColor Yellow
        Write-Host "Public Key Algorithm: $($csr.PublicKey.Oid.FriendlyName)" -ForegroundColor Yellow
        Write-Host "Public Key Size: $($csr.PublicKey.Key.KeySize) bits" -ForegroundColor Yellow
    }
}

function Analyze-Certificate {
    $certPath = Read-Host "Enter the path to the certificate file"
    if (-not (Test-Path $certPath)) {
        Write-Host "Certificate file not found." -ForegroundColor Red
        return
    }

    if ($openSSLAvailable) {
        Write-Host "`nCertificate Analysis:" -ForegroundColor Yellow
        & openssl x509 -in $certPath -noout -text
    }
    else {
        Write-Host "OpenSSL is not available. Limited analysis will be performed." -ForegroundColor Yellow
        $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($certPath)
        
        Write-Host "`nCertificate Subject: $($cert.Subject)" -ForegroundColor Yellow
        Write-Host "Issuer: $($cert.Issuer)" -ForegroundColor Yellow
        Write-Host "Valid From: $($cert.NotBefore)" -ForegroundColor Yellow
        Write-Host "Valid To: $($cert.NotAfter)" -ForegroundColor Yellow
        Write-Host "Serial Number: $($cert.SerialNumber)" -ForegroundColor Yellow
        Write-Host "Thumbprint: $($cert.Thumbprint)" -ForegroundColor Yellow
    }
}

function Generate-SelfSignedCertificate {
    $subject = Read-Host "Enter the subject (e.g., CN=example.com)"
    $validityDays = Read-Host "Enter validity period in days (default is 365)"
    if ([string]::IsNullOrWhiteSpace($validityDays)) { $validityDays = 365 }

    $outputPath = Join-Path -Path $env:USERPROFILE -ChildPath "Desktop\self_signed_certificate.pfx"
    $password = Read-Host "Enter a password for the PFX file" -AsSecureString

    $cert = New-SelfSignedCertificate -Subject $subject -CertStoreLocation Cert:\CurrentUser\My `
        -KeyExportPolicy Exportable -KeySpec Signature -KeyLength 2048 -KeyAlgorithm RSA `
        -HashAlgorithm SHA256 -NotAfter (Get-Date).AddDays($validityDays)

    Export-PfxCertificate -Cert $cert -FilePath $outputPath -Password $password

    Remove-Item $cert.PSPath

    Write-Host "Self-signed certificate generated and saved to: $outputPath" -ForegroundColor Green
}

function Convert-CertificateFormat {
    if (-not $openSSLAvailable) {
        Write-Host "This feature requires OpenSSL, which is not available." -ForegroundColor Red
        return
    }

    $inputPath = Read-Host "Enter the path to the input certificate file"
    if (-not (Test-Path $inputPath)) {
        Write-Host "Input file not found." -ForegroundColor Red
        return
    }

    $outputFormat = Read-Host "Enter the desired output format (PEM, DER, P12)"
    $outputPath = Join-Path -Path $env:USERPROFILE -ChildPath "Desktop\converted_certificate.$($outputFormat.ToLower())"

    switch ($outputFormat.ToUpper()) {
        "PEM" { & openssl x509 -in $inputPath -outform PEM -out $outputPath }
        "DER" { & openssl x509 -in $inputPath -outform DER -out $outputPath }
        "P12" {
            $password = Read-Host "Enter a password for the P12 file" -AsSecureString
            $plainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password))
            & openssl pkcs12 -export -in $inputPath -out $outputPath -password pass:$plainPassword
        }
        default { Write-Host "Unsupported output format." -ForegroundColor Red; return }
    }

    Write-Host "Certificate converted and saved to: $outputPath" -ForegroundColor Green
}

function Check-CertificateExpiration {
    $certPath = Read-Host "Enter the path to the certificate file"
    if (-not (Test-Path $certPath)) {
        Write-Host "Certificate file not found." -ForegroundColor Red
        return
    }

    $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($certPath)
    $daysUntilExpiration = ($cert.NotAfter - (Get-Date)).Days

    Write-Host "`nCertificate Expiration Information:" -ForegroundColor Yellow
    Write-Host "Subject: $($cert.Subject)"
    Write-Host "Expiration Date: $($cert.NotAfter)"
    Write-Host "Days Until Expiration: $daysUntilExpiration"

    if ($daysUntilExpiration -le 30) {
        Write-Host "Warning: Certificate will expire soon!" -ForegroundColor Red
    }
}

function Verify-CertificateChain {
    $certPath = Read-Host "Enter the path to the certificate file"
    if (-not (Test-Path $certPath)) {
        Write-Host "Certificate file not found." -ForegroundColor Red
        return
    }

    $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($certPath)
    $chain = New-Object System.Security.Cryptography.X509Certificates.X509Chain
    $chainBuilt = $chain.Build($cert)

    Write-Host "`nCertificate Chain Verification:" -ForegroundColor Yellow
    if ($chainBuilt) {
        Write-Host "Certificate chain is valid." -ForegroundColor Green
        Write-Host "`nCertificate Chain:"
        foreach ($element in $chain.ChainElements) {
            Write-Host "  Subject: $($element.Certificate.Subject)"
            Write-Host "  Issuer: $($element.Certificate.Issuer)"
            Write-Host "  Valid From: $($element.Certificate.NotBefore)"
            Write-Host "  Valid To: $($element.Certificate.NotAfter)"
            Write-Host ""
        }
    }
    else {
        Write-Host "Certificate chain is not valid." -ForegroundColor Red
        Write-Host "`nChain Status:"
        foreach ($status in $chain.ChainStatus) {
            Write-Host "  $($status.StatusInformation)"
        }
    }
}

function Extract-PublicKey {
    if (-not $openSSLAvailable) {
        Write-Host "This feature requires OpenSSL, which is not available." -ForegroundColor Red
        return
    }

    $certPath = Read-Host "Enter the path to the certificate file"
    if (-not (Test-Path $certPath)) {
        Write-Host "Certificate file not found." -ForegroundColor Red
        return
    }

    $outputPath = Join-Path -Path $env:USERPROFILE -ChildPath "Desktop\public_key.pem"
    & openssl x509 -in $certPath -pubkey -noout > $outputPath

    Write-Host "Public key extracted and saved to: $outputPath" -ForegroundColor Green
}

# Main program loop
do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-9)"

    switch ($choice) {
        "1" { Generate-CSR }
        "2" { Analyze-CSR }
        "3" { Analyze-Certificate }
        "4" { Generate-SelfSignedCertificate }
        "5" { Convert-CertificateFormat }
        "6" { Check-CertificateExpiration }
        "7" { Verify-CertificateChain }
        "8" { Extract-PublicKey }
        "9" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "9") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "9")

This Certificate Request Toolkit includes:

  1. A menu-driven interface for easy navigation.
  2. Functions for various certificate-related tasks:
    • Generating Certificate Signing Requests (CSRs)
    • Analyzing CSRs
    • Analyzing certificates
    • Generating self-signed certificates
    • Converting certificate formats
    • Checking certificate expiration
    • Verifying certificate chains
    • Extracting public keys from certificates
  3. Support for both OpenSSL (when available) and .NET methods for certain operations.
  4. Comprehensive error handling and user guidance.

Key features:

  • CSR generation with customizable subject, key size, and Subject Alternative Names (SANs)
  • Detailed analysis of CSRs and certificates
  • Self-signed certificate generation for testing purposes
  • Certificate format conversion (requires OpenSSL)
  • Certificate expiration checking
  • Certificate chain verification
  • Public key extraction from certificates (requires OpenSSL)
  • Fallback to .NET methods when OpenSSL is not available for some features

This tool is particularly useful for:

  • System administrators managing SSL/TLS certificates
  • Security professionals working with digital certificates
  • Developers needing to generate CSRs or analyze certificates
  • IT professionals troubleshooting certificate-related issues

To use this script effectively:

  1. Run the script in PowerShell
  2. Ensure OpenSSL is installed and available in the system PATH for full functionality
  3. Use the menu to navigate between different certificate-related tasks
  4. Follow the prompts to provide necessary information for each operation

This comprehensive toolkit provides a wide range of certificate management and analysis capabilities, making it a valuable resource for anyone working with digital certificates in a Windows environment.

Dr. Scripto and the Impenetrable Password Paradox

It was a typical Tuesday at the PowerShell Academy, or so everyone thought. Dr. Scripto, the renowned PowerShell wizard, was sipping his morning coffee (from his favorite cmdlet-decorated mug, of course) when the Dean burst into his office.

“Dr. Scripto!” the Dean exclaimed, out of breath. “We have a crisis! The academy’s password policy has been deemed too weak by the auditors. We need a new, foolproof password generation system, and we need it yesterday!”

Dr. Scripto’s eyes twinkled with excitement. “Fear not, dear Dean! This sounds like a job for PowerShell!”

He swiftly turned to his computer, his fingers flying across the keyboard as he began to craft a password generator script.

function New-SecurePassword {
    param (
        [int]$Length = 16,
        [int]$SpecialChars = 2,
        [int]$Numbers = 2
    )

    $CharSet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    $SpecialCharSet = '!@#$%^&*()_+-=[]{}|;:,.<>?'
    $NumberSet = '0123456789'

    $Password = New-Object char[] $Length
    $Random = New-Object System.Random

    # Fill with random letters
    for ($i = 0; $i -lt $Length; $i++) {
        $Password[$i] = $CharSet[$Random.Next(0, $CharSet.Length)]
    }

    # Ensure special characters
    for ($i = 0; $i -lt $SpecialChars; $i++) {
        $Index = $Random.Next(0, $Length)
        $Password[$Index] = $SpecialCharSet[$Random.Next(0, $SpecialCharSet.Length)]
    }

    # Ensure numbers
    for ($i = 0; $i -lt $Numbers; $i++) {
        $Index = $Random.Next(0, $Length)
        $Password[$Index] = $NumberSet[$Random.Next(0, $NumberSet.Length)]
    }

    return -join $Password
}

# Generate a password
$NewPassword = New-SecurePassword
Write-Host "Generated Password: $NewPassword"

“Eureka!” Dr. Scripto exclaimed. “This script will generate passwords so secure, even I might have trouble remembering them!”

The Dean looked puzzled. “But Dr. Scripto, if they’re hard to remember, won’t our staff just write them down on sticky notes?”

Dr. Scripto stroked his PowerShell-blue beard thoughtfully. “Ah, the eternal password paradox. Secure yet memorable… This calls for phase two of our project!”

He quickly added to his script:

function New-MemorablePassword {
    $Adjectives = @('Happy', 'Sleepy', 'Grumpy', 'Bashful', 'Sneezy', 'Dopey', 'Doc')
    $Nouns = @('Dwarf', 'Princess', 'Apple', 'Forest', 'Castle', 'Mirror', 'Witch')
    $SpecialChars = @('!', '@', '#', '$', '%', '^', '&')
    $Numbers = 1..99

    $Password = (Get-Random -InputObject $Adjectives) +
                (Get-Random -InputObject $Nouns) +
                (Get-Random -InputObject $SpecialChars) +
                (Get-Random -InputObject $Numbers).ToString("00")

    return $Password
}

# Generate a memorable password
$MemorablePassword = New-MemorablePassword
Write-Host "Generated Memorable Password: $MemorablePassword"

“Voila!” Dr. Scripto announced. “Now we have two options: ultra-secure for our critical systems, and memorable yet still quite secure for our staff!”

The Dean was impressed. “Dr. Scripto, you’ve done it again! But… how do we decide which password type to use for each system?”

Dr. Scripto’s eyes gleamed with the promise of a new challenge. “Ah, my dear Dean, that sounds like a perfect topic for next week’s advanced PowerShell decision-making algorithms class!”

As the Dean left, already feeling more secure, Dr. Scripto turned to his computer with a grin. “Now, to create a PowerShell script that generates PowerShell scripts that generate passwords… The possibilities are endless!”

And so, another day at the PowerShell Academy came to a close, with Dr. Scripto already dreaming of his next scripting adventure. For in the world of PowerShell, every problem was just another opportunity for an elegant solution… and perhaps a touch of scripting magic.

Advanced Password Generator Tool

<#
.SYNOPSIS
Advanced Password Generator Tool

.DESCRIPTION
This script provides an advanced password generation tool with features including
customizable generation criteria, password strength evaluation, password history,
and additional utility functions.

.NOTES
File Name      : AdvancedPasswordGenerator.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\AdvancedPasswordGenerator.ps1
#>

# Import required modules
Add-Type -AssemblyName System.Web

# Global variables
$script:passwordHistory = @()
$script:maxHistorySize = 10
$script:passwordFilePath = Join-Path -Path $env:USERPROFILE -ChildPath "Documents\PasswordGeneratorHistory.txt"

function Show-Menu {
    Clear-Host
    Write-Host "=== Advanced Password Generator Tool ===" -ForegroundColor Cyan
    Write-Host "1. Generate Password"
    Write-Host "2. Set Password Options"
    Write-Host "3. View Current Settings"
    Write-Host "4. View Password History"
    Write-Host "5. Evaluate Password Strength"
    Write-Host "6. Generate Passphrase"
    Write-Host "7. Export Password History"
    Write-Host "8. Exit"
}

function Set-PasswordOptions {
    $script:passwordLength = Read-Host "Enter password length (default is 16)"
    if ([string]::IsNullOrWhiteSpace($script:passwordLength)) { $script:passwordLength = 16 }
    
    $script:includeUppercase = Read-Host "Include uppercase letters? (Y/N, default is Y)"
    $script:includeUppercase = ($script:includeUppercase -ne 'N')
    
    $script:includeLowercase = Read-Host "Include lowercase letters? (Y/N, default is Y)"
    $script:includeLowercase = ($script:includeLowercase -ne 'N')
    
    $script:includeNumbers = Read-Host "Include numbers? (Y/N, default is Y)"
    $script:includeNumbers = ($script:includeNumbers -ne 'N')
    
    $script:includeSpecialChars = Read-Host "Include special characters? (Y/N, default is Y)"
    $script:includeSpecialChars = ($script:includeSpecialChars -ne 'N')

    $script:excludeSimilarChars = Read-Host "Exclude similar characters (O, 0, I, l, 1)? (Y/N, default is N)"
    $script:excludeSimilarChars = ($script:excludeSimilarChars -eq 'Y')
    
    Write-Host "Password options updated." -ForegroundColor Green
}

function View-CurrentSettings {
    Write-Host "`nCurrent Password Generation Settings:" -ForegroundColor Yellow
    Write-Host "Password Length: $script:passwordLength"
    Write-Host "Include Uppercase: $($script:includeUppercase ? 'Yes' : 'No')"
    Write-Host "Include Lowercase: $($script:includeLowercase ? 'Yes' : 'No')"
    Write-Host "Include Numbers: $($script:includeNumbers ? 'Yes' : 'No')"
    Write-Host "Include Special Characters: $($script:includeSpecialChars ? 'Yes' : 'No')"
    Write-Host "Exclude Similar Characters: $($script:excludeSimilarChars ? 'Yes' : 'No')"
    Write-Host ""
}

function Generate-Password {
    $characterSet = @()
    if ($script:includeUppercase) { $characterSet += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.ToCharArray() }
    if ($script:includeLowercase) { $characterSet += 'abcdefghijklmnopqrstuvwxyz'.ToCharArray() }
    if ($script:includeNumbers) { $characterSet += '0123456789'.ToCharArray() }
    if ($script:includeSpecialChars) { $characterSet += '!@#$%^&*()_+-=[]{}|;:,.<>?'.ToCharArray() }

    if ($script:excludeSimilarChars) {
        $characterSet = $characterSet | Where-Object { $_ -notin 'O', '0', 'I', 'l', '1' }
    }

    if ($characterSet.Count -eq 0) {
        Write-Host "Error: No character set selected. Please update your settings." -ForegroundColor Red
        return
    }

    $password = -join (1..$script:passwordLength | ForEach-Object { Get-Random -InputObject $characterSet })
    
    Write-Host "`nGenerated Password:" -ForegroundColor Green
    Write-Host $password
    Write-Host ""

    $strength = Evaluate-PasswordStrength -Password $password
    Write-Host "Password Strength: $strength" -ForegroundColor Yellow

    Add-ToPasswordHistory -Password $password

    $saveToFile = Read-Host "Do you want to save this password to a file? (Y/N)"
    if ($saveToFile -eq 'Y') {
        $fileName = "GeneratedPassword_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt"
        $filePath = Join-Path -Path $env:USERPROFILE -ChildPath "Desktop\$fileName"
        $password | Out-File -FilePath $filePath
        Write-Host "Password saved to: $filePath" -ForegroundColor Green
    }
}

function Evaluate-PasswordStrength {
    param ([string]$Password)

    $score = 0

    if ($Password.Length -ge 12) { $score += 2 }
    elseif ($Password.Length -ge 8) { $score += 1 }

    if ($Password -cmatch "[A-Z]") { $score += 1 }
    if ($Password -cmatch "[a-z]") { $score += 1 }
    if ($Password -match "\d") { $score += 1 }
    if ($Password -match "[^a-zA-Z0-9]") { $score += 1 }

    switch ($score) {
        0 { return "Very Weak" }
        1 { return "Weak" }
        2 { return "Moderate" }
        3 { return "Strong" }
        4 { return "Very Strong" }
        default { return "Extremely Strong" }
    }
}

function Add-ToPasswordHistory {
    param ([string]$Password)

    $script:passwordHistory = @($Password) + $script:passwordHistory
    if ($script:passwordHistory.Count -gt $script:maxHistorySize) {
        $script:passwordHistory = $script:passwordHistory[0..($script:maxHistorySize - 1)]
    }
}

function View-PasswordHistory {
    if ($script:passwordHistory.Count -eq 0) {
        Write-Host "Password history is empty." -ForegroundColor Yellow
        return
    }

    Write-Host "`nPassword History (Most Recent First):" -ForegroundColor Yellow
    for ($i = 0; $i -lt $script:passwordHistory.Count; $i++) {
        Write-Host "$($i + 1). $($script:passwordHistory[$i])"
    }
    Write-Host ""
}

function Generate-Passphrase {
    $wordList = @("apple", "banana", "cherry", "date", "elderberry", "fig", "grape", "honeydew", "kiwi", "lemon", "mango", "nectarine", "orange", "papaya", "quince", "raspberry", "strawberry", "tangerine", "ugli", "vanilla", "watermelon", "xigua", "yuzu", "zucchini")
    $passphrase = -join ((1..4 | ForEach-Object { Get-Random -InputObject $wordList }) -join "-")
    
    Write-Host "`nGenerated Passphrase:" -ForegroundColor Green
    Write-Host $passphrase
    Write-Host ""

    Add-ToPasswordHistory -Password $passphrase
}

function Export-PasswordHistory {
    if ($script:passwordHistory.Count -eq 0) {
        Write-Host "Password history is empty. Nothing to export." -ForegroundColor Yellow
        return
    }

    $script:passwordHistory | Out-File -FilePath $script:passwordFilePath
    Write-Host "Password history exported to: $script:passwordFilePath" -ForegroundColor Green
}

# Initialize default settings
$script:passwordLength = 16
$script:includeUppercase = $true
$script:includeLowercase = $true
$script:includeNumbers = $true
$script:includeSpecialChars = $true
$script:excludeSimilarChars = $false

# Main program loop
do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-8)"

    switch ($choice) {
        "1" { Generate-Password }
        "2" { Set-PasswordOptions }
        "3" { View-CurrentSettings }
        "4" { View-PasswordHistory }
        "5" { 
            $pwToEvaluate = Read-Host "Enter a password to evaluate"
            $strength = Evaluate-PasswordStrength -Password $pwToEvaluate
            Write-Host "Password Strength: $strength" -ForegroundColor Yellow
        }
        "6" { Generate-Passphrase }
        "7" { Export-PasswordHistory }
        "8" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "8") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "8")

This Advanced Password Generator Tool includes:

  1. A menu-driven interface with expanded options.
  2. Enhanced functions for password generation and management:
    • Customizable password generation with more options
    • Password strength evaluation
    • Password history tracking
    • Passphrase generation
    • Export functionality for password history
  3. Additional features:
    • Option to exclude similar characters (O, 0, I, l, 1) for improved readability
    • Passphrase generation using a predefined word list
    • Ability to evaluate the strength of any given password
    • Password history with a configurable size limit
    • Export functionality to save password history to a file

Key features:

  • More flexible and customizable password generation
  • Built-in password strength evaluation
  • Password history tracking for easy reference
  • Passphrase generation as an alternative to traditional passwords
  • Ability to export password history for backup or review
  • Enhanced user interface with more options and information

This tool is particularly useful for:

  • System administrators requiring advanced password management capabilities
  • Security professionals needing to generate and evaluate various types of passwords
  • Users who want a comprehensive tool for creating and managing strong passwords
  • IT professionals implementing or reviewing password policies

To use this script effectively:

  1. Run the script in PowerShell
  2. Use the expanded menu to access various features
  3. Customize password generation settings as needed
  4. Generate passwords or passphrases
  5. Use the password strength evaluation feature to check existing passwords
  6. Manage and export password history as required

This advanced script provides a more comprehensive approach to password generation and management, offering additional features for security-conscious users and professionals.

Password Generator Tool

<#
.SYNOPSIS
Password Generator Tool

.DESCRIPTION
This script generates secure passwords based on user-defined criteria including
length, and the inclusion of uppercase letters, lowercase letters, numbers, and special characters.

.NOTES
File Name      : PasswordGenerator.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V3 or later
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\PasswordGenerator.ps1
#>

function Show-Menu {
    Clear-Host
    Write-Host "=== Password Generator Tool ===" -ForegroundColor Cyan
    Write-Host "1. Generate Password"
    Write-Host "2. Set Password Options"
    Write-Host "3. View Current Settings"
    Write-Host "4. Exit"
}

function Set-PasswordOptions {
    $script:passwordLength = Read-Host "Enter password length (default is 12)"
    if ([string]::IsNullOrWhiteSpace($script:passwordLength)) { $script:passwordLength = 12 }
    
    $script:includeUppercase = Read-Host "Include uppercase letters? (Y/N, default is Y)"
    $script:includeUppercase = ($script:includeUppercase -ne 'N')
    
    $script:includeLowercase = Read-Host "Include lowercase letters? (Y/N, default is Y)"
    $script:includeLowercase = ($script:includeLowercase -ne 'N')
    
    $script:includeNumbers = Read-Host "Include numbers? (Y/N, default is Y)"
    $script:includeNumbers = ($script:includeNumbers -ne 'N')
    
    $script:includeSpecialChars = Read-Host "Include special characters? (Y/N, default is Y)"
    $script:includeSpecialChars = ($script:includeSpecialChars -ne 'N')
    
    Write-Host "Password options updated." -ForegroundColor Green
}

function View-CurrentSettings {
    Write-Host "`nCurrent Password Generation Settings:" -ForegroundColor Yellow
    Write-Host "Password Length: $script:passwordLength"
    Write-Host "Include Uppercase: $($script:includeUppercase ? 'Yes' : 'No')"
    Write-Host "Include Lowercase: $($script:includeLowercase ? 'Yes' : 'No')"
    Write-Host "Include Numbers: $($script:includeNumbers ? 'Yes' : 'No')"
    Write-Host "Include Special Characters: $($script:includeSpecialChars ? 'Yes' : 'No')"
    Write-Host ""
}

function Generate-Password {
    $characterSet = @()
    if ($script:includeUppercase) { $characterSet += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.ToCharArray() }
    if ($script:includeLowercase) { $characterSet += 'abcdefghijklmnopqrstuvwxyz'.ToCharArray() }
    if ($script:includeNumbers) { $characterSet += '0123456789'.ToCharArray() }
    if ($script:includeSpecialChars) { $characterSet += '!@#$%^&*()_+-=[]{}|;:,.<>?'.ToCharArray() }

    if ($characterSet.Count -eq 0) {
        Write-Host "Error: No character set selected. Please update your settings." -ForegroundColor Red
        return
    }

    $password = -join (1..$script:passwordLength | ForEach-Object { Get-Random -InputObject $characterSet })
    
    Write-Host "`nGenerated Password:" -ForegroundColor Green
    Write-Host $password
    Write-Host ""

    $saveToFile = Read-Host "Do you want to save this password to a file? (Y/N)"
    if ($saveToFile -eq 'Y') {
        $fileName = "GeneratedPassword_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt"
        $filePath = Join-Path -Path $env:USERPROFILE -ChildPath "Desktop\$fileName"
        $password | Out-File -FilePath $filePath
        Write-Host "Password saved to: $filePath" -ForegroundColor Green
    }
}

# Initialize default settings
$script:passwordLength = 12
$script:includeUppercase = $true
$script:includeLowercase = $true
$script:includeNumbers = $true
$script:includeSpecialChars = $true

# Main program loop
do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-4)"

    switch ($choice) {
        "1" { Generate-Password }
        "2" { Set-PasswordOptions }
        "3" { View-CurrentSettings }
        "4" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "4") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "4")

This Password Generator Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to:
    • Generate passwords based on user-defined criteria
    • Set password generation options
    • View current password generation settings
  3. Customizable options for password generation:
    • Password length
    • Inclusion of uppercase letters
    • Inclusion of lowercase letters
    • Inclusion of numbers
    • Inclusion of special characters
  4. Option to save generated passwords to a file on the desktop.
  5. Default settings for quick password generation.

Key features:

  • Flexible password generation based on user preferences
  • Ability to customize password complexity
  • Option to save generated passwords securely
  • User-friendly interface for easy operation
  • Viewing current settings for transparency

This tool is particularly useful for:

  • System administrators needing to generate secure passwords
  • Users who want to create strong, customized passwords
  • IT professionals managing password policies
  • Anyone needing quick access to randomly generated passwords

To use this script effectively:

  1. Run the script in PowerShell
  2. Use the menu to navigate between generating passwords, setting options, and viewing current settings
  3. Customize the password generation criteria as needed
  4. Generate passwords and optionally save them to files

This script provides a simple yet effective way to generate secure passwords with customizable criteria, helping to enhance security practices in various IT and personal scenarios.

Windows Firewall Analyzer Tool – Target Computer

<#
.SYNOPSIS
Windows Firewall Analyzer Tool

.DESCRIPTION
This script analyzes and audits Windows Firewall configurations, rules, and profiles
on local or remote Windows systems. It provides insights into firewall settings,
rule configurations, and potential security issues.

.NOTES
File Name      : WindowsFirewallAnalyzer.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later, administrator rights
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\WindowsFirewallAnalyzer.ps1
#>

# Import required module
Import-Module NetSecurity

# Global variables
$global:reportPath = "$env:USERPROFILE\Desktop\Windows_Firewall_Analysis_Report_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"
$global:targetComputer = $env:COMPUTERNAME

<#
.SYNOPSIS
Displays the main menu of the tool.
#>
function Show-Menu {
    Clear-Host
    Write-Host "=== Windows Firewall Analyzer Tool ===" -ForegroundColor Cyan
    Write-Host "Current Target: $global:targetComputer"
    Write-Host "1. Set Target Computer"
    Write-Host "2. Analyze Firewall Profiles"
    Write-Host "3. Review Inbound Rules"
    Write-Host "4. Review Outbound Rules"
    Write-Host "5. Check for Potentially Risky Rules"
    Write-Host "6. Analyze Rule Applications"
    Write-Host "7. Check Firewall Logging Settings"
    Write-Host "8. Generate Comprehensive HTML Report"
    Write-Host "9. Exit"
}

<#
.SYNOPSIS
Sets the target computer for analysis.
#>
function Set-TargetComputer {
    $computer = Read-Host "Enter the name of the target computer (or press Enter for local machine)"
    if ([string]::IsNullOrWhiteSpace($computer)) {
        $global:targetComputer = $env:COMPUTERNAME
    } else {
        $global:targetComputer = $computer
    }
    Write-Host "Target computer set to: $global:targetComputer" -ForegroundColor Green
}

<#
.SYNOPSIS
Analyzes Firewall Profiles.

.OUTPUTS
Array of PSObjects containing firewall profile details.
#>
function Analyze-FirewallProfiles {
    Write-Host "`nAnalyzing Firewall Profiles..." -ForegroundColor Yellow
    $profiles = Get-NetFirewallProfile -CimSession $global:targetComputer
    $results = @()
    foreach ($profile in $profiles) {
        $results += [PSCustomObject]@{
            Name = $profile.Name
            Enabled = $profile.Enabled
            DefaultInboundAction = $profile.DefaultInboundAction
            DefaultOutboundAction = $profile.DefaultOutboundAction
            AllowInboundRules = $profile.AllowInboundRules
            AllowLocalFirewallRules = $profile.AllowLocalFirewallRules
            AllowLocalIPsecRules = $profile.AllowLocalIPsecRules
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Reviews Inbound Rules.

.OUTPUTS
Array of PSObjects containing inbound rule details.
#>
function Review-InboundRules {
    Write-Host "`nReviewing Inbound Rules..." -ForegroundColor Yellow
    $rules = Get-NetFirewallRule -CimSession $global:targetComputer | Where-Object { $_.Direction -eq "Inbound" }
    $results = @()
    foreach ($rule in $rules) {
        $results += [PSCustomObject]@{
            Name = $rule.Name
            DisplayName = $rule.DisplayName
            Enabled = $rule.Enabled
            Action = $rule.Action
            Profile = $rule.Profile
            Protocol = (Get-NetFirewallPortFilter -AssociatedNetFirewallRule $rule).Protocol
            LocalPort = (Get-NetFirewallPortFilter -AssociatedNetFirewallRule $rule).LocalPort -join ", "
            RemoteAddress = (Get-NetFirewallAddressFilter -AssociatedNetFirewallRule $rule).RemoteAddress -join ", "
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Reviews Outbound Rules.

.OUTPUTS
Array of PSObjects containing outbound rule details.
#>
function Review-OutboundRules {
    Write-Host "`nReviewing Outbound Rules..." -ForegroundColor Yellow
    $rules = Get-NetFirewallRule -CimSession $global:targetComputer | Where-Object { $_.Direction -eq "Outbound" }
    $results = @()
    foreach ($rule in $rules) {
        $results += [PSCustomObject]@{
            Name = $rule.Name
            DisplayName = $rule.DisplayName
            Enabled = $rule.Enabled
            Action = $rule.Action
            Profile = $rule.Profile
            Protocol = (Get-NetFirewallPortFilter -AssociatedNetFirewallRule $rule).Protocol
            RemotePort = (Get-NetFirewallPortFilter -AssociatedNetFirewallRule $rule).RemotePort -join ", "
            RemoteAddress = (Get-NetFirewallAddressFilter -AssociatedNetFirewallRule $rule).RemoteAddress -join ", "
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Checks for Potentially Risky Rules.

.OUTPUTS
Array of PSObjects containing potentially risky rule details.
#>
function Check-PotentiallyRiskyRules {
    Write-Host "`nChecking for Potentially Risky Rules..." -ForegroundColor Yellow
    $rules = Get-NetFirewallRule -CimSession $global:targetComputer
    $results = @()
    foreach ($rule in $rules) {
        $isRisky = $false
        $riskFactors = @()

        if ($rule.Enabled -and $rule.Action -eq "Allow" -and $rule.Direction -eq "Inbound") {
            $portFilter = Get-NetFirewallPortFilter -AssociatedNetFirewallRule $rule
            $addressFilter = Get-NetFirewallAddressFilter -AssociatedNetFirewallRule $rule

            if ($portFilter.LocalPort -contains "Any" -or $portFilter.LocalPort -contains "*") {
                $isRisky = $true
                $riskFactors += "Allows any port"
            }
            if ($addressFilter.RemoteAddress -contains "Any" -or $addressFilter.RemoteAddress -contains "*") {
                $isRisky = $true
                $riskFactors += "Allows any remote address"
            }
        }

        if ($isRisky) {
            $results += [PSCustomObject]@{
                Name = $rule.Name
                DisplayName = $rule.DisplayName
                Direction = $rule.Direction
                Action = $rule.Action
                RiskFactors = $riskFactors -join ", "
            }
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Analyzes Rule Applications.

.OUTPUTS
Array of PSObjects containing rule application details.
#>
function Analyze-RuleApplications {
    Write-Host "`nAnalyzing Rule Applications..." -ForegroundColor Yellow
    $rules = Get-NetFirewallRule -CimSession $global:targetComputer
    $results = @()
    foreach ($rule in $rules) {
        $appFilter = Get-NetFirewallApplicationFilter -AssociatedNetFirewallRule $rule
        if ($appFilter.Program -and $appFilter.Program -ne "Any") {
            $results += [PSCustomObject]@{
                RuleName = $rule.Name
                DisplayName = $rule.DisplayName
                Application = $appFilter.Program
                Enabled = $rule.Enabled
                Direction = $rule.Direction
                Action = $rule.Action
            }
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Checks Firewall Logging Settings.

.OUTPUTS
PSObject containing firewall logging settings.
#>
function Check-FirewallLoggingSettings {
    Write-Host "`nChecking Firewall Logging Settings..." -ForegroundColor Yellow
    $profiles = Get-NetFirewallProfile -CimSession $global:targetComputer
    $results = @()
    foreach ($profile in $profiles) {
        $results += [PSCustomObject]@{
            ProfileName = $profile.Name
            LogAllowed = $profile.LogAllowed
            LogBlocked = $profile.LogBlocked
            LogIgnored = $profile.LogIgnored
            LogFileName = $profile.LogFileName
            LogMaxSizeKilobytes = $profile.LogMaxSizeKilobytes
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Generates a comprehensive HTML report of all analyses.

.PARAMETER AllResults
Hashtable containing all analysis results.

.OUTPUTS
Saves an HTML report to the desktop.
#>
function Generate-HTMLReport {
    param([hashtable]$AllResults)

    Write-Host "`nGenerating Comprehensive HTML Report..." -ForegroundColor Yellow
    $reportContent = @"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Windows Firewall Analysis Report</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 1200px; margin: 0 auto; padding: 20px; }
        h1, h2, h3 { color: #0078D4; }
        table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
    </style>
</head>
<body>
    <h1>Windows Firewall Analysis Report</h1>
    <p>Generated on: $(Get-Date)</p>
    <p>Target Computer: $global:targetComputer</p>

    <h2>Firewall Profiles</h2>
    $($AllResults.FirewallProfiles | ConvertTo-Html -Fragment)

    <h2>Inbound Rules</h2>
    $($AllResults.InboundRules | ConvertTo-Html -Fragment)

    <h2>Outbound Rules</h2>
    $($AllResults.OutboundRules | ConvertTo-Html -Fragment)

    <h2>Potentially Risky Rules</h2>
    $($AllResults.RiskyRules | ConvertTo-Html -Fragment)

    <h2>Rule Applications</h2>
    $($AllResults.RuleApplications | ConvertTo-Html -Fragment)

    <h2>Firewall Logging Settings</h2>
    $($AllResults.LoggingSettings | ConvertTo-Html -Fragment)
</body>
</html>
"@

    $reportContent | Out-File -FilePath $global:reportPath
    Write-Host "Report generated and saved to: $global:reportPath" -ForegroundColor Green
}

# Main program loop
$allResults = @{}

do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-9)"

    switch ($choice) {
        "1" { Set-TargetComputer }
        "2" { $allResults.FirewallProfiles = Analyze-FirewallProfiles }
        "3" { $allResults.InboundRules = Review-InboundRules }
        "4" { $allResults.OutboundRules = Review-OutboundRules }
        "5" { $allResults.RiskyRules = Check-PotentiallyRiskyRules }
        "6" { $allResults.RuleApplications = Analyze-RuleApplications }
        "7" { $allResults.LoggingSettings = Check-FirewallLoggingSettings }
        "8" { Generate-HTMLReport -AllResults $allResults }
        "9" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "9") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "9")

This Windows Firewall Analyzer Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to analyze various aspects of Windows Firewall:
    • Analysis of Firewall Profiles
    • Review of Inbound Rules
    • Review of Outbound Rules
    • Check for Potentially Risky Rules
    • Analysis of Rule Applications
    • Check Firewall Logging Settings
  3. Ability to set a target computer for remote analysis.
  4. Comprehensive error handling for each analysis function.
  5. A function to generate an HTML report of all collected data.

Key features:

  • Detailed analysis of Windows Firewall profiles and their settings
  • Comprehensive review of inbound and outbound firewall rules
  • Identification of potentially risky firewall rules
  • Analysis of application-specific firewall rules
  • Review of firewall logging settings
  • Support for local and remote firewall analysis
  • Comprehensive HTML report generation

This tool is particularly useful for:

  • System administrators managing Windows Firewall configurations
  • Security professionals auditing firewall settings
  • IT professionals troubleshooting firewall-related issues
  • Network administrators reviewing firewall rules across multiple systems

To use this script effectively:

  1. Run PowerShell as an administrator
  2. Ensure you have the necessary permissions to access firewall settings (local or remote)
  3. Have the NetSecurity module available (typically included in Windows by default)

This script provides a comprehensive overview of Windows Firewall configurations, making it easier to audit and maintain firewall settings, identify potential security issues, and ensure the proper configuration of firewall rules across Windows systems.

Microsoft 365 Security Check Tool

<#
.SYNOPSIS
Microsoft 365 Security Check Tool

.DESCRIPTION
This script analyzes and audits various security aspects of a Microsoft 365 environment,
providing insights into user accounts, licenses, Exchange Online, SharePoint Online,
Teams, and other security settings.

.NOTES
File Name      : M365SecurityCheckTool.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later, Microsoft 365 PowerShell modules, and appropriate admin permissions
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\M365SecurityCheckTool.ps1
#>

# Check and install required modules
$requiredModules = @("MSOnline", "ExchangeOnlineManagement", "Microsoft.Online.SharePoint.PowerShell", "MicrosoftTeams", "AzureAD")
foreach ($module in $requiredModules) {
    if (!(Get-Module -ListAvailable -Name $module)) {
        Write-Host "Installing $module module..." -ForegroundColor Yellow
        Install-Module -Name $module -Force -AllowClobber
    }
}

# Import required modules
Import-Module MSOnline
Import-Module ExchangeOnlineManagement
Import-Module Microsoft.Online.SharePoint.PowerShell
Import-Module MicrosoftTeams
Import-Module AzureAD

# Global variables
$global:reportPath = "$env:USERPROFILE\Desktop\M365_Security_Analysis_Report_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"

<#
.SYNOPSIS
Displays the main menu of the tool.
#>
function Show-Menu {
    Clear-Host
    Write-Host "=== Microsoft 365 Security Check Tool ===" -ForegroundColor Cyan
    Write-Host "1. Analyze User Accounts and MFA Status"
    Write-Host "2. Check License Assignments"
    Write-Host "3. Analyze Exchange Online Security Settings"
    Write-Host "4. Check SharePoint Online and OneDrive Security"
    Write-Host "5. Analyze Teams Security Settings"
    Write-Host "6. Check Azure AD Security Configuration"
    Write-Host "7. Analyze Conditional Access Policies"
    Write-Host "8. Check Data Loss Prevention Policies"
    Write-Host "9. Analyze Audit Log Settings"
    Write-Host "10. Generate Comprehensive HTML Report"
    Write-Host "11. Exit"
}

<#
.SYNOPSIS
Connects to Microsoft 365 services.
#>
function Connect-M365Services {
    Write-Host "Connecting to Microsoft 365 services..." -ForegroundColor Yellow
    Connect-MsolService
    Connect-ExchangeOnline
    $orgName = (Get-MsolCompanyInformation).DisplayName
    $adminSiteUrl = "https://$($orgName.Replace(' ', ''))-admin.sharepoint.com"
    Connect-SPOService -Url $adminSiteUrl
    Connect-MicrosoftTeams
    Connect-AzureAD
}

<#
.SYNOPSIS
Analyzes user accounts and MFA status.

.OUTPUTS
Array of PSObjects containing user account and MFA details.
#>
function Analyze-UserAccountsAndMFA {
    Write-Host "`nAnalyzing User Accounts and MFA Status..." -ForegroundColor Yellow
    $users = Get-MsolUser -All
    $results = @()
    foreach ($user in $users) {
        $mfaStatus = if ($user.StrongAuthenticationRequirements.State) { $user.StrongAuthenticationRequirements.State } else { "Disabled" }
        $results += [PSCustomObject]@{
            UserPrincipalName = $user.UserPrincipalName
            DisplayName = $user.DisplayName
            IsLicensed = $user.IsLicensed
            MFAStatus = $mfaStatus
            LastPasswordChangeTimestamp = $user.LastPasswordChangeTimestamp
            BlockCredential = $user.BlockCredential
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Checks license assignments.

.OUTPUTS
Array of PSObjects containing license assignment details.
#>
function Check-LicenseAssignments {
    Write-Host "`nChecking License Assignments..." -ForegroundColor Yellow
    $licenses = Get-MsolAccountSku
    $results = @()
    foreach ($license in $licenses) {
        $results += [PSCustomObject]@{
            AccountSkuId = $license.AccountSkuId
            ActiveUnits = $license.ActiveUnits
            ConsumedUnits = $license.ConsumedUnits
            AvailableUnits = ($license.ActiveUnits - $license.ConsumedUnits)
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Analyzes Exchange Online security settings.

.OUTPUTS
PSObject containing Exchange Online security settings.
#>
function Analyze-ExchangeOnlineSecurity {
    Write-Host "`nAnalyzing Exchange Online Security Settings..." -ForegroundColor Yellow
    $transportRules = Get-TransportRule
    $malwareFilterPolicy = Get-MalwareFilterPolicy
    $result = [PSCustomObject]@{
        TransportRuleCount = $transportRules.Count
        MalwareFilterEnabled = $malwareFilterPolicy.Enabled
        AuditLogEnabled = (Get-AdminAuditLogConfig).UnifiedAuditLogIngestionEnabled
        DefaultAuthenticationPolicy = (Get-OrganizationConfig).DefaultAuthenticationPolicy
    }
    $result | Format-List
    return $result
}

<#
.SYNOPSIS
Checks SharePoint Online and OneDrive security.

.OUTPUTS
PSObject containing SharePoint Online and OneDrive security settings.
#>
function Check-SharePointOneDriveSecurity {
    Write-Host "`nChecking SharePoint Online and OneDrive Security..." -ForegroundColor Yellow
    $sharingCapability = Get-SPOTenant | Select-Object SharingCapability
    $conditionalAccessPolicy = Get-SPOTenant | Select-Object ConditionalAccessPolicy
    $result = [PSCustomObject]@{
        SharingCapability = $sharingCapability.SharingCapability
        ConditionalAccessPolicy = $conditionalAccessPolicy.ConditionalAccessPolicy
        OneDriveForBusinessSharingCapability = (Get-SPOTenant).OneDriveForBusinessSharingCapability
    }
    $result | Format-List
    return $result
}

<#
.SYNOPSIS
Analyzes Teams security settings.

.OUTPUTS
PSObject containing Teams security settings.
#>
function Analyze-TeamsSecuritySettings {
    Write-Host "`nAnalyzing Teams Security Settings..." -ForegroundColor Yellow
    $teamsSettings = Get-CsTeamsClientConfiguration
    $result = [PSCustomObject]@{
        AllowEmailIntoChannel = $teamsSettings.AllowEmailIntoChannel
        AllowDropBox = $teamsSettings.AllowDropBox
        AllowBox = $teamsSettings.AllowBox
        AllowGoogleDrive = $teamsSettings.AllowGoogleDrive
        AllowShareFile = $teamsSettings.AllowShareFile
    }
    $result | Format-List
    return $result
}

<#
.SYNOPSIS
Checks Azure AD security configuration.

.OUTPUTS
PSObject containing Azure AD security configuration.
#>
function Check-AzureADSecurityConfig {
    Write-Host "`nChecking Azure AD Security Configuration..." -ForegroundColor Yellow
    $passwordPolicy = Get-MsolPasswordPolicy -TenantId (Get-MsolCompanyInformation).ObjectId
    $ssoState = (Get-MsolCompanyInformation).SelfServePasswordResetEnabled
    $result = [PSCustomObject]@{
        PasswordValidityPeriod = $passwordPolicy.ValidityPeriod
        MinimumPasswordLength = $passwordPolicy.MinimumPasswordLength
        PasswordComplexityEnabled = $passwordPolicy.StrongPasswordRequired
        SelfServicePasswordResetEnabled = $ssoState
    }
    $result | Format-List
    return $result
}

<#
.SYNOPSIS
Analyzes Conditional Access Policies.

.OUTPUTS
Array of PSObjects containing Conditional Access Policy details.
#>
function Analyze-ConditionalAccessPolicies {
    Write-Host "`nAnalyzing Conditional Access Policies..." -ForegroundColor Yellow
    $policies = Get-AzureADMSConditionalAccessPolicy
    $results = @()
    foreach ($policy in $policies) {
        $results += [PSCustomObject]@{
            DisplayName = $policy.DisplayName
            State = $policy.State
            IncludeUsers = $policy.Conditions.Users.IncludeUsers -join ", "
            ExcludeUsers = $policy.Conditions.Users.ExcludeUsers -join ", "
            IncludeApplications = $policy.Conditions.Applications.IncludeApplications -join ", "
            GrantControls = $policy.GrantControls.BuiltInControls -join ", "
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Checks Data Loss Prevention Policies.

.OUTPUTS
Array of PSObjects containing DLP Policy details.
#>
function Check-DLPPolicies {
    Write-Host "`nChecking Data Loss Prevention Policies..." -ForegroundColor Yellow
    $policies = Get-DlpCompliancePolicy
    $results = @()
    foreach ($policy in $policies) {
        $results += [PSCustomObject]@{
            Name = $policy.Name
            Mode = $policy.Mode
            Enabled = $policy.Enabled
            ExchangeLocation = $policy.ExchangeLocation -join ", "
            SharePointLocation = $policy.SharePointLocation -join ", "
            OneDriveLocation = $policy.OneDriveLocation -join ", "
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Analyzes Audit Log Settings.

.OUTPUTS
PSObject containing Audit Log settings.
#>
function Analyze-AuditLogSettings {
    Write-Host "`nAnalyzing Audit Log Settings..." -ForegroundColor Yellow
    $auditConfig = Get-AdminAuditLogConfig
    $result = [PSCustomObject]@{
        UnifiedAuditLogIngestionEnabled = $auditConfig.UnifiedAuditLogIngestionEnabled
        OperationsToLog = $auditConfig.AdminAuditLogCmdlets -join ", "
    }
    $result | Format-List
    return $result
}

<#
.SYNOPSIS
Generates a comprehensive HTML report of all analyses.

.PARAMETER AllResults
Hashtable containing all analysis results.

.OUTPUTS
Saves an HTML report to the desktop.
#>
function Generate-HTMLReport {
    param([hashtable]$AllResults)

    Write-Host "`nGenerating Comprehensive HTML Report..." -ForegroundColor Yellow
    $reportContent = @"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Microsoft 365 Security Analysis Report</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 1200px; margin: 0 auto; padding: 20px; }
        h1, h2, h3 { color: #0078D4; }
        table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
        .warning { color: orange; }
        .critical { color: red; }
    </style>
</head>
<body>
    <h1>Microsoft 365 Security Analysis Report</h1>
    <p>Generated on: $(Get-Date)</p>

    <h2>User Accounts and MFA Status</h2>
    $($AllResults.UserAccountsAndMFA | ConvertTo-Html -Fragment)

    <h2>License Assignments</h2>
    $($AllResults.LicenseAssignments | ConvertTo-Html -Fragment)

    <h2>Exchange Online Security Settings</h2>
    $($AllResults.ExchangeOnlineSecurity | ConvertTo-Html -Fragment)

    <h2>SharePoint Online and OneDrive Security</h2>
    $($AllResults.SharePointOneDriveSecurity | ConvertTo-Html -Fragment)

    <h2>Teams Security Settings</h2>
    $($AllResults.TeamsSecuritySettings | ConvertTo-Html -Fragment)

    <h2>Azure AD Security Configuration</h2>
    $($AllResults.AzureADSecurityConfig | ConvertTo-Html -Fragment)

    <h2>Conditional Access Policies</h2>
    $($AllResults.ConditionalAccessPolicies | ConvertTo-Html -Fragment)

    <h2>Data Loss Prevention Policies</h2>
    $($AllResults.DLPPolicies | ConvertTo-Html -Fragment)

    <h2>Audit Log Settings</h2>
    $($AllResults.AuditLogSettings | ConvertTo-Html -Fragment)
</body>
</html>
"@

    $reportContent | Out-File -FilePath $global:reportPath
    Write-Host "Report generated and saved to: $global:reportPath" -ForegroundColor Green
}

# Main program loop
Connect-M365Services
$allResults = @{}

do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-11)"

    switch ($choice) {
        "1" { $allResults.UserAccountsAndMFA = Analyze-UserAccountsAndMFA }
        "2" { $allResults.LicenseAssignments = Check-LicenseAssignments }
        "3" { $allResults.ExchangeOnlineSecurity = Analyze-ExchangeOnlineSecurity }
        "4" { $allResults.SharePointOneDriveSecurity = Check-SharePointOneDriveSecurity }
        "5" { $allResults.TeamsSecuritySettings = Analyze-TeamsSecuritySettings }
        "6" { $allResults.AzureADSecurityConfig = Check-AzureADSecurityConfig }
        "7" { $allResults.ConditionalAccessPolicies = Analyze-ConditionalAccessPolicies }
        "8" { $allResults.DLPPolicies = Check-DLPPolicies }
        "9" { $allResults.AuditLogSettings = Analyze-AuditLogSettings }
        "10" { Generate-HTMLReport -AllResults $allResults }
        "11" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "11") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "11")

# Disconnect from services
Disconnect-ExchangeOnline -Confirm:$false
Disconnect-SPOService
Disconnect-MicrosoftTeams
Disconnect-AzureAD

This Microsoft 365 Security Check Tool includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to analyze various security aspects of Microsoft 365:
    • User account analysis and MFA status
    • License assignment check
    • Exchange Online security settings analysis
    • SharePoint Online and OneDrive security check
    • Teams security settings analysis
    • Azure AD security configuration check
    • Conditional Access Policies analysis
    • Data Loss Prevention Policies check
    • Audit Log settings analysis
  3. Automatic installation of required PowerShell modules.
  4. Connection to necessary Microsoft 365 services.
  5. A function to generate an HTML report of all collected data.

Key features:

  • Comprehensive analysis of user accounts, including MFA status
  • Detailed insights into license assignments and usage
  • Review of Exchange Online, SharePoint Online, and OneDrive security settings
  • Analysis of Teams security configuration
  • Azure AD security settings check
  • Examination of Conditional Access and DLP policies
  • Audit log configuration review
  • HTML report generation for easy sharing and viewing of results

This tool is particularly useful for:

  • Microsoft 365 administrators
  • IT security professionals managing Microsoft 365 environments
  • Compliance officers ensuring adherence to security standards
  • Anyone needing to perform a security audit of their Microsoft 365 environment

To use this script effectively:

  1. Run PowerShell as an administrator
  2. Ensure you have the necessary permissions to access Microsoft 365 services (Global Administrator or appropriate admin roles)
  3. Have an active internet connection
  4. Review the generated HTML report for a comprehensive overview of your Microsoft 365 environment’s security status

This script provides a comprehensive overview of the security settings in a Microsoft 365 environment, making it easier to identify potential security issues, misconfigurations, or areas that need attention across various Microsoft 365 services.

Dr. Scripto and the Windows Security Conundrum

It was a dark and stormy night at the PowerShell Academy. Dr. Scripto was burning the midnight oil, working on his latest research project: “Harnessing the Power of PowerShell for Advanced Windows Security.” Lightning flashed outside his window, illuminating the room filled with humming servers and blinking LEDs.

Suddenly, an alarm blared through the building. Dr. Scripto’s eyes widened as he saw a red warning message flash across his screen: “SECURITY BREACH DETECTED!”

“Great gates of Redmond!” Dr. Scripto exclaimed, his fingers already flying across the keyboard. “It seems we have an uninvited guest in our systems!”

He quickly opened a PowerShell console and began investigating:

Get-WinEvent -FilterHashtable @{LogName='Security'; ID=4624} -MaxEvents 100 | 
    Where-Object {$_.Properties[8].Value -eq 3} |
    Select-Object TimeCreated, @{N='Username';E={$_.Properties[5].Value}}

“Aha!” he muttered, stroking his PowerShell-blue beard. “Multiple failed login attempts from an unknown source!”

Just then, his star pupil, Lisa, burst into the room. “Dr. Scripto! I saw the alarm. What’s happening?”

“We’re under attack, my dear,” Dr. Scripto replied calmly. “But fear not, for with PowerShell as our shield, no cyber-villain shall prevail!”

Together, they set to work. Dr. Scripto began crafting a script to strengthen their defenses:

# Enable Windows Firewall
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True

# Enable real-time protection in Windows Defender
Set-MpPreference -DisableRealtimeMonitoring $false

# Ensure PowerShell logging is enabled
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -Name EnableScriptBlockLogging -Value 1

# Check for and install Windows updates
Install-WindowsUpdate -AcceptAll -AutoReboot

As they worked, Dr. Scripto explained each step to Lisa. “Remember, in the world of security, knowledge is power, and PowerShell is our knowledge amplifier!”

Lisa nodded, absorbing every word. She then suggested, “What if we create a script to continuously monitor for suspicious activities?”

“Brilliant idea!” Dr. Scripto beamed. Together, they wrote a monitoring script:

while ($true) {
    Get-WinEvent -FilterHashtable @{LogName='Security'; ID=4625} -MaxEvents 10 |
        Where-Object {$_.TimeCreated -gt (Get-Date).AddMinutes(-5)} |
        ForEach-Object {
            Send-MailMessage -To "security@powershellacademy.com" -From "monitor@powershellacademy.com" -Subject "Failed Login Attempt" -Body "Failed login attempt detected for user $($_.Properties[5].Value) from IP $($_.Properties[19].Value)"
        }
    Start-Sleep -Seconds 300
}

As the script ran, they could see it catching and reporting suspicious activities in real-time. The attack was being thwarted!

Hours passed, and finally, the alarms fell silent. Dr. Scripto and Lisa had successfully defended the Academy’s systems.

“Well done, Lisa!” Dr. Scripto said proudly. “You’ve shown true PowerShell prowess today.”

Lisa beamed with pride. “Thank you, Dr. Scripto. But I couldn’t have done it without your guidance and the power of PowerShell!”

Dr. Scripto chuckled, “Indeed, my dear. Remember, in the realm of Windows security, PowerShell is our greatest ally. It allows us to automate, monitor, and respond with unprecedented speed and precision.”

As the sun began to rise, casting a golden glow over the Academy, Dr. Scripto turned to Lisa with a twinkle in his eye. “Now, how about we turn this adventure into next week’s lesson? ‘Practical PowerShell for Windows Security’ has a nice ring to it, don’t you think?”

Lisa nodded enthusiastically. “I can’t wait!”

And so, another exciting night at the PowerShell Academy came to an end, with Dr. Scripto and his students once again proving that with PowerShell, no security challenge is too great to overcome.

Advanced Security Analyzer Tool for Windows Server

<#
.SYNOPSIS
Advanced Security Analyzer Tool for Windows Server

.DESCRIPTION
This script performs a comprehensive security analysis on a Windows Server,
providing detailed insights into various security aspects and potential vulnerabilities.

.NOTES
File Name      : AdvancedWindowsServerSecurityAnalyzer.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later, administrator rights on a Windows Server
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\AdvancedWindowsServerSecurityAnalyzer.ps1
#>

# Import required modules
Import-Module ActiveDirectory
Import-Module GroupPolicy

# Global variables
$global:reportPath = "$env:USERPROFILE\Desktop\Advanced_WindowsServer_Security_Analysis_Report_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"

<#
.SYNOPSIS
Displays the main menu of the tool.
#>
function Show-Menu {
    Clear-Host
    Write-Host "=== Advanced Windows Server Security Analyzer Tool ===" -ForegroundColor Cyan
    Write-Host "1.  Analyze Windows Updates and Patches"
    Write-Host "2.  Audit User Accounts and Permissions"
    Write-Host "3.  Check Firewall and Network Security"
    Write-Host "4.  Review File System and Share Permissions"
    Write-Host "5.  Analyze Services and Running Processes"
    Write-Host "6.  Check Group Policy Settings"
    Write-Host "7.  Audit Event Logs"
    Write-Host "8.  Analyze Installed Software"
    Write-Host "9.  Check for Common Vulnerabilities"
    Write-Host "10. Review Encryption and Certificate Settings"
    Write-Host "11. Generate Comprehensive HTML Report"
    Write-Host "12. Exit"
}

<#
.SYNOPSIS
Analyzes Windows Updates and Patches.

.OUTPUTS
PSObject containing Windows Updates and Patch status.
#>
function Analyze-WindowsUpdatesAndPatches {
    Write-Host "`nAnalyzing Windows Updates and Patches..." -ForegroundColor Yellow
    $updateSession = New-Object -ComObject Microsoft.Update.Session
    $updateSearcher = $updateSession.CreateUpdateSearcher()
    $pendingUpdates = $updateSearcher.Search("IsInstalled=0")
    $installedUpdates = Get-HotFix | Sort-Object -Property InstalledOn -Descending

    $result = [PSCustomObject]@{
        PendingUpdatesCount = $pendingUpdates.Updates.Count
        LastUpdateDate = $installedUpdates[0].InstalledOn
        CriticalUpdatesCount = ($pendingUpdates.Updates | Where-Object { $_.MsrcSeverity -eq "Critical" }).Count
        RecentlyInstalledUpdates = $installedUpdates | Select-Object -First 5 | ForEach-Object { "$($_.HotFixID) - $($_.InstalledOn)" }
    }

    $result | Format-List
    return $result
}

<#
.SYNOPSIS
Audits User Accounts and Permissions.

.OUTPUTS
Array of PSObjects containing user account and permission details.
#>
function Audit-UserAccountsAndPermissions {
    Write-Host "`nAuditing User Accounts and Permissions..." -ForegroundColor Yellow
    $users = Get-ADUser -Filter * -Properties Enabled, PasswordLastSet, LastLogonDate, PasswordNeverExpires, MemberOf
    $results = @()
    foreach ($user in $users) {
        $adminGroups = $user.MemberOf | Where-Object { $_ -like "*admin*" }
        $results += [PSCustomObject]@{
            Username = $user.SamAccountName
            Enabled = $user.Enabled
            PasswordLastSet = $user.PasswordLastSet
            LastLogon = $user.LastLogonDate
            PasswordNeverExpires = $user.PasswordNeverExpires
            InAdminGroup = if ($adminGroups) { $true } else { $false }
            AdminGroups = $adminGroups -join ", "
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Checks Firewall and Network Security.

.OUTPUTS
PSObject containing firewall and network security details.
#>
function Check-FirewallAndNetworkSecurity {
    Write-Host "`nChecking Firewall and Network Security..." -ForegroundColor Yellow
    $firewallProfiles = Get-NetFirewallProfile
    $openPorts = Get-NetTCPConnection | Where-Object { $_.State -eq 'Listen' }
    
    $result = [PSCustomObject]@{
        DomainProfileEnabled = ($firewallProfiles | Where-Object { $_.Name -eq "Domain" }).Enabled
        PrivateProfileEnabled = ($firewallProfiles | Where-Object { $_.Name -eq "Private" }).Enabled
        PublicProfileEnabled = ($firewallProfiles | Where-Object { $_.Name -eq "Public" }).Enabled
        OpenPorts = $openPorts | Select-Object LocalPort, OwningProcess
        InboundRulesCount = (Get-NetFirewallRule -Direction Inbound).Count
        OutboundRulesCount = (Get-NetFirewallRule -Direction Outbound).Count
    }
    
    $result | Format-List
    return $result
}

<#
.SYNOPSIS
Reviews File System and Share Permissions.

.OUTPUTS
Array of PSObjects containing file system and share permission details.
#>
function Review-FileSystemAndSharePermissions {
    Write-Host "`nReviewing File System and Share Permissions..." -ForegroundColor Yellow
    $shares = Get-SmbShare | Where-Object { $_.Name -notlike "*$" }
    $results = @()
    foreach ($share in $shares) {
        $acl = Get-Acl $share.Path
        $permissions = $acl.Access | ForEach-Object {
            "$($_.IdentityReference) - $($_.FileSystemRights)"
        }
        $results += [PSCustomObject]@{
            ShareName = $share.Name
            Path = $share.Path
            Permissions = $permissions -join "; "
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Analyzes Services and Running Processes.

.OUTPUTS
Array of PSObjects containing service and process details.
#>
function Analyze-ServicesAndProcesses {
    Write-Host "`nAnalyzing Services and Running Processes..." -ForegroundColor Yellow
    $services = Get-WmiObject Win32_Service | Where-Object { $_.StartMode -eq 'Auto' -and $_.State -eq 'Running' }
    $processes = Get-Process | Where-Object { $_.CPU -gt 10 -or $_.WorkingSet -gt 100MB }
    
    $results = @()
    foreach ($service in $services) {
        $results += [PSCustomObject]@{
            Type = "Service"
            Name = $service.Name
            DisplayName = $service.DisplayName
            StartName = $service.StartName
            State = $service.State
        }
    }
    foreach ($process in $processes) {
        $results += [PSCustomObject]@{
            Type = "Process"
            Name = $process.Name
            ID = $process.Id
            CPU = $process.CPU
            Memory = [math]::Round($process.WorkingSet / 1MB, 2)
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Checks Group Policy Settings.

.OUTPUTS
Array of PSObjects containing Group Policy setting details.
#>
function Check-GroupPolicySettings {
    Write-Host "`nChecking Group Policy Settings..." -ForegroundColor Yellow
    $gpos = Get-GPO -All
    $results = @()
    foreach ($gpo in $gpos) {
        $report = Get-GPOReport -Guid $gpo.Id -ReportType XML
        $settingsCount = ([xml]$report).GPO.Computer.ExtensionData.Extension.Policy.Count + 
                         ([xml]$report).GPO.User.ExtensionData.Extension.Policy.Count
        $results += [PSCustomObject]@{
            Name = $gpo.DisplayName
            CreationTime = $gpo.CreationTime
            ModificationTime = $gpo.ModificationTime
            SettingsCount = $settingsCount
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Audits Event Logs.

.OUTPUTS
Array of PSObjects containing event log details.
#>
function Audit-EventLogs {
    Write-Host "`nAuditing Event Logs..." -ForegroundColor Yellow
    $logs = @("System", "Security", "Application")
    $results = @()
    foreach ($log in $logs) {
        $events = Get-EventLog -LogName $log -Newest 100 | Group-Object -Property EntryType
        foreach ($eventType in $events) {
            $results += [PSCustomObject]@{
                LogName = $log
                EventType = $eventType.Name
                Count = $eventType.Count
            }
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Analyzes Installed Software.

.OUTPUTS
Array of PSObjects containing installed software details.
#>
function Analyze-InstalledSoftware {
    Write-Host "`nAnalyzing Installed Software..." -ForegroundColor Yellow
    $software = Get-WmiObject -Class Win32_Product | Select-Object Name, Vendor, Version, InstallDate
    $software | Format-Table -AutoSize
    return $software
}

<#
.SYNOPSIS
Checks for Common Vulnerabilities.

.OUTPUTS
Array of PSObjects containing vulnerability check results.
#>
function Check-CommonVulnerabilities {
    Write-Host "`nChecking for Common Vulnerabilities..." -ForegroundColor Yellow
    $results = @()

    # Check for SMBv1
    $smbv1 = Get-WindowsOptionalFeature -Online -FeatureName SMB1Protocol
    $results += [PSCustomObject]@{
        Check = "SMBv1 Enabled"
        Status = if ($smbv1.State -eq "Enabled") { "Vulnerable" } else { "Secure" }
    }

    # Check for PowerShell v2
    $psv2 = Get-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2
    $results += [PSCustomObject]@{
        Check = "PowerShell v2 Enabled"
        Status = if ($psv2.State -eq "Enabled") { "Vulnerable" } else { "Secure" }
    }

    # Check RDP settings
    $rdpEnabled = (Get-ItemProperty "HKLM:\System\CurrentControlSet\Control\Terminal Server").fDenyTSConnections -eq 0
    $nlaEnabled = (Get-ItemProperty "HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp").UserAuthentication -eq 1
    $results += [PSCustomObject]@{
        Check = "RDP Enabled without NLA"
        Status = if ($rdpEnabled -and -not $nlaEnabled) { "Vulnerable" } else { "Secure" }
    }

    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Reviews Encryption and Certificate Settings.

.OUTPUTS
PSObject containing encryption and certificate details.
#>
function Review-EncryptionAndCertificates {
    Write-Host "`nReviewing Encryption and Certificate Settings..." -ForegroundColor Yellow
    $certs = Get-ChildItem -Path Cert:\LocalMachine\My
    $tlsSettings = Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\*\*' | Where-Object { $_.Enabled -ne $null }

    $result = [PSCustomObject]@{
        CertificateCount = $certs.Count
        ExpiredCertificates = ($certs | Where-Object { $_.NotAfter -lt (Get-Date) }).Count
        TLS10Enabled = ($tlsSettings | Where-Object { $_.PSPath -like "*TLS 1.0*" -and $_.Enabled -eq 1 }) -ne $null
        TLS11Enabled = ($tlsSettings | Where-Object { $_.PSPath -like "*TLS 1.1*" -and $_.Enabled -eq 1 }) -ne $null
        TLS12Enabled = ($tlsSettings | Where-Object { $_.PSPath -like "*TLS 1.2*" -and $_.Enabled -eq 1 }) -ne $null
    }

    $result | Format-List
    return $result
}

<#
.SYNOPSIS
Generates a comprehensive HTML report of all analyses.

.PARAMETER AllResults
Hashtable containing all analysis results.

.OUTPUTS
Saves an HTML report to the desktop.
#>
function Generate-HTMLReport {
    param([hashtable]$AllResults)

    Write-Host "`nGenerating Comprehensive HTML Report..." -ForegroundColor Yellow
    $reportContent = @"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Advanced Windows Server Security Analysis Report</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 1200px; margin: 0 auto; padding: 20px; }
        h1, h2, h3 { color: #0078D4; }
        table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
        .vulnerable { color: red; font-weight: bold; }
        .secure { color: green; }
    </style>
</head>
<body>
    <h1>Advanced Windows Server Security Analysis Report</h1>
    <p>Generated on: $(Get-Date)</p>

    <h2>Windows Updates and Patches</h2>
    $($AllResults.UpdatesAndPatches | ConvertTo-Html -Fragment)

    <h2>User Accounts and Permissions</h2>
    $($AllResults.UserAccounts | ConvertTo-Html -Fragment)

    <h2>Firewall and Network Security</h2>
    $($AllResults.FirewallSecurity | ConvertTo-Html -Fragment)

    <h2>File System and Share Permissions</h2>
    $($AllResults.FileSystemPermissions | ConvertTo-Html -Fragment)

    <h2>Services and Running Processes</h2>
    $($AllResults.ServicesAndProcesses | ConvertTo-Html -Fragment)

    <h2>Group Policy Settings</h2>
    $($AllResults.GroupPolicySettings | ConvertTo-Html -Fragment)

    <h2>Event Logs Summary</h2>
    $($AllResults.EventLogs | ConvertTo-Html -Fragment)

    <h2>Installed Software</h2>
    $($AllResults.InstalledSoftware | ConvertTo-Html -Fragment)

    <h2>Common Vulnerabilities Check</h2>
    $($AllResults.Vulnerabilities | ForEach-Object {
        $_.Status = if ($_.Status -eq "Vulnerable") { '<span class="vulnerable">Vulnerable</span>' } else { '<span class="secure">Secure</span>' }
        $_
    } | ConvertTo-Html -Fragment)

    <h2>Encryption and Certificate Settings</h2>
    $($AllResults.EncryptionSettings | ConvertTo-Html -Fragment)
</body>
</html>
"@

    $reportContent | Out-File -FilePath $global:reportPath
    Write-Host "Report generated and saved to: $global:reportPath" -ForegroundColor Green
}

# Main program loop
$allResults = @{}

do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-12)"

    switch ($choice) {
        "1"  { $allResults.UpdatesAndPatches = Analyze-WindowsUpdatesAndPatches }
        "2"  { $allResults.UserAccounts = Audit-UserAccountsAndPermissions }
        "3"  { $allResults.FirewallSecurity = Check-FirewallAndNetworkSecurity }
        "4"  { $allResults.FileSystemPermissions = Review-FileSystemAndSharePermissions }
        "5"  { $allResults.ServicesAndProcesses = Analyze-ServicesAndProcesses }
        "6"  { $allResults.GroupPolicySettings = Check-GroupPolicySettings }
        "7"  { $allResults.EventLogs = Audit-EventLogs }
        "8"  { $allResults.InstalledSoftware = Analyze-InstalledSoftware }
        "9"  { $allResults.Vulnerabilities = Check-CommonVulnerabilities }
        "10" { $allResults.EncryptionSettings = Review-EncryptionAndCertificates }
        "11" { Generate-HTMLReport -AllResults $allResults }
        "12" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "12") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "12")

This Advanced Security Analyzer Tool for Windows Server includes:

  1. A comprehensive menu-driven interface.
  2. Advanced functions to analyze various security aspects:
    • Detailed Windows Updates and Patch analysis
    • In-depth user account and permission auditing
    • Comprehensive firewall and network security check
    • Detailed file system and share permissions review
    • Analysis of services and running processes
    • Group Policy settings check
    • Event log auditing
    • Installed software analysis
    • Common vulnerabilities check
    • Encryption and certificate settings review
  3. Detailed HTML report generation with color-coded vulnerability indicators.

Key features:

  • Comprehensive analysis of Windows Updates, including pending and critical updates
  • Detailed user account analysis, including admin group memberships
  • In-depth firewall analysis, including open ports and rule counts
  • File system and share permission auditing
  • Service and process analysis with focus on auto-start services and resource-intensive processes
  • Group Policy analysis
  • Event log summary for system, security, and application logs
  • Installed software inventory
  • Checks for common vulnerabilities like SMBv1, PowerShell v2, and insecure RDP settings
  • Review of encryption settings and certificate status

This tool is particularly useful for:

  • System administrators performing thorough security audits
  • IT security professionals conducting in-depth security assessments
  • Compliance officers ensuring adherence to security standards
  • Anyone needing a comprehensive overview of a Windows Server’s security posture

To use this script effectively:

  1. Run PowerShell as an administrator on the Windows Server you want to analyze
  2. Ensure you have the necessary permissions to query system information and Active Directory (if applicable)
  3. Review the generated HTML report for a detailed overview of the server’s security status

This script provides a comprehensive and advanced way to analyze the security of a Windows Server, helping to identify potential security issues, misconfigurations, and vulnerabilities across various aspects of the system.

Simple Security Analyzer Tool for Windows Server

<#
.SYNOPSIS
Simple Security Analyzer Tool for Windows Server

.DESCRIPTION
This script analyzes basic security settings and configurations on a Windows Server,
providing insights into potential security issues and misconfigurations.

.NOTES
File Name      : WindowsServerSecurityAnalyzer.ps1
Author         : [Your Name]
Prerequisite   : PowerShell V5.1 or later, administrator rights on a Windows Server
Version        : 1.0
Date           : [Current Date]

.EXAMPLE
.\WindowsServerSecurityAnalyzer.ps1
#>

# Global variables
$global:reportPath = "$env:USERPROFILE\Desktop\WindowsServer_Security_Analysis_Report_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"

<#
.SYNOPSIS
Displays the main menu of the tool.
#>
function Show-Menu {
    Clear-Host
    Write-Host "=== Windows Server Security Analyzer Tool ===" -ForegroundColor Cyan
    Write-Host "1. Check Windows Updates Status"
    Write-Host "2. Analyze User Accounts"
    Write-Host "3. Check Firewall Status"
    Write-Host "4. Review Shared Folders"
    Write-Host "5. Check Services Running as SYSTEM"
    Write-Host "6. Analyze Password Policy"
    Write-Host "7. Check for Unquoted Service Paths"
    Write-Host "8. Generate Comprehensive HTML Report"
    Write-Host "9. Exit"
}

<#
.SYNOPSIS
Checks Windows Updates status.

.OUTPUTS
PSObject containing Windows Updates status.
#>
function Check-WindowsUpdates {
    Write-Host "`nChecking Windows Updates Status..." -ForegroundColor Yellow
    $updateSession = New-Object -ComObject Microsoft.Update.Session
    $updateSearcher = $updateSession.CreateUpdateSearcher()
    $pendingUpdates = $updateSearcher.Search("IsInstalled=0")

    $result = [PSCustomObject]@{
        PendingUpdatesCount = $pendingUpdates.Updates.Count
        LastUpdateDate = (Get-HotFix | Sort-Object -Property InstalledOn -Descending | Select-Object -First 1).InstalledOn
    }

    $result | Format-List
    return $result
}

<#
.SYNOPSIS
Analyzes user accounts.

.OUTPUTS
Array of PSObjects containing user account details.
#>
function Analyze-UserAccounts {
    Write-Host "`nAnalyzing User Accounts..." -ForegroundColor Yellow
    $users = Get-LocalUser
    $results = @()
    foreach ($user in $users) {
        $results += [PSCustomObject]@{
            Username = $user.Name
            Enabled = $user.Enabled
            PasswordExpires = $user.PasswordExpires
            LastLogon = $user.LastLogon
            PasswordRequired = $user.PasswordRequired
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Checks firewall status.

.OUTPUTS
PSObject containing firewall status.
#>
function Check-FirewallStatus {
    Write-Host "`nChecking Firewall Status..." -ForegroundColor Yellow
    $firewallProfiles = Get-NetFirewallProfile
    $result = [PSCustomObject]@{
        DomainProfile = ($firewallProfiles | Where-Object { $_.Name -eq "Domain" }).Enabled
        PrivateProfile = ($firewallProfiles | Where-Object { $_.Name -eq "Private" }).Enabled
        PublicProfile = ($firewallProfiles | Where-Object { $_.Name -eq "Public" }).Enabled
    }
    $result | Format-List
    return $result
}

<#
.SYNOPSIS
Reviews shared folders.

.OUTPUTS
Array of PSObjects containing shared folder details.
#>
function Review-SharedFolders {
    Write-Host "`nReviewing Shared Folders..." -ForegroundColor Yellow
    $shares = Get-SmbShare | Where-Object { $_.Name -notlike "*$" }
    $results = @()
    foreach ($share in $shares) {
        $results += [PSCustomObject]@{
            Name = $share.Name
            Path = $share.Path
            Description = $share.Description
            AccessBasedEnumerationEnabled = $share.FolderEnumerationMode
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Checks services running as SYSTEM.

.OUTPUTS
Array of PSObjects containing service details.
#>
function Check-SystemServices {
    Write-Host "`nChecking Services Running as SYSTEM..." -ForegroundColor Yellow
    $services = Get-WmiObject Win32_Service | Where-Object { $_.StartName -eq "LocalSystem" }
    $results = @()
    foreach ($service in $services) {
        $results += [PSCustomObject]@{
            Name = $service.Name
            DisplayName = $service.DisplayName
            StartMode = $service.StartMode
            State = $service.State
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Analyzes password policy.

.OUTPUTS
PSObject containing password policy details.
#>
function Analyze-PasswordPolicy {
    Write-Host "`nAnalyzing Password Policy..." -ForegroundColor Yellow
    $policy = Get-LocalSecurityPolicy
    $result = [PSCustomObject]@{
        PasswordHistorySize = $policy.'PasswordHistorySize'
        MaximumPasswordAge = $policy.'MaximumPasswordAge'
        MinimumPasswordAge = $policy.'MinimumPasswordAge'
        MinimumPasswordLength = $policy.'MinimumPasswordLength'
        PasswordComplexity = $policy.'PasswordComplexity'
    }
    $result | Format-List
    return $result
}

<#
.SYNOPSIS
Checks for unquoted service paths.

.OUTPUTS
Array of PSObjects containing services with unquoted paths.
#>
function Check-UnquotedServicePaths {
    Write-Host "`nChecking for Unquoted Service Paths..." -ForegroundColor Yellow
    $services = Get-WmiObject Win32_Service | Where-Object { $_.PathName -notlike '"*"' -and $_.PathName -like '* *' }
    $results = @()
    foreach ($service in $services) {
        $results += [PSCustomObject]@{
            Name = $service.Name
            DisplayName = $service.DisplayName
            PathName = $service.PathName
        }
    }
    $results | Format-Table -AutoSize
    return $results
}

<#
.SYNOPSIS
Generates a comprehensive HTML report of all analyses.

.PARAMETER AllResults
Hashtable containing all analysis results.

.OUTPUTS
Saves an HTML report to the desktop.
#>
function Generate-HTMLReport {
    param([hashtable]$AllResults)

    Write-Host "`nGenerating Comprehensive HTML Report..." -ForegroundColor Yellow
    $reportContent = @"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Windows Server Security Analysis Report</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 1200px; margin: 0 auto; padding: 20px; }
        h1, h2, h3 { color: #0078D4; }
        table { border-collapse: collapse; width: 100%; margin-bottom: 20px; }
        th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
        th { background-color: #f2f2f2; }
    </style>
</head>
<body>
    <h1>Windows Server Security Analysis Report</h1>
    <p>Generated on: $(Get-Date)</p>

    <h2>Windows Updates Status</h2>
    $($AllResults.WindowsUpdates | ConvertTo-Html -Fragment)

    <h2>User Accounts</h2>
    $($AllResults.UserAccounts | ConvertTo-Html -Fragment)

    <h2>Firewall Status</h2>
    $($AllResults.FirewallStatus | ConvertTo-Html -Fragment)

    <h2>Shared Folders</h2>
    $($AllResults.SharedFolders | ConvertTo-Html -Fragment)

    <h2>Services Running as SYSTEM</h2>
    $($AllResults.SystemServices | ConvertTo-Html -Fragment)

    <h2>Password Policy</h2>
    $($AllResults.PasswordPolicy | ConvertTo-Html -Fragment)

    <h2>Unquoted Service Paths</h2>
    $($AllResults.UnquotedServicePaths | ConvertTo-Html -Fragment)
</body>
</html>
"@

    $reportContent | Out-File -FilePath $global:reportPath
    Write-Host "Report generated and saved to: $global:reportPath" -ForegroundColor Green
}

# Main program loop
$allResults = @{}

do {
    Show-Menu
    $choice = Read-Host "`nEnter your choice (1-9)"

    switch ($choice) {
        "1" { $allResults.WindowsUpdates = Check-WindowsUpdates }
        "2" { $allResults.UserAccounts = Analyze-UserAccounts }
        "3" { $allResults.FirewallStatus = Check-FirewallStatus }
        "4" { $allResults.SharedFolders = Review-SharedFolders }
        "5" { $allResults.SystemServices = Check-SystemServices }
        "6" { $allResults.PasswordPolicy = Analyze-PasswordPolicy }
        "7" { $allResults.UnquotedServicePaths = Check-UnquotedServicePaths }
        "8" { Generate-HTMLReport -AllResults $allResults }
        "9" { Write-Host "Exiting program..." -ForegroundColor Yellow; break }
        default { Write-Host "Invalid choice. Please try again." -ForegroundColor Red }
    }

    if ($choice -ne "9") {
        Read-Host "`nPress Enter to continue..."
    }
} while ($choice -ne "9")

This Simple Security Analyzer Tool for Windows Server includes:

  1. A menu-driven interface for easy navigation.
  2. Functions to analyze various security aspects:
    • Windows Updates status
    • User account analysis
    • Firewall status check
    • Shared folder review
    • Services running as SYSTEM
    • Password policy analysis
    • Check for unquoted service paths
  3. HTML report generation for all collected data.

Key features:

  • Quick overview of pending Windows Updates
  • Analysis of local user accounts and their settings
  • Firewall status check for all profiles
  • Review of non-default shared folders
  • Identification of services running with high privileges (SYSTEM)
  • Password policy review
  • Detection of potential vulnerabilities like unquoted service paths
  • Comprehensive HTML report generation

This tool is particularly useful for:

  • System administrators performing quick security checks
  • IT professionals conducting basic security audits
  • Anyone needing to get a quick overview of a Windows Server’s security posture

To use this script effectively:

  1. Run PowerShell as an administrator on the Windows Server you want to analyze
  2. Ensure you have the necessary permissions to query system information
  3. Review the generated HTML report for a comprehensive overview of the server’s security status

This script provides a simple yet effective way to perform basic security checks on a Windows Server, helping to identify potential security issues and misconfigurations quickly.