1

I am blocked with my code

I will try to explain what I would like to do with it, my code is to scan the different windows services, to keep in memory only what uses an .exe and then to search among them the ones that the users have full control of. I would like it to display the service and its rights at the end.

$services = Get-WmiObject win32_service | ?{$_.PathName -like '*.exe*'} | select Name, State, Pathname, StartName  | Out-Null 
foreach ($service in $services) {
$var = "{0}.exe" -f ($Service.PathName -Split ".exe")[0] 
foreach ($right in $var ){

if ( (Get-Acl $var).Access -ccontains "BUILTIN\Utilisateurs FullControl "{
    
    Write-Warning " Exploit detected "
}

 }
 }

thank you in advance for your feedback

JPBlanc
  • 70,406
  • 17
  • 130
  • 175

2 Answers2

5
Get-CimInstance Win32_Service |
  Where-Object { $_.PathName -like '*.exe*'} | 
    Select-Object Name, State, Pathname, StartName |
      ForEach-Object {
        $_.PathName = ($_.PathName -split '(?<=\.exe\b)')[0].Trim('"')
        Add-Member -PassThru -InputObject $_ Acl (Get-Acl -LiteralPath $_.PathName)
      } | 
        Where-Object { 
          $_.Acl.Access.Where({
             $_.IdentityReference -ceq 'BUILTIN\Utilisateurs' -and 
              $_.FileSystemRights -eq 'FullControl' 
          }, 'First').Count -gt 0
        }

Note that I've replaced Get-WmiObject with Get-CimInstance, because the CIM cmdlets superseded the WMI cmdlets in PowerShell v3 (released in September 2012). Therefore, the WMI cmdlets should be avoided, not least because PowerShell (Core) (v6+), where all future effort will go, doesn't even have them anymore. Note that WMI still underlies the CIM cmdlets, however. For more information, see this answer.

The above uses the ForEach-Object call to:

  • update the .PathName property of each object to contain only the - unquoted - path of the executable with each service.

  • add an .Acl property to each object via Add-Member, containing the service executable's ACL, obtained via Get-Acl.

The resulting list of objects is then filtered by those whose service-executable ACL contains an entry for identity BUILTIN\Utilisateurs[1] with full control over the executable.

That is, the resulting objects are effectively those for which you meant to issue Write-Warning " Exploit detected "


As for what you tried:

  • $services = ... | Out-Null by definition captures nothing[2] in variable $services, given that Out-Null's purpose is to suppress output.

  • While $var = "{0}.exe" -f ($Service.PathName -Split ".exe")[0] does extract the executable path (although .exe should be \.exe\b, for robustness), it may include enclosing double quotes, which should be stripped.

  • It's unclear where $rights comes from.

  • You cannot use -ccontains to match across multiple properties of an object, and note that the purpose of the -contains operator and its variants is to test presence of a value in full, in a collection, not to look for a substring in a single string.


[1] It's interesting to see that these identity references are localized; the equivalent on a US-English system would be BUILTIN\Users. Generally, it would be better to obtain a culture-independent representation of this identity, namely its SID, and use that for comparison: $_.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]).Value -eq 'S-1-5-32-545'

[2] Loosely speaking, $null; technically, it is the singleton value that PowerShell uses to signal "no output received", [System.Management.Automation.Internal.AutomationNull]::Value.

mklement0
  • 382,024
  • 64
  • 607
  • 775
1

If I begin by the begining you terminate your first line by | out-null so $services contains nothing.

Then you forgot a ")" in your if.

You should present your code with indentations.

Be carefull :

"{0}.exe" -f ("C:\WINDOWS\system32\msiexec.exe /V"-Split ".exe")[0] 

Gives :

C:\WINDOWS\system32\ms.exe

So use a '\' before the '.' :

"{0}.exe" -f ("C:\WINDOWS\system32\msiexec.exe /V"-Split "\.exe")[0]

which gives (regular expression story ?):

C:\WINDOWS\system32\msiexec.exe

So it will give something like that.

$services = Get-WmiObject win32_service | ?{$_.PathName -like '*.exe*'} | select Name, State, Pathname, StartName  
foreach ($service in $services) {
  $var = "{0}.exe" -f ($Service.PathName -Split "\.exe")[0] 
  if ((Get-Acl $var.Trim('"') -ErrorAction Stop) -ccontains "BUILTIN\Utilisateurs FullControl "){
    Write-Warning " Exploit detected "
  }
}
JPBlanc
  • 70,406
  • 17
  • 130
  • 175