Windows Event Log Evasion via Native APIs


Threat actors can leverage native Windows API calls to install malicious services without generating correlating entries in the event log. Using native APIs to install services instead of the standard API calls allow threat actors to bypass security controls and event logging. This technique was utilised in the infamous Stuxnet malware sample created by the alleged US and Israeli government to target the Iranian nuclear program. It also happens to be one of my favourite malware samples <3. I will not be covering what native API calls are – for more information please take a read of one of my previous tweets..

This technique is not new (as it was used by Stuxnet), however, a lot of analysts in the industry see the event logs as a single source of truth without realising that sometimes it’s not always the case. As such, it’s always prudent for a responder/hunter/detection engineer to correlate various streams of evidence per artefact versus relying on a single source of evidence. @HarlanCarvey calls this building an ‘artifact constellation’ and I think this is a fantastic phrase that perfectly describes this situation. 

In this blog post I’m going to highlight how services can be installed through native API calls to evade detection and then focus on detection mechanisms through memory forensics. It’s difficult to talk about this topic without covering some process internal information so the blog has been structured to cover:

  • How the technique works and how it bypasses event logging
  • Why the volatility plugins “svcscan” does not detect services installed via this method
  • Detection methodology


PART 1: HOW THE TECHNIQUE WORKS

If no “evasion” techniques are used, services are typically created through a standard Windows API call to “CreateServiceA” or “CreateService” – you can read the full documentation for this API here. This API is also called whenever you use the native Windows executable “sc.exe” to register a service on a machine. A call to this API subsequently generates entries in the event log which corresponds to the service creation event IDs that a responder would be used to seeing. 

Threat actors can create services without relying on the typical API call to “CreateServiceA” by directly interacting with the Windows native API calls. For example, the “StartService” API will a make a call to the native API “NdrClientCall2” along with registering the service start events in the event logs. However, by directly calling “NdrClientCall2” to start a service that’s had the registry keys manually created – the service is started and running and no correlating event logs are created – thus evading detection. This will result in a malicious service running and no correlating event log entry. To take this a step further, the threat actors can then remove the evidence in the registry and any correlating evidence loaded in the memory of “services.exe”. This leaves you with little to no registry artefacts and no event log information to analyse. 

Stuxnet utilises this technique to register two malicious services to run malicious kernel drivers using a call to the native API “NtLoadDriver”. However, the malware did not remove the artefacts hidden within the registry (because these registry values are required to call NtLoadDriver). This API is documented in the NTAPI Undocumented Functions website here. To call the API, you just pass one value – the driver name and ensure that the registry has had the path to the malicious driver set. 


Normally, when given a memory sample, analysts will run the “svcscan” plugin in Volatility to hunt for services. When confronted with Stuxnet – you will notice this does not return results showing the malicious services. The two malicious services that exist in Stuxnet are called “mrxnet” and “mrxcls”.  Running the “svcscan” module you cannot see evidence of these services existing either. 


However, referring to the documentation on NtLoadDriver where a registry value needs to be set. Iterating through the registry keys within the memory sample shows that these services indeed exist. So why is this the case? Why didn’t the svcscan plugin pick up on this service?


This is an important place to reflect because it’s important for analysts to understand how the tools they use “work”. Reliance on running plugins without understanding how they work may hamstring an analyst’s ability to figure out alternate methods to hunt. 


PART 2: WHY DOESN'T 'SVCSCAN' DETECT THIS?

These two methods do not detect the malicious Stuxnet services because by directly calling native APIs instead of the standard APIs, Service Control Manager (SCM) is bypassed meaning there are no service records created in memory. Let’s go through each of the two methods and why they fail… 

Method 1: Traversing the VAD tree looking for memory sections in “services.exe” that might show malicious running services.

The plugin “svcscan” traverses the VAD tree. The VAD is a Virtual Address Descriptor and is used to store the memory ranges used by a process in the structure of a hierarchical tree. As Stuxnet directly interacts with NTLoadDriver, there is no correlating “data” in the process memory of services.exe, thus, traversing the VAD tree will not return any information on the two malicious services. 

For some more background on Windows internals, unlinking, PEB, EPROCESS and other structures please look at this previous tweet I made.


Method 2: Looking for service records in the memory sample with tags “sErv” and “serH” 

This technique iterates through the entire memory sample looking for any service records with those tags that might have been unlinked from Service Control Manager’s (SCM) doubly linked list. This method fails because there is no creation of a correlating service record _SERVICE_RECORD structure when a call to NtLoadDriver is made. 

This is why looking for “sErv” and “serH” tags does not detect the services because the record was never created. Service Control Manager (SCM) stores information about services that are installed on a machine in a linked-list or a doubly-linked list. The screenshot below shows the organisation of this structure in a doubly-linked list (older versions of Windows) as “ServiceList” at 0x0. 



PART 3: DETECTION METHODOLOGY

When hunting for malicious service creations – this is the logic I would apply from start to finish. Always look for correlating evidence that strengthens a finding versus settling from the results of 1 artefact. 

The general IR workflow for most malware / less sophisticated threat actors, the below bullet points cover the course of action. In the instance of Stuxnet, these detection techniques may not have provided any findings nor enough information to determine the malicious drivers and services. 

1. Review event logs for 7045, 7035, 7034, 7036, 7040, 4697 service creation

2. Review registry keys for services:
  • HKLM\SYSTEM\CurrentControlSet\Services
  • HKLM\SYSTEM\ControlSet001\Services
  • HKLM\SYSTEM\ControlSet002\Services

3. Review command line logging for signs of services being created using “sc.exe”, “at.exe”

4. Review artefacts for execution i.e. Shimcache, Prefetch, Amcache

5. Review $MFT/$I30 for signs of malicious file creation (i.e. dropped .DLLs, .EXEs etc)

6. Use Volatility “svcscan” to pick up on signs of unlinked services and to find services running 

In the instance of Stuxnet… the following actions were also required to form a more complete detection as NTLoadDriver was called by Stuxnet to register malicious driver services. 

7. Detect the malicious driver on the disk (can also be done without memory forensics by correlating creation timestamps on disk)


8. Correlate the malicious driver files with the loaded kernel modules to PROVE that the service was running on the system. This means these drivers were running. 


9. Detect on native API calls to NTLoadDriver and NdrClientCall2 along with other API calls to functions that allow direct writing of registry keys. Normally EDR tools monitor and alert on the calling of StartService and CreateServiceA – but as demonstrated in this post… this method would bypass that detection.

For detection engineers, I would consider looking for calls to NTLoadDriver and NdrClientCall2 along with other API calls to StartService, RegCreateKey, RegSetValue and correlating evidence being written to the registry keys listed above. 

Finally, if you’re interested in reading a full write-up on analysing Stuxnet – I really recommend this write-up by MNIN here. There are a lot of nuanced techniques baked inside this sample.



REFERENCES
https://docs.microsoft.com/en-us/windows/win32/api/winsvc/nf-winsvc-createservicea
https://undocumented.ntinternals.net/
http://mnin.blogspot.com/2011/06/examining-stuxnets-footprint-in-memory.html

Comments

Popular posts from this blog

Forensic Analysis of AnyDesk Logs

Successful 4624 Anonymous Logons to Windows Server from External IPs?

How to Reverse Engineer and Patch an iOS Application for Beginners: Part I