Click here to Skip to main content
13,143,637 members (30,110 online)
Click here to Skip to main content
Add your own
alternative version

Stats

8.9K views
182 downloads
23 bookmarked
Posted 30 Jan 2017

The Secrets of Google Chrome Credentials

, 30 Jan 2017
Rate this:
Please Sign up or sign in to vote.
Chrome stores all passwords and other credentials in an encrypted database but guess what: they can be retrieved by anyone with the proper knowledge. This article will show you how.

The program and any updates will be available at Source Forge

Introduction

This article is one of several articles covering the secrets of obtaining stored (and encrypted) credentials stored by browsers (and other applications, for example: MS Outlook). The first article covered Wi-Fi credentials. This article covered Google Chrome and how credentials are stored and can be fetched from it.  

The Profile Folder

Chrome stores the user’s credentials inside a special folder called the “profile folder”. The first step would be understanding where to find that folder. To understand better, note that Chrome has a built in mechanism for displaying important information about its version and installation location. To view this information just type: "chrome://version/" in the Address Bar.  

Among the many pieces of information displayed, please refer to "Profile Path", which is where the sensitive data is kept.

To get this path programmatically we need to do as follow:

#define FORENSICS_CHROMECREDENTIALS_PATH _T("\\Google\\Chrome\\User Data\\Default\\")

bool result = false;
TCHAR szProfileFolderPath[MAX_PATH];
result = SHGetSpecialFolderPath(0, szProfileFolderPath, CSIDL_LOCAL_APPDATA, 0);
StrCat(szProfileFolderPath, FORENSICS_CHROMECREDENTIALS_PATH);

First we obtained the user specific path of his or her Windows' user account. That can be c:\users\john\ or c:\users\myself\, and since we don't know it, we don't use any hardcoded value but obtain it during runtime. 

The second part is the relative path of the Google data, which is constant so we do keep that part hardcoded. When we combine the two, we get the path.

Now that we have the path, we need to focus in one specific file which is in fact a SQLite3 database: Login Data.

To get that file we add "\" (_T("\\") to the path and then the string _T("Login Data") and when we do, szProfileFolderPath will hold the full path of the database we need to open.

#define FORENSICS_CHROMECREDENTIALS_DB _T("\\Login Data")
StrCat(szProfileFolderPath, FORENSICS_CHROMECREDENTIALS_DB);

Before we open this database it is advised to copy it to another file so it won't intervene with any instance of Google Chrome currently opened, and by doing so, there is no need to shut down Chrome before we operate. 

#define TEMP_CHROME_DB    _T("temp.db")
CopyFile(szProfileFolderPath, TEMP_CHROME_DB, FALSE);

Some notes about SQLite3

During the day to day development work at Secured Globe, Inc. we use SQLite3 a lot. Most of forensics information out there is associated one way or another with SQLite3. Sqlite3 can be used at the source code level (adding sqlite3.c and sqlite3.h to your program, or as a static / dynamic library). 

We use it with two additional enhancements:

- CppSqlite3 - a wrapper which can ensure better handling with UNICODE test (without it, sqlite3 can hardly deal with international characters within its databases). The first versions were published here at Code Project. 

- SEE - a paid library ($2,000 per license) sold by Sqlite3 which allows an application to read and write encrypted database files. Four different encryption algorithms are supported:

  • RC4
  • AES-128 in OFB mode
  • AES-128 in CCM mode
  • AES-256 in OFB mode

 

The following article is very handy when it comes to helping people using Sqlite3 in their programs, and especially Windows programs.

Fetching the credentials from the SQLite3 Database

Next we open the database and run a query on the specific table we need for the stored credentials. This table is called "logins". We predefine the query to be executed on this table as follow:

#define CHROME_CRED_SQL_QUERY "SELECT signon_realm,username_value,password_value,date_created FROM logins"

Then we can open the database and run this query:

