I’m taking a quick break from our Empire series to bring you something my ATD teammate Matt Nelson and myself have been working on over the last month or so- a project called PowerSCCM. This is the first primarily defensive-oriented post I’ve published, but fear not, more offensive material is in the hopper ;)
Using Microsoft’s System Center Configuration Manager (SCCM) for unintended purposes has been on a people’s radar since Dave Kennedy’s “Owning One To Rule Them All” presentation at Defcon 20. Matt expanded on this type of material in his ShmooCon Firetalk “Red Team Upgrades: Using SCCM for Malware Deployment” and accompanying blog post. I’ve recently started getting involved in some defensive development with @jaredcatkinson and @mattifestation, and we began to look into SCCM as a data source for defensive/hunt purposes. We’re fans of taking advantage of existing solutions and infrastructure for both defensive and offensive applications, and the amount of host data SCCM collects makes it an ideal candidate for finding maliciousness in an enterprise. It also has the benefit of not tipping your hand to adversaries who may be monitoring for things like defensive agents.
This post will cover the background and design considerations of PowerSCCM, as well as some of the defensive applications of the toolset. @enigma0x3 just released a post as well that covers more background on SCCM, as well as the offensive capabilities of the project. Definitely check out his post in order to gain a more complete knowledge of PowerSCCM and its capabilities.
But before I start, here’s some background and previous work on using SCCM for defensive purposes:
- “Using SCCM to violate best practices” by Brandon Helms
- “Microsoft’s Accidental Enterprise DFIR Tool” by Keith Tyler
- “SCCM (System Center Configuration Manager) and Incident Response” part 1 and part 2 on the Hexacorn blog
- “Mining For Evil” by John McLeod and Mike Pilkington at the SANS 2013 DFIR Summit
There are a few existing SCCM toolsets as well (that I’m aware of, if I missed something let me know) which PowerSCCM drew inspiration from:
- Brandon Helms’ SCCM-Enumeration
- SCCM POSH by Rikard Rönnkvist
Note: PowerSCCM is a new codebase with limited testing, so if you hit an issue or have a suggestion for something else to collect, let us know!
PowerSCCM’s goal is to provide an easy way to connect to, query, and manipulate an installation of SCCM. While there is a set of existing Microsoft-supported SCCM cmdlets, PowerSCCM was built as a single self-contained file that’s PowerShell version 2.0 compatible. This was done to ensure it works in nearly all environments and functions appropriately in an offensive context. You can load up PowerSCCM either by cloning the repository and dropping it into C:\Windows\System32\WindowsPowerShell\v1.0\Modules\ (or %UserProfile%\Documents\WindowsPowerShell\Modules) and executing Import-Module PowerSCCM, or by importing the .ps1 directly.
PowerSCCM integrates a session model similar to the CimSession cmdlets. To create a new connection to a SCCM server over WMI or SQL (more on this later), use New-SccmSession with an optional -Credential parameter to specify alternate credentials for the connection.
If you don’t already know the SCCM site code, you can enumerate this with Find-SccmSiteCode, which also accepts -ConnectionType and -Credential parameters. You can also use Find-LocalSccmInfo to enumerate the SCCM site configuration for the current host you’re executing PowerSCCM on, granted that it’s enrolled in SCCM.
New-SCCMSession will return a custom PowerSccm.Session object which can be used with any of the querying cmdlets though the -Session argument. You can also use Get-SccmSession to return all currently registered session objects and pipe the results directly to most cmdlets.
If you have multiple sessions established, you can instruction Get-SccmSession to only return sessions matching a particular -Id, -Name, -ComputerName, -SiteCode, or -ConnectionType.
The SCCM SQL Schema
One way to interact with a SCCM installation is through a MSSQL database connection directly into the SCCM database for a particular site. You can use -ConnectionType SQL with New-SCCMSession to specify a SQL connection for the session.
The SCCM schema is not pretty and is not well documented. Slide 14 from the “Mining For Evil” presentation shows what I mean:
It took Matt Nelson and myself a while to get a grasp on the backend schema and what fields proved the most useful. There’s some Microsoft documentation on a few interesting views, and the “Mining For Evil” and Keith’s blog post were also good resources. Here are some of the tables/views that we ended up with:
- v_GS_SERVICE – currently installed services
- v_HS_SERVICE – historical information on installed services
- v_GS_AUTOSTART_SOFTWARE – information about programs in a few auto start locations (note that this is not as complete as something like Autoruns)
- v_GS_PROCESS – information on currently running processes
- v_HS_PROCESS – historical information on running processes
- v_GS_CCM_RECENTLY_USED_APPS – information on recently used applications
- v_GS_SYSTEM_DRIVER – details on drivers currently installed
- v_GS_SYSTEM_CONSOLE_USER – information on console usage, complete with user information
- v_GS_SoftwareFile – details on inventoried files (more on this in ‘Tuning SCCM for Defense’ below)
- v_GS_BROWSER_HELPER_OBJECT – information on installed browser helper objects
- v_GS_SHARE – details on created shares
- vMDMUsersPrimaryMachines – details on primary user -> machine mappings
SCCM: WMI vs SQL
It’s also possible to interact with an SCCM installation through a number of WMI classes that reside in the SMS WMI provider. While Microsoft states that “…there is no direct mapping for a SQL view and the SMS Provider WMI schema class…“, in general there’s a fairly reasonable mapping between parts of the SQL schema and an associated WMI class. While Microsoft DOES provide documentation of the Configuration Manager SMS Namespace, I recommend WMI Explorer for exploring the WMI classes yourself on a specific SCCM server.
So SQL versus WMI for SCCM administration, why use one over the other? Why not just pick the best method and build the toolset around that?
In order to interact with the WMI classes on a remote SCCM server, 9 times out of 10 the account context you’re querying information from will need to have administrative rights on the remote system. In some environments the permissions for the SCCM SQL database are delegated more granularly, so the connection method you choose may be influenced by the privileges of the user context you’re operating in.
For querying interesting information we want (like installed services or applications) the exact results returned can also vary between the WMI and SQL methods. The SQL Schema has various prebuilt views that pull from different tables, and we can also execute joins to pull together additional information for a query. An example in PowerSCCM is pulling in the stored IP addresses for computers that show up in query results. We can execute these joins through the SQL statement itself, reducing the amount of post-processing we need to do by offloading some of the work onto the SCCM SQL server itself.
With the WMI Query Language (WQL) you’re restricted to basic filters and the data contained within each WMI class, i.e. you can not execute the equivalent of JOIN. And since the SQL Schema and WMI Namespace do not line up perfectly, you will get differing results, so which connection method you use will be situation-dependent. We generally like SQL connections for defense and WMI connections for offense.
PowerSCCM implements both the SQL query and the WMI query for cmdlets where possible. This means you can pass a session from Get-SccmSession to a cmdlet like Get-SccmService and you will get results regardless of the connection method.
Tuning SCCM for Defense
In order to get the most defensive value out an SCCM installation, it helps to enable additional hardware and software inventory settings as several interesting things (like drivers) are not inventoried by default.
In the System Center Configuration Manager interface go to Administration -> ‘Client Settings’ and open the properties of the client settings you’re currently pushing out. Under ‘Hardware Inventory’ click ‘Set Classes’ and make sure the following classes are enabled:
- AutoStart Software – Asset Intelligence (SMS_AutoStartSoftware)
- Browser Helper Object – Asset Intelligence (SMS_BrowserHelperObject)
- Driver – VxD (Win32_DriverVXD)
- Process (Win32_Process)
- Recently Used Applications (CCM_RecentlyUsedApps)
- Shares (Win32_Share)
- System Console Usage – Asset Intelligence (SMS_SystemConsoleUsage)
- System Console User – Asset Intelligence (SMS_SystemConsoleUser)
You can also modify the ‘Hardware inventory schedule’ if desired, which changes the inventorying interval (default of 7 days).
Next, ensure that under Settings, ‘Software Metering’ is enabled and the schedule is what you want for your environment:
Finally, under ‘Software Inventory’ consider setting ‘Inventory these file types’ to all .exe’s on all hard disks:
Now, on to what you can do with all this inventoried information!
|Get-SccmService||Information about the current set of running services on Sccm clients|
|Get-SccmServiceHistory||Information about the historical set of running services on Sccm clients|
|Get-SccmAutoStart||Information about programs registered in various autostart locations on Sccm clients|
|Get-SccmProcess||Information about the current set of running processes on Sccm clients|
|Get-SccmProcessHistory||Information about the historical set of running processes on Sccm clients|
|Get-SccmRecentlyUsedApplication||Information on recently launched applications on Sccm clients|
|Get-SccmDriver||Information on drivers installed on Sccm clients|
|Get-SccmConsoleUsage||Information on console usage on Sccm clients, complete with user information|
|Get-SccmSoftwareFile||Information on inventoried software files|
|Get-SccmBrowserHelperObject||Information on browser helper objects installed on Sccm clients|
|Find-SccmRenamedCMD||Finds renamed cmd.exe executables using Get-SccmRecentlyUsedApplication and appropriate filters|
|Find-SccmUnusualEXE||Finds recently launched applications that don't end in *.exe using Get-SccmRecentlyUsedApplication and appropriate filters|
|Find-SccmRareApplication||Finds the rarest -Limit
|Find-SccmPostExploitation||Finds recently launched applications commonly used in post-exploitation|
|Find-SccmPostExploitationFile||Finds indexed .exe's commonly used in post-exploitation|
|Find-SccmMimikatz||Finds launched mimikatz instances by searching the 'FileDescription' and 'CompanyName' fields of recently launched applications|
|Find-SccmMimikatzFile||Finds inventoried mimikatz.exe instances by searching the 'FileDescription' field of inventoried .exe's|
SCCM has great potential for incident response/hunt applications and deserves a spot in the defensive tool belt. Hopefully PowerSCCM can provide defenders with a flexible interface for interfacing with SCCM installations and spark ideas for what else the information from SCCM can be used for. The cmdlets in the project are just a start, so if you can think of any other interesting ideas for finding ‘likely bad’ let us know! And be sure to check out Matt Nelson’s post for the offensive capabilities of PowerSCCM.
5 thoughts on “PowerSCCM”
Pingback: Offensive Operations with PowerSCCM | enigma0x3
Fyi, sccm uses extended wmi query language which is perfectly capable of doing joins.
What is an example of that syntax? The Microsoft documentation for WQL doesn’t seem to call out JOINs.
accidentally ran into your post again. Never noticed your follow-up question.
Extended wql is documented https://docs.microsoft.com/en-us/sccm/develop/core/understand/extended-wmi-query-language
Pingback: MMS 2019: What’d We Learn? – Dam Good Admin