Introducing: The Google Chrome Password Recovery Tool

Today, I wanted to backup all my passwords stored in Google Chrome. I thought that would be an easy task, but it turns out, that this is not supported, at least as far as I can tell. There is an option to view the shared passwords one-by-one, but that was not really an option for me.

So, I decided to write a small program to extract the passwords from Chrome. Since Chrome (or Chromium, to be exact), is open source, I pulled the source from http://dev.chromium.org/getting-involved, compiled it, and starting looking around trying to figure out how passwords are stored. The setup and build experience was much nicer than what I have tried with other open source projects I have looked at; there are detailed build instructions with only a few steps available, and after setting up, it just works, in a Visual Studio 2008 solution. A full recompile does take some time however (45 minutes on my machine).

I quickly found out that Chrome stores most of its user and configuration data in small SQLite databases stored on disk in the AppData/Local/Google/Chrome/User Data directory. So, reading the data was no problem after grabbing a copy of the ADO .NET Provider for SQLite, as well as the sqlite3.dll binary from http://www.sqlite.org/. The data I was after (user names and passwords) is stored in the file named Web Data. This contains a table named logins, which contains the URL for which the login is valid, some details about the html form where the password has been used (in order to allow Chrome to auto-fill password boxes for you), and the username and password. It also contains a "preferred" and "blacklisted_by_user" column.

Decrypting the passwords

The passwords is, obviously for security reasons, not stored in plain text. Rather, they are encrypted, so I needed to figure out how they are encrypted and how to decrypt them. The answer lies in the Chromium source, where the Encryptor class contains the following method:

bool Encryptor::EncryptString(const std::string& plaintext,
                              std::string* ciphertext) {
  DATA_BLOB input;
  input.pbData = const_cast<BYTE*>(
    reinterpret_cast<const BYTE*>(plaintext.data()));
  input.cbData = static_cast<DWORD>(plaintext.length());

  DATA_BLOB output;
  BOOL result = CryptProtectData(&input, L"", NULL, NULL, NULL,
                                 0, &output);
  if (!result)
    return false;

  // this does a copy
  ciphertext->assign(reinterpret_cast<std::string::value_type*>(output.pbData),
                     output.cbData);

  LocalFree(output.pbData);
  return true;
}

As it turns out, the Windows Data Protection (DPAPI) is used to encrypt the data, namely the CryptProtectData function as shown above. Therefore, I can relatively easy decrypt the data, using the CryptUnprotectData function, as long as I do not try to decrypt the password of other users - the DPAPI encrypts with a key based on the current user's login credentials. I first tried to do the decrypting in C# using P/Invoke the the CryptUnprotect function, but for some reason, I could not get that to work. I kept getting a credentials dialog from Windows when trying it, which is not what i want. Luckily, after googling a bit, I found out that there already exist a managed wrapper for doing this, namely the ProtectedData class. After switching to using this, there were no problems decrypting the passwords.

The password recovery tool

I wrote a tiny C# console program to dump the passwords. They can be dumped to the console (default) or to an XML file. Running the program without parameters will try to dump all the passwords to the console. You might need to have Chrome closed while doing this. Run the program with the -help switch to display a short usage information message.

I am including the program for download here - both in a precompiled form and the C# source. It requires .NET Framework 3.5. The program as well as it's source is free for use non-commercially and is provided without any warranty or obligations for me, neither explicit or implied. It probably won't kill your cat, but don't come to me crying about it if it does ;-). If you wish to use the source or derivate thereof in a commercial product, contact me for permission first.

Download:

What is missing ?
It would be nice to have an option to import the exported passwords into a new Chrome installation on another computer. I am considering adding it, but don't really need it at this time. It should be relatively easy - if you happen to develop the feature based on my work, please email me the source.

Comments

