$null = New-Module { . "$PSScriptRoot/Constants.ps1"; . "$PSScriptRoot/Registry.ps1"; . "$PSScriptRoot/../Types/OneShotTask.ps1"; . "$PSScriptRoot/../../lib/Settings.ps1"; $oneShotTaskName = "PortValhalla OneShot"; $logName = "Application"; $oneShotTrigger = 1337; $taskOption = "OneShotTask"; $getErrorPath = { Join-Path (Get-ArtifactRoot) "error.txt"; }; $getUserName = { "$(Get-SetupUser)OneShot"; }; $taskSetter = { param([Nullable[OneShotTask]] $Task) Set-SetupOption $taskOption ([string]$Task); }; <# .SYNOPSIS Gets the current OneShot task. #> function Get-OneShotTask { $task = Get-SetupOption $taskOption; if ($task) { return [OneShotTask]$task; } else { return $null; } } <# .SYNOPSIS Registers a task for listening to OneShot invocations. #> function Enable-OneShotListener { $tempTask = "PortValhalla Temp"; $user = & $getUserName; $password = [string]([guid]::NewGuid()); $adminGroup = @{ SID = [SecurityIdentifier]::new([WellKnownSidType]::BuiltinAdministratorsSid, $null); }; $null = New-LocalUser -Name $user -Password (ConvertTo-SecureString -AsPlainText $password); Add-LocalGroupMember -Member $user @adminGroup; $logPath = Join-Path (Get-ArtifactRoot) "OneShotTask.log"; $path = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList"; $null = New-Item -Force -ErrorAction SilentlyContinue $path; Set-ItemProperty $path -Name $user -Value 0; $action = New-ScheduledTaskAction -Execute "pwsh" -Argument "-Command & { $([string](Get-StartupCommand)) } 2>&1 | Tee-Object -FilePath $(ConvertTo-Injection $logPath)"; schtasks /Create /SC ONEVENT /EC $logName /MO "*[System[Provider[@Name='$logName'] and EventID=$($oneShotTrigger)]]" /TR cmd.exe /TN $tempTask; $trigger = (Get-ScheduledTask $tempTask).Triggers; $null = Register-ScheduledTask -Force $oneShotTaskName -Action $action -Trigger $trigger -RunLevel Highest -User $user -Password $password; $null = Unregister-ScheduledTask -Confirm:$false $tempTask; } <# .SYNOPSIS Removes the OneShot task. #> function Disable-OneShotListener { Unregister-ScheduledTask -Confirm:$false $oneShotTaskName; $user = Get-LocalUser (& $getUserName); [string] $sid = $user.SID; Remove-LocalUser $user; Get-CimInstance Win32_UserProfile | Where-Object { $_.SID -eq $sid } | Remove-CimInstance; } <# .SYNOPSIS Invokes a one-shot task. .PARAMETER Task The task to run. #> function Invoke-OneShot { param( [OneShotTask] $Task ) $errorPath = & $getErrorPath; & $taskSetter $Task; & { $identifier = "EventLog$oneShotTrigger"; $log = [System.Diagnostics.EventLog]::new($logName); $log.EnableRaisingEvents = $true; $null = Register-ObjectEvent -InputObject $log -EventName EntryWritten -Action { $entry = $Event.SourceEventArgs.Entry; $trigger = $Event.MessageData.Trigger; $identifier = $Event.MessageData.Identifier; if ($entry.EventID -eq $trigger) { $null = New-Event -SourceIdentifier $identifier; } } ` -MessageData @{ Trigger = $oneShotTrigger; Identifier = $identifier; }; Write-EventLog -LogName $logName -Source $logName -EventId $oneShotTrigger -Message "Starting OneShot task ``$(Get-OneShotTask)``…"; for ($i = 0; $i -lt 2; $i++) { Remove-Event -EventIdentifier (Wait-Event -SourceIdentifier $identifier).EventIdentifier; } }; if (Test-Path $errorPath) { $errorMessage = Get-Content $errorPath; Remove-Item $errorPath; if ($errorMessage) { Write-Error $errorMessage; } } } <# .SYNOPSIS Executes the specified action and notifies the OneShot task executor. #> function Start-OneShot { try { Write-Host "Running OneShot task ``$(Get-OneShotTask)``"; switch (Get-OneShotTask) { ([OneShotTask]::InitializeMSAccount) { Initialize-UserCreation; } ([OneShotTask]::DisableUAC) { Disable-UAC; Register-Setup; } } } catch { $errorPath = & $getErrorPath; Set-Content -Path $errorPath -Value $Error; Set-UserPermissions $errorPath; } finally { & $taskSetter $null; Write-EventLog -LogName $logName -Source $logName -EventId $oneShotTrigger -Message "The OneShot task ``$(Get-OneShotTask)`` finished."; } } }