Click here to Skip to main content
14,550,787 members

The Secrets of Google Chrome Credentials

Rate this:
5.00 (17 votes)
Please Sign up or sign in to vote.
5.00 (17 votes)
30 Jan 2017CPOL
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.
This article covers Google Chrome and how credentials are stored and how they can be fetched from it.


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 covers 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.

Image 1

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 follows:

#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);

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.


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 the 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 follows:

#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
catch (CppSQLite3Exception &e)
    // Handle exceptions here
    return false;
CppSQLite3Query SqlQuery;
CString sql;
    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 process 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 the 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;
        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 decrypt later.


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.QuadPart = lltm * 10;
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:

Image 2

The program and any updates will be available at 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 should 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.


  • 30th January, 2017: Initial version


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


About the Author

Michael Haephrati
CEO Secured Globe, Inc.
United States United States
Michael Haephrati, Musician and CEO and co-founder of Secured Globe, Inc. 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.

Comments and Discussions

Questioncompile on Mac Pin
Member 1471838816-Jan-20 5:02
MemberMember 1471838816-Jan-20 5:02 
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
mvaMichael 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
mvaMichael 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
mveRichard MacCutchan30-Jan-17 22:24 
AnswerMessage Closed Pin
1-Feb-17 0:50
mvaMichael Haephrati1-Feb-17 0:50 
GeneralRe: Source code ... Pin
Richard MacCutchan1-Feb-17 1:10
mveRichard MacCutchan1-Feb-17 1:10 
GeneralRe: Source code ... Pin
Michael Haephrati1-Feb-17 1:20
mvaMichael 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.

Posted 30 Jan 2017


28 bookmarked