Google pack is a set of software made available free by Google including programs by Google like Chrome and Picasa or other vendors like Mozilla Firefox and Adobe Reader. What is strange about the Google pack is its webpage, where it shows the applications you have installed on your computer and the applications that are not installed already.
The question that pops first is, how does a webpage knows what software is installed on my computer? I decided to see how does it work, inspecting Google’s coming-from-hell javascript files and trying to figure out how things are put together. To be honest, my motivation was first to know if I can use Google’s technique to leverage any information about other installed software on someone’s computer or not, and the answer I simply: no you cant, don’t bother.
Google’s pack webpage http://pack.google.com/ links to a javascript file and have some application parameters initialized at the page loading, with a notable array of guid ‘s and application names:
- {'93613D9F-C440-475B-8379-E7B7E37DAAB7':'ci_ar',
- '71339EA2-A88C-11DE-8E3D-65F655D89593':'ci_avast',
- '8A69D345-D564-463C-AFF1-A69D9E530F96':'ci_chrome',
- '74AF07D8-FB8F-4D51-8AC7-927721D56EBB':'ci_earth',
- …}
It turns out that Google stores information of the applications in the Windows registry (not exactly the same technique on other systems) at the path HKEY_LOCAL_MACHINE\SOFTWARE\Google\Google Updater\AppData\. My research was mainly about how does the Javascript code figure out how to fetch these information from the registry and if it is possible to make it read information from other locations in the registry.
Using burp proxy to intercept and change the applications guid on the fly in the html page, I didn’t come to any result, and it turns out that the only information that is read from the registry was only from inside HKEY_LOCAL_MACHINE\SOFTWARE\Google\Google Updater\AppData\.
So the only trick left was to analyze the javascript file http://pack.google.com/cominst.js?2 (go ahead, take a look), if you want to try the code yourself, you can use the console in firebug under firefox or the Developer Tools (Ctrl + Shit + I) under Google chrome.
The javascript code defines some objects used to manipulate all the operations from reading the list of applications available, to fetching the applications already installed etc…
First a script on the page creates a _CI_Pack object named pack, this pack object have a property named plugin that contains a Plugin object which is the main piece of code we are looking for. This plugin is an embed object installed on the page with the function Plugin.createCIObject that inserts the following code on the page :
- <embed id="CIPlugin_14" type="application/x-vnd.google.cominstctrl.14" width="0" height="0">
This plugin then exposes an attribute called ciobj which is the one reading information from the registry.
In fact this plugin preloads all the information from the registry found in HKEY_LOCAL_MACHINE\SOFTWARE\Google\Google Updater\AppData\ in advance, and the guids that are presented in the pack object have no effect on these information, that’s why we can’t inject or make the plugin read other keys outside this path.
You can read the guid of the applications loaded by the pluing using this code :
- var b = pack.plugin;
- var e = b.ciobj;
- alert(e.Applications.Length);
- for (i = 0;i<e.Applications.Length; i++)
- alert(e.Applications.ElementAt(i).Id);
How the plugin discover the installed applications :
The plugin object uses a simple method to know if the application is installed or not, installed applications have a version number associated with their corresponding object, if the application is not installed, the version number have the value of null, Google checks if the version number is not null, and hence figures out if the application id already installed or not.
- function d(m) {
- if (!m) return false;
- var o = c[m.Id.toUpperCase()];
- if (!o) return false;
- if (b.ci_mimeNum >= 14) { //Here the script check for the installed application
- m = m.Version;
- if (!m) return false
- }
- return i[o] = true
- }
Note that every object in pack.plugin.ciobj.Applications have the two properties exposed for javascript which are Id and Version. The script is really complicated due to the shortening in the variable names, and this function is the one responsible for returning the installed apps function getInstalledList(b, c).
And that’s it, maybe when someone else wonders someday how Google Pack fetch the information of installed applications on the visitor’s computer, he won’t hopefully waste 3 or such days trying to figure out how that javascript file works.