RunAs-System.ps1
|
<#PSScriptInfo
.VERSION 1.0.0 .GUID f1611271-49f6-4fe9-b037-26a22715196f .AUTHOR Jeff Gilbert .COMPANYNAME Community .COPYRIGHT Community Script .RELEASENOTES 10.23.2026 1.0.0 Initial release #> <# .SYNOPSIS Launches a PowerShell target script as SYSTEM. .DESCRIPTION Downloads PsExec, verifies its Microsoft signature, and launches the target script as SYSTEM. If already running as SYSTEM, runs the target script directly. Unrecognized arguments are passed through to the target. If the supplied script path does not exist, this launcher will also look for scripts that have previously been installed and are available via PowerShell's installed script locations or PATH, such as scripts installed from the PowerShell Gallery or other package managers. .PARAMETER Path Script to launch. If the file is not found locally, the script will attempt to resolve a previously installed copy by name from the PowerShell installed script locations and common script directories. .PARAMETER Args Arguments passed through to the target script. .EXAMPLE & ".\RunAs-System.ps1" example-script.ps1 Runs the adjacent example-script.ps1 as SYSTEM and forwards the output path and event-day options to it. .EXAMPLE & ".\RunAs-System.ps1" -Path C:\Scripts\Target.ps1 -Mode Audit Runs the specified target script as SYSTEM and forwards -Mode Audit. .EXAMPLE & ".\RunAs-System.ps1" -Path C:\Scripts\Target.ps1 -Args @('-Mode', 'Audit', '-OutputPath', 'C:\Support Files') Runs the target script as SYSTEM and forwards multiple arguments, including an output path containing spaces. .NOTES Requires Windows. SYSTEM relaunch requires internet access to live.sysinternals.com and permission to run PsExec and create its service. #> [CmdletBinding()] param ( [Parameter()] [ValidateNotNullOrEmpty()] [string]$Path = (Join-Path -Path $PSScriptRoot -ChildPath 'example-script.ps1'), [Parameter(ValueFromRemainingArguments = $true)] [object[]]$Args ) Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) { $scriptName = Split-Path -Path $Path -Leaf $scriptBaseName = [System.IO.Path]::GetFileNameWithoutExtension($scriptName) $candidatePaths = [System.Collections.Generic.List[string]]::new() $installedCommand = Get-Command -Name $scriptName -CommandType ExternalScript -ErrorAction SilentlyContinue | Select-Object -First 1 if ($installedCommand -and $installedCommand.Path) { $candidatePaths.Add($installedCommand.Path) } try { $installedScripts = Get-InstalledScript -Name $scriptBaseName -ErrorAction SilentlyContinue foreach ($installedScript in $installedScripts) { if ($installedScript.InstalledLocation) { $candidatePaths.Add((Join-Path -Path $installedScript.InstalledLocation -ChildPath $scriptName)) } } } catch { } $scriptDirectories = @( (Join-Path -Path $HOME -ChildPath 'Documents\WindowsPowerShell\Scripts'), (Join-Path -Path $HOME -ChildPath 'Documents\PowerShell\Scripts'), (Join-Path -Path $env:ProgramFiles -ChildPath 'WindowsPowerShell\Scripts'), (Join-Path -Path $env:ProgramFiles -ChildPath 'PowerShell\Scripts') ) foreach ($scriptDirectory in $scriptDirectories) { $candidatePaths.Add((Join-Path -Path $scriptDirectory -ChildPath $scriptName)) } $installedPath = $candidatePaths | Select-Object -Unique | Where-Object { Test-Path -LiteralPath $_ -PathType Leaf } | Select-Object -First 1 if ($installedPath) { $Path = $installedPath } else { throw "Target script was not found: $Path" } } $Path = (Resolve-Path -LiteralPath $Path).ProviderPath $currentIdentity = [System.Security.Principal.WindowsIdentity]::GetCurrent() if ($currentIdentity.IsSystem) { & $Path @Args return } $principal = [System.Security.Principal.WindowsPrincipal]::new($currentIdentity) if (-not $principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)) { throw 'Running the target as SYSTEM requires an elevated PowerShell session. Run PowerShell as administrator and try again.' } Write-Host 'Relaunching target script as SYSTEM...' $psExecDirectory = Join-Path $env:TEMP ('IntuneRemediation-PsExec-' + [guid]::NewGuid()) try { New-Item -Path $psExecDirectory -ItemType Directory | Out-Null $psExecArchive = Join-Path $psExecDirectory 'PsExec.zip' Write-Host 'Downloading PsExec to relaunch the target script as SYSTEM.' Invoke-WebRequest ` -Uri 'https://live.sysinternals.com/Files/PsExec.zip' ` -OutFile $psExecArchive ` -UseBasicParsing Expand-Archive -LiteralPath $psExecArchive -DestinationPath $psExecDirectory $psExecPath = Join-Path $psExecDirectory 'PsExec64.exe' $signature = Get-AuthenticodeSignature -LiteralPath $psExecPath if ($signature.Status -ne 'Valid' -or $signature.SignerCertificate.Subject -notmatch 'O=Microsoft Corporation(?:,|$)') { throw 'PsExec64.exe does not have a valid Microsoft signature.' } $psExecArguments = @( '-accepteula', '-s', '-i', 'powershell.exe', '-NoProfile', '-NoExit', '-File', $Path ) if ($Args) { $psExecArguments += $Args } & $psExecPath @psExecArguments if ($LASTEXITCODE -ne 0) { throw "PsExec or the target script returned exit code $LASTEXITCODE." } } finally { if (Test-Path -LiteralPath $psExecDirectory) { Remove-Item -LiteralPath $psExecDirectory -Recurse -Force -ErrorAction SilentlyContinue } } |