Last active
May 3, 2023 20:12
-
-
Save jcefoli/816fac3234531f842217dd292a5188ce to your computer and use it in GitHub Desktop.
Script that creates a scheduled task to keep your RDP session alive to work around nonsensical GPOs that inhibit productivity
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Keeps you productive by spoofing activity to prevent GPO idle timeouts, RDP disconnects, sleep, etc. | |
.Description | |
This script creates a Scheduled Task that runs at login which uses Kernel SetThreadExecutionState to prevent GPOs | |
from disconnecting your RDP session. Will also prevent sleeping/screensavers/display timeouts | |
See the example below for a one liner that will download and execute this script directly from GitHub! | |
ASSUMPTIONS AND WARNINGS: | |
============================== | |
- This will most likely be frowned upon by your security team. Please do not break any rules/compliance | |
- I am not responsible for any security issues that arise from misuse of this script (session hijacking, etc). Always log off when idle | |
- If run on a laptop/desktop, it will use more energy and prevent screen timeouts / sleep! Be environmentally conscious! | |
.NOTES | |
Version: 1.0.0 | |
Author: jcefoli | |
Creation Date: 1/5/2021 | |
.EXAMPLE | |
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://gist.githubusercontent.com/jcefoli/816fac3234531f842217dd292a5188ce/raw/9a1368cbdeea3cbb2f6a554216b335b6c9dd62a0/keepaliveScheduler.ps1')) | |
#> | |
$dateStamp = Get-Date -Format "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffffff" | |
$currentUserSID = ([System.Security.Principal.WindowsIdentity]::GetCurrent()).User.Value | |
$schTaskXML = @" | |
<?xml version="1.0" encoding="UTF-16"?> | |
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"> | |
<RegistrationInfo> | |
<Date>CHANGEME</Date> | |
<Author>CHANGEME</Author> | |
<URI>\Keepalive</URI> | |
</RegistrationInfo> | |
<Triggers> | |
<LogonTrigger> | |
<Enabled>true</Enabled> | |
<UserId>CHANGEME</UserId> | |
</LogonTrigger> | |
<SessionStateChangeTrigger> | |
<Enabled>true</Enabled> | |
<StateChange>RemoteConnect</StateChange> | |
<UserId>CHANGEME</UserId> | |
</SessionStateChangeTrigger> | |
</Triggers> | |
<Principals> | |
<Principal id="Author"> | |
<UserId>CHANGEME_SID</UserId> | |
<LogonType>InteractiveToken</LogonType> | |
<RunLevel>LeastPrivilege</RunLevel> | |
</Principal> | |
</Principals> | |
<Settings> | |
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy> | |
<DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries> | |
<StopIfGoingOnBatteries>true</StopIfGoingOnBatteries> | |
<AllowHardTerminate>false</AllowHardTerminate> | |
<StartWhenAvailable>false</StartWhenAvailable> | |
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable> | |
<IdleSettings> | |
<StopOnIdleEnd>true</StopOnIdleEnd> | |
<RestartOnIdle>false</RestartOnIdle> | |
</IdleSettings> | |
<AllowStartOnDemand>true</AllowStartOnDemand> | |
<Enabled>true</Enabled> | |
<Hidden>false</Hidden> | |
<RunOnlyIfIdle>false</RunOnlyIfIdle> | |
<DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession> | |
<UseUnifiedSchedulingEngine>true</UseUnifiedSchedulingEngine> | |
<WakeToRun>false</WakeToRun> | |
<ExecutionTimeLimit>PT0S</ExecutionTimeLimit> | |
<Priority>7</Priority> | |
</Settings> | |
<Actions Context="Author"> | |
<Exec> | |
<Command>powershell</Command> | |
<Arguments>-WindowStyle Hidden -File "C:\Users\$($env:USERNAME)\keepalive.ps1"</Arguments> | |
</Exec> | |
</Actions> | |
</Task> | |
"@ | |
# https://gist.github.com/jcefoli/36ed07c08dc3795648b3f45185f721c5 | |
$rdpKeepalivePS1 = @" | |
`$host.ui.RawUI.WindowTitle = "Idle Keepalive" | |
`$dotNetCode = @' | |
[DllImport("kernel32.dll", CharSet = CharSet.Auto,SetLastError = true)] | |
public static extern void SetThreadExecutionState(uint esFlags); | |
'@ | |
`$ste = Add-Type -memberDefinition `$dotNetCode -name System -namespace Win32 -passThru | |
`$ES_CONTINUOUS = [uint32]"0x80000000" #Requests that the other EXECUTION_STATE flags set remain in effect until SetThreadExecutionState is called again with the ES_CONTINUOUS flag set and one of the other EXECUTION_STATE flags cleared. | |
`$ES_AWAYMODE_REQUIRED = [uint32]"0x00000040" #Requests Away Mode to be enabled. | |
`$ES_DISPLAY_REQUIRED = [uint32]"0x00000002" #Requests display availability (display idle timeout is prevented). | |
`$ES_SYSTEM_REQUIRED = [uint32]"0x00000001" #Requests system availability (sleep idle timeout is prevented). | |
Write-Verbose "Power Plan suspended with option: `$option" | |
`$ste::SetThreadExecutionState(`$ES_CONTINUOUS -bor `$ES_SYSTEM_REQUIRED -bor `$ES_DISPLAY_REQUIRED) | |
read-host "Keepalive active. Press any key to quit" | |
Write-Verbose "Power Plan suspension ended" | |
`$ste::SetThreadExecutionState(`$ES_CONTINUOUS) | |
#powercfg -requests | |
"@ | |
# Replacements | |
$schTaskXML = $schTaskXML -replace "<Date>CHANGEME</Date>", "<Date>$dateStamp</Date>" | |
$schTaskXML = $schTaskXML -replace "<Author>CHANGEME</Author>", "<Author>$($env:USERDOMAIN)\$($env:USERNAME)</Author>" | |
$schTaskXML = $schTaskXML -replace "<UserId>CHANGEME</UserId>", "<UserId>$($env:USERDOMAIN)\$($env:USERNAME)</UserId>" | |
$schTaskXML = $schTaskXML -replace "<UserId>CHANGEME_SID</UserId>", "<UserId>$($currentUserSID)</UserId>" | |
# Write Necessary Files | |
$rdpKeepalivePS1 | Out-File -FilePath "C:\Users\$($env:USERNAME)\keepalive.ps1" -Encoding ascii | |
$schTaskXML | Out-File -FilePath "C:\Users\$($env:USERNAME)\keepalive.xml" -Encoding ascii | |
# Schedule the task | |
. schtasks /delete /tn "RDP Keepalive" /f | |
. schtasks /create /xml "$home\keepalive.xml" /tn "RDP Keepalive" /IT | |
# Cleanup | |
Remove-Item -Path "$home\keepalive.xml" -Force |
How to use pls
If you copy and paste Line 23 into an Administrator elevated powershell, it will download the components needed to create a Scheduled Task that runs at logon of the current user, which will invoke a powershell script to prevent idle every time you log on
Although this is safe, I really don't recommend running things you find on the internet without fully understanding all of the code and what it's doing.
Hello Jcefoli - it worked great !! , thank you for amazing work!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How to use pls