Gorstaks password rotator

Anonymous
powershell
02/18/2026 10:10 PM
8.5 KB
12
Indexable
#Requires -RunAsAdministrator
<#
.SYNOPSIS
    One-shot install: run once as Administrator, no input. Sets up password rotation
    (random every 10 min after logon, blank again at logoff) and sets current user password to blank.
#>
$ErrorActionPreference = 'Stop'
$TargetDir = 'C:\ProgramData\PasswordRotator'
$OnLogonTaskName = 'PasswordRotator-OnLogon'

# Embedded worker script (runs as SYSTEM from ProgramData; handles Logon / Rotate / Logoff)
$WorkerScript = @'
param([string]$Mode, [string]$Username)
$ErrorActionPreference = 'Stop'
$TargetDir = if ($PSScriptRoot) { $PSScriptRoot } else { 'C:\ProgramData\PasswordRotator' }
$UserFile = Join-Path $TargetDir 'currentuser.txt'

function Get-LoggedInUser {
    $cs = Get-WmiObject -Class Win32_ComputerSystem -ErrorAction SilentlyContinue
    $user = $cs.UserName
    if (-not $user) { return $null }
    if ($user -match '\\') { return $user.Split('\')[-1] }
    return $user
}
function Set-UserPassword {
    param([string]$U, [string]$P)
    if ([string]::IsNullOrWhiteSpace($U)) { return }
    try {
        Set-LocalUser -Name $U -Password (ConvertTo-SecureString -String $P -AsPlainText -Force) -ErrorAction Stop
    } catch {
        try {
            [ADSI]$adsi = "WinNT://$env:COMPUTERNAME/$U,user"
            $adsi.SetPassword($P)
        } catch {
            "$(Get-Date -Format o) Set-UserPassword: $_" | Out-File (Join-Path $TargetDir 'log.txt') -Append
        }
    }
}
function Set-UserPasswordBlank {
    param([string]$N)
    if ([string]::IsNullOrWhiteSpace($N)) { return }
    try {
        [ADSI]$adsi = "WinNT://$env:COMPUTERNAME/$N,user"
        $adsi.SetPassword('')
    } catch {
        try { & net user $N '' } catch { "$(Get-Date -Format o) Blank: $_" | Out-File (Join-Path $TargetDir 'log.txt') -Append }
    }
}
function New-RandomPwd {
    $c = 'abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789!@#$%'
    -join ((1..24) | ForEach-Object { $c[(Get-Random -Maximum $c.Length)] })
}
function Remove-TasksForUser { param([string]$U)
    $s = $U -replace '[^a-zA-Z0-9]', '_'
    @("PasswordRotator-10Min-$s", "PasswordRotator-OnLogoff-$s") | ForEach-Object { Unregister-ScheduledTask -TaskName $_ -Confirm:$false -ErrorAction SilentlyContinue }
}

switch ($Mode) {
    'Logon' {
        $u = Get-LoggedInUser
        if (-not $u) { exit 0 }
        if (-not (Test-Path $TargetDir)) { New-Item -Path $TargetDir -ItemType Directory -Force | Out-Null }
        $u | Set-Content -Path $UserFile -Force
        Remove-TasksForUser -U $u
        $safe = $u -replace '[^a-zA-Z0-9]', '_'
        $worker = Join-Path $TargetDir 'Worker.ps1'
        $principal = New-ScheduledTaskPrincipal -UserId 'SYSTEM' -LogonType ServiceAccount -RunLevel Highest
        $trigger10 = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(10) -RepetitionInterval (New-TimeSpan -Minutes 10) -RepetitionDuration (New-TimeSpan -Days 3650)
        $action10 = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$worker`" -Mode Rotate"
        Register-ScheduledTask -TaskName "PasswordRotator-10Min-$safe" -Action $action10 -Trigger $trigger10 -Principal $principal -Settings (New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable) -Force | Out-Null
        $triggerOff = New-ScheduledTaskTrigger -AtLogOff -User $u
        $actionOff = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$worker`" -Mode Logoff -Username $u"
        Register-ScheduledTask -TaskName "PasswordRotator-OnLogoff-$safe" -Action $actionOff -Trigger $triggerOff -Principal $principal -Settings (New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -StartWhenAvailable) -Force | Out-Null
        Start-Sleep -Seconds 60
        Set-UserPassword -U $u -P (New-RandomPwd)
    }
    'Rotate' {
        if (-not (Test-Path $UserFile)) { exit 0 }
        $u = (Get-Content -Path $UserFile -Raw).Trim()
        if ($u) { Set-UserPassword -U $u -P (New-RandomPwd) }
    }
    'Logoff' {
        if ($Username) {
            Set-UserPasswordBlank -N $Username
            $s = $Username -replace '[^a-zA-Z0-9]', '_'
            Unregister-ScheduledTask -TaskName "PasswordRotator-10Min-$s" -Confirm:$false -ErrorAction SilentlyContinue
            Unregister-ScheduledTask -TaskName "PasswordRotator-OnLogoff-$s" -Confirm:$false -ErrorAction SilentlyContinue
        }
    }
}
'@

# Install: deploy worker, create logon task, set current user password to blank
function Install {
    if (-not (Test-Path $TargetDir)) { New-Item -Path $TargetDir -ItemType Directory -Force | Out-Null }
    $WorkerScript | Set-Content -Path (Join-Path $TargetDir 'Worker.ps1') -Encoding UTF8 -Force
    $workerPath = Join-Path $TargetDir 'Worker.ps1'
    $principal = New-ScheduledTaskPrincipal -UserId 'SYSTEM' -LogonType ServiceAccount -RunLevel Highest
    $trigger = New-ScheduledTaskTrigger -AtLogOn -User 'Everyone'
    $action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$workerPath`" -Mode Logon"
    $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable
    Register-ScheduledTask -TaskName $OnLogonTaskName -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Force | Out-Null
    try {
        $currentUser = (Get-WmiObject -Class Win32_ComputerSystem).UserName
        if ($currentUser -match '\\') { $currentUser = $currentUser.Split('\')[-1] }
        if ($currentUser) {
            [ADSI]$adsi = "WinNT://$env:COMPUTERNAME/$currentUser,user"
            $adsi.SetPassword('')
        }
    } catch { }
}

# Uninstall
function Uninstall {
    Unregister-ScheduledTask -TaskName $OnLogonTaskName -Confirm:$false -ErrorAction SilentlyContinue
    Get-ScheduledTask -TaskPath '\' | Where-Object { $_.TaskName -like 'PasswordRotator-*' } | Unregister-ScheduledTask -Confirm:$false -ErrorAction SilentlyContinue
    if (Test-Path $TargetDir) { Remove-Item -Path $TargetDir -Recurse -Force -ErrorAction SilentlyContinue }
}

$Action = $args[0]
if ($Action -eq 'Uninstall') { Uninstall; exit 0 }
Install
Write-Host 'Done. Password rotator installed; current user password set to blank.'
Editor is loading...
Leave a Comment