This post has 18 comments:
Gokul
On 2009-06-19 20:01, Gokul wrote:
I am unable to get your source working. It's failing in the openconnection method.<br />Pleas help. <br />Thanks<br /><br />Attached Error details for reference<br />Exception occured:<br />ConfigurationErrorsException: Failed to find or load the registered .Net Framework Data Provider.<br />Stack Trace:<br /> at System.Data.Common.DbProviderFactories.GetFactory(DataRow providerRow)<br /> at System.Data.Common.DbProviderFactories.GetFactory(String providerInvariantName)<br /> at dr.ChromePasswordRecover.LoginReader.OpenConnection() in C:\test\ChromePasswordRecover\LoginReader.cs:line 102<br /> at dr.ChromePasswordRecover.LoginReader.GetLogins(String url) in C:\test\ChromePasswordRecover\LoginReader.cs:line 56<br /> at dr.ChromePasswordRecover.Program.RunProgram(String[] args) in C:\test\ChromePasswordRecover\Program.cs:line 49<br /> at dr.Commons.ConsoleUtility.BaseProgram.Main[T](Func`1 constructor, String[] args) in C:\test\dr.Commons\ConsoleUtility\BaseProgram.cs:line 67<br />
Gokul
On 2009-06-19 20:45, Gokul wrote:
The above issue is resolved. <br />open the properties of "System.Data.SQLite.dll" file and set CopyLocal to true. It works like a charm :)
sdblepas
On 2009-07-29 06:59, sdblepas wrote:
Hi<br />Thx for your script but here's what going on<br />any idea?<br />THX<br /><br /><br />Exception occured:<br />SQLiteException: The database file is locked<br />database is locked<br />Stack Trace:<br /> at System.Data.SQLite.SQLite3.Prepare(SQLiteConnection cnn, String strSql, SQ<br />LiteStatement previous, UInt32 timeoutMS, String& strRemain)<br /> at System.Data.SQLite.SQLiteCommand.BuildNextCommand()<br /> at System.Data.SQLite.SQLiteCommand.GetStatement(Int32 index)<br /> at System.Data.SQLite.SQLiteDataReader.NextResult()<br /> at System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd, CommandBehavi<br />or behave)<br /> at System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior behavior)<br /> at System.Data.SQLite.SQLiteCommand.ExecuteNonQuery()<br /> at System.Data.SQLite.SQLiteConnection.Open()<br /> at dr.ChromePasswordRecover.LoginReader.OpenConnection()<br /> at dr.ChromePasswordRecover.LoginReader.GetLogins(String url)<br /> at dr.ChromePasswordRecover.Program.RunProgram(String[] args)<br /> at dr.Commons.ConsoleUtility.BaseProgram.Main[T](Func`1 constructor, String[]<br /> args)
rilley
On 2009-08-12 12:27, rilley wrote:
this tool doesn`t work with "web data" files from another machine :( how can i decrypt if is from another machine...
Dennis Riis
On 2009-08-12 12:40, Dennis Riis wrote:
You cannot decrypt passwords from a file obtained from another machine, this is by design.
Akhil Sakpal
On 2009-09-13 20:29, Akhil Sakpal wrote:
awesome stuff.. thanx... <br /><br />@ sdblepas <br /><br />Close chrome and then try to run the exe.. if u r running chrome the db will be locked...
grim
On 2009-12-09 13:31, grim wrote:
Hi! great stuff<br />in command line if u type so:<br />cprecover.exe -> pass.txt<br />it saves them to a txt file named pass
autumn
On 2010-01-11 01:55, autumn wrote:
Where does it save the passwords to? I run cprecover.exe and everything seems to work (it runs through some stuff and then exits automatically), but now I don't know where they are!
autumn
On 2010-01-11 02:37, autumn wrote:
okay, I figured it out and thought I would post just in case anyone finds themselves in the same predicament:<br /><br />1) Open Command Prompt<br />2) Type the complete path to cprecover.exe (for example, my file is saved to the desktop so I type "Desktop\cprecover.exe")<br />3) This should return a list of URLs, usernames, and passwords<br />4) If you want to save all these files in a document, type "Desktop\cprecover.exe > passwords.txt"<br />5) You will find the passwords.txt file in your personal folder (the file where you access your documents, music, photos, etc.)<br /><br />YAY for Dennis Riis!
Vladi
On 2010-08-25 13:34, Vladi wrote:
Thanks a lot!<br />works perfect on win7 64bit.<br />this tool saved me a lot of screenshots ;)<br /><br />Tnx again<br /><br />;)
Syl
On 2010-08-28 11:16, Syl wrote:
Doesn't seem to work with Chrome 6.0.472.51 beta.<br />It seems to read the right file (because I have an error if Chrome is running), but after closing Chrome and running cprecover again, it displays an empty list. The xml dump is also empty.
Syl
On 2010-08-28 11:21, Syl wrote:
yup, could make it work 2 sec later ^^;<br />Copy "Login Data" from C:\Users\[USER]\AppData\Local\Google\Chrome\User Data\Default in you cprecover directory, then run "cprecover.exe -file:"Login Data" -dump:password.xml"
Sumit
On 2010-09-03 17:31, Sumit wrote:
Great tool <br />thanks for your hard work <br />worked perfectly
Prince Of Code
On 2010-09-26 08:29, Prince Of Code wrote:
This one has a problem of dotnet framework to be installed. rather can we write a plugin for chrome that does this job of exporting all the password. would that sounds simple. I m thinking of writing if you guys say that.<br /><br />Prince Of Code
freelancer
On 2010-11-03 13:52, freelancer wrote:
Thanks to program author for writing it, and thanks to Syl for comment about how to use it on newer Chrome versions. It worked and saved me at least an hour :)
Frank
On 2014-04-24 19:48, Frank wrote:
Link is broken. Please fix! I'm glad you took the time to figure this out.
keith is best
On 2014-06-04 07:53, keith is best wrote:
Please make available OSX binaries :) for 10.9 or newer for chromium 35 or newer I am very-not-interested in using a google account to export my private/secret site account information
zen
On 2014-08-12 02:54, zen wrote:
this is the new link http://cprecover.codeplex.com/releases/view/81306

Leave a comment:

Your name:
Your email:
Comment:
Verification: What is the result of 8 minus 6 ?
Answer incorrect. Please try again.