Contents
The meeting was a short one. "Marketing has decided that the deployed application should self register via a web service once it is downloaded and launched the first time." The boss announced. "We'll write a cookie with an id field that will link the application to the record from the download page. The first time the application launches, it shall read this cookie and register via the web service." After a short pause, he continued. "Your mission, should you choose to accept it, is to get the cookie from whatever browser the customer is using and make it work."
Thus I embarked on a quest to find four cookie jars and to discover the secret of extracting a cookie from each one. Each successive cookie jar in this quest was more difficult than the previous one to crack. Here is an account of that quest.
Internet Explorer stores cookies in plain text files on the file system. In fact, to see them, open Internet Explorer and navigate to: Tools>Internet Options>General Tab>[Browsing history group]Settings> ViewFiles and you will see a directory full of cookies mixed in with a lot of other stuff. Go ahead open one and take a look.
Hmm... there's something strange going on here. Look at the filename in the title bar; MQNANRD2.txt doesn't match Cookie:dmacdermot@www.codeproject.com/. Well it turns out that these files are only a sort of cookie shortcut and this folder is not the real cookie jar! Furthermore, the real cookie is tucked away in a file with a cryptic name so you won't be able to use a file search to find it.
I determined that to get the cookie and value from Internet Explorer, I had to do the following:
- Find where the cookies were stored in the file system.
- Search the contents of each file in the directory for the desired cookie/hostname.
- Once found, search that file for the desired field tag and then read out the value.
Here is the code to do just that:
private static bool GetCookie_InternetExplorer
(string strHost, string strField, ref string Value)
{
Value = string.Empty;
bool fRtn = false;
string strPath, strCookie;
string[] fp;
StreamReader r;
int idx;
try
{
strField = strField + "\n";
strPath = Environment.GetFolderPath(Environment.SpecialFolder.Cookies);
Version v = Environment.OSVersion.Version;
if (IsWindows7())
{
strPath += @"\low";
}
fp = Directory.GetFiles(strPath, "*.txt");
foreach (string path in fp)
{
idx = -1;
r = File.OpenText(path);
strCookie = r.ReadToEnd();
r.Close();
if(System.Text.RegularExpressions.Regex.IsMatch(strCookie, strHost))
{
idx = strCookie.ToUpper().IndexOf(strField.ToUpper());
}
if (-1 < idx)
{
idx += strField.Length;
Value = strCookie.Substring(idx, strCookie.IndexOf('\n', idx) -idx);
if (!Value.Equals(string.Empty))
{
fRtn = true;
break;
}
}
}
}
catch (Exception)
{
Value = string.Empty;
fRtn = false;
}
return fRtn;
}
I navigated to Chrome's cookie manager by opening the browser and clicking the Wrench. Then choosing Options and in the newly opened tab selecting Under the hood. In the privacy group, I clicked Content Settings... Under Cookies, I selected All cookies and site data... and viewed a clickable list of cookies. This was all well and good but it didn't give me any clue as to where Chrome stored the actual cookies. So I Googled it!
It turns out that Google stores cookies in a SQLite3 database buried several layers down inside your LocalApplicationData folder of your profile. On an XP system, the path would be something like this: C:\Documents and Settings\[User Name]\Local Settings\Application Data\Google\Chrome\User Data\Default\Cookies. However, it is going to be different with later versions of Windows.
Here is the code I came up with to find it every time (hopefully).
private static string GetChromeCookiePath()
{
string s = Environment.GetFolderPath(
Environment.SpecialFolder.LocalApplicationData);
s += @"\Google\Chrome\User Data\Default\cookies";
if (!File.Exists(s))
return string.Empty;
return s;
}
Now that I found the cookie jar, I just had to get inside and find my cookie. Fortunately for me, I had already used SQLite extensively and already had the tools at hand to easily crack this nut. I included the ADO.NET adapter for SQLite, System.Data.SQLite [^], in my project and coded my way in. Here's the method I used:
private static bool GetCookie_Chrome(string strHost, string strField, ref string Value)
{
Value = string.Empty;
bool fRtn = false;
string strPath, strDb;
strPath = GetChromeCookiePath();
if (string.Empty == strPath)
return false;
try
{
strDb = "Data Source=" + strPath + ";pooling=false";
using (SQLiteConnection conn = new SQLiteConnection(strDb))
{
using (SQLiteCommand cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT value FROM cookies WHERE host_key LIKE '%" +
strHost + "%' AND name LIKE '%" + strField + "%';";
conn.Open();
using (SQLiteDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
Value = reader.GetString(0);
if (!Value.Equals(string.Empty))
{
fRtn = true;
break;
}
}
}
conn.Close();
}
}
}
catch (Exception)
{
Value = string.Empty;
fRtn = false;
}
return fRtn;
}
In order to find Firefox cookies, I opened Firefox and navigated to: Tools>Options>Privacy tab>Show Cookies. Open popped a nice cookie manager that again hinted at another database storage solution. A little searching confirmed my suspicion and lo: SQLite again!
I duplicated the method I used to find the Chrome cookie jar and modified it to find the one for Firefox. Here is the resulting method:
private static string GetFireFoxCookiePath()
{
string s = Environment.GetFolderPath(
Environment.SpecialFolder.ApplicationData);
s += @"\Mozilla\Firefox\Profiles\";
try
{
DirectoryInfo di = new DirectoryInfo(s);
DirectoryInfo[] dir = di.GetDirectories("*.default");
if (dir.Length != 1)
return string.Empty;
s += dir[0].Name + @"\" + "cookies.sqlite";
}
catch (Exception)
{
return string.Empty;
}
if (!File.Exists(s))
return string.Empty;
return s;
}
Notice the line:
DirectoryInfo[] dir = di.GetDirectories("*.default");
Firefox is a bit more tricky in burying the location of the cookie file. In my case, the path turned out to be: C:\Documents and Settings\[User Name]\Application Data\Mozilla\Firefox\Profiles\cig7kfll.default\cookies.sqlite. Now cig7kfll could be anything, but fortunately there is only one such folder in this branch of the tree. I hope it stays that way.
The next thing I tried to do was open the cookie jar as I had done previously with Chrome. No luck... I was locked out! It turns out that FireFox locks this file while the browser is open so in order to read it, I had to take the following steps:
- Copy
cookies.sqlite
to a temporary file. - Open and perform a SQL query on the temporary file to get my cookie.
- Close and delete the temporary file.
Here is the code to do just that:
private static bool GetCookie_FireFox(string strHost, string strField, ref string Value)
{
Value = string.Empty;
bool fRtn = false;
string strPath, strTemp, strDb;
strTemp = string.Empty;
strPath = GetFireFoxCookiePath();
if (string.Empty == strPath)
return false;
try
{
strTemp = strPath + ".temp";
strDb = "Data Source=" + strTemp + ";pooling=false";
File.Copy(strPath, strTemp, true);
using (SQLiteConnection conn = new SQLiteConnection(strDb))
{
using (SQLiteCommand cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT value FROM moz_cookies WHERE host LIKE '%" +
strHost + "%' AND name LIKE '%" + strField + "%';";
conn.Open();
using (SQLiteDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
Value = reader.GetString(0);
if (!Value.Equals(string.Empty))
{
fRtn = true;
break;
}
}
}
conn.Close();
}
}
}
catch (Exception)
{
Value = string.Empty;
fRtn = false;
}
if (string.Empty != strTemp)
{
File.Delete(strTemp);
}
return fRtn;
}
In order to find Opera cookies, I opened Opera and navigated to: Opera button>Settings>Preferences>Advanced Tab. I then selected Cookies from the list and clicked Manage Cookies... Again, I encountered a nice cookie manager and so I Googled the location of the file itself. My efforts yielded the following method for locating the Opera cookie jar.
private static string GetOperaCookiePath()
{
string s = Environment.GetFolderPath(
Environment.SpecialFolder.ApplicationData);
s += @"\Opera\Opera\cookies4.dat";
if (!File.Exists(s))
return string.Empty;
return s;
}
Now any file ending with a .dat extension does not bode well. I had a suspicion that the file was saved in some kind of proprietary format but mustering hope, I attempted to open it with my trusty SQLite viewer. No luck. Next, I applied the Hex editor. Suspicion confirmed. Being somewhat lazy and hoping beyond hope that someone had attempted a parser for this file before, I hunted the dark corners of the World Wide Web. After much sleuthing, I found a solution! But wait, what's this? Alas, it was all written in Delphi!
Great minds write great software in Delphi, any time I have wanted some obscure snippet, something beyond the common stuff that you can find just about anywhere, invariably it is written in Delphi. I have also played around with many freeware Delphi translators and come to one conclusion: the only Delphi translator that really works is the one between my ears.
Having never learned Delphi or Pascal, I first scanned the source code looking for code patterns and elements of structure, then typed them into C# equivalents making a number of educated guesses along the way but not trying to really understand anything yet. This resulted in a bunch of pseudo C# code that was more familiar to my eyes. I went through this pseudo code, method by method, and began to turn it into actual C# code. I began to recognize what was going on at this stage, so I only needed a third pass over the source, mostly refactoring, to polish off the file parser.
In addition to the Delphi solution, I found some links to some helpful technical documentation[^] as well as Opera's Technical documentation [^]. In a nut shell; Opera stores cookies in a domain tree that can be recursively searched and compactly stored. As illustrated in the following diagram:

