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

本地管理员密码变更检测PowerShell脚本求助

本地管理员密码变更检测与通知脚本求助

我是一名新手,需要编写PowerShell脚本实现本地管理员账户的检测/修复,并且在有人尝试或修改指定本地管理员密码时发送通知。我已经为所有电脑创建了名为OfflineAdmin的本地管理员账户及对应密码,但自己写的脚本没达到预期效果,原脚本如下:

# This script is intended to create a custom local administrator for offline use on Entra ID joined computers.

# Define the username and password
$Username = "OfflineAdmin"

$Password = "pppppp"

# Check if the user already exists
$ExistingUser = Get-LocalUser -Name $Username -ErrorAction SilentlyContinue

if ($ExistingUser) {
    "The user exists." 
    # If the user exists, update the password and set it to never expire
    Set-LocalUser -Name $Username -Password (ConvertTo-SecureString -AsPlainText $Password -Force) -PasswordNeverExpires $true
} else {
    "Adding the user." 
    # If the user doesn't exist, create the local user and set the password to never expire
    New-LocalUser -Name $Username -Password (ConvertTo-SecureString -AsPlainText $Password -Force) -PasswordNeverExpires
    # Then add the new user to the local administrators group
    $AdminGroup = Get-LocalGroup -Name "Administrators"
    $AdminUser = Get-LocalUser -Name $Username
    Add-LocalGroupMember -Group $AdminGroup -Member $AdminUser
}
Stop-Transcript

# Define the event log properties when someone change the password
$LogName = "Security"
$EventID = 4738  # Event ID for a user account was changed (password change)

# Specify the email details
$EmailFrom = "notify@email.com"
$EmailTo = "admin@admin.com"
$Subject = "Local Admin Password Change Notification"
$SMTPServer = "smtp-mail.outlook.com"

# Get the latest event from the Security log
$latestEvent = Get-WinEvent -LogName $LogName -FilterXPath "*[System[(EventID=$EventID)]]" | Select-Object -First 1

# Check if the event is not null (i.e., a password change event is found)
if ($latestEvent -ne $null) {
    # Extract relevant information from the event
    $EventTime = $latestEvent.TimeCreated
    $Username = $latestEvent.Properties[0].Value
    $ComputerName = $latestEvent.Properties[1].Value

 # Compose the email body
    $Body = "Local admin password changed on $ComputerName.`r`n`r`n"
    $Body += "Username: $Username`r`n"
    $Body += "Event Time: $EventTime`r`n"

    # Send the email
    Send-MailMessage -From $EmailFrom -To $EmailTo -Subject $Subject -Body $Body -SmtpServer     $SMTPServer
} else {
    Write-Host "No password change events found."
}

原脚本核心问题

  • 逻辑顺序错误:先执行账户密码重置,再读取事件日志,导致每次运行脚本都会触发自身的密码修改事件,产生误报
  • 事件筛选不精准:仅用EventID 4738会捕获所有用户的账户变更,无法只针对OfflineAdmin
  • 事件属性提取错误:4738事件的属性索引对应值不正确,无法准确获取目标账户和执行者信息
  • SMTP配置缺失:Outlook的SMTP服务器需要SSL认证和端口配置,原脚本未设置导致邮件无法发送
  • 无对应启动转录的Stop-Transcript会触发报错

修正后的脚本

# 定义目标本地管理员账户信息
$targetUsername = "OfflineAdmin"
$targetPassword = "pppppp"

# 1. 检测并修复本地管理员账户
$existingUser = Get-LocalUser -Name $targetUsername -ErrorAction SilentlyContinue

if ($existingUser) {
    Write-Host "账户 $targetUsername 已存在"
    # 可选:如果需要强制保持密码为设定值,保留下面一行;若要允许修改并仅检测通知,注释掉
    # Set-LocalUser -Name $targetUsername -Password (ConvertTo-SecureString -AsPlainText $targetPassword -Force) -PasswordNeverExpires $true
} else {
    Write-Host "创建本地管理员账户 $targetUsername..."
    New-LocalUser -Name $targetUsername -Password (ConvertTo-SecureString -AsPlainText $targetPassword -Force) -PasswordNeverExpires $true
    Add-LocalGroupMember -Group "Administrators" -Member $targetUsername
    Write-Host "账户已添加到本地管理员组"
}

# 2. 检测目标账户的密码变更事件并发送通知
$logName = "Security"
$eventID = 4738
# 精准筛选仅针对目标账户的密码变更事件
$filterXPath = "*[System[(EventID=$eventID)]] and *[EventData[Data[@Name='TargetUserName']='$targetUsername']]"

# 邮件配置
$emailFrom = "notify@email.com"
$emailTo = "admin@admin.com"
$subject = "警告:本地管理员密码已变更"
$smtpServer = "smtp-mail.outlook.com"
$smtpPort = 587
# 可预先存储凭据,避免每次输入:$smtpCredential = Import-Clixml -Path "C:\Path\To\Credential.xml"
$smtpCredential = Get-Credential -Message "输入SMTP账户凭据"

# 获取最近一次针对目标账户的密码变更事件
try {
    $latestEvent = Get-WinEvent -LogName $logName -FilterXPath $filterXPath -MaxEvents 1 -ErrorAction Stop
} catch {
    Write-Host "未找到针对 $targetUsername 的密码变更事件"
    exit
}

# 提取事件关键信息
$eventTime = $latestEvent.TimeCreated
$computerName = $env:COMPUTERNAME
# 4738事件中,索引4的属性是执行变更的账户名
$changedBy = $latestEvent.Properties[4].Value

# 构建邮件内容
$body = @"
警告:本地管理员账户 $targetUsername 的密码已被修改!

计算机名称:$computerName
变更时间:$eventTime
执行者账户:$changedBy
"@

# 发送邮件
try {
    Send-MailMessage -From $emailFrom -To $emailTo -Subject $subject -Body $body -SmtpServer $smtpServer -Port $smtpPort -UseSsl -Credential $smtpCredential
    Write-Host "通知邮件已发送"
} catch {
    Write-Host "发送邮件失败:$_"
}

脚本改进说明

  • 分离账户管理与事件检测逻辑,避免自触发误报
  • 使用XPath精准筛选目标账户的4738事件,排除其他用户的变更
  • 修正事件属性索引,正确提取执行者信息
  • 添加Outlook SMTP的SSL和认证配置,确保邮件正常发送
  • 增加错误处理,避免脚本意外终止
  • 可选注释密码强制重置逻辑,根据需求选择是否允许用户修改密码并仅做通知

内容的提问来源于stack exchange,提问作者Carol Ceguerra

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 23:10:18