Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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

kriskoneru commented Oct 2, 2018

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. ???

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