Skip to content

Instantly share code, notes, and snippets.

@idavis
Created March 5, 2011 18:52
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save idavis/856603 to your computer and use it in GitHub Desktop.
Save idavis/856603 to your computer and use it in GitHub Desktop.
Impersonate a user and execute a script block as that user
param( [ScriptBlock] $scriptBlock )
<#
.SYNOPSIS
Impersonates a user and executes a script block as that user. This is an interactive script
and a window will open in order to securely capture credentials.
.EXAMPLE
Use-Impersonation.ps1 {Get-ChildItem 'C:\' | Foreach { Write-Host $_.Name }}
This writes the contents of 'C:\' impersonating the user that is entered.
#>
$logonUserSignature =
@'
[DllImport( "advapi32.dll" )]
public static extern bool LogonUser( String lpszUserName,
String lpszDomain,
IntPtr lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken );
'@
$AdvApi32 = Add-Type -MemberDefinition $logonUserSignature -Name "AdvApi32" -Namespace "PsInvoke.NativeMethods" -PassThru
$closeHandleSignature =
@'
[DllImport( "kernel32.dll", CharSet = CharSet.Auto )]
public static extern bool CloseHandle( IntPtr handle );
'@
$Kernel32 = Add-Type -MemberDefinition $closeHandleSignature -Name "Kernel32" -Namespace "PsInvoke.NativeMethods" -PassThru
$credentials = Get-Credential
try
{
$Logon32ProviderDefault = 0
$Logon32LogonInteractive = 2
$tokenHandle = [IntPtr]::Zero
$userName = Split-Path $credentials.UserName -Leaf
$domain = Split-Path $credentials.UserName
$unmanagedString = [IntPtr]::Zero;
$success = $false
try
{
$unmanagedString = [System.Runtime.InteropServices.Marshal]::SecureStringToGlobalAllocUnicode($credentials.Password);
$success = $AdvApi32::LogonUser($userName, $domain, $unmanagedString, $Logon32LogonInteractive, $Logon32ProviderDefault, [Ref] $tokenHandle)
}
finally
{
[System.Runtime.InteropServices.Marshal]::ZeroFreeGlobalAllocUnicode($unmanagedString);
}
if (!$success )
{
$retVal = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
Write-Host "LogonUser was unsuccessful. Error code: $retVal"
return
}
Write-Host "LogonUser was successful."
Write-Host "Value of Windows NT token: $tokenHandle"
$identityName = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
Write-Host "Current Identity: $identityName"
$newIdentity = New-Object System.Security.Principal.WindowsIdentity( $tokenHandle )
$context = $newIdentity.Impersonate()
$identityName = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
Write-Host "Impersonating: $identityName"
Write-Host "Executing custom script"
& $scriptBlock
}
catch [System.Exception]
{
Write-Host $_.Exception.ToString()
}
finally
{
if ( $context -ne $null )
{
$context.Undo()
}
if ( $tokenHandle -ne [System.IntPtr]::Zero )
{
$Kernel32::CloseHandle( $tokenHandle )
}
}
@kriskoneru
Copy link

windows powershell ISE crashes exactly at this $context = $newIdentity.Impersonate()

my scenario is i will be calling a powershell scripit as domain1/user1 and in this powershell script the user has to be changed to domain2/user2 so can i do this using this script ???.. and also i need to end impersonation once the task is completed. any thoughts would be greatly helpful. ( Can you change the script to change to a new user instead of logged in user ?? or some sample code ???)

I do not know why the windows powershell is crashing exactly at this step. ???

@yuzhaninan
Copy link

yuzhaninan commented Dec 26, 2023

Can you advise how to perform impersonation and exit the context if there is no $CONTEXT variable left in memory? Or is this impossible?

Maybe like this ? UPD:
$RtS = @"
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool RevertToSelf();
"@

$CRTS = Add-Type -MemberDefinition $RtS -Name "CRTS2" -Namespace "PsInvoke.NativeMethods" -PassThru
$CRTS::RevertToSelf()

@yuzhaninan
Copy link

How to perform impersonation by also increasing administrator rights?

@idavis
Copy link
Author

idavis commented Jan 16, 2024

@yuzhaninan Sorry, I don't know.

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