Skip to content

Instantly share code, notes, and snippets.

@pldmgg
Last active November 29, 2018 17:10
Show Gist options
  • Select an option

  • Save pldmgg/efbf250408a783d7f4aad948ebdb8c45 to your computer and use it in GitHub Desktop.

Select an option

Save pldmgg/efbf250408a783d7f4aad948ebdb8c45 to your computer and use it in GitHub Desktop.
Circumvent Double-Hop Issue via self-deleting Remote Schedule Task
Install-Module EncryptDecrypt
Import-Module EncryptDecrypt
# New Encrypted File
$DomainAdminAcct = "zero\zeroadmin"
$PwdSS = Read-Host -Prompt "Enter the password for $DomainAdminAcct" -AsSecureString
$PwdPT = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($PwdSS))
$NewPwdFileResult = New-EncryptedFile -SourceType String -ContentToEncrypt $PwdPT -FileToOutput "C:\Secrets\EncryptedPwd.txt"
$PfxFileItem = Get-Item $($NewPwdFileResult | Where-Object {$_.AllFileOutputs -match "\.pfx"})
$EncryptedPwdFileItem = Get-Item $($NewPwdFileResult | Where-Object {$_.AllFileOutputs -match "\.rsaencrypted"})
$EncryptedPwdFileBytes = [System.IO.File]::ReadAllBytes($EncryptedPwdFileItem.FullName)
$PfxFileBytes = [System.IO.File]::ReadAllBytes($PfxFileItem.FullName)
$RemoteScriptsDirPath = "C:\Scripts\powershell"
$EncryptedPwdFileDestination = "$RemoteScriptsDirPath\$($EncryptedPwdFileItem.Name)"
$PfxFileDestination = "$RemoteScriptsDirPath\$($PfXFileItem.Name)"
$InstallationLogPath = "$RemoteScriptsDirPath\ProgramInstall$(Get-Date -Format MMddyy_hhmmss).log"
$ComputersToUpdate = Get-ADComputer -SearchBase "OU=Workstations,DC=domain,DC=COM" -Filter *| %{$_.DNSHostName}
$EncrypDecryptModuleFunctions = $(Get-Module EncryptDecrypt).Invoke({$FunctionsForSBUse})
Invoke-Command -ComputerName $ComputersToUpdate -ArgumentList @($PfxFileBytes,$EncryptedPwdFileBytes) -ScriptBlock {
[System.IO.File]::WriteAllBytes($using:PfxFileDestination, $args[0])
[System.IO.File]::WriteAllBytes($using:EncryptedPwdFileDestination, $args[1])
try {
# Load the EncryptDecrypt Module remotely
$using:EncrypDecryptModuleFunctions | Where-Object {$_ -ne $null} | foreach {Invoke-Expression $_ -ErrorAction SilentlyContinue}
# Decrypt the password for $using:DomainAdminAcct
$DecryptionResult = Get-DecryptedContent -SourceType String -ContentToDecrypt $(Get-Content $using:EncryptedPwdFileDestination) -PathToPfxFile $using:PfxFileDestination -NoFileOutput
$PlainTextPwd = $DecryptionResult.DecryptedContent
# Create a Scheduled Task to run your myscript.ps1 from your share
$SchTaskScriptPath = "$using:RemoteScriptsDirPath\SchTaskScriptToInstallProgram.ps1"
$ExecutionScript = @(
"Start-Transcript -Path '$using:InstallationLogPath' -Append"
# NOTE: You could just add the content of myscript.ps1 here directly as an array of strings instead of executing from the file share
'& \\domain.com\dfsshare\share\myscript.ps1'
'Stop-Transcript'
'# Optionally delete this script file after it is finished running'
'Remove-Item -LiteralPath $MyInvocation.MyCommand.Path -Force'
)
Set-Content -Path $SchTaskScriptPath -Value $ExecutionScript
$Trigger = New-ScheduledTaskTrigger -Once -At $(Get-Date).AddSeconds(10)
# Put a time limit on how long it should take to install/uninstall
$TimeLimitInMinutes = 15
$Trigger.EndBoundary = $(Get-Date).AddMinutes($TimeLimitInMinutes).ToString('s')
$TaskName = "InstallProgram"
# IMPORTANT NOTE: The double quotes around the -File value are MANDATORY. They CANNOT be single quotes or without quote or the Scheduled Task will error out!
$null = Register-ScheduledTask -Force -TaskName $TaskName -User $using:DomainAdminAcct -Password $PlainTextPwd -Action $(
New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -NoLogo -NonInteractive -ExecutionPolicy Bypass -File `"$SchTaskScriptPath`""
) -Trigger $Trigger -Settings $(New-ScheduledTaskSettingsSet -DeleteExpiredTaskAfter 00:00:01)
Start-Sleep -Seconds 15
if ($(Get-ScheduledTask -TaskName $TaskName).State -eq "Ready") {
Start-ScheduledTask -TaskName $TaskName
}
# Wait $TimeLimitInMinutes + 1 minutes...
$Counter = 0
while ($(Get-ScheduledTask -TaskName $TaskName).State -ne 'Ready' -and $Counter -le $($TimeLimitInMinutes+1)) {
$PercentComplete = [Math]::Round(($Counter/60)*100)
Write-Progress -Activity "Running Scheduled Task '$TaskName'" -Status "$PercentComplete% Complete:" -PercentComplete $PercentComplete
Start-Sleep -Seconds 60
$Counter++
}
if ($(Get-ScheduledTask -TaskName $TaskName).State -ne 'Ready') {
Write-Warning "The Scheduled Task $TaskName has been running for over $TimeLimitInMinutes and has not finished! Stopping and removing..."
Stop-ScheduledTask -TaskName $TaskName
}
# Remove the Scheduled Task
$null = Unregister-ScheduledTask -TaskName $TaskName -Confirm:$False
# Remove the $using:PfxFileDestination and $using:EncryptedPwdFileDestination
Remove-Item $using:PfxFileDestination -Force
Remove-Item $using:EncryptedPwdFileDestination -Force
}
catch {
# Remove the $using:PfxFileDestination and $using:EncryptedPwdFileDestination
Remove-Item $using:PfxFileDestination -Force
Remove-Item $using:EncryptedPwdFileDestination -Force
Write-Error $_
return
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment