question

vineeth-2730 avatar image
0 Votes"
vineeth-2730 asked EdWalsh-0783 commented

get specific service data from out-object output in powershell

I have used the below code to get all the user rights data, but i want to filter out just the Privilege = "SeServiceLogonright" and PrivilegeName = "Log on as service", how can i get the required data, please help,

requires -version 2


Fail script if we can't find SecEdit.exe

$SecEdit = Join-Path ([Environment]::GetFolderPath([Environment+SpecialFolder]::System)) "SecEdit.exe"
if ( -not (Test-Path $SecEdit) ) {
Write-Error "File not found - '$SecEdit'" -Category ObjectNotFound
exit
}

LookupPrivilegeDisplayName Win32 API doesn't resolve logon right display

names, so use this hashtable

$UserLogonRights = @{
"SeBatchLogonRight" = "Log on as a batch job"
"SeDenyBatchLogonRight" = "Deny log on as a batch job"
"SeDenyInteractiveLogonRight" = "Deny log on locally"
"SeDenyNetworkLogonRight" = "Deny access to this computer from the network"
"SeDenyRemoteInteractiveLogonRight" = "Deny log on through Remote Desktop Services"
"SeDenyServiceLogonRight" = "Deny log on as a service"
"SeInteractiveLogonRight" = "Allow log on locally"
"SeNetworkLogonRight" = "Access this computer from the network"
"SeRemoteInteractiveLogonRight" = "Allow log on through Remote Desktop Services"
"SeServiceLogonRight" = "Log on as a service"
}

Create type to invoke LookupPrivilegeDisplayName Win32 API

$Win32APISignature = @'
[DllImport("advapi32.dll", SetLastError=true)]
public static extern bool LookupPrivilegeDisplayName(
string systemName,
string privilegeName,
System.Text.StringBuilder displayName,
ref uint cbDisplayName,
out uint languageId
);
'@
$AdvApi32 = Add-Type advapi32 $Win32APISignature -Namespace LookupPrivilegeDisplayName -PassThru

Use LookupPrivilegeDisplayName Win32 API to get display name of privilege

(except for user logon rights)

function Get-PrivilegeDisplayName {
param(
[String] $name
)
$displayNameSB = New-Object System.Text.StringBuilder 1024
$languageId = 0
$ok = $AdvApi32::LookupPrivilegeDisplayName($null, $name, $displayNameSB, [Ref] $displayNameSB.Capacity, [Ref] $languageId)
if ( $ok ) {
$displayNameSB.ToString()
}
else {
# Doesn't lookup logon rights, so use hashtable for that
if ( $UserLogonRights[$name] ) {
$UserLogonRights[$name]
}
else {
$name
}
}
}

Outputs list of hashtables as a PSObject

function Out-Object {
param(
[System.Collections.Hashtable[]] $hashData
)
$order = @()
$result = @{}
$hashData | ForEach-Object {
$order += ($.Keys -as [Array])[0]
$result += $

}
New-Object PSObject -Property $result | Select-Object $order
}

Translates a SID in the form *S-1-5-... to its account name;

function Get-AccountName {
param(
[String] $principal
)
if ( $principal[0] -eq "*" ) {
$sid = New-Object System.Security.Principal.SecurityIdentifier($principal.Substring(1))
$sid.Translate([Security.Principal.NTAccount])
}
else {
$principal
}
}

