Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Script that creates a scheduled task to keep your RDP session alive to work around nonsensical GPOs that inhibit productivity
<#
.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
@Lonely16gbRam

This comment has been minimized.

Copy link

@Lonely16gbRam Lonely16gbRam commented May 21, 2021

How to use pls

@jcefoli

This comment has been minimized.

Copy link
Owner Author

@jcefoli jcefoli commented May 24, 2021

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment