本地管理员密码变更检测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
相关产品推荐
相关产品推荐

