PowerShell调用LogonUserA实现用户模拟失败问题求助
我编写了一段结合LogonUserA和ImpersonateLoggedOnUser Windows API函数的PowerShell代码,尝试模拟远程机器的管理员用户,但运行后发现并未切换身份,仍然是当前用户。
我的代码:
$userName = "administrator" $domain = "target-win" $password = Read-Host -Prompt 'Enter password:' -AsSecureString function GetCurrentPrincipal { return [System.Security.Principal.WindowsIdentity]::GetCurrent().Name } $logonUserSignature = @' [DllImport( "advapi32.dll" )] public static extern bool LogonUser( String lpszUserName, String lpszDomain, String 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 try { $Logon32Provider = 3 #LOGON32_PROVIDER_WINNT50 $Logon32Type = 9 #LOGON32_LOGON_NEW_CREDENTIALS $tokenHandle = [IntPtr]::Zero $success = $AdvApi32::LogonUser($userName, $domain, ([Net.NetworkCredential]::new('', $password).Password), $Logon32Type, $Logon32Provider, [Ref] $tokenHandle) 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 = GetCurrentPrincipal Write-Host "Current Identity: $identityName" $newIdentity = New-Object System.Security.Principal.WindowsIdentity( $tokenHandle ) $context = $newIdentity.Impersonate() $identityName = GetCurrentPrincipal Write-Host "Impersonating: $identityName" } catch [System.Exception] { Write-Host $_.Exception.ToString() } finally { if ( $context -ne $null ) { $context.Undo() } if ( $tokenHandle -ne [System.IntPtr]::Zero ) { $Kernel32::CloseHandle( $tokenHandle ) } }
运行输出:
LogonUser was successful. Value of Windows NT token: 4364 Current Identity: COMPONENTS\Administrator Impersonating: COMPONENTS\Administrator True
我认为代码逻辑正确,但无法定位问题,求解决建议。
修改登录类型(LogonType):你当前使用的
LOGON32_LOGON_NEW_CREDENTIALS(值为9)仅用于后续网络请求时替换凭证,不会改变本地线程的执行身份。要真正切换本地上下文用户,建议使用:LOGON32_LOGON_INTERACTIVE(值为2):交互式登录,提供完整的用户上下文LOGON32_LOGON_NETWORK_CLEARTEXT(值为8):明文网络登录,适合明确的身份切换场景
验证登录提供者匹配:对应修改后的登录类型,可保留
LOGON32_PROVIDER_WINNT50(值为3),或改用LOGON32_PROVIDER_DEFAULT(值为0),确保两者兼容。检查密码转换正确性:临时添加输出,验证
([Net.NetworkCredential]::new('', $password).Password)是否正确将安全字符串转为明文密码,避免凭证传递错误。确认权限配置:当前运行PowerShell的用户必须拥有
SeImpersonatePrivilege或SeAssignPrimaryTokenPrivilege权限,否则模拟操作会静默失败。可执行以下命令检查权限:whoami /priv直接调用Win32模拟API:替换.NET的
$newIdentity.Impersonate(),改用原生ImpersonateLoggedOnUserAPI更可靠。添加以下签名到$logonUserSignature中:[DllImport("advapi32.dll", SetLastError = true)] public static extern bool ImpersonateLoggedOnUser(IntPtr hToken);然后在代码中调用
$AdvApi32::ImpersonateLoggedOnUser($tokenHandle),并检查返回值是否成功。
内容的提问来源于stack exchange,提问作者sbagnato

