为 'Domain users' 设置 WMI 权限
Set WMI permissions for 'Domain users'
我在 PowerShell 中创建了两个函数,一个创建命名空间 ROOT\CustomCMClasses
,另一个创建 class Test
。这件作品很好:
Param (
$Namespace = 'CustomCMClasses',
$Class = 'Test'
)
Function New-WMINamespaceHC{
if (Get-WmiObject -Namespace 'root' -Class '__NAMESPACE' | Where-Object {$_.Name -eq $Namespace}) {
Write-Verbose "WMI Namespace 'root$Namespace' exists"
}
else {
Write-Verbose "Create WMI namespace 'root$Namespace'"
$Ns = [WMICLASS]'root:__Namespace'
$NewNamespace = $Ns.createInstance()
$NewNamespace.Name = $Namespace
$NewNamespace.Put()
}
}
Function New-WMIClassHC {
if (Get-WmiObject -List -Namespace "root$Namespace" | Where-Object {$_.Name -eq $Class}) {
Write-Verbose "WMI Class '$Class' exists"
}
else {
Write-Verbose "Create WMI Class '$Class'"
$NewClass = New-Object System.Management.ManagementClass ("root$Namespace", [String]::Empty, $Null);
$NewClass['__CLASS'] = $Class
$NewClass.Qualifiers.Add('Static', $true)
$NewClass.Properties.Add('Key', [System.Management.CimType]::String, $false)
$NewClass.Properties['Key'].Qualifiers.Add('Key', $true)
$NewClass.Properties.Add('Value1', [System.Management.CimType]::UInt32, $false)
$NewClass.Properties.Add('Value2', [System.Management.CimType]::String, $false)
$NewClass.Put()
}
}
此时我需要授予新命名空间的 Domain users
权限,以便他们能够在本地客户端上向其中写入数据(无需远程处理)。这是我找到很多信息但现在卡住了的地方。
Microsoft 博客上有一个 script I tried to tweak, but it's overly complicated for my needs and it failed so I found and tweaked the following 代码:
Function Add-WMIPermissions {
[CmdLetBinding()]
Param (
[String]$Principal = 'DOMAIN.NET\Domain users',
[String]$Namespace = 'CustomCMClasses'
)
Function Get-Sid {
Param (
$DSIdentity
)
$ID = new-object System.Security.Principal.NTAccount($DSIdentity)
Return $ID.Translate([System.Security.Principal.SecurityIdentifier]).toString()
}
$Sid = Get-Sid $Principal
$WMISDDL = "A;CI;CCWP;;;$Sid"
$WMISDDLPartialMatch = "A;\w*;\w+;;;$Sid"
$security = Get-WmiObject -Namespace root$Namespace -Class __SystemSecurity
$binarySD = @($null)
$result = $security.PsBase.InvokeMethod('GetSD',$binarySD)
$converter = New-Object system.management.ManagementClass Win32_SecurityDescriptorHelper
$CurrentWMISDDL = $converter.BinarySDToSDDL($binarySD[0])
if (($CurrentWMISDDL.SDDL -match $WMISDDLPartialMatch) -and ($CurrentWMISDDL.SDDL -notmatch $WMISDDL)) {
$NewWMISDDL = $CurrentWMISDDL.SDDL -replace $WMISDDLPartialMatch, $WMISDDL
}
else {
$NewWMISDDL = $CurrentWMISDDL.SDDL += '(' + $WMISDDL + ')'
}
$WMIbinarySD = $converter.SDDLToBinarySD($NewWMISDDL)
$WMIconvertedPermissions = ,$WMIbinarySD.BinarySD
if ($CurrentWMISDDL.SDDL -match $WMISDDL) {
Write-Verbose 'Current WMI Permissions matches desired value'
}
else {
$result = $security.PsBase.InvokeMethod('SetSD',$WMIconvertedPermissions)
if($result='0'){
Write-Verbose 'WMI permissions applied'
}
}
}
Add-WMIPermissions -Verbose
明明权限已正确应用,但用户仍然无法向WMI写入数据。使用 WMI 对我来说是新的,所以非常感谢任何帮助。
查看普通用户(Domain users
)是否有权限的测试代码:
$WMIClass = [WMICLASS]('root\' + $Namespace + ':' + $Class)
$WMIInstance = $WMIClass.CreateInstance()
$WMIInstance.Key = 'Unique value identifier 5'
$WMIInstance.Value1 = 101
$WMIInstance.Value2 = 'Status Ok'
$WMIInstance.Put()
解决了部分写入的问题:
Function Set-WMIPermissionsHC {
Param (
[String]$Namespace = 'CustomCMClasses',
[String]$Class = 'Test',
[String]$Account = 'DOMAIN\Domain users',
[String]$Computer = $env:COMPUTERNAME
)
Function Get-Sid {
Param (
$Account
)
$ID = New-Object System.Security.Principal.NTAccount($Account)
Return $ID.Translate([System.Security.Principal.SecurityIdentifier]).toString()
}
$SID = Get-Sid $Account
$SDDL = "A;CI;CCSWWP;;;$SID"
$DCOMSDDL = "A;;CCDCRP;;;$SID"
$Reg = [WMICLASS]"\$Computer\root\default:StdRegProv"
$DCOM = $Reg.GetBinaryValue(2147483650,'software\microsoft\ole','MachineLaunchRestriction').uValue
$Security = Get-WmiObject -ComputerName $Computer -Namespace "root$Namespace" -Class __SystemSecurity
$Converter = New-Object System.Management.ManagementClass Win32_SecurityDescriptorHelper
$BinarySD = @($null)
$Result = $Security.PsBase.InvokeMethod('GetSD', $BinarySD)
$OutSDDL = $Converter.BinarySDToSDDL($BinarySD[0])
$OutDCOMSDDL = $Converter.BinarySDToSDDL($DCOM)
$NewSDDL = $OutSDDL.SDDL += '(' + $SDDL + ')'
$NewDCOMSDDL = $OutDCOMSDDL.SDDL += '(' + $DCOMSDDL + ')'
$WMIbinarySD = $Converter.SDDLToBinarySD($NewSDDL)
$WMIconvertedPermissions = ,$WMIbinarySD.BinarySD
$DCOMbinarySD = $Converter.SDDLToBinarySD($NewDCOMSDDL)
$DCOMconvertedPermissions = ,$DCOMbinarySD.BinarySD
$Result = $Security.PsBase.InvokeMethod('SetSD', $WMIconvertedPermissions)
$Result = $Reg.SetBinaryValue(2147483650,'software\microsoft\ole','MachineLaunchRestriction', $DCOMbinarySD.binarySD)
Write-Verbose 'WMI Permissions set'
}
感谢this blog and the Microsoft blog解释权限
我在 PowerShell 中创建了两个函数,一个创建命名空间 ROOT\CustomCMClasses
,另一个创建 class Test
。这件作品很好:
Param (
$Namespace = 'CustomCMClasses',
$Class = 'Test'
)
Function New-WMINamespaceHC{
if (Get-WmiObject -Namespace 'root' -Class '__NAMESPACE' | Where-Object {$_.Name -eq $Namespace}) {
Write-Verbose "WMI Namespace 'root$Namespace' exists"
}
else {
Write-Verbose "Create WMI namespace 'root$Namespace'"
$Ns = [WMICLASS]'root:__Namespace'
$NewNamespace = $Ns.createInstance()
$NewNamespace.Name = $Namespace
$NewNamespace.Put()
}
}
Function New-WMIClassHC {
if (Get-WmiObject -List -Namespace "root$Namespace" | Where-Object {$_.Name -eq $Class}) {
Write-Verbose "WMI Class '$Class' exists"
}
else {
Write-Verbose "Create WMI Class '$Class'"
$NewClass = New-Object System.Management.ManagementClass ("root$Namespace", [String]::Empty, $Null);
$NewClass['__CLASS'] = $Class
$NewClass.Qualifiers.Add('Static', $true)
$NewClass.Properties.Add('Key', [System.Management.CimType]::String, $false)
$NewClass.Properties['Key'].Qualifiers.Add('Key', $true)
$NewClass.Properties.Add('Value1', [System.Management.CimType]::UInt32, $false)
$NewClass.Properties.Add('Value2', [System.Management.CimType]::String, $false)
$NewClass.Put()
}
}
此时我需要授予新命名空间的 Domain users
权限,以便他们能够在本地客户端上向其中写入数据(无需远程处理)。这是我找到很多信息但现在卡住了的地方。
Microsoft 博客上有一个 script I tried to tweak, but it's overly complicated for my needs and it failed so I found and tweaked the following 代码:
Function Add-WMIPermissions {
[CmdLetBinding()]
Param (
[String]$Principal = 'DOMAIN.NET\Domain users',
[String]$Namespace = 'CustomCMClasses'
)
Function Get-Sid {
Param (
$DSIdentity
)
$ID = new-object System.Security.Principal.NTAccount($DSIdentity)
Return $ID.Translate([System.Security.Principal.SecurityIdentifier]).toString()
}
$Sid = Get-Sid $Principal
$WMISDDL = "A;CI;CCWP;;;$Sid"
$WMISDDLPartialMatch = "A;\w*;\w+;;;$Sid"
$security = Get-WmiObject -Namespace root$Namespace -Class __SystemSecurity
$binarySD = @($null)
$result = $security.PsBase.InvokeMethod('GetSD',$binarySD)
$converter = New-Object system.management.ManagementClass Win32_SecurityDescriptorHelper
$CurrentWMISDDL = $converter.BinarySDToSDDL($binarySD[0])
if (($CurrentWMISDDL.SDDL -match $WMISDDLPartialMatch) -and ($CurrentWMISDDL.SDDL -notmatch $WMISDDL)) {
$NewWMISDDL = $CurrentWMISDDL.SDDL -replace $WMISDDLPartialMatch, $WMISDDL
}
else {
$NewWMISDDL = $CurrentWMISDDL.SDDL += '(' + $WMISDDL + ')'
}
$WMIbinarySD = $converter.SDDLToBinarySD($NewWMISDDL)
$WMIconvertedPermissions = ,$WMIbinarySD.BinarySD
if ($CurrentWMISDDL.SDDL -match $WMISDDL) {
Write-Verbose 'Current WMI Permissions matches desired value'
}
else {
$result = $security.PsBase.InvokeMethod('SetSD',$WMIconvertedPermissions)
if($result='0'){
Write-Verbose 'WMI permissions applied'
}
}
}
Add-WMIPermissions -Verbose
明明权限已正确应用,但用户仍然无法向WMI写入数据。使用 WMI 对我来说是新的,所以非常感谢任何帮助。
查看普通用户(Domain users
)是否有权限的测试代码:
$WMIClass = [WMICLASS]('root\' + $Namespace + ':' + $Class)
$WMIInstance = $WMIClass.CreateInstance()
$WMIInstance.Key = 'Unique value identifier 5'
$WMIInstance.Value1 = 101
$WMIInstance.Value2 = 'Status Ok'
$WMIInstance.Put()
解决了部分写入的问题:
Function Set-WMIPermissionsHC {
Param (
[String]$Namespace = 'CustomCMClasses',
[String]$Class = 'Test',
[String]$Account = 'DOMAIN\Domain users',
[String]$Computer = $env:COMPUTERNAME
)
Function Get-Sid {
Param (
$Account
)
$ID = New-Object System.Security.Principal.NTAccount($Account)
Return $ID.Translate([System.Security.Principal.SecurityIdentifier]).toString()
}
$SID = Get-Sid $Account
$SDDL = "A;CI;CCSWWP;;;$SID"
$DCOMSDDL = "A;;CCDCRP;;;$SID"
$Reg = [WMICLASS]"\$Computer\root\default:StdRegProv"
$DCOM = $Reg.GetBinaryValue(2147483650,'software\microsoft\ole','MachineLaunchRestriction').uValue
$Security = Get-WmiObject -ComputerName $Computer -Namespace "root$Namespace" -Class __SystemSecurity
$Converter = New-Object System.Management.ManagementClass Win32_SecurityDescriptorHelper
$BinarySD = @($null)
$Result = $Security.PsBase.InvokeMethod('GetSD', $BinarySD)
$OutSDDL = $Converter.BinarySDToSDDL($BinarySD[0])
$OutDCOMSDDL = $Converter.BinarySDToSDDL($DCOM)
$NewSDDL = $OutSDDL.SDDL += '(' + $SDDL + ')'
$NewDCOMSDDL = $OutDCOMSDDL.SDDL += '(' + $DCOMSDDL + ')'
$WMIbinarySD = $Converter.SDDLToBinarySD($NewSDDL)
$WMIconvertedPermissions = ,$WMIbinarySD.BinarySD
$DCOMbinarySD = $Converter.SDDLToBinarySD($NewDCOMSDDL)
$DCOMconvertedPermissions = ,$DCOMbinarySD.BinarySD
$Result = $Security.PsBase.InvokeMethod('SetSD', $WMIconvertedPermissions)
$Result = $Reg.SetBinaryValue(2147483650,'software\microsoft\ole','MachineLaunchRestriction', $DCOMbinarySD.binarySD)
Write-Verbose 'WMI Permissions set'
}
感谢this blog and the Microsoft blog解释权限