Sync all scripts from website downloads — 352 scripts total
Includes updated JS challenge scripts with Claude-User whitelist, same-site referer bypass, Blackbox-Exporter allowed bot, and all new exporters, cheat sheets, and automation scripts.
This commit is contained in:
@@ -0,0 +1,310 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Checks password expiration for both AD and local Windows accounts.
|
||||
.DESCRIPTION
|
||||
Auto-detects whether the current user is a domain or local account,
|
||||
queries the appropriate source for password expiration, and shows
|
||||
a notification if the password expires within the warning threshold.
|
||||
Can be scheduled via Task Scheduler to run at logon or daily.
|
||||
.PARAMETER WarningDays
|
||||
Number of days before expiration to start warning. Default: 14
|
||||
.PARAMETER User
|
||||
Check a specific user instead of the current user.
|
||||
.PARAMETER Quiet
|
||||
Suppress output unless password is within the warning window.
|
||||
.PARAMETER Test
|
||||
Force notification even if expiry is not near.
|
||||
.PARAMETER Help
|
||||
Show usage information.
|
||||
.NOTES
|
||||
Author: Phil Connor <contact@mylinux.work>
|
||||
License: MIT (https://opensource.org/licenses/MIT)
|
||||
Version: 1.02
|
||||
#>
|
||||
|
||||
param(
|
||||
[int]$WarningDays = 14,
|
||||
[string]$User = "",
|
||||
[switch]$Quiet,
|
||||
[switch]$Test,
|
||||
[switch]$InstallScheduledTask,
|
||||
[int]$TaskIntervalMinutes = 60,
|
||||
[Alias("h")]
|
||||
[switch]$Help
|
||||
)
|
||||
|
||||
if ($Help) {
|
||||
Write-Host @"
|
||||
Usage: .\password-expiry-check.ps1 [OPTIONS]
|
||||
|
||||
Check password expiration for domain (AD) and local Windows accounts.
|
||||
Auto-detects account type. Shows desktop popup when expiry is near.
|
||||
|
||||
Options:
|
||||
-WarningDays N Warning threshold in days (default: 14)
|
||||
-User USERNAME Check a specific user (default: current user)
|
||||
-Quiet Suppress output unless password is within warning window
|
||||
-Test Force notification even if expiry is not near
|
||||
-InstallScheduledTask Create a scheduled task for recurring checks
|
||||
-TaskIntervalMinutes N Interval for scheduled task (default: 60)
|
||||
-Help Show this help
|
||||
|
||||
Examples:
|
||||
.\password-expiry-check.ps1 # check current user
|
||||
.\password-expiry-check.ps1 -WarningDays 30 # warn within 30 days
|
||||
.\password-expiry-check.ps1 -User jdoe # check specific user
|
||||
.\password-expiry-check.ps1 -Test # force notification
|
||||
.\password-expiry-check.ps1 -Quiet # silent unless near expiry
|
||||
.\password-expiry-check.ps1 -InstallScheduledTask # create scheduled task
|
||||
"@
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Determine which username to check
|
||||
$CheckUsername = if ($User -ne "") { $User } else { $env:USERNAME }
|
||||
|
||||
if ($InstallScheduledTask) {
|
||||
$taskName = "PasswordExpiryCheck"
|
||||
$existingTask = Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue
|
||||
|
||||
if (-not $existingTask) {
|
||||
$taskAction = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$($MyInvocation.MyCommand.Path)`" -Quiet"
|
||||
|
||||
if (-not $TaskIntervalMinutes -or $TaskIntervalMinutes -le 0) {
|
||||
throw "TaskIntervalMinutes must be a positive integer"
|
||||
}
|
||||
|
||||
$taskTrigger = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(1) -RepetitionInterval (New-TimeSpan -Minutes $TaskIntervalMinutes) -RepetitionDuration (New-TimeSpan -Days 365)
|
||||
$taskPrincipal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
|
||||
|
||||
try {
|
||||
Write-Host "Creating scheduled task: $taskName"
|
||||
Register-ScheduledTask -TaskName $taskName -Action $taskAction -Trigger $taskTrigger -Principal $taskPrincipal -Description "Checks password expiry every $TaskIntervalMinutes minutes"
|
||||
|
||||
$createdTask = Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue
|
||||
if (-not $createdTask) {
|
||||
throw "Failed to verify scheduled task creation"
|
||||
}
|
||||
Write-Host "Successfully created scheduled task: $taskName" -ForegroundColor Green
|
||||
} catch {
|
||||
Write-Error "Failed to create auto-start task: $($_.Exception.Message)"
|
||||
throw
|
||||
}
|
||||
} else {
|
||||
Write-Host "Scheduled task '$taskName' already exists, skipping creation"
|
||||
}
|
||||
}
|
||||
|
||||
function Get-AccountType {
|
||||
$computerSystem = Get-WmiObject Win32_ComputerSystem
|
||||
$isDomainJoined = $computerSystem.PartOfDomain
|
||||
|
||||
if ($isDomainJoined -and ($env:USERDOMAIN -ne $env:COMPUTERNAME)) {
|
||||
return "Domain"
|
||||
}
|
||||
return "Local"
|
||||
}
|
||||
|
||||
function Get-ADPasswordExpiry {
|
||||
param([string]$Username)
|
||||
|
||||
try {
|
||||
# Method 1: net user /domain (works without RSAT)
|
||||
$netUser = net user $Username /domain 2>&1
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
$expiryLine = $netUser | Select-String "Password expires"
|
||||
if ($expiryLine) {
|
||||
$dateStr = ($expiryLine -split "\s{2,}")[1].Trim()
|
||||
if ($dateStr -ne "Never") {
|
||||
return [datetime]::Parse($dateStr)
|
||||
}
|
||||
return "Never"
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Warning "net user /domain method failed: $_"
|
||||
}
|
||||
|
||||
try {
|
||||
# Method 2: ADSI (no RSAT required)
|
||||
$searcher = New-Object DirectoryServices.DirectorySearcher
|
||||
$searcher.Filter = "(&(objectCategory=person)(objectClass=user)(sAMAccountName=$Username))"
|
||||
$searcher.PropertiesToLoad.AddRange(@("pwdLastSet", "msDS-UserPasswordExpiryTimeComputed"))
|
||||
$result = $searcher.FindOne()
|
||||
|
||||
if ($result) {
|
||||
$expiryTicks = $result.Properties["msDS-UserPasswordExpiryTimeComputed"]
|
||||
if ($expiryTicks -and $expiryTicks[0] -gt 0 -and $expiryTicks[0] -lt [long]::MaxValue) {
|
||||
return [datetime]::FromFileTime($expiryTicks[0])
|
||||
}
|
||||
return "Never"
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Warning "ADSI method failed: $_"
|
||||
}
|
||||
|
||||
return $null
|
||||
}
|
||||
|
||||
function Get-LocalPasswordExpiry {
|
||||
param([string]$Username)
|
||||
|
||||
# Method 1: Get-LocalUser (available on Windows 10/Server 2016+)
|
||||
if (Get-Command Get-LocalUser -ErrorAction SilentlyContinue) {
|
||||
try {
|
||||
$localUser = Get-LocalUser -Name $Username -ErrorAction Stop
|
||||
if ($localUser.PasswordExpires) {
|
||||
return $localUser.PasswordExpires
|
||||
}
|
||||
return "Never"
|
||||
}
|
||||
catch {
|
||||
Write-Warning "Get-LocalUser method failed: $_"
|
||||
}
|
||||
}
|
||||
|
||||
# Method 2: net user (fallback)
|
||||
try {
|
||||
$netUser = net user $Username 2>&1
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
$expiryLine = $netUser | Select-String "Password expires"
|
||||
if ($expiryLine) {
|
||||
$dateStr = ($expiryLine -split "\s{2,}")[1].Trim()
|
||||
if ($dateStr -ne "Never") {
|
||||
return [datetime]::Parse($dateStr)
|
||||
}
|
||||
return "Never"
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Warning "net user method failed: $_"
|
||||
}
|
||||
|
||||
return $null
|
||||
}
|
||||
|
||||
function Show-TerminalBanner {
|
||||
param(
|
||||
[string]$Title,
|
||||
[string]$Message
|
||||
)
|
||||
|
||||
# Word-wrap message to fit within the box (max 42 chars per line)
|
||||
$words = $Message -split '\s+'
|
||||
$lines = @()
|
||||
$currentLine = ""
|
||||
foreach ($word in $words) {
|
||||
if ($currentLine.Length -eq 0) {
|
||||
$currentLine = $word
|
||||
} elseif (($currentLine.Length + 1 + $word.Length) -le 42) {
|
||||
$currentLine += " $word"
|
||||
} else {
|
||||
$lines += $currentLine
|
||||
$currentLine = $word
|
||||
}
|
||||
}
|
||||
if ($currentLine.Length -gt 0) { $lines += $currentLine }
|
||||
|
||||
Write-Host ""
|
||||
Write-Host ([char]0x2554 + ([string][char]0x2550 * 46) + [char]0x2557)
|
||||
Write-Host ([char]0x2551 + (" " * 46) + [char]0x2551)
|
||||
Write-Host ([char]0x2551 + " " + $Title.PadRight(42) + " " + [char]0x2551)
|
||||
Write-Host ([char]0x2551 + ([string][char]0x2500 * 46) + [char]0x2551)
|
||||
foreach ($line in $lines) {
|
||||
Write-Host ([char]0x2551 + " " + $line.PadRight(42) + " " + [char]0x2551)
|
||||
}
|
||||
Write-Host ([char]0x2551 + (" " * 46) + [char]0x2551)
|
||||
Write-Host ([char]0x255A + ([string][char]0x2550 * 46) + [char]0x255D)
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
function Show-MessageBoxNotification {
|
||||
param(
|
||||
[string]$Title,
|
||||
[string]$Message
|
||||
)
|
||||
|
||||
# Terminal banner (always shown)
|
||||
Show-TerminalBanner -Title $Title -Message $Message
|
||||
|
||||
# Desktop dialog - requires user to click OK to dismiss
|
||||
try {
|
||||
Add-Type -AssemblyName System.Windows.Forms -ErrorAction Stop
|
||||
[System.Windows.Forms.MessageBox]::Show(
|
||||
$Message,
|
||||
$Title,
|
||||
[System.Windows.Forms.MessageBoxButtons]::OK,
|
||||
[System.Windows.Forms.MessageBoxIcon]::Warning
|
||||
) | Out-Null
|
||||
} catch {
|
||||
# Non-interactive session (Server Core, SSH, etc.) - banner is sufficient
|
||||
}
|
||||
}
|
||||
|
||||
# --- Main ---
|
||||
|
||||
$accountType = Get-AccountType
|
||||
|
||||
if ($accountType -eq "Domain") {
|
||||
$expiryDate = Get-ADPasswordExpiry -Username $CheckUsername
|
||||
}
|
||||
else {
|
||||
$expiryDate = Get-LocalPasswordExpiry -Username $CheckUsername
|
||||
}
|
||||
|
||||
$displayUser = if ($User -ne "") { $User } else { "$env:USERDOMAIN\$env:USERNAME" }
|
||||
|
||||
if ($expiryDate -eq "Never") {
|
||||
if (-not $Quiet) {
|
||||
Write-Host "Account Type: $accountType"
|
||||
Write-Host "User: $displayUser"
|
||||
Write-Host "Password is set to never expire."
|
||||
}
|
||||
if ($Test) {
|
||||
Show-MessageBoxNotification -Title "Password Expiry Test" -Message "Account: $displayUser ($accountType) - password never expires. (-Test mode)"
|
||||
}
|
||||
exit 0
|
||||
}
|
||||
|
||||
if (-not $expiryDate) {
|
||||
if (-not $Quiet) {
|
||||
Write-Host "Account Type: $accountType"
|
||||
Write-Host "User: $displayUser"
|
||||
Write-Host "Could not determine password expiry date."
|
||||
}
|
||||
exit 1
|
||||
}
|
||||
|
||||
$daysRemaining = ($expiryDate - (Get-Date)).Days
|
||||
|
||||
# Quiet mode - exit silently if not near expiry
|
||||
if ($Quiet -and $daysRemaining -gt $WarningDays -and -not $Test) {
|
||||
exit 0
|
||||
}
|
||||
|
||||
Write-Host "Account Type: $accountType"
|
||||
Write-Host "User: $displayUser"
|
||||
Write-Host "Password Expires: $($expiryDate.ToString('yyyy-MM-dd HH:mm'))"
|
||||
Write-Host "Days Remaining: $daysRemaining"
|
||||
|
||||
if ($daysRemaining -le 0) {
|
||||
$title = "PASSWORD EXPIRED"
|
||||
$message = "Your password has EXPIRED as of $($expiryDate.ToString('yyyy-MM-dd')).`nPlease change it immediately (Ctrl+Alt+Del > Change Password)."
|
||||
Show-MessageBoxNotification -Title $title -Message $message
|
||||
}
|
||||
elseif ($daysRemaining -le $WarningDays) {
|
||||
$title = "Password Expiring Soon"
|
||||
$message = "Your password will expire in $daysRemaining day(s) on $($expiryDate.ToString('yyyy-MM-dd')).`nPlease change it soon (Ctrl+Alt+Del > Change Password)."
|
||||
Show-MessageBoxNotification -Title $title -Message $message
|
||||
}
|
||||
elseif ($Test) {
|
||||
$title = "Password Expiry Test"
|
||||
$message = "Your password will expire in $daysRemaining day(s) on $($expiryDate.ToString('yyyy-MM-dd')). (-Test mode)"
|
||||
Show-MessageBoxNotification -Title $title -Message $message
|
||||
}
|
||||
else {
|
||||
Write-Host "Password expiry is more than $WarningDays days away. No notification needed."
|
||||
}
|
||||
Reference in New Issue
Block a user