Last active
January 20, 2025 01:30
-
-
Save jborean93/3c148df03545023c671ddefb2d2b5ffc to your computer and use it in GitHub Desktop.
Invoke a scriptblock in powershell with impersonation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Add-Type -Namespace PInvoke -Name NativeMethods -MemberDefinition @' | |
| [DllImport("Kernel32.dll")] | |
| public static extern bool CloseHandle( | |
| IntPtr hObject); | |
| [DllImport("Advapi32.dll", SetLastError = true)] | |
| public static extern bool ImpersonateLoggedOnUser( | |
| IntPtr hToken); | |
| [DllImport("Advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] | |
| public static extern bool LogonUserW( | |
| string lpszUsername, | |
| string lpszDomain, | |
| IntPtr lpszPassword, | |
| UInt32 dwLogonType, | |
| UInt32 dwLogonProvider, | |
| out IntPtr phToken); | |
| [DllImport("Advapi32.dll")] | |
| public static extern bool RevertToSelf(); | |
| '@ | |
| Function Invoke-WithImpersonation { | |
| [CmdletBinding()] | |
| param ( | |
| [Parameter(Mandatory=$true)] | |
| [ScriptBlock] | |
| $ScriptBlock, | |
| [Parameter(Mandatory=$true)] | |
| [PSCredential] | |
| $Credential | |
| ) | |
| $user = $Credential.UserName | |
| $domain = $null | |
| if ($user.Contains('\')) { | |
| $domain, $user = $user -split '\\', 2 | |
| } | |
| $passPtr = [System.Runtime.InteropServices.Marshal]::SecureStringToGlobalAllocUnicode($Credential.Password) | |
| try { | |
| $token = [IntPtr]::Zero | |
| $res = [PInvoke.NativeMethods]::LogonUserW( | |
| $user, | |
| $domain, | |
| $passPtr, | |
| 2, # LOGON32_LOGON_INTERACTIVE | |
| 0, # LOGON32_PROVIDER_DEFAULT | |
| [ref]$token | |
| ); $err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() | |
| } finally { | |
| [System.Runtime.InteropServices.Marshal]::ZeroFreeGlobalAllocUnicode($passPtr) | |
| } | |
| if (-not $res) { | |
| $exp = [System.ComponentModel.Win32Exception]$res | |
| Write-Error -Message "Failed to log on user: $($exp.Exception.Message)" -Exception $exp | |
| return | |
| } | |
| try { | |
| $res = [PInvoke.NativeMethods]::ImpersonateLoggedOnUser( | |
| $token | |
| ); $err = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() | |
| if (-not $res) { | |
| $exp = [System.ComponentModel.Win32Exception]$res | |
| Write-Error -Message "Failed to impersonate user: $($exp.Exception.Message)" -Exception $exp | |
| return | |
| } | |
| try { | |
| &$ScriptBlock | |
| } finally { | |
| $null = [PInvoke.NativeMethods]::RevertToSelf() | |
| } | |
| } finally { | |
| $null = [PInvoke.NativeMethods]::CloseHandle($token) | |
| } | |
| } | |
| Invoke-WithImpersonation -Credential (Get-Credential) -ScriptBlock { | |
| [System.Security.Principal.WindowsIdentity]::GetCurrent().Name | |
| }.GetNewClosure() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment