We where telling “encryption jokes” (like ROT26) at the office, until a colleague mentioned that a part of the Windows Registry is ROT13 encrypted.

It appeared to be true, Windows Explorer will store info about the programs you run in registry key

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist\{75048700-EF1F-11D0-9888-006097DEACF9}\Count.

The value names stored in this key are ROT13 encrypted.

Google for UserAssist and you’ll find several pages where this is explained in detail, like this one. Some of these pages mention programs to decrypt ROT13, but I didn’t find a program to display and manage the UserAssist data. So I decided to write my own, just for the fun of it.

I wanted this program to have a GUI and I didn’t want to spend much time coding low-level details, so I decided to code it with the Microsoft .NET 2.0 Framework.

I posted my program (source code and binaries) here on the gotdotnet site.

Download the ZIP file, you’ll have to extract UserAssist\UserAssist\bin\Release\UserAssist.exe to get my program. There is no setup, it’s just one executable.

I used Microsoft Visual C# 2005 Express Edition because it’s free, so you can examine and modify my program. But it’s not needed to run my program, you’ll only need the .NET Framework 2.0 runtime to run my program (download it only if you have a problem running my program, if you have an up-to-date version of Windows XP, the .NET 2.0 Framework will already be installed).

My program displays the decrypted UserAssist entries as a treeview:

ROT13 is a monoalphabetic substitution cipher, these ciphers are very easy to decrypt, e.g. by frequency analysis. The namespace System.Security.Cryptography in .NET 2.0 does not implement the ROT13 cipher, I had to implement my own method.

While I developed my program, I became intrigued with the binary data. Because I had no access to the Internet at that time, I had to resort to the good old trial and error technique to discover the meaning of this data (I tested my program on Windows XP SP2).

For all entries starting with UEME_RUN, the binary data is 16 bytes long. The first 4 bytes at first always remained zero, and the fifth byte increased with one each time I ran the corresponding program (like notepad.exe). Because the sixth, seventh and eight byte are zero, I surmized that the 4 bytes starting at byte 5 are a 32 bit counter. Data on Intel machines is usually stored in little-endian format, this means that the least significant byte is stored first, e.g. a 32 bit integer with value 9 is stored as 09 00 00 00. When I ran a program the first time, this counter was initialized to the value of 6. This was also the case when I deleted the entry and ran the program again.

The remaining 8 bytes changed apparently at random each time I ran the corresponding program, but in fact only the least significant bytes changed. I hypothesized that the remaining 8 bytes are a timestamp. I ran notepad, noted the value of the 8 bytes, ran notepad exactly one minute later and noted the new value of the 8 bytes. The difference was 0x23B9D020, or 599380000, which is almost equal to 60 seconds times 10.000.000. Hence it definitely was a timestamp, I tried to convert the 8 last bytes to a timestamp with the C# method DateTime.FromFileTime, and Bingo!, I got the date and time when I last ran notepad.

Now back to the first 4 bytes. I noticed a trend: they are set to the value of the last 4 bytes of the UEME_CTLSESSION, and these 4 bytes appear to be a 32 bit counter that increases each time the user logs on (only after a reboot?). I need to analyze this further.

To summarize, the 16 data bytes are organized as:

• 4 bytes, meaning unknown, probably a 32 bit integer, appears to be a session counter

• 4 bytes, a 32 bit integer, counts the number of times the corresponding program was executed, is equal to 6 for the first run

• 8 bytes, a 64 bit timestamp, last time the corresponding program was executed

When you select an entry in the treeview, the binary data will be decoded and displayed at the bottom of the form.

My program should be self-explanatory.

Right-click an entry to clear it:

Clear All will delete the root keys, thus deleting all entries and also preventing Windows Explorer to record program execution until you perform a new logon (in fact, the entries are (re)created when Windows Explorer is started).

Caution: the UserAssist entries are used by Windows to display programs you use frequently in the Start menu:

Clearing the UserAssist entries will impact the Most Frequently Used Programs portion of your Start menu.

Reverse-Engineering the UserAssist entries was relatively easy, but I can’t explain why they are ROT13 encrypted!