Last Friday I was debugging random programs I found on my hard drive when I saw this:
Apparently µtorrent is sending lots of unrelated data back to the µtorrent servers when checking for program updates. I wanted to know what. Google was not very helpful. A thread in the official forum was all I found and that thread did not exactly have a lot of information. Apparently I had to figure out things myself.
Unfortunately it turned out that µtorrent is sending a lot more data than can be seen in the screenshot so this little project took longer than originally planned. In fact I am only 90% done but I don't want to put any more time into this. One weekend is already too much time spent on this. So, here's what I figured out.
The URL in the screenshot is not complete. Depending on the state of the program certain URL arguments are omitted. In perfect conditions about 40 arguments that describe the user's system, the µtorrent settings, and µtorrent usage statistics are sent to the server. Here's the list in order of how they would appear in the URL.
Format string: v=%d
Description: This value identifies the µtorrent version. I used version 1.8.5 Build 17414. The 0x4406 is the build number. I am too lame to figure out how 0x30B relates to 1.8.5.
Format string: &qv=%d
Description: When I said I'm only 90% done this is what I meant. I can't figure out a way to trigger this URL part. I know it relates to the "dw" setting of the settings.dat file but I can't figure out what setting "dw" is. Anyway, this value is probably another version identifier. In the forum thread I linked above there's someone who had the qv appear in his update URL. His value was the same as for the 'v' argument.
Format string: &lv=%d_%d_%U
Description: The first %d is the value stored in the 'version' file inside your utorrent.lng language definition file (which is really a ZIP archive). The second %d was always 0, no matter what I did. Looking at the assembly code I think it can be any value between 0 and maybe 4, I just did not manage to trigger other values because finding the right execution paths was too time consuming. The %U is the locale of the GUI language selected in µtorrent.
Format string: &i=%d
Description: If the value is 128 (0x80) beta versions are considered when checking for updates. If the value is 0x00 only release versions are considered. I think there are other possible values (0x10, 0x20, 0x40?) but I did not manage to trigger them.
Format string: &l=%U
Description: A language identifier as returned by the API function GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, ..., ...).
Format string: &k=%U
Description: Of all the values I did not figure out this is the one I know least about.
Format string: &c=%U
Description: A country name identifier as returned by the API function GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SISO3166CTRYNAME, ..., ...).
Format string: &w=%X
Description: The return value of the API function GetVersion().
Format string: &e=%d
Description: 1 if Wine is detected by checking for certain registry keys.
Format string: &t=%d
Description: A number that says whether the PC uses IPv6 combined with a check whether the user is running Windows Vista or higher.
Format string: &h=%s
Description: OK, this value is a bit complicated. The gist is that this is a unique identifier for the user's computer that is generated when µtorrent is first installed. This value is then stored in the settings.dat file and transmitted to the µtorrent update server every time the program checks for updates. The individual steps to generate this value are:
- Concatenate the return values of QueryPerformanceCounter, GetCurrentProcessId, GetTickCount, and the number of seconds since 1970 into an array of 20 bytes.
- Create a SHA hash of that array.
- Use the SHA hash to modify a Mersenne Twister table that was previously generated with the constants found in this paper.
- Get a random 32 bit number (salt) with the help of the Mersenne Twister.
- Create a new 14 bytes array by concatenating the salt, the return value of UUIDCreateSequential, and the volume serial number of the user's C: drive as returned by GetVolumeInformationA.
- SHA-hash that array and overwrite it with the generated SHA-hash but start at position 4 so you do not overwrite the salt.
- SHA-hash the array again but without the salt (basically SHA-hash the SHA-hash from step 6). Once again overwrite the array with the hash value starting at position 4.
- SHA-hash just the salt.
- Add the hashes generated in steps 7 and 8 DWORD by DWORD and prepend the unmodified salt.
- Store the value in settings.dat as the setting with name 'cid' (possibly Computer ID).
- When checking for an update take the first 12 bytes of that 24 bytes value starting from position 4 (skip the salt).
- Base64 encode this value and add it to the URL.
Format string: &c_up=%u
Description: I don't know, I could not trigger that value.
Format string: &c_down=%u
Description: I don't know, I could not trigger that value.
Format string: &t_up=%Lu
Description: The total number of bytes uploaded to torrents since µtorrent was installed.
Format string: &t_down=%Lu
Description: The total number of bytes downloaded from torrents since µtorrent was installed.
Format string: &m_up=%d
Description: Configured maximum upload rate in KB/s.
Format string: &m_down=%d
Description: Configured maximum download rate in KB/s.
Format string: &aul=%d
Description: 1 if Automatic Maximum Upload Rate is enabled.
Format string: &wui=%d
Description: 1 if Web Interface is enabled.
Format string: &rsf=%d
Description: Number of configured RSS feeds.
Format string: &rsa=%d
Description: Number of configured RSS feeds whose torrents are downloaded automatically.
Format string: &tor_all=%d
Description: The number of known torrents.
Format string: &tor_down=%d
Description: The number of downloading torrents.
Format string: &tor_cmp=%d
Description: The number of complete torrents.
Format string: &tor_act=%d
Description: The number of active torrents.
Format string: &tor_in=%d
Description: The number of inactive torrents.
Format string: &tor_nl=%d
Description: The number of uncategorized torrents (No Label group in the GUI).
Format string: &sch=%d
Description: 1 if the scheduler is enabled.
Format string: &nat_state=%d
Description: Describes the network state. FF = Not connected; 00 = Not Connectable/Listen Error; 01 = No incoming connections; 02 = OK.
Format string: &up=%d
Description: Possibly UPnP related (1 = UPnP active and in use I think)
Format string: &np=%d
Description: Possibly NAT-PnP related (1 = NAT-PnP active and in use I think)
Format string: &ot=%d
Description: Total number of successfully established connections since µtorrent was started.
Format string: &ou=%d
Description: Couldn't trigger this no matter how many Linux ISOs I downloaded. Probably another outgoing connections stat.
Format string: &oh=%d
Description: Couldn't trigger this no matter how many Linux ISOs I downloaded. Probably another outgoing connections stat.
Format string: &it=%d
Description: Couldn't trigger this no matter how many Linux ISOs I downloaded. Probably another incoming connections stat.
Format string: &iu=%d
Description: Total number of established incoming connections since µtorrent was started.
Format string: &ih=%d
Description: Couldn't trigger this no matter how many Linux ISOs I downloaded. Probably another incoming connections stat.
Format string: &bo=%Lu
Description: Creation date of settings.dat in seconds since January 1st 1970. So basically the installation date.
Format string: &def_tor
Description: 1 if µtorrent is the default torrent client. Roughly a million registry keys are checked to verify this.
Format string: &tb=%d
Description: 1 if the Yandex toolbar is installed, 2 if the Ask toolbar is installed (and properly configured; once again checking a million registry keys). 3 if both toolbars are installed.
The good news is that we are done now. The bad news is that there is not just update.php but also installstats.php and updatestats.php which both take lovely argument lists with different argument values. I have also had a brief look at the upcoming µtorrent 2 beta. That version is sending out even more data. I leave all of that (and the settings.dat entry 'cid2' which is another computer identifier value) as an exercise to the reader.
Oh yeah, there is a setting in the preferences dialog (Send detailed info when checking for updates) where you can disable all of this data sending. However, it's enabled by default so your data is sent out at least once when you first start the program.