You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

非管理员权限运行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

我觉得漏了些东西,但找不到问题,希望脚本不用管理员权限也能正常运行。


问题分析与修复

核心问题

  1. 提前执行敏感命令:你直接将Add-LocalGroupMember ...赋值给$sScriptCommand,这会在当前非管理员会话中立即执行该命令,直接触发权限拒绝,根本没等到PsExec去运行它。
  2. PsExec命令格式错误:传递给PsExec的PowerShell命令需要用-Command参数包裹,并且要将整个逻辑作为字符串传递,否则PowerShell无法正确解析。
  3. 部分前置操作权限不足:读取注册表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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 16:14:52