commit 7700e3a14940b5fae78ab5c6a31322e7902d0e8a Author: Kyle Date: Thu Apr 10 14:26:15 2025 +0000 Upload files to "/" diff --git a/WindowsHealthAudit.ps1 b/WindowsHealthAudit.ps1 new file mode 100644 index 0000000..aae9096 --- /dev/null +++ b/WindowsHealthAudit.ps1 @@ -0,0 +1,195 @@ +<# +.SYNOPSIS + Windows Device Health Audit with Auto-Elevation +.DESCRIPTION + Performs comprehensive system checks with automatic admin elevation when needed. + Logs to: C:\Logs\DeviceAudit\AUDIT_[HOSTNAME]_[DATE].log +.NOTES + Version: 1.2 + Author: Your Name +.EXAMPLE + # Basic check (non-admin): + .\WindowsHealthAudit.ps1 +.EXAMPLE + # Full check (auto-elevates to admin if needed): + .\WindowsHealthAudit.ps1 -Full +#> + +param( + [switch]$Full = $false +) + +#region Initial Setup +# ------------------ +$logDir = "C:\Logs\DeviceAudit" +$logFile = "$logDir\AUDIT_$($env:COMPUTERNAME)_$(Get-Date -Format 'ddMMyyyy').log" + +# Create log directory if missing +if (-not (Test-Path $logDir)) { + New-Item -Path $logDir -ItemType Directory -Force | Out-Null +} + +# Clear previous log +if (Test-Path $logFile) { + Clear-Content $logFile +} +#endregion + +#region Logging Function +# --------------------- +function Write-Log { + param ( + [string]$Message, + [string]$Level = "INFO" + ) + $timestamp = Get-Date -Format "dd-MM-yyyy HH:mm:ss" + $logEntry = "$timestamp $Level`: $Message" + Write-Output $logEntry + $logEntry | Out-File -FilePath $logFile -Append -Encoding UTF8 +} +#endregion + +#region Self-Elevation +# ------------------- +$isAdmin = [bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).Groups -match 'S-1-5-32-544') + +if ($Full -and (-not $isAdmin)) { + Write-Host "Re-launching as administrator..." -ForegroundColor Yellow + try { + $scriptPath = $MyInvocation.MyCommand.Path + Start-Process pwsh -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -Full" -Verb RunAs -WindowStyle Hidden + exit + } catch { + Write-Host "Failed to elevate! Running in basic mode." -ForegroundColor Red + $Full = $false + } +} +#endregion + +#region Main Audit +# --------------- +Write-Log "=== WINDOWS DEVICE HEALTH AUDIT ===" +Write-Log "Host: $($env:COMPUTERNAME)" +Write-Log "User: $($env:USERNAME)" +Write-Log "Mode: $(if ($Full) {'FULL (Admin)'} else {'BASIC (Non-Admin)'})" +Write-Log "Date: $(Get-Date -Format 'dd-MM-yyyy HH:mm:ss')" +Write-Log "" + +# 1. System Information +Write-Log "=== SYSTEM INFORMATION ===" +$os = Get-CimInstance Win32_OperatingSystem +$computer = Get-CimInstance Win32_ComputerSystem +$uptime = (Get-Date) - $os.LastBootUpTime + +Write-Log "OS: $($os.Caption) (Build: $($os.BuildNumber))" +Write-Log "Uptime: $($uptime.Days)d $($uptime.Hours)h $($uptime.Minutes)m" +Write-Log "Manufacturer: $($computer.Manufacturer)" +Write-Log "Model: $($computer.Model)" +Write-Log "RAM: $([math]::Round($computer.TotalPhysicalMemory / 1GB, 2)) GB" +Write-Log "" + +# 2. Performance Metrics +Write-Log "=== PERFORMANCE ===" +$cpuLoad = (Get-CimInstance Win32_Processor | Measure-Object -Property LoadPercentage -Average).Average +$memory = Get-CimInstance Win32_OperatingSystem +$usedMem = [math]::Round(($memory.TotalVisibleMemorySize - $memory.FreePhysicalMemory) / 1MB, 2) +$totalMem = [math]::Round($memory.TotalVisibleMemorySize / 1MB, 2) + +Write-Log "CPU Load: $cpuLoad%" +Write-Log "Memory Usage: $usedMem/$totalMem GB ($([math]::Round(($usedMem/$totalMem)*100))% used)" +Write-Log "" + +# 3. Disk Information +Write-Log "=== DISK STORAGE ===" +Get-CimInstance Win32_LogicalDisk -Filter "DriveType = 3" | ForEach-Object { + $freeGB = [math]::Round($_.FreeSpace / 1GB, 2) + $totalGB = [math]::Round($_.Size / 1GB, 2) + $pctUsed = [math]::Round(($totalGB - $freeGB) / $totalGB * 100, 2) + + if ($pctUsed -gt 90) { + Write-Log "WARNING: $($_.DeviceID) low space: $freeGB GB free ($pctUsed% used)" -Level "WARNING" + } else { + Write-Log "$($_.DeviceID): $freeGB GB free of $totalGB GB ($pctUsed% used)" + } +} +Write-Log "" + +# 4. Admin-Only Checks +if ($Full) { + Write-Log "=== ADMIN CHECKS ===" + + # Disk Health (SMART) + try { + $disks = Get-PhysicalDisk | Select-Object FriendlyName, HealthStatus, OperationalStatus + $disks | ForEach-Object { + if ($_.HealthStatus -ne "Healthy") { + Write-Log "Disk health alert: $($_.FriendlyName) is $($_.HealthStatus)" -Level "ERROR" + } else { + Write-Log "Disk health: $($_.FriendlyName) is Healthy" + } + } + } catch { + Write-Log "WARNING: Could not retrieve disk health data" -Level "WARNING" + } + Write-Log "" + + # BitLocker Status + if (Get-Command -Name Get-BitLockerVolume -ErrorAction SilentlyContinue) { + $bitlocker = Get-BitLockerVolume | Where-Object { $_.VolumeType -eq "OperatingSystem" } + if ($bitlocker.ProtectionStatus -eq "On") { + Write-Log "BitLocker: Enabled ($($bitlocker.EncryptionPercentage)% encrypted)" + } else { + Write-Log "WARNING: BitLocker is not enabled on OS drive" -Level "WARNING" + } + } + Write-Log "" +} +#endregion + +#region Common Checks +# ------------------ +# 5. Windows Updates +Write-Log "=== UPDATES ===" +$lastUpdate = Get-HotFix | Sort-Object InstalledOn -Descending | Select-Object -First 1 +Write-Log "Last Update: $($lastUpdate.HotFixID) on $($lastUpdate.InstalledOn)" +Write-Log "" + +# 6. Security Status +Write-Log "=== SECURITY ===" +$defender = Get-MpComputerStatus +if ($defender.AntivirusEnabled) { + Write-Log "Windows Defender: Active" +} else { + Write-Log "ERROR: Windows Defender is disabled" -Level "ERROR" +} +Write-Log "" + +# 7. Event Log Errors +Write-Log "=== CRITICAL EVENTS (24h) ===" +$criticalEvents = Get-WinEvent -FilterHashtable @{ + LogName = 'System','Application' + Level = 1,2 + StartTime = (Get-Date).AddDays(-1) +} -MaxEvents 5 -ErrorAction SilentlyContinue + +if ($criticalEvents) { + $criticalEvents | ForEach-Object { + Write-Log "Event $($_.Id) [$($_.ProviderName)]: $($_.Message)" -Level "ERROR" + } +} else { + Write-Log "No critical events found" +} +#endregion + +#region Completion +# --------------- +Write-Log "" +Write-Log "=== AUDIT COMPLETE ===" +Write-Log "Mode: $(if ($Full) {'FULL (Admin)'} else {'BASIC (Non-Admin)'})" +Write-Log "Log saved to: $logFile" + +# Open log file if running interactively +if ($Host.Name -match "ConsoleHost") { + Invoke-Item $logFile +} +#endregion \ No newline at end of file