◁ BACK TO HOME nullsector.cc // post // secrets-dumping-browsers

SECRETS DUMPING FROM MODERN BROWSERS

— CHROMIUM & APP BOUND ENCRYPTION

In recent times i have become interested in how infostealers work so well even with modern systems security features, so i took a look at how underground market infostealers operate and tried to reproduce some of the most important features. In this post im going to show how i wrote a working proof of concept of an infostealer in CGO.

This is just for educational purposes only, you should not use it without authorization... Foremost as the author im saying this is just a POC and it lacks of sophistication so its not a good idea to use it in real world environments, you are more than welcome to fork it and recreate your own, as you will see through the post the code is very comprehensive as its majority is written in golang

HURDLES // 00

The biggest hurdle to overcome while developing such software is probably encryption. Modern version of OSs and browsers all use encryption to safely store sensitive data, the great news is that everything is stored locally in the machine, you dont need to breach into nothing you just have to bypass the encryption mechanism of your machine/browser

There are obviously other obstacle to overcome but those are generally more related to the concept of malware.

MICROSOFT DPAPI // 01

Windows by itself implement Data Protection API for data storage security

FIG.01DPAPI — FLOW CHART
Diagram of the Microsoft DPAPI data protection flow
▚ FIG.01 DPAPI — DATA PROTECTION FLOW CHART

Every application inside the system can have access to this API and use it to secure store their data, however dpapi has a big weakness: In order to access it someone only need to work from the user context, this mean that every medium-integrity process running in the user session can easily decrypt data using CryptUnprotectData function

DPAPI key generation:

Encryption:

Decryption:

This was all that Chromium based browser were doing to store data inside PCs before v20

APP BOUND ENCRYPTION // 02

Google has raised the bar introducing App Bound Encryption

FIG.02APP BOUND ENCRYPTION — OVERVIEW
Diagram explaining how App Bound Encryption works
▚ FIG.02 APP BOUND ENCRYPTION — HIGH LEVEL OVERVIEW

This ensure that only the elevated services can decrypt the stored data and only the browser process can request to decrypt the data.

Now, google recognize the fact that this architecture is not 100% secure, they themselves said that a successful bypass would be process injection or an elevated instance of the malware, but as it is right now this work fine and achieve its purpose

This is a high level overview of how ABE encryption work:

To better understand we can have a look chromium source code

Usage of validation_data:

FIG.03CHROMIUM SOURCE — VALIDATION_DATA
Chromium elevation service source code showing the usage of validation_data
▚ FIG.03 ELEVATOR.CC — USAGE OF VALIDATION_DATA

Usage of data_to_encrypt:

FIG.04CHROMIUM SOURCE — DATA_TO_ENCRYPT
Chromium elevation service source code showing the usage of data_to_encrypt
▚ FIG.04 ELEVATOR.CC — BUILDING DATA_TO_ENCRYPT

Double layer of DPAPI encryption:

FIG.05CHROMIUM SOURCE — CRYPTPROTECTDATA
Chromium elevation service source code showing the double layer of DPAPI encryption
▚ FIG.05 ELEVATOR.CC — DOUBLE DPAPI ENCRYPTION LAYER

The decryption is what we have just said but in reverse + the path validation if specified. Everything is then stored inside \Local State file as os_crypt.app_bound_encrypted_key.

There are some known bypass to this:

As you will see my program use a simple implementation of dll injection

BYPASSING ABE USING INJECTION // 03

The plan for bypassing ABE encryption includes 2 components: A function working as injector and the dll to inject. What the program will achieve is decrypting sensitive informations stored inside browsers appdata folder using the IElevator COM object

This methodology is highly effective because it allows the dll to initialize the COM instance using chrome CLSID_Elevator from the browser context

Injector function:

Dll injected:

DLL INJECTION // 04

This function is pretty straightforward, you inject a dll inside browser process spawned with the --headless argument

FIG.06POC — INJECTDLL
Source code of the InjectDll dll injection function
▚ FIG.06 INJECTDLL — DLL INJECTION FUNCTION

InjectDll will then get the handle to the new instance of the browser, allocate as much memory as the length of the dll path, write the dll inside the allocated memory and load it creating a new thread with LoadLibraryA as a argument

To make this more sophisticated someone could try some sort of Dll hijack or reflective Dll injection