CppSQLite3DB CredentialsDB; // we define a CppSQLite3DB object
try
{
    CredentialsDB.open(TEMP_CHROME_DB);
}
catch (CppSQLite3Exception &e)
{
    // Handle exceptions here
    return false;
}
CppSQLite3Query SqlQuery;
CString sql;
sql = CHROME_CRED_SQL_QUERY;
try
{
    SqlQuery = CredentialsDB.execQuery(sql);
}
catch (CppSQLite3Exception &e)
{
    // Handle query execution's exceptions here
    return 0;
}
int count = 0;
int size = 0;

The SGBrowserCredentials Data Structure

The SGBrowserCredentials (Secured Globe Browser Credentials) is used for any procecss of fetching browser credentials and is capable of holding the relevant fields which are common to all browsers. 

We define the single element and a CSimpleArray for the purpose of collecting the results of our program. We also use CTime for the date/time stamp of each entry. We do so to be able to compare credentials from different sources (browsers), as each browser use a different method for storing date and time. The importance of date/time for the scope of our program is to be able to use it later for filtering the results. For example: being able to tell which new credentials were created since 1.1.2017 or since last time we checked.

typedef struct _SGBrowserCredentials
{
    int Browser; // 0 = chrome, 1 = ie, 2 = firefox, 
    TCHAR Site[256];
    TCHAR UserName[80];
    TCHAR Password[256];
    CTime DateCreated;
    _SGBrowserCredentials()
    {
        Site[0] = 0;
        UserName[0] = 0;
        Password[0] = 0;
        DateCreated = NULL;
    }
} SGBrowserCredentials;

typedef CSimpleArray<SGBrowserCredentials> SGBrowserCredentialsArray;

Reading the data

After running the SQL query, we should expect to get a number of records. Each record is a single entry such as a stored credentials. We use the following local variables:

WCHAR *Site, *User, *CreationDate;

DATA_BLOB DataIn, DataOut;

to store a single record. We read also encrypted data which we will decrypted later.        

#define CHROME_DB_FIELD_SITE 0
#define CHROME_DB_FIELD_USER 1
#define CHROME_DB_ENC_FIELD_PASS 2
#define CHROME_DB_FIELD_DATE 3

Then the loop we run over the results looks like this:

while (!SqlQuery.eof())
{
    Site = (WCHAR *)SqlQuery.fieldValue(CHROME_DB_FIELD_SITE);
    User = (WCHAR *)SqlQuery.fieldValue(CHROME_DB_FIELD_USER);
    DataIn.pbData = (LPBYTE)SqlQuery.getBlobField(CHROME_DB_ENC_FIELD_PASS, size);
    DataIn.cbData = size;
    CreationDate = (WCHAR *)SqlQuery.fieldValue(CHROME_DB_FIELD_DATE);
...

Now we need to decrypt the encrypted part and that can be done smoothly as long as you run the program from where the database was originally stored. The reason for that is that the encryption is based on the Windows logon system. If you copy the database and try to open it from another machine, you won't be able to decrypt the password but just to see the other fields. 

Decrypting encrypted data

To decrypt the data use CryptUnprotectData which decrypts password (in a DATA_BLOB structure). 

bool bDecrypted = CryptUnprotectData(&DataIn, 0, 0, 0, 0, 8, &DataOut);

If it has succeed, we will have the decrypted password in DataOut

Handling Chrome's Date/Time format

Before we create the single record and add it to our dynamic array we need to interpret the way date and time of each entry are kept by Chrome. It would be easiest to convert the date/time (fetched as string from the database) into a FILETIME object. The FILETIME structure contains a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC). First, we need to grab the first 10 digits of the long number used by Chrome and store it in a ULONGLONG variable (using _wcstoui64).  Then we multiple it by 10 and assign the "LowPart" and "HighPart" to the FILETIME object.

ULONGLONG lltm = _wcstoui64(ChromeTime.GetString(), NULL, 10);
ULARGE_INTEGER uLarge;
uLarge.QuadPart = lltm * 10;
FILETIME ftTime;
ftTime.dwHighDateTime = uLarge.HighPart;
ftTime.dwLowDateTime = uLarge.LowPart;

