{"id":1034,"date":"2012-06-13T20:05:04","date_gmt":"2012-06-13T20:05:04","guid":{"rendered":"http:\/\/www.hexacorn.com\/blog\/?p=1034"},"modified":"2021-07-07T17:57:41","modified_gmt":"2021-07-07T17:57:41","slug":"prefetch-hash-calculator-a-hash-lookup-table-xpvistaw7w2k3w2k8","status":"publish","type":"post","link":"https:\/\/www.hexacorn.com\/blog\/2012\/06\/13\/prefetch-hash-calculator-a-hash-lookup-table-xpvistaw7w2k3w2k8\/","title":{"rendered":"Prefetch Hash Calculator + a hash lookup table xp\/vista\/w7\/w2k3\/w2k8"},"content":{"rendered":"<p><strong>Update 4<br \/>\n<\/strong><\/p>\n<p>In July 2013 I added a little bit about \/Prefetch:xxx command line argument. Read it <a href=\"https:\/\/www.hexacorn.com\/blog\/2013\/07\/06\/the-argument-about-prefetchx-or-the-other-way-around\/\">here<\/a>.<\/p>\n<p><strong>Update 3<\/strong><\/p>\n<p>In October 2012 I added a small addendum <a title=\"Prefetch file names and UNC paths\" href=\"https:\/\/www.hexacorn.com\/blog\/2012\/10\/29\/prefetch-file-names-and-unc-paths\/\">here<\/a> describing how the UNC paths are being processed by the algorithm.<\/p>\n<p><strong>Update 2<\/strong><\/p>\n<p>I previously wrote that &#8220;<em>Windows 7 introduces another quirky change &#8211; device path now starts from volume2 (if anyone knows why, please let me know).<\/em>&#8220;. One good fellow forensic investigator (he asked to remain anonymous) came back to me with an explanation &#8211; it&#8217;s a 100MB reserved partition that occupies volume number 1 on <a href=\"https:\/\/social.technet.microsoft.com\/Forums\/en-NZ\/w7itproinstall\/thread\/29fa0858-8971-413b-ba8a-d033aa6dae55\">Windows 7<\/a>.<\/p>\n<p>In most cases, results of prefetch hash calculator tool will be valid for Windows 7 as most of W7 users have this hidden partition present. Now, if someone intentionally removes the hidden partition and uses volume 1 as C:, the resulting hashes will be incorrect.<\/p>\n<p>The short fix is to quickly modify the script to count volumes from C-B, instead of C-A (lines 111 and 137).<\/p>\n<p>The issue between mapping the logical drives (DOS names) and physical devices is a bit of an issue and a next version of the script will be a bit smarter in this aspect. Stay tuned.<\/p>\n<p><strong>Update<\/strong><\/p>\n<p>Added Windows 8 Customer Preview 32-bit (inline). Will update script later.<\/p>\n<p><strong>Old <\/strong><strong>Post<\/strong><\/p>\n<p>I guess at this moment of time everyone is familiar with a content of <strong>\\windows\\Prefetch<\/strong> folder as well as the value it has\u00a0 for a forensic investigation or IR\/malware analysis. There are multiple scripts available out there that can parse the content of Prefetch files, and even running simple strings on the .pf files are good enough to point us into a place where the malware or its files are stored. Of course, one has to also remember that Prefetch analysis can be fooled by a couple of tricks eg. <a href=\"https:\/\/www.hexacorn.com\/blog\/2011\/12\/05\/forensic-riddle-3-answer\/\">PrefetchADS<\/a> as well as a <a href=\"https:\/\/www.hexacorn.com\/blog\/2012\/03\/16\/the-shortest-anti-forensics-code-in-the-world-take-2\/\">10+ seconds delay before opening any file<\/a> trick.<\/p>\n<p>This post is about the actual hashing algorithm used by Prefetch files.<\/p>\n<h4>History<\/h4>\n<p>It has been already discussed previously <a href=\"http:\/\/42llc.net\/?p=375\">here<\/a>, <a href=\"http:\/\/www.woanware.co.uk\/?page_id=173\">here<\/a>, and <a href=\"http:\/\/kitrap08.blogspot.hk\/2011\/07\/windows-logical-prefetcher.html\">here<\/a>, but I always felt there is more to the story, so I decided to provide some more information about what&#8217;s going on under the hood&#8230; and update the knowledge base with algorithms for newer versions of Windows.<\/p>\n<h4>Algorithms covered in this post<\/h4>\n<ul>\n<li>Windows XP 32-bit<\/li>\n<li>Windows Vista 32-bit<\/li>\n<li>Windows 7 32-bit<\/li>\n<li>Windows 7 64-bit<\/li>\n<li>Windows 8 32-bit (Customer Preview)<\/li>\n<li>Windows Server 2003 32-bit<\/li>\n<li>Windows Server 2008 32-bit<\/li>\n<li>Windows Server 2008 64-bit<\/li>\n<\/ul>\n<p>As far as I can tell:<\/p>\n<ul>\n<li>The presented algorithms most likely work for all the service packs, new releases (one exception is 2008 R2 &#8211; see below).<\/li>\n<li>Prefetching is by default disabled on Servers\u00a0 (2003 and 2008), but can be enabled.<\/li>\n<li>Prefetching on 2008 R2 is disabled and doesn&#8217;t seem to be available for enabling (prefetch calculation code is still present; relevant discussion <a href=\"https:\/\/social.technet.microsoft.com\/Forums\/en-US\/windowsserver2008r2general\/thread\/ca451db2-762b-44b7-a100-9d0d6a4230d7\">here<\/a>).<\/li>\n<\/ul>\n<h4>Prefetch file naming algorithm vs. hashing function<\/h4>\n<p>There is fundamentally one single Prefetch hashing algorithm used by various Windows versions, except it has been slightly modified over the time. I must emphasize here a distinction between a <em>Prefetch\u00a0file naming algorithm<\/em> and a<em> hashing function<\/em> (I chose these names on my own, but I think they are quite relevant):<\/p>\n<ul>\n<li><em>Prefetch\u00a0file naming algorithm<\/em> &#8211; produces the string e.g. RUNDLL32.EXE-35A2A03F.pf<\/li>\n<li><em>Hashing function<\/em> &#8211; produces a hash or multiple hashes that are building the final part of a Prefetch file name e.g. 35A2A03F<\/li>\n<\/ul>\n<p>The reason why I need to emphasize it will become clearer later.<\/p>\n<h4>Hashing functions<\/h4>\n<p>There are 3 hashing functions\u00a0 used by variations of Prefetch file naming algorithm that I am aware of:<\/p>\n<ul>\n<li>Windows XP 32-bit\/Windows Server 2003<\/li>\n<li>Windows Vista 32-bit<\/li>\n<li>Windows 7\/Windows Server 2008\/Windows 8 32-bit<\/li>\n<\/ul>\n<p>The code implementing all of them as well as for Prefetch file naming algorithm is available in a script attached to this post.<\/p>\n<h4>Prefetch file naming algorithm &#8211; analysis 1\/2<\/h4>\n<p>When you run an application for an example say&#8230;\u00a0 notepad.exe, the following things happen:<\/p>\n<ul>\n<li>The full path for the file is determined e.g. c:\\windows\\notepad.exe.<\/li>\n<li>The path isconverted to Unicode string.<\/li>\n<li>The full path is converted from to a device path e.g. \\DEVICE\\HARDDISKVOLUME1\\WINDOWS\\NOTEPAD.EXE.<\/li>\n<li>Now, the hashing function is applied to the buffer.<\/li>\n<li>Then the Prefetch file name is determined as a filename-hash e.g. CALC.EXE-02CD573A.pf.<\/li>\n<\/ul>\n<p>The hashing function is implemented by a function <strong>CcPfHashValue<\/strong> and its original code has been already provided (for XP) on the <a href=\"http:\/\/kitrap08.blogspot.hk\/2011\/07\/windows-logical-prefetcher.html\">blog<\/a> I mentioned earlier. Newer versions of Windows store hashing functions code either inline or inside <strong>PfCalculateProcessHas<\/strong>h\/<strong>PfSnScanCommandLine <\/strong>functions<strong>.<\/strong><\/p>\n<p>Looking at CcPfHashValue in windbg we can see the following:<\/p>\n<p><a href=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2012\/06\/prefetch1.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter\" title=\"prefetch1\" src=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2012\/06\/prefetch1-300x205.png\" alt=\"\" width=\"300\" height=\"205\" \/><\/a><\/p>\n<p>The assembly code converted to perl looks as follows:<\/p>\n<pre>sub hash_xp\n{\n\u00a0 my $devpath_u = shift;\n\u00a0 my $hash = 0;\n\u00a0 for (my $i=0; $i&lt;length($devpath_u); $i++)\n\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0 my $char = ord(substr($devpath_u,$i,1));\n\u00a0\u00a0\u00a0\u00a0\u00a0 $hash = ( ($hash * 37) + $char ) % 4294967296;\n\u00a0\u00a0\u00a0\u00a0\u00a0 #print STDERR sprintf(\"%08lX\",$hash).' '.substr($devpath_u,$i,1).\"\\n\";\n\u00a0 }\n\u00a0 $hash = ($hash * 314159269) % 4294967296;\n\n\u00a0 $hash = 0x100000000-$hash if ($hash&gt;0x80000000);\n\u00a0 $hash = (abs($hash) % 1000000007) % 4294967296;\n\u00a0 return $hash;\n}<\/pre>\n<p>Now, knowing the hashing algorithm, it is tempting to assume that you could do this:<\/p>\n<pre>for each .exe file on the system\n   find its full path\n      apply the algorithm\n       build a lookup table of all possible 'full path to .exe' &amp; 'hash' pairs\n           use it as a reference while analyzing the content\n           of the actual Prefetch folder.<\/pre>\n<p>Well, indeed you can do it and the script provided as an attachment to this article is doing exactly this. It generates hashes for known .exe files extracted from various Windows systems + also for known rundll32.exe calls (If you find any missing entry, please let me know).<\/p>\n<p>The script also accepts file names as a command line argument which can be used to instantly calculate the hash for a file of your choice and it can calculates the hash for XP (32-bit), Vista (32-bit) and Windows 7 (32- and 64-bit) as well as for 32-bit versions of Windows Server 2003 and 2008.<\/p>\n<p>So far so good. We can now build a lookup table that we can then use to associate known Prefetch hashes with the actual full paths.<\/p>\n<p>But hold on, what about the hashes for programs that are executed with a command line arguments?<\/p>\n<p>Turns out that for a typical application without a command line argument hashing function is applied only once and only to the the path; the command line arguments are simply ignored. And using command line when launching the applications doesn&#8217;t change a thing. One can run e.g. Notepad as <strong>notepad.exe<\/strong> and also with a command line argument e.g. <strong>notepad.exe 1.txt.<\/strong> The hash will remain the same.<\/p>\n<h4>Prefetch file naming algorithm &#8211; analysis 2\/2<\/h4>\n<p>I mentioned &#8216;typical&#8217;. This is where the things get\u00a0 a bit ugly. There are two exceptions when hash calculation becomes a bit more complex. It has to do with the two following cases:<\/p>\n<ul>\n<li>the application ran is a so-called hosting application e.g. <strong>rundll32.exe<\/strong>, <strong>mmc.exe<\/strong>, and newer versions of Windows systems also include<strong> dllhost.exe<\/strong> and <strong>svchost.exe<br \/>\n<\/strong><\/li>\n<li>there is a command line \/Prefetch used (I skip this bit in this post)<\/li>\n<\/ul>\n<p>In these cases, the Prefetch file name no longer relies on a device .exe path only. It does take it into account of course, but it also includes a command line used to launch an application itself and\/or \/Prefetch command line argument if it exists.<\/p>\n<p>For example, running a command:<\/p>\n<p style=\"text-align: center;\"><strong>rundll32.exe shell32.dll,Control_RunDLL main.cpl @0<\/strong><\/p>\n<p>gives us a Mouse Properties dialog box:<\/p>\n<p><a href=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2012\/06\/prefetch3.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter\" title=\"prefetch3\" src=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2012\/06\/prefetch3-266x300.png\" alt=\"\" width=\"266\" height=\"300\" \/><\/a><\/p>\n<p>The following happen when you run it:<\/p>\n<ul>\n<li>The full path for the file is determined e.g. c:\\windows\\system32\\rundll32.exe<\/li>\n<li>The Path is stored\/converted to Unicode string<\/li>\n<li>The full path is converted from to a device path e.g. \\DEVICE\\HARDDISKVOLUME1\\WINDOWS\\RUNDLL32.EXE<\/li>\n<li>Now, the hashing function is applied for the first time (I refer to it below as hash1) and is calculated on the path like this:<\/li>\n<\/ul>\n<p><a href=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2012\/06\/prefetch21.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter\" title=\"prefetch2\" src=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2012\/06\/prefetch21.png\" alt=\"\" width=\"290\" height=\"44\" \/><\/a><\/p>\n<ul>\n<li>Then comes the second part: the command line<\/li>\n<li>The second hash (I refer to it below as hash2) is calculated on a case-sensitive path+command line combo and it includes quotation marks (XP) e.g.:<\/li>\n<\/ul>\n<p><a href=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2012\/06\/prefetch4.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter\" title=\"prefetch4\" src=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2012\/06\/prefetch4.png\" alt=\"\" width=\"283\" height=\"56\" \/><\/a><\/p>\n<ul>\n<li>Once the 2 hashes are calculated, they are added together.<\/li>\n<li>So, the actual hash string used in a Prefetch file name is a sum of hash1+hash2; this is why I made the distinction between the Prefetch file naming algorithm and hashing function at the very beginning of the article &#8211; they are 2 different things; one relies on another to build a final file name string<\/li>\n<li>In this particular case, the Prefetch file name is RUNDLL32.EXE-40E8EB31.pf (XP-32bit only).<\/li>\n<\/ul>\n<p>Okay, so the problem with anything that runs via rundll32.exe (or other hosting application) is that the path is case sensitive and any change to it generates a new Prefetch file name \ud83d\ude41<\/p>\n<p>Indeed, as an experiment, you can try running the following commands (run on XP-32bit):<\/p>\n<ul>\n<li>rundll32.exe shell32.dll,Control_RunDLL main.cpl @0\n<ul>\n<li>produces RUNDLL32.EXE-40E8EB31.pf<\/li>\n<\/ul>\n<\/li>\n<li>rundll32.exe <strong>S<\/strong>hell32.dll,Control_RunDLL main.cpl @0\n<ul>\n<li>produces RUNDLL32.EXE-3EEC4634.pf<\/li>\n<\/ul>\n<\/li>\n<li>rundll32.exe s<strong>H<\/strong>ell32.dll,Control_RunDLL main.cpl @0\n<ul>\n<li>produces RUNDLL32.EXE-48FA8C58.pf<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>The second problem comes from the path of the actual rundll32.exe. The hashing function is applied twice and it walks through a buffer storing device path to rundll32.exe + command line, and this one is case-sensitive. So, any change to the path generates a different hash1; that is,<\/p>\n<ul>\n<li>c:\\WINDOWS<\/li>\n<li>c:\\wINDOWS<\/li>\n<li>c:\\windows<\/li>\n<\/ul>\n<p>will produce different hashes \ud83d\ude41<\/p>\n<p>Last, but not least, even a number of spaces between the rundll32.exe path and its command line makes a difference as well e.g.<\/p>\n<ul>\n<li>rundll32.exe shell32.dll,Control_RunDLL main.cpl @0<\/li>\n<li>rundll32.exe\u00a0 shell32.dll,Control_RunDLL main.cpl @0<\/li>\n<li>rundll32.exe\u00a0\u00a0 shell32.dll,Control_RunDLL main.cpl @0<\/li>\n<\/ul>\n<p>will also produce different hashes (hash2)!<\/p>\n<p>While it is possible to build some sort of rainbow tables for all such possible Prefetch path&amp;command line combinations, it&#8217;s time consuming and most of the time not worth it.<\/p>\n<p>There are still good news though. And I already mentioned it earlier.\u00a0 Instead of building large lookup tables, it is easier to find all .exe file names + all references to rundll32.exe 9and othe rhosting applications listed earlier) within the evidence (e.g. extract strings from a full image+from memory+malware samples+registry), and calculate the hashes of the exact path name or path+command line as present in evidence. We will end up with a small list of pairs:<\/p>\n<ul>\n<li>Prefetch file name<\/li>\n<li>full path<\/li>\n<\/ul>\n<p>that can be used for lookups for each particular forensic case.<\/p>\n<h4>The Prefetching file naming algorithms on various systems<\/h4>\n<p>As you now know, a simple change in a path, an extra space, or a case-sensitivity of a letter changes the final name of a Prefetch file. Sadly, this is partially the reason why hash calculated for one system doesn&#8217;t work for another.<\/p>\n<p>Each version of the Windows OS uses a different prefetching file naming algorithm<\/p>\n<ul>\n<li>Windows XP 32-bit<\/li>\n<\/ul>\n<p style=\"padding-left: 30px;\">sum of hash_xp (on devicename and c: = volume1)+ hash_xp(quoted path+command line)<\/p>\n<ul>\n<li>Windows Vista 32-bit<\/li>\n<\/ul>\n<p style=\"padding-left: 30px;\">sum of hash_vista (on devicename and c: = volume1)+ hash_vista(quoted path+command line)<\/p>\n<ul>\n<li>Windows 7 32-bit<\/li>\n<\/ul>\n<p style=\"padding-left: 30px;\">sum of hash_w7 (on devicename and c: = volume2 )+ hash_w7(quoted path+command line)<\/p>\n<ul>\n<li>Windows 7 64-bit<\/li>\n<\/ul>\n<p style=\"padding-left: 30px;\">sum of hash_w7 (on devicename and c: = volume2 )+ hash_w7(unquoted path+command line prefixed with extra blank character<\/p>\n<ul>\n<li>Windows 8 32-bit<\/li>\n<\/ul>\n<p style=\"padding-left: 30px;\">sum of hash_w7 (on devicename and c: = volume2 )+ hash_w7(unquoted path+command line prefixed with extra blank character<\/p>\n<ul>\n<li>Windows Server 2003 32-bit<\/li>\n<\/ul>\n<p style=\"padding-left: 30px;\">sum of hash_xp (on devicename and c: = volume1 )+ hash_xp(unquoted path+command line)<\/p>\n<ul>\n<li>Windows Server 2008 32-bit<\/li>\n<\/ul>\n<p style=\"padding-left: 30px;\">sum of hash_w7 (on devicename and c: = volume1 )+ hash_w7(unquoted path+command line prefixed with extra blank character)<\/p>\n<p>Example for<\/p>\n<p style=\"text-align: center;\"><strong>C:\\WINDOWS\\system32\\rundll32.exe &#8221; shell32.dll,Control_RunDLL hdwwiz.cpl&#8221;<\/strong><\/p>\n<p>looks as follows:<\/p>\n<ul>\n<li>\n<pre>XP\u00a0\u00a0\u00a0 (32-bit)\u00a0 RUNDLL32.EXE-213BB9F5.pf<\/pre>\n<\/li>\n<li>\n<pre>Vista (32-bit)\u00a0 RUNDLL32.EXE-9E75AB16.pf<\/pre>\n<\/li>\n<li>\n<pre>W7\u00a0\u00a0\u00a0 (32-bit)\u00a0 RUNDLL32.EXE-CD32988B.pf<\/pre>\n<\/li>\n<li>\n<pre>2003\u00a0 (32-bit)\u00a0 RUNDLL32.EXE-36767DBD.pf<\/pre>\n<\/li>\n<li>\n<pre>2008\u00a0 (32-bit)\u00a0 RUNDLL32.EXE-06E5B2CA.pf<\/pre>\n<\/li>\n<li>\n<pre>W7\u00a0\u00a0\u00a0 (64-bit)\u00a0 RUNDLL32.EXE-35A2A03F.pf<\/pre>\n<\/li>\n<li>\n<pre>W8 CP (32-bit)\u00a0 RUNDLL32.EXE-35A2A03F.pf<\/pre>\n<\/li>\n<\/ul>\n<h4>The script and a simple hash lookup table<\/h4>\n<p>It is a very simple algorithm, yet the differences and subtleties make it very confusing.<\/p>\n<p>As mentioned before, the script attached to this post will calculate all the known hashes based on command line arguments. And if there are no command line arguments, it will generate a lookup table for a lot of known\u00a0 file names + known rundll32.exe combinations (e.g. these launching various system properties applets) that may be immediately used against evidence. At any time, you can also provide your own file list.<\/p>\n<p>To run:<\/p>\n<ul>\n<li>prefhashcalc.pl &lt;path&gt; &#8221; &lt;command line&gt;&#8221;<\/li>\n<\/ul>\n<p>OR<\/p>\n<ul>\n<li>prefhashcalc.pl -f &lt;filelist&gt;<\/li>\n<\/ul>\n<p>OR<\/p>\n<ul>\n<li>prefhashcalc.pl &gt; &lt;prefetch_lookup_table file&gt;<\/li>\n<\/ul>\n<p>Examples:<\/p>\n<ul>\n<li>prefhashcalc.pl c:\\windows\\notepad.exe<\/li>\n<li>prefhashcalc.pl c:\\windows\\system32\\notepad.exe<\/li>\n<li>prefhashcalc.pl C:\\WINDOWS\\system32\\rundll32.exe &#8221; shell32.dll,Control_RunDLL main.cpl @0&#8243;<\/li>\n<li>prefhashcalc.pl C:\\WINDOWS\\system32\\rundll32.exe &#8221;\u00a0 shell32.dll,Control_RunDLL main.cpl @0&#8243;<\/li>\n<li>prefhashcalc.pl &gt; lookup_table_of_all_known.txt<\/li>\n<li>prefhashcalc.pl -f myfilelist.txt &gt; my_lookup_tablet.txt<\/li>\n<\/ul>\n<p><strong>Note: <\/strong><\/p>\n<p><strong>for hosting applications e.g. rundll32.exe you need to prefix the actual command line\u00a0 argument for a hosting application\u00a0 with a blank character or more of them as they are directly concatenated before passed to hashing function, using arguments like this:<\/strong><\/p>\n<ul>\n<li style=\"text-align: left;\">C:\\WINDOWS\\system32\\rundll32.<strong>exe &#8220;shell32<\/strong>.dll,Control_RunDLL main.cpl @0&#8243;<\/li>\n<\/ul>\n<p>would make the function calculate hash for<\/p>\n<ul>\n<li style=\"text-align: left;\">C:\\WINDOWS\\system32\\rundll32.<strong>exeshell32<\/strong>.dll,Control_RunDLL main.cpl @0<\/li>\n<\/ul>\n<p>which is incorrect.<\/p>\n<p>Script detects this situation and prints the error message. You can see an example use below:<\/p>\n<p><a href=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2012\/06\/prefetch9.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-medium wp-image-1054\" title=\"prefetch9\" src=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2012\/06\/prefetch9-300x44.png\" alt=\"\" width=\"300\" height=\"44\" srcset=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2012\/06\/prefetch9-300x44.png 300w, https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2012\/06\/prefetch9-1024x151.png 1024w, https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2012\/06\/prefetch9.png 1525w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>Running:<\/p>\n<ul>\n<li>prefhashcalc.pl &gt; lookup_table_of_all_known.txt<\/li>\n<\/ul>\n<p>produces a lookup table that you can grep or import to Excel and use VLOOKUP function to search for the known Prefetch file name.<\/p>\n<p>The lookup is generated using the following algorithm:<\/p>\n<pre>for each entry on a list attached to the script<\/pre>\n<pre>\u00a0\u00a0\u00a0\u00a0\u00a0 for each letter from c: to f:<\/pre>\n<pre>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 for each supported operating system<\/pre>\n<pre>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 calculate hash and print lookup entries to the output\n                 (including lower\/upper case)<\/pre>\n<p><a href=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2012\/06\/prefetchA.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter  wp-image-1058\" title=\"prefetchA\" src=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2012\/06\/prefetchA-300x76.png\" alt=\"\" width=\"300\" height=\"76\" srcset=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2012\/06\/prefetchA-300x76.png 300w, https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2012\/06\/prefetchA-1024x261.png 1024w, https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2012\/06\/prefetchA-1006x250.png 1006w, https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2012\/06\/prefetchA-990x250.png 990w, https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2012\/06\/prefetchA.png 1165w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<h4>Download<\/h4>\n<p>You can download the script <a href=\"https:\/\/hexacorn.com\/d\/prefhashcalc.pl\">here<\/a>.<\/p>\n<p>And the pregenerated lookup table for Prefetch hashes file is <a href=\"https:\/\/hexacorn.com\/d\/prefetch_hashes_lookup.zip\">here<\/a>.<\/p>\n<h4>Final words<\/h4>\n<p>Few things come to mind that I have not looked at but may be worth checking:<\/p>\n<ul>\n<li>hash collisions &#8211; there must be paths that produce the same Prefetch file names.<\/li>\n<li>\/Prefetch command line argument.<\/li>\n<li>Prefetch settings under the following key allow for Prefetch setting manipulation (even the location of Prefetch files &#8211; this could be an interesting anti-forensics technique)<\/li>\n<\/ul>\n<pre>       HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\\n          Control\\Session Manager\\Memory Management\\\n              PrefetchParameters<\/pre>\n<p>Thanks for reading and testing the script; note that it is a first version and may contain bugs. If you spot anything wrong, please let me know. Thanks in advance.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Update 4 In July 2013 I added a little bit about \/Prefetch:xxx command line argument. Read it here. Update 3 In October 2012 I added a small addendum here describing how the UNC paths are being processed by the algorithm. &hellip; <a href=\"https:\/\/www.hexacorn.com\/blog\/2012\/06\/13\/prefetch-hash-calculator-a-hash-lookup-table-xpvistaw7w2k3w2k8\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[15,19],"tags":[],"_links":{"self":[{"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/posts\/1034"}],"collection":[{"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/comments?post=1034"}],"version-history":[{"count":29,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/posts\/1034\/revisions"}],"predecessor-version":[{"id":7840,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/posts\/1034\/revisions\/7840"}],"wp:attachment":[{"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/media?parent=1034"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/categories?post=1034"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/tags?post=1034"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}