The Prefetch file format has been studied extensively. There is a lot of research on this subject already, so I won’t reinvent any wheels here. Knowing that among the artefacts listed in the prefetch files are libraries loaded by our applications, I wanted to understand how the process of logging these libraries works in different scenarios, and how it can be tricked. Could I still load my library without Prefetch knowing?
Feel free to skip the background information, which is mostly for me to have things clear in my mind before starting to work. If you’re not familiar with the topic, I strongly encourage you to go start with Forensic Magazine and read Decoding Prefetch Files for Forensic Purposes Part 1 and Part 2.
Prefetch files are created by Windows when an application is run from a particular location for the very first time and updated on subsequent runs on the program. Their purpose is to speed up the applications by loading data from disk into memory before it is needed. Also, Prefetch will attempt to compute and save new data files each time the system starts up. Forensics Wiki goes into excellent detail on prefetch files and links to further resources.
Prefetch files are also great artifacts in a forensic investigations, very useful when building a timeline of applications that have been run on a system.
Prefetch files are named in a format containing the name of the application followed by an eight character hash of the location where the application was run and the .PF extension. To understand how this hash is generated, check this very in-depth Hexacorn blog post.
The name of the corresponding .pf file depends on the path of the application.
The prefetch related settings are held in the following registry key:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PrefetchParameters
For example, in order to alter the prefetch creation, we can modify EnablePrefetcher value as follows:
0 = Disabled 1 = Application Launch Prefetch 2 = Boot Prefetch 3 = Prefetch All
Forensic artefacts from the prefetch files
- Evidence of program execution - Even if the program has since been deleted, a prefetch file may still exist on the system to provide evidence of execution.
- Application running count - At every re-run from the same location, the corresponding .pf file will be updated with the number of times it was executed.
- Artefacts from malicious files - Using forensic tools, we can list libraries loaded by an application or even opened files.
- Original application path - It’s possible to calculate the application path based on the hash in the name. Depending on the version of Windows the file was taken from, a different hashing function is used. Definitely worth checking Prefetch file names and UNC paths.
- First and last time of execution - Creation date of the prefetch file shows the first time an application was executed, while the last time is stored in the .pf file. This can also reveal “time stomping” attempts. If malware alters the timestamp of an application, it might not be aware of the information captured in the corresponding prefetch file.
Prefetch parsers and libraries
- Windows Prefetch File (PF) format by Joachim Metz
- WinPrefetchView by Nir Sofer
- Windows-Prefetch-Parser by Adam Witt
- Windows-Prefetch-Carver by Adam Witt
- Windows Prefetch Parser by TZWorks
Logging loaded libraries
So let’s see different ways of loading libraries and how they are logged by the prefetching process. A very important detail to keep in mind: according to the first Forensic Magazine article mentioned previously:
Monitoring occurs for ten seconds after an application is started.
- Implicit linking
This linking method is also referred to as static load or load-time dynamic linking. With implicit linking, the executable using the DLL links to an import library (.lib file) provided by the maker of the DLL. The operating system loads the DLL when the executable is loaded.
Result: To test this, the application below executes something inside a TLS callback then immediately terminates execution.before the main function. However, a prefetch file is still created accordingly.
Code: static loading
- Explicit linking
This linking method is sometimes referred to as dynamic load or run-time dynamic linking. With explicit linking, the executable using the DLL must make function calls to explicitly load and unload the DLL and to access the DLL’s exported functions.
Result: Again, no surprises, libraries are correctly mentioned. Even if no function is called there is still a corresponding DLL entry in the .pf file.
Code: dynamic load.
- Explicit linking (manual)
This technique is frequently used in exploits, which need to first find the base address of kernel32.dll and then the address of LoadLibrary function manually. Very prevalent technique.
Result: Again, loaded libraries are listed correctly. Although this trick works to defeat various host-based protection mechanisms, in this case the OS correctly keeps track of what has been loaded and the information in the prefetch files is correct.
Code: This program is using inline assembly to jump inside a function, instead of calling. Function parameters and the return address are adjusted and pushed manually.
- Delayed loading
Using this method, the libraries will be loaded only when needed. With Visual Studio, we can specify libraries for delayed loading using a specific linker option.
Result: Delayed loaded libraries are also present in the prefetch files.
- DLL Injection
Now things start to become interesting. There are multuple methods to inject a library into another process. The OpenSecurityResearch Dll injector project implements some of these known injection techniques and references others. Download the source code, compile it and play with the options. Let’s try for example the injection method using CreateRemoteThread():
> dllInjector-x86.exe -p 3328 -l myDll.dll -P -c
Result: As you migt have expected, there is no mention of the library being injected in the prefetch file corresponding to the injected process. While testing these techniques I’ve noticed something which can be much worse for the forensic investigator - injecting a library into a process, within its first seconds of activity, generates a crash of the Prefetch Manager and no prefetch files will be created until the next restart. This behaviour seems to reproduce very often on a Windows 7 32bit VM. Anyways, more tests to follow.
Code: Simple dll.
- Reflective DLL loading
If you don’t know what reflective DLL loading is, go read about it now! In this case the library implements a minimal PE loader in order to load itself.
Result: Because the loader of the OS is not involved, there is no mention of the library being loaded in the prefetch file corresponding to the host process.
- Artificially delayed loading
This technique relies on the observation above that Windows will monitor an application only for 10 seconds after launch. We’ll introduce an artificial delay of 10+ seconds.
Result: Anything loaded after that period will not be recorded in the prefetch file.
|Explicit linking (manual)||NO|
|Dll injection||YES ( +nasty bug)|
|Reflective dll loading||YES|
|Articifial delayed loading||YES|
Another unexplained (yet!) behaviour can be seen in the video above. The script shown on the left side is run two times. The first run produces the expected results - two prefetch files and correct output of Process Explorer. But if you watch carefully the second run, you can see that although the program renamed as Bug-Secret.exe is running (based on the title bar of the message box), Process Explorer lists something different - Bug.exe. Also no prefetch file gets created.
Fortunately this bug cannot be reproduced reliably, so it won’t cause problems for forensic examinations.
In the next part of this blogpost we’ll look at the way these incredibly important forensic artefacts, the prefetch files, are actually created and how (and if!) an intruder trying to hide its traces could work around them.