非管理员权限运行PowerShell脚本时Add-LocalGroupMember访问拒绝问题
问题:非管理员权限运行PowerShell脚本添加本地组时提示权限拒绝
我写了一段PowerShell脚本,用来把指定组加入本地Administrators组。为了执行Add-LocalGroupMember命令,我在脚本里用psexec.exe以本地管理员账户运行该命令。脚本用管理员身份运行ISE或直接运行时完全正常,但非管理员权限运行时会提示Add-LocalGroupMember : Access denied。我搞不懂原因,因为脚本应该是通过本地管理员账户执行命令的。
原脚本如下(已移除敏感信息):
#Retreiving local admin group name (can be Administrators or Administrateurs depending of the PC language) $groupeAdminLocal = Get-LocalGroup | Where-Object { $_.Name -like "*admin*" -and $_.Description -notlike "*Hyper*" } | Select-Object -ExpandProperty Name #Group I would like to add niside my local Admin group $adAdminGroup = "Computer-Admins-Group" #Retreiving local admin account name (can be Administrator or Administrateur depentding of the PC language) $username = Get-LocalGroupMember -Group $groupeAdminLocal | Where-Object { $_.Name -like "FRD*" } | Select-Object -ExpandProperty Name #If no Administrator or Administrateur accounts found, we use "guestaccount" (specific case from my environment, local Admin account may have been renamed) if (-not $username) { $username = "guestaccount" } $admin = $username.Split("\\") $admin = $admin[1] $username = ".\" + $admin #First part of the local admin password $sVisAdminFirstPartPass = "Localpass1" #Path where is stored the last part of the local admin password $regPath = "HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System" $regValueName = "LegalNoticeTest" #We get the content of the registry key $regContent = (Get-ItemProperty -Path $regPath).$regValueName $regContent = $regContent -replace '\s+', ' ' #Regex to look for the string inside parenthesis (second part of the password) $pattern = '\(([^)]+)\)' $matches = [regex]::matches($regContent, $pattern) if ($matches.Count -gt 0) { $lastMatch = $matches[$matches.Count - 1].Groups[1].Value $password = $sVisAdminFirstPartPass + $lastMatch #this line is used to assemble the password (first part + second part located inside the registry) } #I declare the command to be run as a local admin $sScriptCommand = Add-LocalGroupMember -Group $groupeAdminLocal -Member $adAdminGroup $sCommand = "\\psexec.exe /accepteula -u " + $username + " -p " + $password + " " + $sScriptCommand #I run a new process to run the above command Start-Process powershell $sCommand
我觉得漏了些东西,但找不到问题,希望脚本不用管理员权限也能正常运行。
问题分析与修复
核心问题
- 提前执行敏感命令:你直接将
Add-LocalGroupMember ...赋值给$sScriptCommand,这会在当前非管理员会话中立即执行该命令,直接触发权限拒绝,根本没等到PsExec去运行它。 - PsExec命令格式错误:传递给PsExec的PowerShell命令需要用
-Command参数包裹,并且要将整个逻辑作为字符串传递,否则PowerShell无法正确解析。 - 部分前置操作权限不足:读取注册表HKLM路径、查询本地组信息的操作,非管理员账户可能没有权限,最好把整个逻辑放到管理员上下文的进程中执行。
修正后的脚本
# 获取本地管理员账户名称(这一步非管理员通常可执行,若不行则移到下面的管理员脚本块内) $groupeAdminLocal = Get-LocalGroup | Where-Object { $_.Name -like "*admin*" -and $_.Description -notlike "*Hyper*" } | Select-Object -ExpandProperty Name $username = Get-LocalGroupMember -Group $groupeAdminLocal | Where-Object { $_.Name -like "FRD*" } | Select-Object -ExpandProperty Name if (-not $username) { $username = "guestaccount" } $admin = $username.Split("\\") $admin = $admin[1] $localAdminUser = ".\" + $admin # 构建需要在管理员上下文执行的完整命令逻辑 $sAdminScript = @" # 本地管理员密码第一部分 `$sVisAdminFirstPartPass = "Localpass1" # 注册表路径(修正双反斜杠为单反斜杠) `$regPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" `$regValueName = "LegalNoticeTest" # 读取注册表内容 `$regContent = (Get-ItemProperty -Path `$regPath).`$regValueName `$regContent = `$regContent -replace '\s+', ' ' # 提取密码第二部分 `$pattern = '\(([^)]+)\)' `$matches = [regex]::matches(`$regContent, `$pattern) if (`$matches.Count -gt 0) { `$lastMatch = `$matches[`$matches.Count - 1].Groups[1].Value `$password = `$sVisAdminFirstPartPass + `$lastMatch } # 执行添加组操作 `$groupeAdminLocal = Get-LocalGroup | Where-Object { `$_.Name -like "*admin*" -and `$_.Description -notlike "*Hyper*" } | Select-Object -ExpandProperty Name Add-LocalGroupMember -Group `$groupeAdminLocal -Member "Computer-Admins-Group" "@ # 构建PsExec命令(注意格式与参数) $psexecPath = "psexec.exe" # 若不在PATH中,请写全绝对路径 $sCommand = """$psexecPath"" /accepteula -h -u $localAdminUser -p `$password powershell -Command ""$sAdminScript""" # 启动进程执行命令 Start-Process cmd -ArgumentList "/c", $sCommand -NoNewWindow
关键修改点
- 封装管理员逻辑为字符串脚本块:用Here-String把需要管理员权限的逻辑全部包裹,避免在当前非管理员会话中提前执行敏感命令。
- 修正PsExec参数:
- 添加
-h参数:强制提升权限(针对UAC,即使账户属于管理员组,默认也需要此参数获取高权限)。 - 用双引号包裹路径和命令,避免空格导致的解析错误。
- 明确指定
powershell -Command来执行字符串形式的脚本。
- 添加
- 修正注册表路径格式:将原脚本的
HKLM:\\改为正确的HKLM:\(单反斜杠)。
额外注意事项
- 确保
psexec.exe路径正确,要么放入系统PATH目录,要么在脚本中写全绝对路径。 - 半明文存储本地管理员密码存在安全风险,建议改用更安全的身份验证方式。
内容的提问来源于stack exchange,提问作者Prodzz Perfect
相关产品推荐
相关产品推荐