The actual cookies (or cookie fields) hang like apples on the tree.
Ok. So after that ordeal, I composed the following method to read the opera cookie:
private static bool GetCookie_Opera(string strHost, string strField, ref string Value)
{
Value = "";
bool fRtn = false;
string strPath;
strPath = GetOperaCookiePath();
if (string.Empty == strPath)
return false;
try
{
OpraCookieJar cookieJar = new OpraCookieJar(strPath);
List<O4Cookie> cookies = cookieJar.GetCookies(strHost);
if (null != cookies)
{
foreach (O4Cookie cookie in cookies)
{
if (cookie.Name.ToUpper().Equals(strField.ToUpper()))
{
Value = cookie.Value;
fRtn = true;
break;
}
}
}
}
catch (Exception)
{
Value = string.Empty;
fRtn = false;
}
return fRtn;
}
It is somewhat beyond the scope of this article to go into detail on parsing the Opera cookie file. However, the class is sufficiently commented and ready to use for reading cookies from Opera. Writing them is not supported in this C# class, but it is supported in the original Delphi solution on Experts Exchange [^].
So you're not a subscriber to EE? Don't let that get you down, try accessing via Google [^].
The chief difference between the Delphi solution and this C# class is how the cookie file is read. The Delphi solution reads from the file stream continually during the parsing process, while the C# class initially reads the file bytes into a buffer and then parses the buffered bytes after the read is completed.
- Feb 13, 2012 version 1.0.0.0