@@ -865,27 +865,34 @@ function Get-ModifiablePath {
865
865
else {
866
866
ForEach($SeparationCharacterSet in $SeparationCharacterSets) {
867
867
$TargetPath.Split($SeparationCharacterSet) | Where-Object {$_ -and ($_.trim() -ne '')} | ForEach-Object {
868
+
868
869
if(($SeparationCharacterSet -notmatch ' ')) {
869
- $TempPath = $([System.Environment]::ExpandEnvironmentVariables($_))
870
870
871
- if(Test-Path -Path $TempPath -ErrorAction SilentlyContinue) {
872
- $CandidatePaths += Resolve-Path -Path $TempPath | Select-Object -ExpandProperty Path
873
- }
874
- else {
875
- # if the path doesn't exist, check if the parent folder allows for modification
876
- try {
877
- $ParentPath = Split-Path $TempPath -Parent
878
- if($ParentPath -and (Test-Path -Path $ParentPath )) {
879
- $CandidatePaths += Resolve-Path -Path $ParentPath -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Path
880
- }
871
+ $TempPath = $([System.Environment]::ExpandEnvironmentVariables($_)).Trim()
872
+
873
+ if($TempPath -and ($TempPath -ne '')) {
874
+ if(Test-Path -Path $TempPath -ErrorAction SilentlyContinue) {
875
+ # if the path exists, resolve it and add it to the candidate list
876
+ $CandidatePaths += Resolve-Path -Path $TempPath | Select-Object -ExpandProperty Path
881
877
}
882
- catch {
883
- # because Split-Path doesn't handle -ErrorAction SilentlyContinue nicely
878
+
879
+ else {
880
+ # if the path doesn't exist, check if the parent folder allows for modification
881
+ try {
882
+ $ParentPath = (Split-Path -Path $TempPath -Parent).Trim()
883
+ if($ParentPath -and ($ParentPath -ne '') -and (Test-Path -Path $ParentPath )) {
884
+ $CandidatePaths += Resolve-Path -Path $ParentPath | Select-Object -ExpandProperty Path
885
+ }
886
+ }
887
+ catch {
888
+ # trap because Split-Path doesn't handle -ErrorAction SilentlyContinue nicely
889
+ }
884
890
}
885
891
}
886
892
}
887
893
else {
888
- $CandidatePaths += Resolve-Path -Path $([System.Environment]::ExpandEnvironmentVariables($_)) -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Path
894
+ # if the separator contains a space
895
+ $CandidatePaths += Resolve-Path -Path $([System.Environment]::ExpandEnvironmentVariables($_)) -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Path | ForEach-Object {$_.Trim()} | Where-Object {($_ -ne '') -and (Test-Path -Path $_)}
889
896
}
890
897
}
891
898
}
@@ -1024,9 +1031,9 @@ function Add-ServiceDacl {
1024
1031
service with using the GetServiceHandle Win32 API call and then uses
1025
1032
QueryServiceObjectSecurity to retrieve a copy of the security descriptor for the service.
1026
1033
1027
- .PARAMETER Service
1034
+ .PARAMETER Name
1028
1035
1029
- An array of one or more ServiceProcess.ServiceController objects from Get-Service. Required .
1036
+ An array of one or more service names to add a service Dacl for. Passable on the pipeline .
1030
1037
1031
1038
.EXAMPLE
1032
1039
@@ -1051,19 +1058,20 @@ function Add-ServiceDacl {
1051
1058
1052
1059
[OutputType('ServiceProcess.ServiceController')]
1053
1060
param (
1054
- [Parameter(Mandatory=$True, ValueFromPipeline=$True)]
1055
- [ServiceProcess.ServiceController[]]
1061
+ [Parameter(Position=0, Mandatory=$True, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)]
1062
+ [Alias('ServiceName')]
1063
+ [String[]]
1056
1064
[ValidateNotNullOrEmpty()]
1057
- $Service
1065
+ $Name
1058
1066
)
1059
1067
1060
1068
BEGIN {
1061
1069
filter Local:Get-ServiceReadControlHandle {
1062
1070
[OutputType([IntPtr])]
1063
1071
param (
1064
1072
[Parameter(Mandatory=$True, ValueFromPipeline=$True)]
1065
- [ServiceProcess.ServiceController]
1066
1073
[ValidateNotNullOrEmpty()]
1074
+ [ValidateScript({ $_ -as 'ServiceProcess.ServiceController' })]
1067
1075
$Service
1068
1076
)
1069
1077
@@ -1078,13 +1086,17 @@ function Add-ServiceDacl {
1078
1086
}
1079
1087
1080
1088
PROCESS {
1081
- ForEach ($IndividualService in $Service) {
1089
+ ForEach($ServiceName in $Name) {
1090
+
1091
+ $IndividualService = Get-Service -Name $ServiceName -ErrorAction Stop
1092
+
1082
1093
try {
1094
+ Write-Verbose "Add-ServiceDacl IndividualService : $($IndividualService.Name)"
1083
1095
$ServiceHandle = Get-ServiceReadControlHandle -Service $IndividualService
1084
1096
}
1085
1097
catch {
1086
1098
$ServiceHandle = $Null
1087
- Write-Warning "Error opening up the service handle with read control for: $($IndividualService.Name)"
1099
+ Write-Verbose "Error opening up the service handle with read control for $($IndividualService.Name) : $_ "
1088
1100
}
1089
1101
1090
1102
if ($ServiceHandle -and ($ServiceHandle -ne [IntPtr]::Zero)) {
@@ -1214,7 +1226,7 @@ function Set-ServiceBinPath {
1214
1226
}
1215
1227
catch {
1216
1228
$ServiceHandle = $Null
1217
- Write-Warning "Error opening up the service handle with read control for $($TargetService.Name) : $_"
1229
+ Write-Verbose "Error opening up the service handle with read control for $IndividualService : $_"
1218
1230
}
1219
1231
1220
1232
if ($ServiceHandle -and ($ServiceHandle -ne [IntPtr]::Zero)) {
@@ -1224,7 +1236,7 @@ function Set-ServiceBinPath {
1224
1236
$Result = $Advapi32::ChangeServiceConfig($ServiceHandle, $SERVICE_NO_CHANGE, $SERVICE_NO_CHANGE, $SERVICE_NO_CHANGE, "$binPath", [IntPtr]::Zero, [IntPtr]::Zero, [IntPtr]::Zero, [IntPtr]::Zero, [IntPtr]::Zero, [IntPtr]::Zero);$LastError = [Runtime.InteropServices.Marshal]::GetLastWin32Error()
1225
1237
1226
1238
if ($Result -ne 0) {
1227
- Write-Verbose "binPath for $($TargetService.Name) successfully set to '$binPath'"
1239
+ Write-Verbose "binPath for $IndividualService successfully set to '$binPath'"
1228
1240
$True
1229
1241
}
1230
1242
else {
@@ -1364,7 +1376,7 @@ function Test-ServiceDaclPermission {
1364
1376
1365
1377
ForEach($IndividualService in $Name) {
1366
1378
1367
- $TargetService = Get-Service -Name $IndividualService | Add-ServiceDacl
1379
+ $TargetService = $IndividualService | Add-ServiceDacl
1368
1380
1369
1381
if($TargetService -and $TargetService.Dacl) {
1370
1382
@@ -1381,7 +1393,7 @@ function Test-ServiceDaclPermission {
1381
1393
ForEach($TargetPermission in $TargetPermissions) {
1382
1394
# check permissions && style
1383
1395
if (($ServiceDacl.AccessRights -band $AccessMask[$TargetPermission]) -ne $AccessMask[$TargetPermission]) {
1384
- Write-Verbose "Current user doesn't have '$TargetPermission' for $($TargetService.Name)"
1396
+ # Write-Verbose "Current user doesn't have '$TargetPermission' for $($TargetService.Name)"
1385
1397
$AllMatched = $False
1386
1398
break
1387
1399
}
@@ -1394,7 +1406,7 @@ function Test-ServiceDaclPermission {
1394
1406
ForEach($TargetPermission in $TargetPermissions) {
1395
1407
# check permissions || style
1396
1408
if (($ServiceDacl.AccessRights -band $AccessMask[$TargetPermission]) -eq $AccessMask[$TargetPermission]) {
1397
- Write-Verbose "Current user has '$TargetPermission' for $($TargetService.Name) "
1409
+ Write-Verbose "Current user has '$TargetPermission' for $IndividualService "
1398
1410
$TargetService
1399
1411
break
1400
1412
}
@@ -1404,7 +1416,7 @@ function Test-ServiceDaclPermission {
1404
1416
}
1405
1417
}
1406
1418
else {
1407
- Write-Warning "Error enumerating the Dacl for service $($TargetService.Name) "
1419
+ Write-Verbose "Error enumerating the Dacl for service $IndividualService "
1408
1420
}
1409
1421
}
1410
1422
}
@@ -1434,14 +1446,15 @@ function Get-ServiceUnquoted {
1434
1446
1435
1447
https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/windows/local/trusted_service_path.rb
1436
1448
#>
1449
+ [CmdletBinding()] param()
1437
1450
1438
1451
# find all paths to service .exe's that have a space in the path and aren't quoted
1439
1452
$VulnServices = Get-WmiObject -Class win32_service | Where-Object {$_} | Where-Object {($_.pathname -ne $null) -and ($_.pathname.trim() -ne '')} | Where-Object { (-not $_.pathname.StartsWith("`"")) -and (-not $_.pathname.StartsWith("'"))} | Where-Object {($_.pathname.Substring(0, $_.pathname.ToLower().IndexOf(".exe") + 4)) -match ".* .*"}
1440
1453
1441
1454
if ($VulnServices) {
1442
1455
ForEach ($Service in $VulnServices) {
1443
1456
1444
- $ModifiableFiles = $Service.pathname | Get-ModifiablePath
1457
+ $ModifiableFiles = $Service.pathname.split(' ') | Get-ModifiablePath
1445
1458
1446
1459
$ModifiableFiles | Where-Object {$_ -and $_.ModifiablePath -and ($_.ModifiablePath -ne '')} | Foreach-Object {
1447
1460
$ServiceRestart = Test-ServiceDaclPermission -PermissionSet 'Restart' -Name $Service.name
@@ -1487,6 +1500,7 @@ function Get-ModifiableServiceFile {
1487
1500
1488
1501
Get a set of potentially exploitable service binares/config files.
1489
1502
#>
1503
+ [CmdletBinding()] param()
1490
1504
1491
1505
Get-WMIObject -Class win32_service | Where-Object {$_ -and $_.pathname} | ForEach-Object {
1492
1506
@@ -1537,6 +1551,7 @@ function Get-ModifiableService {
1537
1551
1538
1552
Get a set of potentially exploitable services.
1539
1553
#>
1554
+ [CmdletBinding()] param()
1540
1555
1541
1556
Get-Service | Test-ServiceDaclPermission -PermissionSet 'ChangeConfig' | ForEach-Object {
1542
1557
@@ -1612,7 +1627,7 @@ function Get-ServiceDetail {
1612
1627
$_
1613
1628
}
1614
1629
catch{
1615
- Write-Warning "Error: $_"
1630
+ Write-Verbose "Error: $_"
1616
1631
$null
1617
1632
}
1618
1633
}
@@ -3689,12 +3704,15 @@ function Get-CachedGPPPassword {
3689
3704
# discover any locally cached GPP .xml files
3690
3705
$XMlFiles = Get-ChildItem -Path $AllUsers -Recurse -Include 'Groups.xml','Services.xml','Scheduledtasks.xml','DataSources.xml','Printers.xml','Drives.xml' -Force -ErrorAction SilentlyContinue
3691
3706
3692
- if ( -not $XMlFiles ) { throw 'No preference files found.' }
3707
+ if ( -not $XMlFiles ) {
3708
+ Write-Verbose 'No preference files found.'
3709
+ }
3710
+ else {
3711
+ Write-Verbose "Found $($XMLFiles | Measure-Object | Select-Object -ExpandProperty Count) files that could contain passwords."
3693
3712
3694
- Write-Verbose "Found $($XMLFiles | Measure-Object | Select-Object -ExpandProperty Count) files that could contain passwords."
3695
-
3696
- ForEach ($File in $XMLFiles) {
3697
- Get-GppInnerFields $File.Fullname
3713
+ ForEach ($File in $XMLFiles) {
3714
+ Get-GppInnerFields $File.Fullname
3715
+ }
3698
3716
}
3699
3717
}
3700
3718
@@ -3839,7 +3857,7 @@ function Invoke-AllChecks {
3839
3857
3840
3858
"`n`n[*] Checking %PATH% for potentially hijackable DLL locations..."
3841
3859
$Results = Find-PathDLLHijack
3842
- $Results | Foreach-Object {
3860
+ $Results | Where-Object {$_} | Foreach-Object {
3843
3861
$AbuseString = "Write-HijackDll -DllPath '$($_.ModifiablePath)\wlbsctrl.dll'"
3844
3862
$_ | Add-Member Noteproperty 'AbuseFunction' $AbuseString
3845
3863
$_
0 commit comments