Back to the Basics: Detecting Malicious Windows Services With Tanium
“The theme I really want you to take away [from this presentation] is: if you really want to protect your network, you really have to know your network.” TAO Chief, NSA, USENIX Enigma 2016
An essential part of “knowing your network” is tracking endpoint persistence mechanisms – the myriad of ways in which an operating system can automatically load and execute code. For over a decade, background services have been one of the most commonly utilized persistence locations in Windows. Available since the era of Windows NT and XP, services provide a reliable way to discretely load processes and libraries in the background upon system boot, user logon, or triggered conditions. While much attention is often paid to tracking novel, covert persistence techniques, it’s important to not lose sight of the basics – especially given how prevalent service-based malware remains.
Keeping a close watch on the system services running across an entire enterprise used to be an impossible task. The state-of-the-art two years ago would be a monthly audit with extensive manual analysis to find anomalies. Today, this can be done on a continuous, automated basis using the Tanium platform and its Incident Response module.
Remote Access Tools (RATs) and other malware can persist as services in three different ways: as stand-alone service executables, hosted service modules and COM+ components. In this post, I’ll review the different ways that attackers abuse Windows services, and how Tanium can help you detect them.
Stand-Alone Services
Stand-alone services run an executable file or command-line specified in the “ImagePath” value within their respective configuration registry keys. The Windows registry contains the configuration settings for all current services under the parent key “HKLM\System\CurrentControlSet\Services”.
Tanium has long-provided the ability to monitor Windows services at-scale (across the entire Windows inventory). The “Service Status with MD5 hash” sensor, for example, collects and compares the service name, state (Running, Stopped, etc.), command-line, ImagePath hash and the user context under which the service is running. This means that stand-alone services will stand out with a low frequency-of-occurrence count if their configuration or state is unusual, or differs among identically named instances. Tanium users have utilized this sensor to identify misconfigured but legitimate services based on status (such as stopped antivirus services), as well as rogue services on the basis of their name, user context, command-line, or differing ImagePath hashes for identically-named service instances.
From an attacker perspective, stand-alone services are not as popular because the executable path is readily available using Task Manager, tasklist.exe, or Service Control Manager queries. Consider an attacker that wishes to disguise malware under the legitimate service name “Print Spooler”. This service has an executable path of “c:\windows\system32\spoolsv.exe”. A tampered instance of the service might load a malicious binary from a file name or location with subtle changes, such as “c:\windows\spoolsv.exe” or “c:\windows\system32\spoolsvc.exe”. This technique can effectively hide malware from “at-a-glance” analysis, but is easily defeated by statistical stacking of the ImagePath or Command Line. Tanium sensors like “Service Status with MD5 hash” will quickly stack these outliers to the edge of the herd for follow-up analysis and investigation.
Hosted Services and COM+ Applications
Hosted services are implemented as libraries – typically Dynamic Link Libraries (DLLs) – rather than stand-alone executable files. They are typically loaded by Windows service hosting process, “svchost.exe”. The screenshot below shows the output of Tanium’s “Service Status with MD5 Hash” sensor for several hosted services, such as “Application Management” and “Base Filtering Engine”. For each service, the supplied hash is that of “svchost.exe” rather than the hosted DLL.
How does Windows know which DLL to load for a given hosted service? The registry configuration for each of these services includes a sub-key and value, “\Parameters\ServiceDLL”, that points to the DLL to be loaded. For efficiency and security reasons, Windows also loads hosted services in groups under shared instances of the hosting process (as opposed to spawning a separate instance of “svchost.exe” for each).
Hosted service groups are configured under the registry key “HKLM\Software\Microsoft\Windows NT\CurrentVersion\Svchost”. Each group provides different levels of access; “netsvcs” is one of the highest-privileged groups for services with network access, and therefore frequently used by attackers. The “netsvcs” value is a string array of service names to be loaded in this group, as depicted in the screenshot below.
Attackers can abuse hosted services to load a malicious DLL in several ways. One approach is to choose a hosted service name that is “unused” – i.e., for which there is no service configured under “HKLM\SYSTEM\CurrentControlSet\services”. Malware droppers could cycle through these unused entries, create the requisite registry keys (including a ServiceDLL parameter) and thereby maintain persistence as a hosted service. For example, on older versions of Windows, attackers often targeted the “6to4” service, present in the “netsvcs” group but often inactive without a corresponding configuration. The attacker could configure this service to point to a reasonable-looking DLL name, such as “c:\windows\system32\6to4svc.dll” and likely pass visual inspection. Another approach is to simply modify the ServiceDLL parameter for an existing but disabled, Windows service and subsequently configure it to automatically start.
COM+ system services are another variation on the theme of hosted services that can load malicious DLLs. In this case, the “dllhost.exe” process loads the COM+ application which can comprise multiple components as DLLs. As an example, the ComSysApp service listed in the screenshot below is responsible for hosting COM+ applications. The command line shows the path to “dllhost.exe” and a “Processid” GUID that identifies the COM+ application, and within code the “components” can be enumerated. The components are DLLs used to implement the application.
To summarize, hosted and COM services provide a covert, widely-used means of persisting RATs and other malware. Analysts must go beyond basic process monitoring or review of service names and ImagePaths, to detect services that load malicious DLLs.
Identifying Rogue Service DLLs with Tanium
Tanium provides several sensors that can help you easily detect and analyze service DLLs at enterprise-scale. First, we’ll introduce a new sensor, “Service Module Details”, to be included in the forthcoming 3.0 release of our Incident Response solution at the end of the month. The screenshot below shows partial output from this sensor (“count” column is omitted).
This sensor provides a stackable view of all three types of services discussed above. Note the inclusion of a “Module Path” column, along with the Service Name and ImagePath. The first two rows in this example display the path to two component DLLs for the COM+ application named “COMSysApp”. The other results are all hosted by “svchost.exe” and include the path to each respective service DLL. Stack analysis of this data, as with all Tanium sensors, occurs in real-time. That means you can find outlier instances of services that load rogue DLLs in seconds across tens or hundreds of thousands of systems.
Identifying Rogue Members of Hosted Service Groups
Last quarter, Tanium’s Incident Response update included another service analysis sensor named “Hosted Service Name Audit”. The screenshot below shows an example of its output for the “netsvcs” group.
The output of this sensor is useful for quickly inspecting the set of services within service groups at-scale. For each group, the “Sorted list of hosted service names” column provides an alphabetized list of service names. This ensures that the output from each system “stacks”; systems containing an uncommon service within a group thereby separated as outliers. Of course, systems may have differing sets of services based on operating system and role, but we’ve found that the sensor’s output yields clusters around OS version and platform type. Tanium users can use the “drill-down” feature to easily interrogate systems with outlier results, or pivot to Tanium Trace to review the historical forensic data surrounding the creation of a rogue service.
Interested in seeing Tanium in action? Schedule a one-to-one demo or attend our weekly webinar. Talk to our Tanium experts at our upcoming events.