PAYLOAD DLL // 05

Majority of the dll code i have used is been taken from this public POC

The first thing (and probably the last) you want to do inside DllMain is to call CreateRemoteThread to execute the main logic. The routine executed by the thread will:

In order to start the ABE key extraction you need to initialize the COM instance for the IElevator object

FIG.07POC — COM INITIALIZATION
Source code initializing the COM instance for the IElevator object
▚ FIG.07 COCREATEINSTANCE — IELEVATOR COM SETUP

You initialize the COM interface with CoCreateInstance specifying the CLSID for the ChromeElevator class and the IID for the IElevator interface. The CLSID is not the same for every chromium based browsers.

After that a proxy is initialized, this allows communications between chrome.exe and the COM object of the elevation service

Now its time to extract the ABE key from its original position

FIG.08POC — ABE KEY EXTRACTION
Source code extracting the app bound key from the Local State file
▚ FIG.08 EXTRACTING THE APP BOUND KEY FROM LOCAL STATE

This function will retrieve the folder of Local State (%LOCALAPPDATA%\Google\Chrome\User Data\) copy its content inside an allocated buffer and start parsing its JSON content in search for the value of the app_bound_encrypted_key, found the encrypted blob is base 64 decoded and saved inside the heap.

Using the encrypted blob now its time to decrypt it using IElevator::DecryptData

FIG.09POC — IELEVATOR::DECRYPTDATA
Source code calling IElevator DecryptData on the encrypted blob
▚ FIG.09 DECRYPTING THE ABE KEY VIA IELEVATOR

This will return a 32 byte AES key

Finally its time to extract logins, cookies, cards...

Browsers store sensitive data in AppData folder (%LOCALAPPDATA%\Google\Chrome\User Data\Default\) inside sqlite databases, accordingly we will need to interact with it through the C code. For this you can just use the sqlite3.c and sqlite3.h of this repository.

All encrypted data blobs have a specific format:

FIG.10ENCRYPTED BLOB — FORMAT
Encrypted data blob format showing the v20 prefix and AES-GCM fields
▚ FIG.10 ENCRYPTED DATA FORMAT — V20 PREFIX VISIBLE

Here you can clearly see the "v20" prefix, we can use this inside the code to see which version of chromium the browser is using and adapt the extraction strategy based on that.

This is the classic way to interact with a sqlite database in C:

FIG.11POC — SQLITE INTERACTION
C code opening and querying the sqlite database
▚ FIG.11 SQLITE — QUERYING THE DATABASE IN C

The executed query to retrieve logins is the follow:

Rows and tables name remain the same for every chromium based browsers

Now its time to decrypt the values returned by the query

FIG.12POC — DECRYPTING VALUES
Source code decrypting the values returned by the sqlite query
▚ FIG.12 DECRYPTING THE VALUES RETURNED BY THE QUERY

First we are going to parse the encrypted blob of AES-GCM

FIG.13POC — AES-GCM BLOB PARSE
Source code parsing the AES-GCM encrypted blob
▚ FIG.13 PARSING THE AES-GCM ENCRYPTED BLOB

We are using the decrypted ABE key with the Windows Cryptography API: Next Generation, for this you will need to import bcrypt.h in your code

FIG.14POC — CNG API
Source code using the Windows Cryptography API Next Generation for decryption
▚ FIG.14 DECRYPTION THROUGH THE WINDOWS CNG API

After this everything is done and we have finally the decrypted logins.

ADDING SUPPORT FOR OTHER BROWSERS // 06

For adding support to more browser we can compile as many dll as browsers we want to support, once the program start it will enumerate all the browsers on the file system and request only the necessary dlls from a remote server

There are a few minor differences to watch out for from one browser to another, one of them is the CLSID and IID, to make sure you are using the right one you can check the specifics for the browser with OleView

FIG.15OLEVIEW — BRAVE
OleView showing the Brave browser elevator CLSID and IID
▚ FIG.15 OLEVIEW — BRAVE ELEVATOR CLSID AND IID

Other than this remember to change the %APPDATA% in order to match the one with the supported browser

CONCLUSION // 07

There are more things to cover but i wont do that now, you can find the full program code here

Other functionalities not described in this post are inside the program on Github, go check it if you are interest!

Useful links:

CONTACT