調整一般使用者擁有特定服務啟動/關閉權限
程式有二個參數:
Username帶入指定的使用者(一般使用者)的帳號名稱ServiceName帶入指定的 Windows 服務名稱
(使用系統管理員的 Powershell 來執行)
範例:
.\Adjust-ServicePermissions.ps1 -Username Tony -ServiceName MyService
互動式程式,按下 y 確認
| # Adjust-ServicePermissions.ps1 | |
| # A script to adjust permissions for Windows services and SCMANAGER | |
| param( | |
| [Parameter(Mandatory=$true, Position=0, HelpMessage="Username to grant permissions to")] | |
| [string]$Username, | |
| [Parameter(Mandatory=$true, Position=1, HelpMessage="Service name to modify")] | |
| [string]$ServiceName | |
| ) | |
| function Write-Log { | |
| param([string]$Message) | |
| $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" | |
| $logMessage = "[$timestamp] $Message" | |
| Write-Host $logMessage | |
| # Create logs directory if it doesn't exist | |
| $logDir = Join-Path -Path $PSScriptRoot -ChildPath "logs" | |
| if (-not (Test-Path -Path $logDir)) { | |
| New-Item -ItemType Directory -Path $logDir | Out-Null | |
| } | |
| # Append to log file | |
| $logFile = Join-Path -Path $logDir -ChildPath "service_permissions_$(Get-Date -Format 'yyyyMMdd').log" | |
| Add-Content -Path $logFile -Value $logMessage | |
| } | |
| function Show-Usage { | |
| Write-Host "USAGE: .\Adjust-ServicePermissions.ps1 <username> <servicename>" | |
| Write-Host " <username> : Username to grant permissions to" | |
| Write-Host " <servicename> : Service name to modify permissions for" | |
| Exit 1 | |
| } | |
| function Apply-Permissions { | |
| param( | |
| [string]$UserSid, | |
| [string]$ServiceSddl, | |
| [string]$ScManagerSddl, | |
| [string]$ModifiedServiceSddl, | |
| [string]$ModifiedScManagerSddl | |
| ) | |
| try { | |
| Write-Log "Applying new permissions to service '$ServiceName'..." | |
| sc.exe sdset $ServiceName $ModifiedServiceSddl | |
| Write-Log "Applying new permissions to SCMANAGER..." | |
| sc.exe sdset SCMANAGER $ModifiedScManagerSddl | |
| Write-Log "Permissions applied successfully." | |
| # Verify changes | |
| $newServiceSddl = & sc.exe sdshow $ServiceName | |
| $newScManagerSddl = & sc.exe sdshow SCMANAGER | |
| Write-Log "New service SDDL: $newServiceSddl" | |
| Write-Log "New SCMANAGER SDDL: $newScManagerSddl" | |
| Write-Host -ForegroundColor Green "Permissions have been successfully applied." | |
| } | |
| catch { | |
| Write-Log "ERROR: Failed to apply permissions: $_" | |
| Write-Host -ForegroundColor Red "Failed to apply permissions. Check the log for details." | |
| } | |
| } | |
| # Validate parameters | |
| if (-not $Username -or -not $ServiceName) { | |
| Show-Usage | |
| } | |
| # Starting | |
| Write-Host "=======================================================" | |
| Write-Host " Windows Service and SCMANAGER Permission Adjuster " | |
| Write-Host "=======================================================" | |
| # Step 1: Log the current state | |
| Write-Log "Starting permission adjustment process" | |
| Write-Log "Username: $Username, Service: $ServiceName" | |
| # Get user SID | |
| try { | |
| $userSid = (Get-WmiObject -Class Win32_UserAccount -Filter "Name='$Username'").SID | |
| if (-not $userSid) { | |
| Write-Log "ERROR: Could not find SID for user '$Username'" | |
| Write-Host -ForegroundColor Red "User '$Username' not found. Please check the username and try again." | |
| Exit 1 | |
| } | |
| Write-Log "User SID: $userSid" | |
| } | |
| catch { | |
| Write-Log "ERROR: Failed to retrieve SID for user '$Username': $_" | |
| Write-Host -ForegroundColor Red "Failed to retrieve SID for user '$Username'. Please check the username and try again." | |
| Exit 1 | |
| } | |
| # Get current service SDDL | |
| try { | |
| $serviceSddl = (cmd /c sc sdshow $ServiceName) | Select-Object -Last 1 | |
| if ($LASTEXITCODE -ne 0) { | |
| Write-Log "ERROR: Failed to retrieve SDDL for service '$ServiceName'" | |
| Write-Host -ForegroundColor Red "Service '$ServiceName' not found or access denied. Please check the service name and try again." | |
| Exit 1 | |
| } | |
| Write-Log "Current service SDDL: $serviceSddl" | |
| } | |
| catch { | |
| Write-Log "ERROR: Exception when retrieving service SDDL: $_" | |
| Write-Host -ForegroundColor Red "Failed to retrieve permissions for service '$ServiceName'. Please check the service name and try again." | |
| Exit 1 | |
| } | |
| # Get current SCMANAGER SDDL | |
| try { | |
| $scManagerSddl = (cmd /c sc sdshow SCMANAGER) | Select-Object -Last 1 | |
| Write-Log "Current SCMANAGER SDDL: $scManagerSddl" | |
| } | |
| catch { | |
| Write-Log "ERROR: Failed to retrieve SDDL for SCMANAGER: $_" | |
| Write-Host -ForegroundColor Red "Failed to retrieve permissions for SCMANAGER. You may not have sufficient privileges." | |
| Exit 1 | |
| } | |
| # Step 2: Modify the permissions | |
| function Modify-ServiceSddl { | |
| param( | |
| [string]$Sddl, | |
| [string]$PermissionToAdd | |
| ) | |
| $modifiedSddl = $Sddl.Trim() | |
| if ($modifiedSddl.LastIndexOf("S:") -ge 0) { | |
| $daclPart = $modifiedSddl.Substring(0, $modifiedSddl.LastIndexOf("S:")) | |
| $saclPart = $modifiedSddl.Substring($modifiedSddl.LastIndexOf("S:")) | |
| } else { | |
| $daclPart = $modifiedSddl | |
| $saclPart = '' | |
| } | |
| # Check if the permission is already present | |
| if ($daclPart -match [regex]::Escape($PermissionToAdd)) { | |
| Write-Log "The specified permissions are already granted." | |
| } else { | |
| $daclPart = $daclPart + $PermissionToAdd | |
| $modifiedSddl = $daclPart + $saclPart | |
| } | |
| return $modifiedSddl | |
| } | |
| # Step 2: Modify the permissions | |
| # For the service | |
| $permissionToAdd = "(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$userSid)" | |
| $modifiedServiceSddl = Modify-ServiceSddl -Sddl $serviceSddl -PermissionToAdd $permissionToAdd | |
| # For SCMANAGER | |
| $scManagerPermissionToAdd = "(A;;CCLCSWRPWPDTLOCRRC;;;$userSid)" | |
| $modifiedScManagerSddl = Modify-ServiceSddl -Sddl $scManagerSddl -PermissionToAdd $scManagerPermissionToAdd | |
| # Step 3: Preview the changes and confirm with the user | |
| Write-Host "`nCurrent permissions:" | |
| Write-Host "------------------------" | |
| Write-Host "Service '$ServiceName': $serviceSddl" | |
| Write-Host "SCMANAGER: $scManagerSddl" | |
| Write-Host "`nNew permissions to be applied:" | |
| Write-Host "------------------------" | |
| Write-Host "Service '$ServiceName': $modifiedServiceSddl" | |
| Write-Host "SCMANAGER: $modifiedScManagerSddl" | |
| $confirmation = Read-Host "`nDo you want to apply these changes? (y/n)" | |
| if ($confirmation -eq 'y') { | |
| Apply-Permissions -UserSid $userSid -ServiceSddl $serviceSddl -ScManagerSddl $scManagerSddl -ModifiedServiceSddl $modifiedServiceSddl -ModifiedScManagerSddl $modifiedScManagerSddl | |
| } else { | |
| Write-Host "Operation cancelled by user." | |
| Write-Log "User cancelled the permission change operation." | |
| } | |
| Write-Host "`nOperation completed. See logs for details." |
Adjust the permissions for a regular user to start/stop a specific service.
The script has two parameters:
Username: Specify the account name of the regular user.ServiceName: Specify the name of the Windows service.(Execute using an administrator's PowerShell.)
Example:
.\Adjust-ServicePermissions.ps1 -Username Tony -ServiceName MyService
Interactive script, Press 'y' to confirm.