24. 05. 2024 Daniel Degasperi Blue Team, SEC4U

How To Detect a Chromium Browser Stealer With Elastic

In this blog, I’ll propose and describe a solution for detecting potential infostealers targeting Chromium-based browsers, taking a cue from the research exposed by Google’s Chrome Security Team (Detecting browser data theft using Windows Event Logs).

Obviously a solution using Elastic 🙂 !

What is an Infostealer (in a nutshell) ?

In the realm of cybersecurity, a “stealer” typically refers to a type of malware designed to steal sensitive information from a victim’s computer or device. This could include passwords, cookies, credit card numbers, personal identification information, and other valuable data.


As suggested in the Google article, malware detection is based on the logging and analysis of specific Windows Events.

The idea is to correlate the two Windows events 4688 “A new process has been created.”, and the event 16385 DPAPIDefInformationEvent, reporting the actual process IDs of the application performing DPAPI (Data Protection API) operations.

What is DPAPI (Data Protection API)?

From Wikipedia

Data Protection Application Programming Interface (DPAPI) is a simple cryptographic application programming interface available as a built-in component in Windows 2000 and later versions of Microsoft Windows operating systems. In theory, the Data Protection API can enable symmetric encryption of any kind of data; in practice, its primary use in the Windows operating system is to perform symmetric encryption of asymmetric private keys, using a user or system secret as a significant contribution of entropy. […]


For our goal we need to enable logging of the Windows channel Microsoft-Windows-Crypto-DPAPI/Debug (https://learn.microsoft.com/en-us/windows/win32/seccng/cng-dpapi). And, of course, collect related events.

Thanks to PowerShell, enabling the new logging channel is very easy. Simply execute the following code (via PowerShell):

$log = ` 
   New-Object System.Diagnostics.Eventing.Reader.EventLogConfiguration ` 
$log.IsEnabled = $True 

Then it’s necessary to move to the Elastic environment and create an ad hoc integration that can collect the newly enabled channel.

In this case we can use the Custom Windows Event Logs integration and set the log channel Microsoft-Windows-Crypto-DPAPI/Debug from which to retrieve logs.

I suggest that you define a consistent dataset name so that logs are easily searchable in Kibana. The same dataset will be used in the creation of the detection rule.

Using explorer.exe, a legitimate case

As a first approach and experiment we launch Chrome via explorer.exe, an absolutely legitimate action.

Here’s the Security channel log for the event 4688 (“A new process has been created.”) related to the execution of Chrome via Explorer.

If we take into account the field NewProcessId and convert it to Base10, we obtain the actual process ID related to the event.

In this case the hex value 0x2540 is 9536 (Convert Base-16 to Base-10).

Here’s the corresponding elastic log for the event 4688:

Below the same log but with zoomed-in details:

Now, searching through event ID 16385 from the Microsoft-Windows-Crypto-DPAPI/Debug channel, we can find the potentially suspicious event triggered by the previous event 4688.

Indeed, the CallerProcessID field shows the process that requested and performed the decryption. Correlating this event 16358 with the previous one (4688), it is evident that this operation was performed by the lawful process Google Chrome.

With the field DataDescription we can be sure that the event is related to browser data instead other DPAPI data.

Simulation via Python stealer, the malicious case

To simulate malicious code, we use the same public script suggested by the Google researchers in the article mentioned at the beginning of this blog post.

One important note: it’s necessary to adjust the script by replacing line 6:

from Crypto.Cipher import AES

The execution of the script generates two events, 4688 and 16358.

Considering what I’ve said above, in this case it’s quite evident that the process that triggered event 16358 is the suspicious Python script info_stealer.py .

The same log but with zoomed-in details :

In this case the CallerProcessID for event 16358 and the respective process ID of event 4688 is the value 3404.

Detection with Elastic

Detection is based on the correlation of the two events in the object and in particular on the sequence of a process creation event (4688) followed by a DPAPIDefInformationEven event (16385).

A proper method to perform this is to define an Event Correlation rule using the Event Query Language (EQL).

As we have seen from the use cases above, the key fields are the process.pid (for the process creation event) and the winlog.event_data.CallerProcessID (for DPAPIDefInformationEvent). These two events must be the same.

A simple EQL query might be:

sequence by host.hostname with maxspan=30s
[ process where event.code == "4688" ] by process.pid
[ any where event.code == "16385" ] by winlog.event_data.CallerProcessID

Unfortunately, in this case it’s not possible to use the by operator because the field process.pid is a number and not a keyword 🙁 !

An alternative solution is the following :

sequence by host.hostname with maxspan=30s
  [ process where event.code == "4688" and not process.executable: ("*chromium.exe", "*brave.exe", "*chrome.exe", "*firefox.exe", "*iexplore.exe", "*maxthon.exe", "*microsoftedge.exe", "*msedge.exe", "*msedgewebview2.exe", "*opera.exe", "*safari.exe", "*seamonkey.exe", "*vivaldi.exe", "*whale.exe", "*CCleanerBrowser.exe") ]
  [ any where event.code == "16385" and winlog.event_data.OperationType: "SPCryptUnprotect" and ?winlog.event_data.DataDescription != null]

To reduce noise, those lawful processes (browsers) that actually trigger the event related to the decryption of their data are excluded!

Considering a time range of 30s we’re quite confident that we won’t have too many events to analyze.

If the rule is triggered, it’s necessary to check the process related to event 4688 and that the winlog.event_data.CallerProcessID and process.pid fields match. Clearly it will be event 4688 immediately before event 16385.







These Solutions are Engineered by Humans

Did you learn from this article? Perhaps you’re already familiar with some of the techniques above? If you find cybersecurity issues interesting, maybe you could start in a cybersecurity or similar position here at Würth Phoenix.

Daniel Degasperi

Daniel Degasperi

Cyber Security Team | Würth Phoenix


Daniel Degasperi

Cyber Security Team | Würth Phoenix

Leave a Reply

Your email address will not be published. Required fields are marked *