Skip to content

Instantly share code, notes, and snippets.

@jcefoli
Last active May 3, 2023 20:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jcefoli/816fac3234531f842217dd292a5188ce to your computer and use it in GitHub Desktop.
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
<#
.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
Copy link

ghost commented May 21, 2021

How to use pls

@jcefoli
Copy link
Author

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.

@sapddic
Copy link

sapddic commented May 3, 2023

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