JumpList files are an interesting forensic artifact and as such they have been thoroughly explored by many researchers over last 2-3 years. There is really a lot of material out there and there are also many tools that parse JumpList files’ structure quite well. This is why in this post I will focus not on the content of JumpList files, but on their… file names.
The JumpList file names are created using hash-like values that in turn are based on something that is called AppID. The Forensics Wiki lists many known Jump List file names based on AppIDs; examples include:
- 918e0ecb43d17e23 used by Notepad (32-bit)
- 9b9cdc69c1c24e2b used by Notepad (64-bit)
- 1bc392b8e104a00e used by Remote Desktop
and so on and so forth. The data from Forensics Wiki has been harvested from many sources and it’s a very useful reference for further research.
The algorithm to create a hash-like value is actually ‘sort of known’. There are posts out there suggesting that the AppID is a nothing but a CRC64 sum taken from the application path. For example, in this post, an Anonymous poster provided a Hexrays Decompiler’s code snapshot taken from shell32.dll showing how the AppID is generated. When I came across this particular comment I decided to verify it. I applied CRC64 sum to an example path and compared it with an expected known file name, and since you are reading this post you are probably guessing that it failed miserably 🙂
Okay, so since it failed and since the algorithm didn’t t seem to be explored in-depth yet I thought I will give it a go. It turned out to be quite simple, but there were a few challenges on the way that may be interesting to know about so I describe it below. I also ended up writing a perl script that I called AppID calculator (appid_calc.pl). It allows you to calculate an AppID based on provided string – more about it below as well. You can find a download link to the script at the bottom of this post.
Using the code snippet I referred to earlier as a guidance, I quickly found the code responsible for generating AppIDs, put the appropriate breakpoints in a debugger, and.. immediately understood why the CRC64 (path) didn’t work for me earlier 🙂
The CRC64 algorithm has been indeed applied to a path, but there are a few quirks:
- The path is first converted to Unicode
- If the path is located in one of locations that are recognized and treated by system in a special way, the path is normalized first
- The CRC64(Path) algorithm applies only to AppIDs automatically generated by the system; At any point of time any application can change its AppID either using the SetCurrentProcessExplicitAppUserModelID API, or can even apply window-specific AppID using IPropertyStore::SetValue to change the PKEY_AppUserModel_ID property of the particular window
- On top of that, the CRC64 uses a non-standard polynomial
First, let’s talk about the CRC64. There are many CRC algorithms out there. In fact, the difference is not only between the length in bits (CRC16, CRC32, CRC64), but also in the configuration of a particular implementation. There are obviously many standard configurations (Wikipedia described quite a few), but the one used in AppID generation is not on the standard list. I know, because the very first thing I tried was to use all standard configurations, but all of them failed :-).
The actual code used by the system relies on a precalculated lookup table, but googling around for the numbers from the table only brought 2-3 hits. In such case, the usual way of solving the issue is to rip the code from the source and reimplement it e.g. in perl. This could be done easily. The 2-3 hits I mentioned earlier refer to a code that was created as a result of reverse engineering of thumbcache.dll file – turns out that the very exact CRC64 configuration/implementation has been used in that DLL.
Exploring the properties of CRC I eventually managed to deduce the CRC configuration and the actual polynomial used to generate the lookup table.
The polynomial used by the AppID algorithm is 0x92C64265D32139A4.
Once I found out I went to google again and this time I also got 2-3 hits only. First two were on the Thumb Cache-related code I already mentioned. The last one was the Microsoft page describing the use of this particular polynomial in a ADSStreamHeader structure:
Crc (8 bytes): A bit-reversed CRC-64 hash of the FCIADS stream from the TimeStamp field to the end of the structure that can be used to validate the integrity of the FCIADS stream. The cyclic redundancy check (CRC) polynomial is x**64 + x**61 + x**58 + x**56 + x**55 + x**52 + x**51 + x**50 + x**47 + x**42 + x**39 + x**38 + x**35 + x**33 + x**32 + x**31 + x**29 + x**26 + x**25 + x**22 + x**17 + x**14 + x**13 + x**9 + x**8 + x**6 + x**3 + 1, with the leading 1 implied. The normal representation is 0x92C64265D32139A4.
That was a good sign and I could now start implementing the appid calculator w/o ripping the lookup tables.
The second issue to solve was the normalization. The paths are normalized using KNOWNFOLDERIDs, so it’s a simple search and replace before applying the CRC.
One aspect of normalization I need to mention is… ambiguity. Depending on the OS (32 vs. 64 bit) different KNOWNFOLDERIDs are applied during the normalization path and it’s quite confusing. I suggest reading the Microsoft page I linked to above for further details.
Last, but not least. – quite a lot applications use SetCurrentProcessExplicitAppUserModelID API to change their AppID after they are executed. For example, the following applications do it (AppID – application name):
- Microsoft.Silverlight.Offline – Silverlight
- Microsoft.InternetExplorer.Default – Internet Explorer
- VMware.Workstation.vmplayer – VMWare Player
- Microsoft.Windows.MediaPlayer32 – Windows Media Player (32-bit)
- Microsoft.Windows.MediaPlayer64 – Windows Media Player (64-bit)
For this reason, attempting to find e.g. AppID of c:\program files\Internet Explorer\iexplore.exe doesn’t really make sense as all IE windows are grouped under Microsoft.InternetExplorer.Default AppID.
AppIDs of InternetExplorer and Sticky Notes
These can be confirmed by looking at Forensic Wiki:
- Microsoft.InternetExplorer.Default – 28C8B86DEAB549A1
- Microsoft.Windows.StickyNotes – 337ED59AF273C758
You may notice that in this example there are 2 different AppIDs shown. This is because of the ambiguity I mentioned earlier; applications running on 64-bit systems can be executed in more than one configuration and since there is WOW64 folder redirection happening AppID needs to be calculated in a context.
The Notepad path looks the same to both 32- and 64-bit application (because of WOW64 folder redirection):
but the AppID depends on a type of Notepad .exe file:
- if it is 32-bit, the AppID is 918E0ECB43D17E23
- if 64-bit, the AppID is 9B9CDC69C1C24E2B.
This can be also confirmed via Forensic Wiki:
Internet Explorer – via path
It gets even more complicated with Program Files folder as it has two versions – with and without (X86) and 32-/64- bit applications both ‘see’ Program Files the same way. As an example we could try to generate a hash for Internet Explorer in various configurations by running appid calculator and providing to it a path to c:\Program Files\Internet Explorer\iexplore.exe. As mentioned earlier IE uses an AppID that it sets up during the launch, so you should never see AppIDs shown on the screenshot below, but it is a simple example to show various configurations of Program Files folder using a well-known path.
Again, I strongly suggest reading the Microsoft Article about KNOWNFOLDERIDs, The appid calculator provides a link to it as well if the path is known to be ambiguous (system32, program files, program files\common).
You can find the script here. This is a first version, coded in a hurry so it may contain bugs. If you find any issues, please let me know. Thanks!
If no argument is passed to it, it will calculate a few sample AppIDs – the examples illustrate various ways one can provide the path to the script:
- c:\program files\Internet Explorer\iexplore.exe