$TemplateFilename = Join-Path ([IO.Path]::GetTempPath()) ([IO.Path]::GetRandomFileName())
$LogFilename = Join-Path ([IO.Path]::GetTempPath()) ([IO.Path]::GetRandomFileName())
$StdOut = & $SecEdit /export /cfg $TemplateFilename /areas USER_RIGHTS /log $LogFilename
if ( $LASTEXITCODE -eq 0 ) {
Select-String '^(Se\S+) = (\S+)' $TemplateFilename | Foreach-Object {
$Privilege = $.Matches[0].Groups[1].Value
$Principals = $
.Matches[0].Groups[2].Value -split ','
foreach ( $Principal in $Principals ) {
Out-Object `
@{"Privilege" = $Privilege},
@{"PrivilegeName" = Get-PrivilegeDisplayName $Privilege},
@{"Principal" = Get-AccountName $Principal}
}
}
}
else {
$OFS = ""
Write-Error "$StdOut"
}
Remove-Item $TemplateFilename,$LogFilename -ErrorAction SilentlyContinue

windows-server-powershell
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

IanXue-MSFT avatar image
0 Votes"
IanXue-MSFT answered EdWalsh-0783 commented

Hi,

Please check if this works for you. Just add some conditional statements.

 #requires -version 2
 $SpecificPrivilege = "SeServiceLogonright" 
    
 # Fail script if we can't find SecEdit.exe
 $SecEdit = Join-Path ([Environment]::GetFolderPath([Environment+SpecialFolder]::System)) "SecEdit.exe"
 if ( -not (Test-Path $SecEdit) ) {
   Write-Error "File not found - '$SecEdit'" -Category ObjectNotFound
   exit
 }
    
 # LookupPrivilegeDisplayName Win32 API doesn't resolve logon right display
 # names, so use this hashtable
 $UserLogonRights = @{
   "SeBatchLogonRight"                 = "Log on as a batch job"
   "SeDenyBatchLogonRight"             = "Deny log on as a batch job"
   "SeDenyInteractiveLogonRight"       = "Deny log on locally"
   "SeDenyNetworkLogonRight"           = "Deny access to this computer from the network"
   "SeDenyRemoteInteractiveLogonRight" = "Deny log on through Remote Desktop Services"
   "SeDenyServiceLogonRight"           = "Deny log on as a service"
   "SeInteractiveLogonRight"           = "Allow log on locally"
   "SeNetworkLogonRight"               = "Access this computer from the network"
   "SeRemoteInteractiveLogonRight"     = "Allow log on through Remote Desktop Services"
   "SeServiceLogonRight"               = "Log on as a service"
 }
    
 # Create type to invoke LookupPrivilegeDisplayName Win32 API
 $Win32APISignature = @'
 [DllImport("advapi32.dll", SetLastError=true)]
 public static extern bool LookupPrivilegeDisplayName(
   string systemName,
   string privilegeName,
   System.Text.StringBuilder displayName,
   ref uint cbDisplayName,
   out uint languageId
 );
 '@
 $AdvApi32 = Add-Type advapi32 $Win32APISignature -Namespace LookupPrivilegeDisplayName -PassThru
    
 # Use LookupPrivilegeDisplayName Win32 API to get display name of privilege
 # (except for user logon rights)
 function Get-PrivilegeDisplayName {
   param(
     [String] $name
   )
   $displayNameSB = New-Object System.Text.StringBuilder 1024
   $languageId = 0
   $ok = $AdvApi32::LookupPrivilegeDisplayName($null, $name, $displayNameSB, [Ref] $displayNameSB.Capacity, [Ref] $languageId)
   if ( $ok ) {
     $displayNameSB.ToString()
   }
   else {
     # Doesn't lookup logon rights, so use hashtable for that
     if ( $UserLogonRights[$name] ) {
       $UserLogonRights[$name]
     }
     else {
       $name
     }
   }
 }
    
 # Outputs list of hashtables as a PSObject
 function Out-Object {
   param(
     [System.Collections.Hashtable[]] $hashData
   )
   $order = @()
   $result = @{}
   $hashData | ForEach-Object {
     $order += ($_.Keys -as [Array])[0]
     $result += $_
   }
   New-Object PSObject -Property $result | Select-Object $order
 }
    
 # Translates a SID in the form *S-1-5-... to its account name;
 function Get-AccountName {
   param(
     [String] $principal
   )
   if ( $principal[0] -eq "*" ) {
     $sid = New-Object System.Security.Principal.SecurityIdentifier($principal.Substring(1))
     $sid.Translate([Security.Principal.NTAccount])
   }
   else {
     $principal
   }
 }
    
 $TemplateFilename = Join-Path ([IO.Path]::GetTempPath()) ([IO.Path]::GetRandomFileName())
 $LogFilename = Join-Path ([IO.Path]::GetTempPath()) ([IO.Path]::GetRandomFileName())
 $StdOut = & $SecEdit /export /cfg $TemplateFilename /areas USER_RIGHTS /log $LogFilename
 if ( $LASTEXITCODE -eq 0 ) {
   Select-String '^(Se\S+) = (\S+)' $TemplateFilename | Foreach-Object {
     $Privilege = $_.Matches[0].Groups[1].Value
     if($Privilege -eq $SpecificPrivilege){
       $Principals = $_.Matches[0].Groups[2].Value -split ','
       foreach ( $Principal in $Principals ) {
         $PrivilegeName = Get-PrivilegeDisplayName $Privilege    
         Out-Object `
           @{"Privilege" = $Privilege},
           @{"PrivilegeName" = $PrivilegeName},
           @{"Principal" = Get-AccountName $Principal}
       }     
     }
   }
 }
 else {
   $OFS = ""
   Write-Error "$StdOut"
 }
 Remove-Item $TemplateFilename,$LogFilename -ErrorAction SilentlyContinue

Best Regards,
Ian Xue
============================================
If the Answer is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Any way to make this work on Remote Servers and output to a single csv, with an additional column for Hostname of server?

  1. Want to feed this a list of servers.

  2. It runs it on each of the servers,

  3. and the final output is a single csv file showing this output,

  4. but with an additional column for HostName so you can see what servers its from.


0 Votes 0 ·