From FILETIME we can always convert to SYSTEMTIME and to CTime easily.

The Program

When you start the program, you will see all stored credentials on your machine. It should look like this:

The program and any updates will be available at www.windowscredentials.com and at Source Forge

About the source code

The source code can be useful for demonstrating not only the functionality described in the article, but some GUI (Graphical User Interface) aspects. The source code project is a Dialog based MFC one, built using Visual Studio Ultimate 2013.  Word of thanks shuold go to Marc Richarme  who created EasySize. His class is used for supporting resizing the dialog while preserving the relative position of the controls it contains. I have used TabCtrlSSL (thanks Derek Lakin) with changes and enhancements we have made. I worked on displaying the browser's icon (Chrome, in this case) in the grid, while displaying it with a transparent color. All images to be shown transparent in the grid (which is in fact a CListCtrl) need to have a common background color (Green / RGB(0,255,0) in my case) and should be saved as a 24 bit BMP file. That's basically the trick. You may also learn from the source code about displaying labels and other controls whilst keeping a common background color to the entire dialog. 

 

* The graphics are copyrighted to Secured Globe, Inc. and should not be used for other purposes / products.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Michael Haephrati
CEO Secured Globe, Inc.
United States United States
Michael Haephrati, is an entrepreneur, inventor and a musician. Haephrati worked on many ventures starting from HarmonySoft, designing Rashumon, the first Graphical Multi-lingual word processor for Amiga computer. During 1995-1996 he worked as a Contractor with Apple at Cupertino. Worked at a research institute made the fist steps developing the credit scoring field in Israel. He founded Target Scoring and developed a credit scoring system named ThiS, based on geographical statistical data, participating VISA CAL, Isracard, Bank Leumi and Bank Discount (Target Scoring, being the VP Business Development of a large Israeli institute).

During 2000, he founded Target Eye, and developed the first remote PC surveillance and monitoring system, named Target Eye.


Other ventures included: Data Cleansing (as part of the DataTune system which was implemented in many organizations.



You may also be interested in...

Pro

Comments and Discussions

 
QuestionAny know issue with the source code? Pin
arut jothi3-Feb-17 8:19
memberarut jothi3-Feb-17 8:19 
AnswerRe: Any know issue with the source code? Pin
Michael Haephrati3-Feb-17 10:13
professionalMichael Haephrati3-Feb-17 10:13 
GeneralRe: Any know issue with the source code? Pin
arut jothi3-Feb-17 11:34
memberarut jothi3-Feb-17 11:34 
GeneralRe: Any know issue with the source code? Pin
Michael Haephrati3-Feb-17 11:47
professionalMichael Haephrati3-Feb-17 11:47 
GeneralRe: Any know issue with the source code? Pin
arut jothi6-Feb-17 4:43
memberarut jothi6-Feb-17 4:43 
GeneralRe: Any know issue with the source code? Pin
arut jothi6-Feb-17 5:55
memberarut jothi6-Feb-17 5:55 
QuestionSource code ... Pin
Richard MacCutchan30-Jan-17 22:24
protectorRichard MacCutchan30-Jan-17 22:24 
AnswerMessage Closed Pin
1-Feb-17 0:50
professionalMichael Haephrati1-Feb-17 0:50 
GeneralRe: Source code ... Pin
Richard MacCutchan1-Feb-17 1:10
protectorRichard MacCutchan1-Feb-17 1:10 
GeneralRe: Source code ... Pin
Michael Haephrati1-Feb-17 1:20
professionalMichael Haephrati1-Feb-17 1:20 
GeneralMy vote of 5 Pin
Hans Flocken30-Jan-17 11:37
memberHans Flocken30-Jan-17 11:37 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.170915.1 | Last Updated 30 Jan 2017
Article Copyright 2017 by Michael Haephrati
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid